/*listenForRouteRecords intercepts all incoming packets to this host and removes their route records before letting the operating system process them. If listenForRouteRecords is true, it also sends filter requests whenever an ICMP packet from 10.4.32.4 arrives. */ func listenForRouteRecords(sendFilterRequests bool) { routerecord.Init() nfq, err := netfilter.NewNFQueue(0, 100000, 0xffff) if err != nil { log.Fatal(err) } defer nfq.Close() for packet := range nfq.GetPackets() { var ipLayer *layers.IPv4 if layer := packet.Packet.Layer(layers.LayerTypeIPv4); layer != nil { ipLayer = layer.(*layers.IPv4) } else { packet.SetVerdict(netfilter.NF_ACCEPT) continue } if routerecord.Shimmed(ipLayer) { /*If the IP layer has a shim, remove it.*/ log.Println("Got AITF shimmed packet from", aitf.Hostname(ipLayer.SrcIP)) rr := routerecord.Unshim(ipLayer) log.Println(rr) if sendFilterRequests { /*If this is a malicious packet, construct a filter request to stop any future undesired traffic from this flow. The policy module simply considers any ICMP traffic from the attacker to be "malicous".*/ if ipLayer.Protocol == layers.IPProtocolICMPv4 && ipLayer.SrcIP.Equal(net.ParseIP("10.4.32.4")) { log.Println("Malicious packet detected from", aitf.Hostname(ipLayer.SrcIP)) req := filter.Request{ Type: filter.FilterReq, SrcIP: ipLayer.SrcIP, DstIP: ipLayer.DstIP, Flow: *rr, } req.Send(rr.Path[len(rr.Path)-1].IP) } } /*Serialize the IP packet. Assuming this is successful, accept it.*/ b, err := routerecord.Serialize(ipLayer) if err != nil { log.Println(err) packet.SetVerdict(netfilter.NF_DROP) } else { packet.SetResult(netfilter.NF_ACCEPT, b) } } else { /*Any packets without a shim can be accepted as-is.*/ log.Println("Got", ipLayer.Protocol, "packet from", aitf.Hostname(ipLayer.SrcIP)) packet.SetVerdict(netfilter.NF_ACCEPT) } } }
/*addRouteRecords intercepts any packets being sent through this router and adds route records to a shim layer before forwarding them.*/ func addRouteRecords() { localIP := aitf.LocalIP() log.Println("My IP address is", aitf.Hostname(localIP)) nfq, err := netfilter.NewNFQueue(0, 100000, 0xffff) if err != nil { log.Fatal(err) } defer nfq.Close() /*Listen for any packets being forwarded by this router and create/update the route record shim layer in each of them.*/ for packet := range nfq.GetPackets() { var ipLayer *layers.IPv4 /*Get the IPv4 layer, or ignore it if it doesn't exist. */ if layer := packet.Packet.Layer(layers.LayerTypeIPv4); layer != nil { ipLayer = layer.(*layers.IPv4) } else { packet.SetVerdict(netfilter.NF_ACCEPT) continue } /*Any local loopback packets can be accepted with modification, as they do not actually go through the network. This is most likely to happen while testing using an iptables rule that may include loopback traffic.*/ if ipLayer.SrcIP.IsLoopback() { packet.SetVerdict(netfilter.NF_ACCEPT) continue } if routerecord.Shimmed(ipLayer) { log.Println("Got AITF shimmed packet from", aitf.Hostname(ipLayer.SrcIP), "for", aitf.Hostname(ipLayer.DstIP)) } else { log.Println("Got", ipLayer.Protocol, "packet from", aitf.Hostname(ipLayer.SrcIP), "for", aitf.Hostname(ipLayer.DstIP)) } /*Shim up the packet. One of the assumptions made is that each route knows which hosts support AITF. All hosts in the test scenerios do, so there's never a need for a router to remove the shim layer.*/ routerecord.Shim(ipLayer, routerecord.NewRouter(localIP, ipLayer.DstIP)) /*Serialize the IP packet. Assuming this is successful, accept it.*/ b, err := routerecord.Serialize(ipLayer) if err != nil { log.Println(err) packet.SetVerdict(netfilter.NF_DROP) } else { packet.SetResult(netfilter.NF_ACCEPT, b) } } }