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 } var ( peers = map[string]*Peer{} peersMutex sync.Mutex nextIP = 3 iface *water.Interface ) func main() { if os.Geteuid() != 0 { 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() } func receivePackets() { log.Println("Listening for packets...") listenAddr, err := net.ResolveUDPAddr("udp", ":38000") if err != nil { panic(err) } listener, err := net.ListenUDP("udp", listenAddr) if err != nil { panic(err) } defer listener.Close() for { buffer := make([]byte, 50000) n, addr, err := listener.ReadFromUDP(buffer) if err != nil { log.Println(err) continue } if n == 0 { continue } go receivePacket(listener, buffer[:n], addr) } } func receivePacket(conn *net.UDPConn, pkt []byte, addr *net.UDPAddr) { if len(pkt) < 4 { log.Println("packet too short") return } version := binary.LittleEndian.Uint16(pkt[0:]) if version != shared.PROTO_VERSION { log.Println("mismatched packet version") return } pktType := binary.LittleEndian.Uint16(pkt[2:]) peerIP := addr.IP.String() switch pktType { case shared.REQ_REGISTER: peersMutex.Lock() defer peersMutex.Unlock() internalIP := fmt.Sprintf("10.1.0.%d", nextIP) if peer, ok := peers[addr.IP.String()]; ok { internalIP = peer.InternalIP } else { peers[addr.IP.String()] = &Peer{ RealIP: peerIP, InternalIP: internalIP, } nextIP++ } resp := shared.BuildPkt(shared.RESP_REGISTER, net.ParseIP(internalIP).To4()) if _, err := conn.WriteToUDP(resp, addr); err != nil { log.Println(err) } case shared.REQ_DATA: fmt.Println("received packet from " + peerIP + ":") fmt.Println(hex.EncodeToString(pkt[4:])) default: log.Println("unknown packet type") } }