April 28, 2016

customize golang tls listener

How ListenAndServeTLS works in Golang

  1. it creates a struct of http.Server type, and then calls the server.ListenAndServe method
  2. http.server.ListenAndServeTLS
    1. clone server.TLSConfig
    2. if tls config has no certs OR a certfile is specified, load certs
    3. create a TLS socket that listens on the TCP port
    4. call server.Serve using that socket
  3. Server.serve
    1. Accept the new connection, returns http.conn
    2. http.conn.serve()


The customize this, one could write his own function like this:

   srv := &Server{Addr: addr, Handler: handler}
    addr := srv.Addr
    if addr == "" {
        addr = ":https"
    }
    config := cloneTLSConfig(srv.TLSConfig)
    if config.NextProtos == nil {
        config.NextProtos = []string{"http/1.1"}
    }

    if len(config.Certificates) == 0 || certFile != "" || keyFile != "" {
        var err error
        config.Certificates = make([]tls.Certificate, 1)
        config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
        if err != nil {
            return err
        }
    }

    ln, err := net.Listen("tcp", addr)
    if err != nil {
        return err
    }

    tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
    return srv.Serve(tlsListener)



April 22, 2016

ipset netlink data structure

header:
\x4c\x00 \x00\x00 total length
\x09\x06 type=09 CMD_ADD \x05\x02 flags:0x0205 request/ack/return-all-matching
\xbb\x83\x1a\x57 seq
\x00\x00\x00\x00 port id

extra header
\x02\x00\x00\x00

payload, in the form of Leng-Type-Value
(len and type are 2 bytes, len includes itself and type. 0 Padded to 4-byte alignment)
Type flags:
   0x80: NEST structure
   0x40: Network Order

\x05\x00 \x01\x00 \x06 \x00\x00\x00 PROTOCOL=6
\x0a\x00 \x02\x00 \x70\x61\x69\x72\x31\x00\x00\x00 SETNAME=pair1
\x24\x00 \x07\x80 IPSET_ATTR_DATA
\x0c\x00 \x01\x80\ IPSET_ATTR_IP
x08\x00\x01\x40\x02\x02\x02\x02 IPV4 2.2.2.2
\x0c\x00\x14\x80 IPSET_ATTR_IP2
\x08\x00\x01\x40 \x04\x04\x04\x04 IP 4.4.4.4
\x08\x00\x09\x40 \x00\x00\x00\x00 IPSTE_ATTR_LINENO 0, network order


== update on 12/13/2018
enum ipset_cmd {
    IPSET_CMD_NONE,
    IPSET_CMD_PROTOCOL, /* 1: Return protocol version */
    IPSET_CMD_CREATE,   /* 2: Create a new (empty) set */
    IPSET_CMD_DESTROY,  /* 3: Destroy a (empty) set */
    IPSET_CMD_FLUSH,    /* 4: Remove all elements from a set */
    IPSET_CMD_RENAME,   /* 5: Rename a set */
    IPSET_CMD_SWAP,     /* 6: Swap two sets */
    IPSET_CMD_LIST,     /* 7: List sets */
    IPSET_CMD_SAVE,     /* 8: Save sets */
    IPSET_CMD_ADD,      /* 9: Add an element to a set */
    IPSET_CMD_DEL,      /* 10: Delete an element from a set */
    IPSET_CMD_TEST,     /* 11: Test an element in a set */
    IPSET_CMD_HEADER,   /* 12: Get set header data only */
    IPSET_CMD_TYPE,     /* 13: Get set type */
    IPSET_MSG_MAX,      /* Netlink message commands */

    /* Commands in userspace: */
    IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
    IPSET_CMD_HELP,     /* 15: Get help */
    IPSET_CMD_VERSION,  /* 16: Get program version */
    IPSET_CMD_QUIT,     /* 17: Quit from interactive mode */

    IPSET_CMD_MAX,

    IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
};

command level attributes:
IPSET_ATTR_PROTOCOL,    /* 1: Protocol version */
IPSET_ATTR_SETNAME, /* 2: Name of the set */
IPSET_ATTR_TYPENAME,    /* 3: Typename */
IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
IPSET_ATTR_REVISION,    /* 4: Settype revision */
IPSET_ATTR_FAMILY,  /* 5: Settype family */
IPSET_ATTR_FLAGS,   /* 6: Flags at command level */
IPSET_ATTR_DATA,    /* 7: Nested attributes */
IPSET_ATTR_ADT,     /* 8: Multiple data containers */
IPSET_ATTR_LINENO,  /* 9: Restore lineno */
IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */

