Merge pull request #223 from jkozera/jkozera/ipv6

IPv6 support
This commit is contained in:
evilsocket 2018-11-22 01:56:19 +01:00 committed by GitHub
commit bc637c7269
Failed to generate hash of commit
4 changed files with 120 additions and 46 deletions

View file

@ -30,10 +30,37 @@ type Connection struct {
func Parse(nfp netfilter.Packet) *Connection {
ipLayer := nfp.Packet.Layer(layers.LayerTypeIPv4)
if ipLayer == nil {
ipLayer6 := nfp.Packet.Layer(layers.LayerTypeIPv6)
if ipLayer == nil && ipLayer6 == nil {
return nil
}
if (ipLayer == nil) {
ip, ok := ipLayer6.(*layers.IPv6)
if ok == false || ip == nil {
return nil
}
// we're not interested in connections
// from/to the localhost interface
if ip.SrcIP.IsLoopback() {
return nil
}
// skip multicast stuff
if ip.SrcIP.IsMulticast() || ip.DstIP.IsMulticast() {
return nil
}
con, err := NewConnection6(&nfp, ip)
if err != nil {
log.Debug("%s", err)
return nil
} else if con == nil {
return nil
}
return con
} else {
ip, ok := ipLayer.(*layers.IPv4)
if ok == false || ip == nil {
return nil
@ -50,12 +77,6 @@ func Parse(nfp netfilter.Packet) *Connection {
return nil
}
// skip broadcasted stuff
// FIXME: this is ugly
if ip.DstIP[3] == 0xff {
return nil
}
con, err := NewConnection(&nfp, ip)
if err != nil {
log.Debug("%s", err)
@ -63,18 +84,11 @@ func Parse(nfp netfilter.Packet) *Connection {
} else if con == nil {
return nil
}
return con
}
}
func NewConnection(nfp *netfilter.Packet, ip *layers.IPv4) (c *Connection, err error) {
c = &Connection{
SrcIP: ip.SrcIP,
DstIP: ip.DstIP,
DstHost: dns.HostOr(ip.DstIP, ip.DstIP.String()),
pkt: nfp,
}
func newConnectionImpl(nfp *netfilter.Packet, c *Connection) (cr *Connection, err error) {
// no errors but not enough info neither
if c.parseDirection() == false {
return nil, nil
@ -94,28 +108,57 @@ func NewConnection(nfp *netfilter.Packet, ip *layers.IPv4) (c *Connection, err e
return nil, fmt.Errorf("Could not find process by its pid %d for: %s", pid, c)
}
return c, nil
}
func NewConnection(nfp *netfilter.Packet, ip *layers.IPv4) (c *Connection, err error) {
c = &Connection{
SrcIP: ip.SrcIP,
DstIP: ip.DstIP,
DstHost: dns.HostOr(ip.DstIP, ip.DstIP.String()),
pkt: nfp,
}
return newConnectionImpl(nfp, c)
}
func NewConnection6(nfp *netfilter.Packet, ip *layers.IPv6) (c *Connection, err error) {
c = &Connection{
SrcIP: ip.SrcIP,
DstIP: ip.DstIP,
DstHost: dns.HostOr(ip.DstIP, ip.DstIP.String()),
pkt: nfp,
}
return newConnectionImpl(nfp, c)
}
func (c *Connection) parseDirection() bool {
ret := false
for _, layer := range c.pkt.Packet.Layers() {
if layer.LayerType() == layers.LayerTypeTCP {
if tcp, ok := layer.(*layers.TCP); ok == true && tcp != nil {
c.Protocol = "tcp"
c.DstPort = int(tcp.DstPort)
c.SrcPort = int(tcp.SrcPort)
return true
ret = true
}
} else if layer.LayerType() == layers.LayerTypeUDP {
if udp, ok := layer.(*layers.UDP); ok == true && udp != nil {
c.Protocol = "udp"
c.DstPort = int(udp.DstPort)
c.SrcPort = int(udp.SrcPort)
return true
ret = true
}
}
}
return false
for _, layer := range c.pkt.Packet.Layers() {
if layer.LayerType() == layers.LayerTypeIPv6 {
if tcp, ok := layer.(*layers.IPv6); ok == true && tcp != nil {
c.Protocol += "6"
}
}
}
return ret
}
func (c *Connection) To() string {

View file

@ -27,6 +27,8 @@ func RunRule(enable bool, rule []string) (err error) {
// fmt.Printf("iptables %s\n", rule)
_, err = core.Exec("iptables", rule)
_, err = core.Exec("ip6tables", rule)
return
}

View file

@ -33,8 +33,6 @@ const (
NF_DEFAULT_QUEUE_SIZE uint32 = 4096
NF_DEFAULT_PACKET_SIZE uint32 = 4096
ipv4version = 0x40
)
var (
@ -167,7 +165,7 @@ func go_callback(queueId C.int, data *C.uchar, length C.int, mark C.uint, idx ui
xdata := C.GoBytes(unsafe.Pointer(data), length)
var packet gopacket.Packet
if xdata[0]&0xf0 == ipv4version {
if (xdata[0] >> 4) == 4 { // first 4 bits is the version
packet = gopacket.NewPacket(xdata, layers.LayerTypeIPv4, gopacketDecodeOptions)
} else {
packet = gopacket.NewPacket(xdata, layers.LayerTypeIPv6, gopacketDecodeOptions)

View file

@ -16,8 +16,8 @@ import (
var (
parser = regexp.MustCompile(`(?i)` +
`\d+:\s+` + // sl
`([a-f0-9]{8}):([a-f0-9]{4})\s+` + // local_address
`([a-f0-9]{8}):([a-f0-9]{4})\s+` + // rem_address
`([a-f0-9]{8,32}):([a-f0-9]{4})\s+` + // local_address
`([a-f0-9]{8,32}):([a-f0-9]{4})\s+` + // rem_address
`[a-f0-9]{2}\s+` + // st
`[a-f0-9]{8}:[a-f0-9]{8}\s+` + // tx_queue rx_queue
`[a-f0-9]{2}:[a-f0-9]{8}\s+` + // tr tm->when
@ -44,10 +44,41 @@ func hexToInt(h string) int {
return int(d)
}
func hexToInt2(h string) (int, int) {
if len(h) > 16 {
d, err := strconv.ParseInt(h[:16], 16, 64)
if err != nil {
log.Fatal("Error while parsing %s to int: %s", h[16:], err)
}
d2, err := strconv.ParseInt(h[16:], 16, 64)
if err != nil {
log.Fatal("Error while parsing %s to int: %s", h[16:], err)
}
return int(d), int(d2)
} else {
d, err := strconv.ParseInt(h, 16, 64)
if err != nil {
log.Fatal("Error while parsing %s to int: %s", h[16:], err)
}
return int(d), 0
}
}
func hexToIP(h string) net.IP {
n := hexToInt(h)
ip := make(net.IP, 4)
n, m := hexToInt2(h)
var ip net.IP
if m != 0 {
ip = make(net.IP, 16)
// TODO: Check if this depends on machine endianness?
binary.LittleEndian.PutUint32(ip, uint32(n >> 32))
binary.LittleEndian.PutUint32(ip[4:], uint32(n))
binary.LittleEndian.PutUint32(ip[8:], uint32(m >> 32))
binary.LittleEndian.PutUint32(ip[12:], uint32(m))
} else {
ip = make(net.IP, 4)
binary.LittleEndian.PutUint32(ip, uint32(n))
}
return ip
}