### **Updated Approach:** - Use `github.com/songgao/water` to create a **TUN** interface. - Use **UDP** to transfer encrypted packets. - Use **ChaCha20-Poly1305** for encryption. --- ## **1. Install Dependencies** ```sh go get github.com/songgao/water golang.org/x/crypto/chacha20poly1305 ``` --- ## **2. `tun.go` (TUN Interface Handler)** This sets up a **TUN interface**. ```go package main import ( "fmt" "log" "github.com/songgao/water" ) func createTUN(name string) *water.Interface { config := water.Config{ DeviceType: water.TUN, } ifce, err := water.New(config) if err != nil { log.Fatalf("Failed to create TUN interface: %v", err) } fmt.Println("TUN interface created:", ifce.Name()) return ifce } ``` --- ## **3. `server.go` (VPN Server)** - Creates a **TUN** interface (`vpn0`). - Listens for UDP packets on `:51820`. - **Decrypts** packets and writes them to the **TUN** interface. ```go package main import ( "crypto/rand" "fmt" "log" "net" "github.com/songgao/water" "golang.org/x/crypto/chacha20poly1305" ) var key = make([]byte, chacha20poly1305.KeySize) func main() { rand.Read(key) // Generate encryption key tunDevice := createTUN("vpn0") defer tunDevice.Close() conn, err := net.ListenPacket("udp", ":51820") if err != nil { log.Fatalf("Failed to start UDP server: %v", err) } defer conn.Close() aead, _ := chacha20poly1305.New(key) buf := make([]byte, 1500) fmt.Println("VPN Server listening on UDP 51820") for { n, addr, err := conn.ReadFrom(buf) if err != nil { log.Println("Read error:", err) continue } nonceSize := aead.NonceSize() if n < nonceSize { continue } nonce, ciphertext := buf[:nonceSize], buf[nonceSize:n] plaintext, err := aead.Open(nil, nonce, ciphertext, nil) if err != nil { log.Println("Decryption failed:", err) continue } tunDevice.Write(plaintext) // Send decrypted data to TUN fmt.Printf("Received %d bytes from %s\n", len(plaintext), addr) } } ``` --- ## **4. `client.go` (VPN Client)** - Creates a **TUN** interface (`vpn-client`). - Captures packets from **TUN**. - **Encrypts** them and sends them to the VPN server via **UDP**. ```go package main import ( "crypto/rand" "fmt" "log" "net" "github.com/songgao/water" "golang.org/x/crypto/chacha20poly1305" ) var key = make([]byte, chacha20poly1305.KeySize) func main() { rand.Read(key) tunDevice := createTUN("vpn-client") defer tunDevice.Close() conn, err := net.Dial("udp", "SERVER_IP:51820") // Replace SERVER_IP if err != nil { log.Fatalf("Failed to connect: %v", err) } defer conn.Close() aead, _ := chacha20poly1305.New(key) packet := make([]byte, 1500) for { n, err := tunDevice.Read(packet) if err != nil { log.Println("TUN Read error:", err) continue } nonce := make([]byte, aead.NonceSize()) rand.Read(nonce) ciphertext := aead.Seal(nil, nonce, packet[:n], nil) conn.Write(append(nonce, ciphertext...)) fmt.Printf("Sent %d encrypted bytes\n", len(ciphertext)) } } ``` --- ## **5. Running the VPN** ### **Step 1: Server Setup** Run the server: ```sh go run server.go ``` This creates `vpn0` and listens for **encrypted** packets. ### **Step 2: Client Setup** On the client machine, replace `SERVER_IP` in `client.go` and run: ```sh go run client.go ``` ### **Step 3: Configure Routing** **On the Server**: Enable forwarding: ```sh sysctl -w net.ipv4.ip_forward=1 iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE ``` **On the Client**: Route traffic through the VPN: ```sh ip route add 10.8.0.0/24 via vpn-client ``` --- ## **6. Testing** Try pinging from the **client**: ```sh ping -I vpn-client 10.8.0.1 ``` You should see **encrypted traffic** flowing. --- ## **Next Steps** - **User authentication** (public keys). - **Multi-client support** (track multiple clients). - **NAT traversal** (STUN/TURN). - **IPv6 support**. Would you like help with **multi-client support** or **NAT traversal**? 🚀