package main import ( "encoding/base64" "encoding/binary" "encoding/hex" "log" "net" "os" "os/exec" "baalvpn/shared" "github.com/songgao/water" ) const ( SERVER_IP = "172.20.12.47" IFACE_NAME = "baalvpn" PSK = "rj5FvWB0n342C6UGrAS0gI3GX5ya+lDmC7/XmgFHF+s=" ) var ( internalIP net.IP = nil serverAddr *net.UDPAddr iface *water.Interface conn *net.UDPConn pskKey []byte ) func main() { if os.Geteuid() != 0 { panic("root permissions needed") } var err error pskKey, err = base64.StdEncoding.DecodeString(PSK) if err != nil { panic(err) } listenAddr, err := net.ResolveUDPAddr("udp", ":38000") 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("got assigned IP by the server:", internalIP.String()) setupInterface() go sendPackets() case shared.RESP_DATA: decryptedPkt, err := shared.DecryptSym(pskKey, pkt[4:]) if err != nil { panic(err) } log.Println("received pkt:", hex.EncodeToString(decryptedPkt)) if _, err := iface.Write(decryptedPkt); err != nil { log.Println(err) } default: log.Println("unknown packet type") } } func setupInterface() { 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()+"/32", "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...") for { pkt := make([]byte, 1500) n, err := iface.Read([]byte(pkt)) if err != nil { panic(err) } pkt = pkt[:n] encryptedPkt, err := shared.EncryptSym(pskKey, pkt) if err != nil { panic(err) } req := shared.BuildPkt(shared.REQ_DATA, encryptedPkt) if _, err := conn.WriteToUDP(req, serverAddr); err != nil { log.Println(err) } } }