Nested attributes:
/* CADT specific attributes */
IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
IPSET_ATTR_IP_TO,   /* 2 */
IPSET_ATTR_CIDR,    /* 3 */
IPSET_ATTR_PORT,    /* 4 */
IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
IPSET_ATTR_PORT_TO, /* 5 */
IPSET_ATTR_TIMEOUT, /* 6 */
IPSET_ATTR_PROTO,   /* 7 */
IPSET_ATTR_CADT_FLAGS,  /* 8 */
IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
/* Reserve empty slots */
IPSET_ATTR_CADT_MAX = 16, 0x10
/* Create-only specific attributes */
IPSET_ATTR_GC,              //0x11
IPSET_ATTR_HASHSIZE,        //0x12
IPSET_ATTR_MAXELEM,         //0x13
IPSET_ATTR_NETMASK,         //0x14
IPSET_ATTR_PROBES,          //0x15
IPSET_ATTR_RESIZE,          //0x16
IPSET_ATTR_SIZE,            //0x17
/* Kernel-only */
IPSET_ATTR_ELEMENTS,
IPSET_ATTR_REFERENCES,
IPSET_ATTR_MEMSIZE,
__IPSET_ATTR_CREATE_MAX,


set type family list:
NFPROTO_UNSPEC =  0, //can be used to include both v4 and v6
NFPROTO_IPV4   =  2,
NFPROTO_ARP    =  3,
NFPROTO_BRIDGE =  7,
NFPROTO_IPV6   = 10,
NFPROTO_DECNET = 12,

#define NLA_F_NESTED        (1 << 15)
#define NLA_F_NET_BYTEORDER (1 << 14)


* strace version 4.23 and upper parses netlink messages. However, the parsing cannot seem to be disabled. You will need the lower version to output hex instead of parsing it.

=== cmd: ipset create filtered hash:ip,port,ip timeout 60

check type is supported?

sendto(3, {{len=56, type=NFNL_SUBSYS_IPSET<<8|IPSET_CMD_TYPE, flags=NLM_F_REQUEST, seq=1544742655, pid=0}, {nfgen_family=AF_INET, version=NFNETLINK_V0, res_id=htons(0), 
[{{nla_len=5, nla_type=0x1}, "\x06"}, protocol version
 {{nla_len=20, nla_type=0x3}, "\x68\x61\x73\x68\x3a\x69\x70\x2c\x70\x6f\x72\x74\x2c\x69\x70\x00"},  type name
 {{nla_len=5, nla_type=0x5}, "\x02"}, type family, 2 is ipv4
 ]}, 56, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 56
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=72, type=NFNL_SUBSYS_IPSET<<8|IPSET_CMD_TYPE, flags=0, seq=1544742655, pid=23011}, {nfgen_family=AF_INET, version=NFNETLINK_V0, res_id=htons(0), [{{nla_len=5, nla_type=NFNETLINK_V1}, "\x06"}, {{nla_len=20, nla_type=0x3}, "\x68\x61\x73\x68\x3a\x69\x70\x2c\x70\x6f\x72\x74\x2c\x69\x70\x00"}, {{nla_len=5, nla_type=0x5}, "\x02"}, {{nla_len=5, nla_type=0x4}, "\x05"}, {{nla_len=5, nla_type=0xa}, "\x00"}]}, iov_len=256}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 72

sendto(3, {{len=92, type=NFNL_SUBSYS_IPSET<<8|IPSET_CMD_CREATE, flags=NLM_F_REQUEST|NLM_F_ACK|0x600, seq=1544742656, pid=0}, {nfgen_family=AF_INET, version=NFNETLINK_V0, res_id=htons(0), [
{{nla_len=5, nla_type=NFNETLINK_V1}, "\x06"}, 
{{nla_len=13, nla_type=0x2}, "\x66\x69\x6c\x74\x65\x72\x65\x64\x00"},  set name "filterd"
{{nla_len=20, nla_type=0x3}, "\x68\x61\x73\x68\x3a\x69\x70\x2c\x70\x6f\x72\x74\x2c\x69\x70\x00"},  "hash:ip,port,ip"
{{nla_len=5, nla_type=0x4}, "\x05"},  revision is 5? seems wrong
{{nla_len=5, nla_type=0x5}, "\x02"}, ipv4
{{nla_len=12, nla_type=NLA_F_NESTED|0x7}, "\x08\x00\x06\x40\x00\x00\x00\x3c"} len=8, type=6 (timeout), net-order, 60s
]}, 92, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 92
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=36, type=NLMSG_ERROR, flags=0, seq=1544742656, pid=23011}, {error=0, msg={len=92, type=NFNL_SUBSYS_IPSET<<8|IPSET_CMD_CREATE, flags=NLM_F_REQUEST|NLM_F_ACK|0x600, seq=1544742656, pid=0}}}, iov_len=4096}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 36




