diff --git a/go/README.md b/go/README.md index 3de6e99..1da96b1 100644 --- a/go/README.md +++ b/go/README.md @@ -1,12 +1,14 @@ `sudo apt install libpcap-dev gcc` ```bash -wlan2eth build wlan2eth.wlan2eth -sudo ./wlan2eth +go mod tidy +go build wlan2eth ``` -If build fails, try `CGO_ENABLED=1` +Run the program like this: -# Issues +``` +./wlan2eth --dhcp-modify-src --eth [name of ethernet] --wlan [name of wireless interface] +``` -- To prevent forwarding duplicates, incoming hash of in packets are cached and checked against subsequent packets. This may cause issues where duplicate packets are blocked. \ No newline at end of file +`--dhcp-modify-src` will modify the client address in the DHCP packets. diff --git a/go/wlan2eth/arp/arp_request.go b/go/wlan2eth/arp/arp_request.go index 1ccb167..ae361d6 100644 --- a/go/wlan2eth/arp/arp_request.go +++ b/go/wlan2eth/arp/arp_request.go @@ -10,7 +10,7 @@ import ( "wlan2eth/logger" ) -func HandleARPRequest(packet gopacket.Packet, srcSocket, dstSocket int, srcName, dstName string, srcMAC, dstMAC net.HardwareAddr, wlan0MAC net.HardwareAddr, eth0 string) { +func HandleARPRequest(packet gopacket.Packet, srcSocket, dstSocket int, srcName, dstName string, srcMAC, dstMAC net.HardwareAddr, eth0MAC, wlan0MAC net.HardwareAddr, eth0 string) { log := logger.GetLogger() arpLayer := packet.Layer(layers.LayerTypeARP).(*layers.ARP) @@ -19,7 +19,8 @@ func HandleARPRequest(packet gopacket.Packet, srcSocket, dstSocket int, srcName, // Add the client to the bridgedClients map srcIP := net.IP(arpLayer.SourceProtAddress) srcHwAddr := arpLayer.SourceHwAddress - AddBridgedClient(srcIP, srcHwAddr, wlan0MAC, eth0) + + AddBridgedClient(srcIP, srcHwAddr, eth0MAC, wlan0MAC, eth0) // Check if the ARP request is an ARP announcement isARPAnnouncement := bytes.Equal(arpLayer.SourceProtAddress, arpLayer.DstProtAddress) diff --git a/go/wlan2eth/arp/clients.go b/go/wlan2eth/arp/clients.go index edb71d3..2c4f05e 100644 --- a/go/wlan2eth/arp/clients.go +++ b/go/wlan2eth/arp/clients.go @@ -22,11 +22,28 @@ func (c ClientInfo) StringMAC() string { var bridgedClients = make(map[string]ClientInfo) var bridgedClientsLock sync.Mutex -func AddBridgedClient(ip net.IP, mac net.HardwareAddr, wlan0MAC net.HardwareAddr, eth0 string) { +func AddBridgedClient(ip net.IP, mac net.HardwareAddr, eth0MAC, wlan0MAC net.HardwareAddr, eth0 string) { log := logger.GetLogger() // Ignore the wlan0 MAC address if bytes.Equal(mac, wlan0MAC) { + log.Debugf("Not adding client IP (wlan0): %s", ip) + return + } + if bytes.Equal(mac, eth0MAC) { + log.Debugf("Not adding client IP (eth0): %s", ip) + return + } + if ip.String() == "0.0.0.0" { + log.Debug("Not adding client IP: 0.0.0.0") + return + } + if isAPIPA(ip) { + log.Debugf("Not adding client IP (APIPA): %s", ip) + return + } + if isExcluded(ip) { + log.Debugf("Not adding client IP (excluded): %s", ip) return } @@ -112,3 +129,16 @@ func AddClientRoutes(eth0 string) { } } } + +func isAPIPA(ip net.IP) bool { + apiStart := net.ParseIP("169.254.0.0").To4() + apiEnd := net.ParseIP("169.254.255.255").To4() + ip4 := ip.To4() + + return ip4 != nil && bytes.Compare(ip4, apiStart) >= 0 && bytes.Compare(ip4, apiEnd) <= 0 +} + +func isExcluded(ip net.IP) bool { + ip4 := ip.To4() + return ip4 != nil && (ip4[3] == 0 || ip4[3] == 255) +} diff --git a/go/wlan2eth/dhcp/dhcp_response.go b/go/wlan2eth/dhcp/dhcp_response.go index e58d5e7..ec89148 100644 --- a/go/wlan2eth/dhcp/dhcp_response.go +++ b/go/wlan2eth/dhcp/dhcp_response.go @@ -9,7 +9,7 @@ import ( "wlan2eth/logger" ) -func HandleDHCPResponse(packet gopacket.Packet, srcSocket, dstSocket int, srcName, dstName string, srcMAC, dstMAC net.HardwareAddr, wlan0MAC net.HardwareAddr, modifyClientSrc bool, eth0 string) { +func HandleDHCPResponse(packet gopacket.Packet, srcSocket, dstSocket int, srcName, dstName string, srcMAC, dstMAC, eth0MAC, wlan0MAC net.HardwareAddr, modifyClientSrc bool, eth0 string) { log := logger.GetLogger() // Get the DHCP layer @@ -23,7 +23,7 @@ func HandleDHCPResponse(packet gopacket.Packet, srcSocket, dstSocket int, srcNam dhcp := dhcpLayer.(*layers.DHCPv4) clientIP := dhcp.YourClientIP if !clientIP.IsUnspecified() { - arp.AddBridgedClient(clientIP, dhcp.ClientHWAddr, wlan0MAC, eth0) + arp.AddBridgedClient(clientIP, dhcp.ClientHWAddr, eth0MAC, wlan0MAC, eth0) } clientMAC, ok := transactionIDToClientMAC[dhcp.Xid] @@ -40,15 +40,22 @@ func HandleDHCPResponse(packet gopacket.Packet, srcSocket, dstSocket int, srcNam // Get the Ethernet layer and cast it to its type ethLayer := packet.Layer(layers.LayerTypeEthernet).(*layers.Ethernet) - // Modify the Ethernet source MAC address of the DHCP packet to clientMAC - ethLayer.SrcMAC = clientMAC + //// Modify the Ethernet source MAC address of the DHCP packet to clientMAC + //ethLayer.SrcMAC = clientMAC + + // Modify the Ethernet source MAC address to point it towards our bridged client + ethLayer.DstMAC = clientMAC // Get the IPv4 and UDP layers and cast them to their respective types ipLayer := packet.Layer(layers.LayerTypeIPv4).(*layers.IPv4) udpLayer := packet.Layer(layers.LayerTypeUDP).(*layers.UDP) // Set the network layer for the UDP checksum computation - udpLayer.SetNetworkLayerForChecksum(ipLayer) + err := udpLayer.SetNetworkLayerForChecksum(ipLayer) + if err != nil { + log.Errorf("Failed to set the network layer for the UDP checksum computation: %v", err) + return + } // Serialize the modified packet buf := gopacket.NewSerializeBuffer() @@ -56,7 +63,7 @@ func HandleDHCPResponse(packet gopacket.Packet, srcSocket, dstSocket int, srcNam FixLengths: true, ComputeChecksums: true, } - err := gopacket.SerializeLayers(buf, opts, ethLayer, ipLayer, udpLayer, dhcp) + err = gopacket.SerializeLayers(buf, opts, ethLayer, ipLayer, udpLayer, dhcp) if err != nil { log.Errorf("Error serializing DHCP response: %v", err) return diff --git a/go/wlan2eth/wlan2eth.go b/go/wlan2eth/wlan2eth.go index 49017ac..3486054 100644 --- a/go/wlan2eth/wlan2eth.go +++ b/go/wlan2eth/wlan2eth.go @@ -145,21 +145,23 @@ func forwardPackets(srcSocket, dstSocket int, srcName string, dstName string) { packet := gopacket.NewPacket(readBuf[:n], layers.LayerTypeEthernet, gopacket.Default) if packet.ErrorLayer() != nil { - log.Errorf("Packet is not in Ethernet format: %v", packet.ErrorLayer().Error()) + log.Warningf("Packet is not in Ethernet format: %v\n%s", packet.ErrorLayer().Error(), packet) continue } ethLayer := packet.Layer(layers.LayerTypeEthernet).(*layers.Ethernet) if ethLayer == nil { - log.Error("Packet does not have Ethernet layer.") + log.Warningf("Packet does not have Ethernet layer:\n%s", packet) continue } + ipv4Layer := packet.Layer(layers.LayerTypeIPv4) + arpLayer := packet.Layer(layers.LayerTypeARP) if arpLayer != nil { arpPacket := arpLayer.(*layers.ARP) if arpPacket.Operation == layers.ARPRequest { - arp.HandleARPRequest(packet, srcSocket, dstSocket, srcName, dstName, srcMAC, dstMAC, wlan0MAC, eth0) + arp.HandleARPRequest(packet, srcSocket, dstSocket, srcName, dstName, srcMAC, dstMAC, eth0MAC, wlan0MAC, eth0) continue } else if arpPacket.Operation == layers.ARPReply { arp.HandleARPResponse(packet, srcSocket, dstSocket, srcName, dstName, srcMAC, dstMAC, eth0MAC) @@ -171,7 +173,7 @@ func forwardPackets(srcSocket, dstSocket int, srcName string, dstName string) { if udpLayer != nil { udp := udpLayer.(*layers.UDP) if udp.SrcPort == layers.UDPPort(67) && udp.DstPort == layers.UDPPort(68) { - dhcp.HandleDHCPResponse(packet, srcSocket, dstSocket, srcName, dstName, srcMAC, dstMAC, wlan0MAC, dhcpModifyClientSrc, eth0) + dhcp.HandleDHCPResponse(packet, srcSocket, dstSocket, srcName, dstName, srcMAC, dstMAC, eth0MAC, wlan0MAC, dhcpModifyClientSrc, eth0) continue } else if udp.SrcPort == layers.UDPPort(68) && udp.DstPort == layers.UDPPort(67) { dhcp.HandleDHCPRequest(packet, srcSocket, dstSocket, srcName, dstName, srcMAC, dstMAC, dhcpModifyClientSrc) @@ -186,12 +188,10 @@ func forwardPackets(srcSocket, dstSocket int, srcName string, dstName string) { rawPacket := readBuf[:n] if len(rawPacket) < 14 { - fmt.Println("too short") + log.Warningf("Packet too short (is this a bug??):\n%s", packet) continue } - ipv4Layer := packet.Layer(layers.LayerTypeIPv4) - // Check if the packet is addressed for eth0 if bytes.Equal(ethLayer.DstMAC, eth0MAC) { copy(rawPacket[0:6], gatewayMAC) // Modify the destination to gatewayMAC @@ -223,7 +223,7 @@ func forwardPackets(srcSocket, dstSocket int, srcName string, dstName string) { // Modify the source MAC address directly in the raw packet data copy(rawPacket[6:12], srcMAC) - } else { + } else if printPackets { log.Debugf("Packet was not IPv4!\n%s", packet) continue } @@ -241,7 +241,30 @@ func forwardPackets(srcSocket, dstSocket int, srcName string, dstName string) { if printPackets { log.Debugf("Forwarded packet from %s to %s:\n%s", srcName, dstName, packet) } else { - log.Debugf("Forwarded packet from %s to %s", srcName, dstName) + var arrow string + if srcName == wlan0 { + arrow = fmt.Sprintf("%s <- %s", eth0, wlan0) + } else { + arrow = fmt.Sprintf("%s -> %s", eth0, wlan0) + } + + if ipv4Layer != nil { + ipv4Packet := ipv4Layer.(*layers.IPv4) + clientMAC, found := arp.GetClientMACByIP(ipv4Packet.DstIP) + var macADDR string + if found { + macADDR = net.HardwareAddr(clientMAC).String() + } else { + macADDR = ":::::" + } + log.WithFields(logrus.Fields{ + "iface": srcName, + "IP": ipv4Packet.DstIP.String(), + "MAC": macADDR, + }).Debugf("Forwarded packet: %s", arrow) + } else { + log.Debugf("Forwarded packet: %s", arrow) + } } time.Sleep(1 * time.Millisecond) }