From 0a968b39100a4529b8e1faa13d08eb4ec7b8f60c Mon Sep 17 00:00:00 2001 From: Toni Date: Tue, 21 Jul 2026 22:21:34 +0200 Subject: [PATCH] relay packets --- client/main.go | 12 +++++-- server/main.go | 95 +++++++++++++++++++++++++++++++++---------------- shared/proto.go | 7 +--- 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/client/main.go b/client/main.go index 997d4d8..40af4a4 100644 --- a/client/main.go +++ b/client/main.go @@ -2,6 +2,7 @@ package main import ( "encoding/binary" + "encoding/hex" "log" "net" "os" @@ -94,15 +95,20 @@ func receivePacket(pkt []byte) { switch pktType { case shared.RESP_REGISTER: internalIP = net.IP(pkt[4:]) - log.Println("Received IP from the server:", internalIP.String()) - initInterface() + log.Println("got assigned IP by the server:", internalIP.String()) + setupInterface() go sendPackets() + case shared.RESP_DATA: + log.Println("received pkt:", hex.EncodeToString(pkt[4:])) + if _, err := iface.Write(pkt[4:]); err != nil { + log.Println(err) + } default: log.Println("unknown packet type") } } -func initInterface() { +func setupInterface() { config := water.Config{DeviceType: water.TAP} config.Name = IFACE_NAME diff --git a/server/main.go b/server/main.go index e34f3c3..c6ad62c 100644 --- a/server/main.go +++ b/server/main.go @@ -2,21 +2,15 @@ package main import ( "encoding/binary" - "encoding/hex" "fmt" "log" "net" "os" - "os/exec" "sync" "baalvpn/shared" - - "github.com/songgao/water" ) -const IFACE_NAME = "baalvpn" - type Peer struct { RealIP string InternalIP string @@ -26,7 +20,7 @@ var ( peers = map[string]*Peer{} peersMutex sync.Mutex nextIP = 3 - iface *water.Interface + conn *net.UDPConn ) func main() { @@ -34,22 +28,6 @@ func main() { panic("root permissions needed") } - config := water.Config{DeviceType: water.TAP} - config.Name = IFACE_NAME - - var err error - iface, err = water.New(config) - if err != nil { - panic(err) - } - - if err := exec.Command("ip", "addr", "add", "10.1.0.2/24", "dev", IFACE_NAME).Run(); err != nil { - panic(err) - } - if err := exec.Command("ip", "link", "set", "dev", IFACE_NAME, "up").Run(); err != nil { - panic(err) - } - receivePackets() } @@ -60,15 +38,15 @@ func receivePackets() { if err != nil { panic(err) } - listener, err := net.ListenUDP("udp", listenAddr) + conn, err = net.ListenUDP("udp", listenAddr) if err != nil { panic(err) } - defer listener.Close() + defer conn.Close() for { buffer := make([]byte, 50000) - n, addr, err := listener.ReadFromUDP(buffer) + n, addr, err := conn.ReadFromUDP(buffer) if err != nil { log.Println(err) continue @@ -77,11 +55,11 @@ func receivePackets() { continue } - go receivePacket(listener, buffer[:n], addr) + go receivePacket(buffer[:n], addr) } } -func receivePacket(conn *net.UDPConn, pkt []byte, addr *net.UDPAddr) { +func receivePacket(pkt []byte, addr *net.UDPAddr) { if len(pkt) < 4 { log.Println("packet too short") return @@ -101,6 +79,7 @@ func receivePacket(conn *net.UDPConn, pkt []byte, addr *net.UDPAddr) { peersMutex.Lock() defer peersMutex.Unlock() + // TODO internalIP := fmt.Sprintf("10.1.0.%d", nextIP) if peer, ok := peers[addr.IP.String()]; ok { @@ -118,9 +97,65 @@ func receivePacket(conn *net.UDPConn, pkt []byte, addr *net.UDPAddr) { log.Println(err) } case shared.REQ_DATA: - fmt.Println("received packet from " + peerIP + ":") - fmt.Println(hex.EncodeToString(pkt[4:])) + log.Println("received packet from " + peerIP + ":") + + frame := pkt[4:] + etherType := binary.BigEndian.Uint16(frame[12:14]) + payload := frame[14:] + + switch etherType { + case 0x0800: // IPv4 + destIP := net.IP(payload[16:20]).String() + if peer := getPeerByInternalIP(destIP); peer != nil { + log.Println("relaying to", peer.RealIP) + resp := shared.BuildPkt(shared.RESP_DATA, frame) + sendTo(peer.RealIP, resp) + } else { + log.Println("unknown dest IP: " + destIP) + } + case 0x0806: // ARP + log.Println("broadcasting ARP") + resp := shared.BuildPkt(shared.RESP_DATA, frame) + broadcast(resp, peerIP) + case 0x86dd: // IPv6 + log.Println("IPv6") // TODO + default: + log.Printf("unhandled EtherType: 0x%x\n", etherType) + } default: log.Println("unknown packet type") } } + +func broadcast(pkt []byte, except string) { + peersMutex.Lock() + defer peersMutex.Unlock() + for _, p := range peers { + if p.RealIP == except { + continue + } + sendTo(p.RealIP, pkt) + } +} + +func sendTo(ip string, pkt []byte) { + addr, err := net.ResolveUDPAddr("udp", ip+":38001") + if err != nil { + log.Println(err) + return + } + if _, err := conn.WriteToUDP(pkt, addr); err != nil { + log.Println(err) + } +} + +func getPeerByInternalIP(internalIP string) *Peer { + peersMutex.Lock() + defer peersMutex.Unlock() + for _, p := range peers { + if p.InternalIP == internalIP { + return p + } + } + return nil +} diff --git a/shared/proto.go b/shared/proto.go index c488023..7ee5da4 100644 --- a/shared/proto.go +++ b/shared/proto.go @@ -9,14 +9,9 @@ const ( REQ_REGISTER RESP_REGISTER REQ_DATA + RESP_DATA ) -func Uint16(v uint16) []byte { - out := make([]byte, 2) - binary.LittleEndian.PutUint16(out, v) - return out -} - func BuildPkt(pktType uint16, data []byte) []byte { out := make([]byte, 4+len(data)) binary.LittleEndian.PutUint16(out[0:], PROTO_VERSION)