package main import ( "encoding/binary" "log" "net" "os" "os/exec" "baalvpn/shared" "github.com/songgao/packets/ethernet" "github.com/songgao/water" ) const ( SERVER_IP = "172.20.12.47" IFACE_NAME = "baalvpn" ) var ( internalIP net.IP = nil serverAddr *net.UDPAddr iface *water.Interface conn *net.UDPConn ) func main() { if os.Geteuid() != 0 { panic("root permissions needed") } listenAddr, err := net.ResolveUDPAddr("udp", ":38001") if err != nil { panic(err) } conn, err = net.ListenUDP("udp", listenAddr) if err != nil { panic(err) } defer conn.Close() serverAddr, err = net.ResolveUDPAddr("udp", SERVER_IP+":38000") if err != nil { panic(err) } go receivePackets() register() <-make(chan int) // block forever } func register() { req := shared.BuildPkt(shared.REQ_REGISTER, []byte{}) if _, err := conn.WriteToUDP(req, serverAddr); err != nil { panic(err) } } func receivePackets() { for { buffer := make([]byte, 50000) n, addr, err := conn.ReadFromUDP(buffer) if err != nil { log.Println(err) continue } if n == 0 { continue } if addr.String() != serverAddr.String() { log.Println("non-server connection rejected") continue } go receivePacket(buffer[:n]) } } func receivePacket(pkt []byte) { 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:]) switch pktType { case shared.RESP_REGISTER: internalIP = net.IP(pkt[4:]) log.Println("Received IP from the server:", internalIP.String()) initInterface() go sendPackets() default: log.Println("unknown packet type") } } func initInterface() { 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", internalIP.String()+"/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) } } func sendPackets() { log.Println("Listening for packets...") var frame ethernet.Frame for { frame.Resize(1500) n, err := iface.Read([]byte(frame)) if err != nil { panic(err) } frame = frame[:n] pkt := shared.BuildPkt(shared.REQ_DATA, frame) if _, err := conn.WriteToUDP(pkt, serverAddr); err != nil { log.Println(err) } } }