=== cmd: ipset create filtered1 hash:ip,port,ip timeout 60

sendto(3, "\x38\x00\x00\x00\x0d\x06\x01\x00\x22\xe7\x12\x5c\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x01\x00\x06\x00\x00\x00\x14\x00\x03\x00\x68\x61\x73\x68\x3a\x69\x70\x2c\x70\x6f\x72\x74\x2c\x69\x70\x00\x05\x00\x05\x00\x02\x00\x00\x00", 56, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 56
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\x48\x00\x00\x00\x0d\x06\x00\x00\x22\xe7\x12\x5c\x3c\x5b\x00\x00\x02\x00\x00\x00\x05\x00\x01\x00\x06\x00\x00\x00\x14\x00\x03\x00\x68\x61\x73\x68\x3a\x69\x70\x2c\x70\x6f\x72\x74\x2c\x69\x70\x00\x05\x00\x05\x00\x02\x00\x00\x00\x05\x00\x04\x00\x05\x00\x00\x00\x05\x00\x0a\x00\x00\x00\x00\x00", 256}], msg_controllen=0, msg_flags=0}, 0) = 72

sendto(3, "\x5c\x00\x00\x00\x02\x06\x05\x06\x23\xe7\x12\x5c\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x01\x00\x06\x00\x00\x00\x0e\x00\x02\x00\x66\x69\x6c\x74\x65\x72\x65\x64\x31\x00\x00\x00\x14\x00\x03\x00\x68\x61\x73\x68\x3a\x69\x70\x2c\x70\x6f\x72\x74\x2c\x69\x70\x00\x05\x00\x04\x00\x05\x00\x00\x00\x05\x00\x05\x00\x02\x00\x00\x00\x0c\x00\x07\x80\x08\x00\x06\x40\x00\x00\x00\x3c", 92, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 92

decoded message:
\x5c\x00\x00\x00 length
\x02\x06 , 0x0602: 0x06 is NFNL_SUBSYS_IPSET, 0x02 is IPSET_CMD_CREATE
#define NFNL_SUBSYS_NONE        0
#define NFNL_SUBSYS_CTNETLINK       1
#define NFNL_SUBSYS_CTNETLINK_EXP   2
#define NFNL_SUBSYS_QUEUE       3
#define NFNL_SUBSYS_ULOG        4
#define NFNL_SUBSYS_OSF         5
#define NFNL_SUBSYS_IPSET       6
#define NFNL_SUBSYS_ACCT        7
#define NFNL_SUBSYS_CTNETLINK_TIMEOUT   8
#define NFNL_SUBSYS_CTHELPER        9
#define NFNL_SUBSYS_COUNT       10

\x05\x06, NLM flags: 0x0605: create | excl | ack |request
/* Flags values */
#define NLM_F_REQUEST       1   /* It is request message.   */
#define NLM_F_MULTI     2   /* Multipart message, terminated by NLMSG_DONE */
#define NLM_F_ACK       4   /* Reply with ack, with zero or error code */
#define NLM_F_ECHO      8   /* Echo this request        */
#define NLM_F_DUMP_INTR     16  /* Dump was inconsistent due to sequence change */
/* Modifiers to GET request */
#define NLM_F_ROOT  0x100   /* specify tree root    */
#define NLM_F_MATCH 0x200   /* return all matching  */
#define NLM_F_ATOMIC    0x400   /* atomic GET       */
#define NLM_F_DUMP  (NLM_F_ROOT|NLM_F_MATCH)
/* Modifiers to NEW request */
#define NLM_F_REPLACE   0x100   /* Override existing        */
#define NLM_F_EXCL  0x200   /* Do not touch, if it exists   */
#define NLM_F_CREATE    0x400   /* Create, if it does not exist */
#define NLM_F_APPEND    0x800   /* Add to end of list       */

\x23\xe7\x12\x5c :seq number
\x00\x00\x00\x00 : port id
\x02\x00\x00\x00 : extra header

\x05\x00 \x01\x00\ x06 length is 5, type is 1, value is 6
\x00\x00\x00, padded to multipe of 4 bytes
\x0e\x00 \x02\x00 \x66\x69\x6c\x74 \x65\x72\x65\x64 \x31\x00\x00\x00, length is 14, type is 2,i.e. set name, name is "filtered1"
\x14\x00 \x03\x00 \x68\x61\x73\x68\x3a\x69\x70\x2c\x70\x6f\x72\x74\x2c\x69\x70\x00
\x05\x00\x04\x00\x05\x00\x00\x00: revision 5
\x05\x00\x05\x00\x02\x00\x00\x00: family 2
\x0c\x00\x07\x80 \x08\x00\x06\x40\x00\x00\x00\x3c, nested attributes, timeout value, networker order of 0x3c

recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\x24\x00\x00\x00\x02\x00\x00\x00\x23\xe7\x12\x5c\x3c\x5b\x00\x00\x00\x00\x00\x00\x5c\x00\x00\x00\x02\x06\x05\x06\x23\xe7\x12\x5c\x00\x00\x00\x00", 4096}], msg_controllen=0, msg_flags=0}, 0) = 36


==cmd: ipset create torlistv6 hash:ip family inet6 hashsize 2048 maxelem 65536
sendto(3, {{len=48, type=NFNL_SUBSYS_IPSET<<8|IPSET_CMD_TYPE, flags=NLM_F_REQUEST, seq=1544745557, pid=0}, {nfgen_family=AF_INET, version=NFNETLINK_V0, res_id=htons(0), [{{nla_len=5, nla_type=NFNETLINK_V1}, "\x06"}, {{nla_len=12, nla_type=0x3}, "\x68\x61\x73\x68\x3a\x69\x70\x00"}, {{nla_len=5, nla_type=0x5}, "\x02"}]}, 48, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 48
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=64, type=NFNL_SUBSYS_IPSET<<8|IPSET_CMD_TYPE, flags=0, seq=1544745557, pid=19683}, {nfgen_family=AF_INET, version=NFNETLINK_V0, res_id=htons(0), [
{{nla_len=5, nla_type=NFNETLINK_V1}, "\x06"}, 
{{nla_len=12, nla_type=0x3}, "\x68\x61\x73\x68\x3a\x69\x70\x00"}, 
{{nla_len=5, nla_type=0x5}, "\x02"}, 
{{nla_len=5, nla_type=0x4}, "\x04"}, 
{{nla_len=5, nla_type=0xa}, "\x00"}]}, iov_len=256}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 64

sendto(3, {{len=92, type=NFNL_SUBSYS_IPSET<<8|IPSET_CMD_CREATE, flags=NLM_F_REQUEST|NLM_F_ACK|0x600, seq=1544745558, pid=0}, {nfgen_family=AF_INET, version=NFNETLINK_V0, res_id=htons(0), [
{{nla_len=5, nla_type=NFNETLINK_V1}, "\x06"}, 
{{nla_len=14, nla_type=0x2}, "\x74\x6f\x72\x6c\x69\x73\x74\x76\x36\x00"}, 
{{nla_len=12, nla_type=0x3}, "\x68\x61\x73\x68\x3a\x69\x70\x00"}, 
{{nla_len=5, nla_type=0x4}, "\x04"}, 
{{nla_len=5, nla_type=0x5}, "\x0a"}, 
{{nla_len=20, nla_type=NLA_F_NESTED|0x7}, "\x08\x00\x12\x40\x00\x00\x08\x00\x08\x00\x13\x40\x00\x01\x00\x00"}
\x08\x00\x12\x40 \x00\x00\x08\x00, hashsize 0x800
\x08\x00\x13\x40 \x00\x01\x00\x00, maxelem 0x10000
]}, 92, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 92
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=36, type=NLMSG_ERROR, flags=0, seq=1544745558, pid=19683}, {error=0, msg={len=92, type=NFNL_SUBSYS_IPSET<<8|IPSET_CMD_CREATE, flags=NLM_F_REQUEST|NLM_F_ACK|0x600, seq=1544745558, pid=0}}}, iov_len=4096}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 36


April 7, 2016

curl test api

In curl, use "--data-urlencode" to encode data

use "-G" to send data in "GET" instead of "POST".

curl  -G "https://myserver.com:1234/msg?msgtype=PUSH" --data-urlencode "msg=hello how are you"