From 56bd1f0d35e032014156885bd59f3c6b1c0758f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Maccagnoni?= Date: Wed, 18 Jul 2018 11:53:34 +0200 Subject: [PATCH 1/4] Add metadata to the packets (unfinished) --- handler.go | 28 +++++++++++++++++++++++++++- nfqueue.go | 15 +++++++++++++++ nfqueue.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/handler.go b/handler.go index f289288..82fa1f8 100644 --- a/handler.go +++ b/handler.go @@ -23,7 +23,12 @@ import ( ) //export handle -func handle(id uint32, buffer *C.uchar, len C.int, queueID int) int { +// func handle(id uint32, buffer *C.uchar, len C.int, hasUid, hasGid int, uid, gid, inDev, outDev, physInDev, physOutDev, nfMark uint32, packetHW *C.struct_nfqnl_msg_packet_hw, queueID int) int { +func handle( + id uint32, buffer *C.uchar, len C.int, + hasUID, hasGID int, uid, gid, inDev, outDev, physInDev, physOutDev, nfMark uint32, hwAddrlen, hwPad uint16, + hwAddress0, hwAddress1, hwAddress2, hwAddress3, hwAddress4, hwAddress5, hwAddress6, hwAddress7 uint8, + queueID int) int { q := queueRegistry.Get(uint16(queueID)) if q == nil { return 0 @@ -32,6 +37,27 @@ func handle(id uint32, buffer *C.uchar, len C.int, queueID int) int { id: id, Buffer: C.GoBytes(unsafe.Pointer(buffer), len), q: q, + Meta: &PacketMeta{ + HasUID: hasUID == 1, + UID: uid, + HasGID: hasGID == 1, + GID: gid, + InDev: inDev, + OutDev: outDev, + PhysInDev: physInDev, + PhysOutDev: physOutDev, + NFMark: nfMark, + HWAddr: []byte{ + hwAddress0, + hwAddress1, + hwAddress2, + hwAddress3, + hwAddress4, + hwAddress5, + hwAddress6, + hwAddress7, + }, + }, } q.handler.Handle(packet) return 0 diff --git a/nfqueue.go b/nfqueue.go index b821edd..2649083 100644 --- a/nfqueue.go +++ b/nfqueue.go @@ -37,9 +37,24 @@ type PacketHandler interface { Handle(p *Packet) } +// PacketMeta contains metadata about a packet +type PacketMeta struct { + HasUID bool + HasGID bool + UID uint32 + GID uint32 + InDev uint32 + OutDev uint32 + PhysInDev uint32 + PhysOutDev uint32 + NFMark uint32 + HWAddr []byte +} + // Packet struct provides the packet data and methods to accept, drop or modify the packet. type Packet struct { Buffer []byte + Meta *PacketMeta id uint32 q *Queue } diff --git a/nfqueue.h b/nfqueue.h index 3ce4b01..f417ac8 100644 --- a/nfqueue.h +++ b/nfqueue.h @@ -18,6 +18,9 @@ #ifndef _GO_NFQUEUE_H #define _GO_NFQUEUE_H +// XXX +#include + #include #include #include @@ -26,13 +29,26 @@ // Maximum packet size of a TCP packet const uint MAX_PACKET_SIZE = 65535; + // handle is the packet handler function implemented in go. // The arguments are: // - id (packet identifier) // - buffer (pointer to the packet data starting from IP layer) // - len (buffer length) +// - had_uid (1 if the packet has an assigned UID) +// - had_gid (1 if the packet has an assigned GID) +// - uid (the UID assigned to the packet) +// - gid (the GID assigned to the packet) +// - indev (input device index) +// - outdev (output device index) +// - physindev (physical input device index) +// - physoutdev (physical output device index) +// - nfmark (NF mark for the packet) +// - hw_addrlen (length of the HW address) +// - hw_pad (padding of the HW address) +// - hw_addr (HW address) // - queue_id (queue identifier) -extern int handle(uint32_t id, unsigned char* buffer, int len, int queue_id); +extern int handle(uint32_t id, unsigned char* buffer, int len, int has_uid, int has_gid, u_int32_t uid, u_int32_t gid, u_int32_t indev, u_int32_t outdev, u_int32_t physindev, u_int32_t physoutdev, u_int32_t nfmark, u_int16_t hw_addrlen, u_int16_t hw_pad, u_int8_t hw_addr0, u_int8_t hw_addr1, u_int8_t hw_addr2, u_int8_t hw_addr3, u_int8_t hw_addr4, u_int8_t hw_addr5, u_int8_t hw_addr6, u_int8_t hw_addr7, int queue_id); int nfqueue_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cb_data) { @@ -40,7 +56,39 @@ int nfqueue_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa); uint32_t id = ntohl(ph->packet_id); int ret = nfq_get_payload(nfa, &buffer); - return handle(id, buffer, ret, (intptr_t)cb_data); + u_int32_t uid = 0; + u_int32_t gid = 0; + int has_uid = nfq_get_uid(nfa, &uid); + int has_gid = nfq_get_gid(nfa, &gid); + u_int32_t indev = nfq_get_indev(nfa); + u_int32_t outdev = nfq_get_outdev(nfa); + u_int32_t physindev = nfq_get_physindev(nfa); + u_int32_t physoutdev = nfq_get_physoutdev(nfa); + u_int32_t nfmark = nfq_get_nfmark(nfa); + struct nfqnl_msg_packet_hw *packet_hw = nfq_get_packet_hw(nfa); + u_int16_t hw_addrlen = 0; + u_int16_t hw_pad = 0; + u_int8_t hw_addr0 = 0; + u_int8_t hw_addr1 = 0; + u_int8_t hw_addr2 = 0; + u_int8_t hw_addr3 = 0; + u_int8_t hw_addr4 = 0; + u_int8_t hw_addr5 = 0; + u_int8_t hw_addr6 = 0; + u_int8_t hw_addr7 = 0; + if (packet_hw != NULL) { + hw_addrlen = packet_hw->hw_addrlen; + hw_pad = packet_hw->_pad; + hw_addr0 = packet_hw->hw_addr[0]; + hw_addr1 = packet_hw->hw_addr[1]; + hw_addr2 = packet_hw->hw_addr[2]; + hw_addr3 = packet_hw->hw_addr[3]; + hw_addr4 = packet_hw->hw_addr[4]; + hw_addr5 = packet_hw->hw_addr[5]; + hw_addr6 = packet_hw->hw_addr[6]; + hw_addr7 = packet_hw->hw_addr[7]; + } + return handle(id, buffer, ret, has_uid, has_gid, uid, gid, indev, outdev, physindev, physoutdev, nfmark, hw_addrlen, hw_pad, hw_addr0, hw_addr1, hw_addr2, hw_addr3, hw_addr4, hw_addr5, hw_addr6, hw_addr7, (intptr_t)cb_data); } static struct nfq_q_handle *nfqueue_create_queue(struct nfq_handle *h, u_int16_t queue_id) { From 1a69cf2ac41bbeb500a4441ba809bb88e881d7c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Maccagnoni?= Date: Wed, 18 Jul 2018 12:18:05 +0200 Subject: [PATCH 2/4] Remove useless import --- nfqueue.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/nfqueue.h b/nfqueue.h index f417ac8..9ac1bd7 100644 --- a/nfqueue.h +++ b/nfqueue.h @@ -18,9 +18,6 @@ #ifndef _GO_NFQUEUE_H #define _GO_NFQUEUE_H -// XXX -#include - #include #include #include From 2ac7f516e5d2e8bda22913d4b6c4ca0b2a8d031c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Maccagnoni?= Date: Wed, 18 Jul 2018 12:33:04 +0200 Subject: [PATCH 3/4] Disable UID and GID for now... ... because most distribs still use libnetfilter_queue 1.0.2, which does not support this stuff --- handler.go | 19 +++++++++++++------ nfqueue.h | 18 ++++++++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/handler.go b/handler.go index 82fa1f8..76c50d5 100644 --- a/handler.go +++ b/handler.go @@ -22,11 +22,14 @@ import ( "unsafe" ) +// Main distribs still use libnetfilter_queue 1.0.2, which does not contain UID and GID stuff +// To work on most systems, I disable them for now + //export handle -// func handle(id uint32, buffer *C.uchar, len C.int, hasUid, hasGid int, uid, gid, inDev, outDev, physInDev, physOutDev, nfMark uint32, packetHW *C.struct_nfqnl_msg_packet_hw, queueID int) int { func handle( id uint32, buffer *C.uchar, len C.int, - hasUID, hasGID int, uid, gid, inDev, outDev, physInDev, physOutDev, nfMark uint32, hwAddrlen, hwPad uint16, + inDev, outDev, physInDev, physOutDev, nfMark uint32, hwAddrlen, hwPad uint16, + // hasUID, hasGID int, uid, gid, inDev, outDev, physInDev, physOutDev, nfMark uint32, hwAddrlen, hwPad uint16, hwAddress0, hwAddress1, hwAddress2, hwAddress3, hwAddress4, hwAddress5, hwAddress6, hwAddress7 uint8, queueID int) int { q := queueRegistry.Get(uint16(queueID)) @@ -38,10 +41,14 @@ func handle( Buffer: C.GoBytes(unsafe.Pointer(buffer), len), q: q, Meta: &PacketMeta{ - HasUID: hasUID == 1, - UID: uid, - HasGID: hasGID == 1, - GID: gid, + HasUID: false, + UID: 0, + HasGID: false, + GID: 0, + // HasUID: hasUID == 1, + // UID: uid, + // HasGID: hasGID == 1, + // GID: gid, InDev: inDev, OutDev: outDev, PhysInDev: physInDev, diff --git a/nfqueue.h b/nfqueue.h index 9ac1bd7..d6dc3ef 100644 --- a/nfqueue.h +++ b/nfqueue.h @@ -26,6 +26,8 @@ // Maximum packet size of a TCP packet const uint MAX_PACKET_SIZE = 65535; +// Main distribs still use libnetfilter_queue 1.0.2, which does not contain UID and GID stuff +// To work on most systems, I disable them for now // handle is the packet handler function implemented in go. // The arguments are: @@ -45,7 +47,8 @@ const uint MAX_PACKET_SIZE = 65535; // - hw_pad (padding of the HW address) // - hw_addr (HW address) // - queue_id (queue identifier) -extern int handle(uint32_t id, unsigned char* buffer, int len, int has_uid, int has_gid, u_int32_t uid, u_int32_t gid, u_int32_t indev, u_int32_t outdev, u_int32_t physindev, u_int32_t physoutdev, u_int32_t nfmark, u_int16_t hw_addrlen, u_int16_t hw_pad, u_int8_t hw_addr0, u_int8_t hw_addr1, u_int8_t hw_addr2, u_int8_t hw_addr3, u_int8_t hw_addr4, u_int8_t hw_addr5, u_int8_t hw_addr6, u_int8_t hw_addr7, int queue_id); +extern int handle(uint32_t id, unsigned char* buffer, int len, u_int32_t indev, u_int32_t outdev, u_int32_t physindev, u_int32_t physoutdev, u_int32_t nfmark, u_int16_t hw_addrlen, u_int16_t hw_pad, u_int8_t hw_addr0, u_int8_t hw_addr1, u_int8_t hw_addr2, u_int8_t hw_addr3, u_int8_t hw_addr4, u_int8_t hw_addr5, u_int8_t hw_addr6, u_int8_t hw_addr7, int queue_id); +// extern int handle(uint32_t id, unsigned char* buffer, int len, int has_uid, int has_gid, u_int32_t uid, u_int32_t gid, u_int32_t indev, u_int32_t outdev, u_int32_t physindev, u_int32_t physoutdev, u_int32_t nfmark, u_int16_t hw_addrlen, u_int16_t hw_pad, u_int8_t hw_addr0, u_int8_t hw_addr1, u_int8_t hw_addr2, u_int8_t hw_addr3, u_int8_t hw_addr4, u_int8_t hw_addr5, u_int8_t hw_addr6, u_int8_t hw_addr7, int queue_id); int nfqueue_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cb_data) { @@ -53,10 +56,12 @@ int nfqueue_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa); uint32_t id = ntohl(ph->packet_id); int ret = nfq_get_payload(nfa, &buffer); - u_int32_t uid = 0; - u_int32_t gid = 0; - int has_uid = nfq_get_uid(nfa, &uid); - int has_gid = nfq_get_gid(nfa, &gid); + // Main distribs still use libnetfilter_queue 1.0.2, which does not contain UID and GID stuff + // To work on most systems, I disable them for now + // u_int32_t uid = 0; + // u_int32_t gid = 0; + // int has_uid = nfq_get_uid(nfa, &uid); + // int has_gid = nfq_get_gid(nfa, &gid); u_int32_t indev = nfq_get_indev(nfa); u_int32_t outdev = nfq_get_outdev(nfa); u_int32_t physindev = nfq_get_physindev(nfa); @@ -85,7 +90,8 @@ int nfqueue_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data hw_addr6 = packet_hw->hw_addr[6]; hw_addr7 = packet_hw->hw_addr[7]; } - return handle(id, buffer, ret, has_uid, has_gid, uid, gid, indev, outdev, physindev, physoutdev, nfmark, hw_addrlen, hw_pad, hw_addr0, hw_addr1, hw_addr2, hw_addr3, hw_addr4, hw_addr5, hw_addr6, hw_addr7, (intptr_t)cb_data); + return handle(id, buffer, ret, indev, outdev, physindev, physoutdev, nfmark, hw_addrlen, hw_pad, hw_addr0, hw_addr1, hw_addr2, hw_addr3, hw_addr4, hw_addr5, hw_addr6, hw_addr7, (intptr_t)cb_data); + // return handle(id, buffer, ret, has_uid, has_gid, uid, gid, indev, outdev, physindev, physoutdev, nfmark, hw_addrlen, hw_pad, hw_addr0, hw_addr1, hw_addr2, hw_addr3, hw_addr4, hw_addr5, hw_addr6, hw_addr7, (intptr_t)cb_data); } static struct nfq_q_handle *nfqueue_create_queue(struct nfq_handle *h, u_int16_t queue_id) { From 287210969fd4753f28f350a77fa5f57cc7a35732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Maccagnoni?= Date: Wed, 18 Jul 2018 15:55:39 +0200 Subject: [PATCH 4/4] Helper functions for packet metadata --- nfqueue.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/nfqueue.go b/nfqueue.go index 2649083..189f8c0 100644 --- a/nfqueue.go +++ b/nfqueue.go @@ -29,6 +29,7 @@ import "C" import ( "errors" "fmt" + "net" "unsafe" ) @@ -51,6 +52,50 @@ type PacketMeta struct { HWAddr []byte } +// InDevName returns the name of the input interface +func (m *PacketMeta) InDevName() string { + iface, err := net.InterfaceByIndex(int(m.InDev)) + if err != nil { + return "" + } + return iface.Name +} + +// OutDevName returns the name of the output interface +func (m *PacketMeta) OutDevName() string { + iface, err := net.InterfaceByIndex(int(m.OutDev)) + if err != nil { + return "" + } + return iface.Name +} + +// PhysInDevName returns the name of the physical input interface +func (m *PacketMeta) PhysInDevName() string { + iface, err := net.InterfaceByIndex(int(m.PhysInDev)) + if err != nil { + return "" + } + return iface.Name +} + +// PhysOutDevName returns the name of the physical output interface +func (m *PacketMeta) PhysOutDevName() string { + iface, err := net.InterfaceByIndex(int(m.PhysOutDev)) + if err != nil { + return "" + } + return iface.Name +} + +// MACAddr returns the human-readable value of the MAC address for the packet source +func (m *PacketMeta) MACAddr() string { + return fmt.Sprintf( + "%02X:%02X:%02X:%02X:%02X:%02X", + m.HWAddr[0], m.HWAddr[1], m.HWAddr[2], m.HWAddr[3], m.HWAddr[4], m.HWAddr[5], + ) +} + // Packet struct provides the packet data and methods to accept, drop or modify the packet. type Packet struct { Buffer []byte