From 9dd15f4abf6ca89da8ff36c8b03f2f0e26bae60a Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Wed, 20 Aug 2014 09:43:59 +0100 Subject: [PATCH] use dst address as source of icmp 3.4, instead of router address For some reason, packets injected with a src ip that isn't in the sub-net of the dst ip get dropped. fixes #1 --- ethernet_decoder.go | 36 ++++++------------------------------ router.go | 10 ++-------- 2 files changed, 8 insertions(+), 38 deletions(-) diff --git a/ethernet_decoder.go b/ethernet_decoder.go index 870dc1bd24..ae8754a7a9 100644 --- a/ethernet_decoder.go +++ b/ethernet_decoder.go @@ -19,39 +19,15 @@ func (dec *EthernetDecoder) DecodeLayers(data []byte) error { return dec.parser.DecodeLayers(data, &dec.decoded) } -func (dec *EthernetDecoder) CheckFrameTooBigFunc(srcMac net.HardwareAddr, localAddrs []net.Addr, handle *pcap.Handle) func(error) error { - networks := make([]LocalAddress, len(localAddrs)) - idx := 0 - for _, addr := range localAddrs { - ip, ipnet, err := net.ParseCIDR(addr.String()) - if err == nil && ip.To4() != nil { - networks[idx] = LocalAddress{ip: ip.To4(), network: ipnet} - idx++ - } - } - networks = networks[:idx] - if len(networks) == 0 { - log.Fatal("Interface has no addresses assigned. Cannot continue") - } - findIP := func(ip net.IP) net.IP { - for _, la := range networks { - if la.network.Contains(ip) { - return la.ip - } - } - // can't find anything, we'll have to rely on default gateway. - return networks[0].ip - } - +func (dec *EthernetDecoder) CheckFrameTooBigFunc(handle *pcap.Handle) func(error) error { return func(err error) error { if ftbe, ok := err.(FrameTooBigError); ok { // we know: 1. ip is valid, 2. it was ip and DF was set - srcIP := findIP(dec.ip.SrcIP) - icmpFrame, err := dec.formICMPMTUPacket(srcMac, srcIP, ftbe.PMTU) + icmpFrame, err := dec.formICMPMTUPacket(ftbe.PMTU) if err != nil { return err } - log.Println("Injecting ICMP 3,4. PMTU:", ftbe.PMTU) + log.Printf("Injecting ICMP 3,4 (%v -> %v): PMTU= %v\n", dec.ip.DstIP, dec.ip.SrcIP, ftbe.PMTU) return handle.WritePacketData(icmpFrame) } else { return err @@ -59,7 +35,7 @@ func (dec *EthernetDecoder) CheckFrameTooBigFunc(srcMac net.HardwareAddr, localA } } -func (dec *EthernetDecoder) formICMPMTUPacket(srcMac net.HardwareAddr, srcIP net.IP, mtu int) ([]byte, error) { +func (dec *EthernetDecoder) formICMPMTUPacket(mtu int) ([]byte, error) { buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, @@ -68,7 +44,7 @@ func (dec *EthernetDecoder) formICMPMTUPacket(srcMac net.HardwareAddr, srcIP net payload := gopacket.Payload(dec.ip.BaseLayer.Contents[:ipHeaderSize+8]) err := gopacket.SerializeLayers(buf, opts, &layers.Ethernet{ - SrcMAC: srcMac, + SrcMAC: dec.eth.DstMAC, DstMAC: dec.eth.SrcMAC, EthernetType: dec.eth.EthernetType}, &layers.IPv4{ @@ -80,7 +56,7 @@ func (dec *EthernetDecoder) formICMPMTUPacket(srcMac net.HardwareAddr, srcIP net TTL: 64, Protocol: layers.IPProtocolICMPv4, DstIP: dec.ip.SrcIP, - SrcIP: srcIP}, + SrcIP: dec.ip.DstIP}, &layers.ICMPv4{ TypeCode: 0x304, Id: 0, diff --git a/router.go b/router.go index c8567b105b..fecf4d2f45 100644 --- a/router.go +++ b/router.go @@ -62,11 +62,7 @@ func (router *Router) sniff(handle *pcap.Handle) { log.Println("Sniffing traffic on", router.Iface) dec := NewEthernetDecoder() - - localAddrs, err := router.Iface.Addrs() - checkFatal(err) - checkFrameTooBig := dec.CheckFrameTooBigFunc(router.Iface.HardwareAddr, localAddrs, handle) - + checkFrameTooBig := dec.CheckFrameTooBigFunc(handle) mac := router.Iface.HardwareAddr if router.Macs.Enter(mac, router.Ourself) { log.Println("Discovered our MAC", mac) @@ -198,9 +194,7 @@ func (router *Router) udpReader(conn *net.UDPConn, handle *pcap.Handle) { } func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, handle *pcap.Handle) FrameConsumer { - localAddrs, err := router.Iface.Addrs() - checkFatal(err) - checkFrameTooBig := dec.CheckFrameTooBigFunc(router.Iface.HardwareAddr, localAddrs, handle) + checkFrameTooBig := dec.CheckFrameTooBigFunc(handle) return func(relayConn *LocalConnection, sender *net.UDPAddr, srcNameByte, dstNameByte []byte, frameLen uint16, frame []byte) error { srcName := PeerNameFromBin(srcNameByte)