### Build AmneziaWG Source: https://github.com/amnezia-vpn/amneziawg-go/blob/master/README.md Build the amneziawg-go project by cloning the repository and running `make`. This requires a Go installation. ```bash $ git clone https://github.com/amnezia-vpn/amneziawg-go $ cd amneziawg-go $ make ``` -------------------------------- ### AmneziaWG Complete Configuration Example Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt A full AmneziaWG client configuration file demonstrating various obfuscation options, custom headers, and peer settings. This INI-style configuration is used with tools like `awg-quick` or `amneziawg-go`. ```ini # /etc/amneziawg/awg0.conf # Complete AmneziaWG configuration file [Interface] PrivateKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE= Address = 10.0.0.2/24 ListenPort = 51820 # AmneziaWG Obfuscation Settings # Junk packets (sent before handshake) Jc = 8 # Number of junk packets Jmin = 50 # Minimum junk packet size (bytes) Jmax = 1000 # Maximum junk packet size (bytes) # Message padding S1 = 96 # Handshake init padding S2 = 96 # Handshake response padding S3 = 32 # Cookie message padding S4 = 0 # Transport message padding # Custom headers (replace standard WireGuard message types) H1 = 1234567890 # Handshake init header H2 = 1234567891-1234567899 # Handshake response header (range) H3 = 1234567900 # Cookie header H4 = 1234568000-1234569000 # Transport header (range) # Custom signature packets (sent before handshake) I1 = # Mimic TLS ClientHello start I2 = # Timestamp + random chars [Peer] PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw= PresharedKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= Endpoint = vpn.example.com:51820 AllowedIPs = 0.0.0.0/0, ::/0 PersistentKeepalive = 25 ``` -------------------------------- ### Setup UAPI Socket for IPC in Go Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Configures the User API (UAPI) for an AmneziaWG interface, enabling external tools to manage the device via Unix socket connections. Ensure the interface name is correctly provided. ```go package main import ( "net" "os" "github.com/amnezia-vpn/amneziawg-go/conn" "github.com/amnezia-vpn/amneziawg-go/device" "github.com/amnezia-vpn/amneziawg-go/ipc" "github.com/amnezia-vpn/amneziawg-go/tun" ) func setupUAPI(interfaceName string, dev *device.Device) error { // Open UAPI socket (creates /var/run/amneziawg/.sock) fileUAPI, err := ipc.UAPIOpen(interfaceName) if err != nil { return err } // Create UAPI listener uapiListener, err := ipc.UAPIListen(interfaceName, fileUAPI) if err != nil { return err } // Handle incoming connections go func() { for { conn, err := uapiListener.Accept() if err != nil { return } // Handle each connection in a goroutine go dev.IpcHandle(conn) } }() return nil } func main() { interfaceName := "awg0" tunDev, _ := tun.CreateTUN(interfaceName, device.DefaultMTU) logger := device.NewLogger(device.LogLevelError, "(awg0) ") dev := device.NewDevice(tunDev, conn.NewDefaultBind(), logger) if err := setupUAPI(interfaceName, dev); err != nil { panic(err) } dev.Up() <-dev.Wait() } // External configuration using awg tool: // awg setconf awg0 /etc/amneziawg/awg0.conf // awg show awg0 ``` -------------------------------- ### Run AmneziaWG Daemon Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Use these commands to start, manage, and check the AmneziaWG daemon. The `-f` or `--foreground` flags are useful for debugging, and `LOG_LEVEL` can be set for verbose logging. ```bash amneziawg-go wg0 ``` ```bash amneziawg-go -f wg0 ``` ```bash amneziawg-go --foreground wg0 ``` ```bash LOG_LEVEL=debug amneziawg-go -f wg0 ``` ```bash amneziawg-go --version ``` ```bash # Output: amneziawg-go 0.0.20250522 # Userspace AmneziaWG daemon for linux-amd64. # Information available at https://amnezia.org ``` ```bash ip link del wg0 ``` ```bash # Or remove socket to trigger shutdown rm -f /var/run/amneziawg/wg0.sock ``` -------------------------------- ### Create TUN Network Interface with AmneziaWG-Go Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Shows how to create a TUN network interface, retrieve its properties like name and MTU, and listen for interface events. Also demonstrates creating a TUN device from an existing file descriptor. ```go package main import ( "fmt" "os" "github.com/amnezia-vpn/amneziawg-go/device" "github.com/amnezia-vpn/amneziawg-go/tun" ) func createTUNExamples() { // Create TUN with name and MTU (Linux) tunDev, err := tun.CreateTUN("awg0", device.DefaultMTU) if err != nil { fmt.Printf("Error: %v\n", err) return } defer tunDev.Close() // Get interface name (may differ from requested on macOS) name, _ := tunDev.Name() fmt.Printf("Created TUN: %s\n", name) // Get current MTU mtu, _ := tunDev.MTU() fmt.Printf("MTU: %d\n", mtu) // Get file descriptor for advanced operations file := tunDev.File() fmt.Printf("FD: %d\n", file.Fd()) // Listen for device events go func() { for event := range tunDev.Events() { switch event { case tun.EventUp: fmt.Println("Interface UP") case tun.EventDown: fmt.Println("Interface DOWN") case tun.EventMTUUpdate: fmt.Println("MTU changed") } } }() // Create from existing file (for FD passing) fd, _ := os.Open("/dev/net/tun") tunFromFile, err := tun.CreateTUNFromFile(fd, 1420) if tunFromFile != nil { defer tunFromFile.Close() } } ``` -------------------------------- ### Open and Use Network Bind Interface Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Demonstrates creating a network bind, opening a specific port, parsing endpoints, setting firewall marks (Linux-specific), and sending/receiving packets. Use `conn.NewStdNetBind()` for cross-platform UDP socket operations. ```go package main import ( "fmt" "net/netip" "github.com/amnezia-vpn/amneziawg-go/conn" ) func bindExample() { // Create standard network bind bind := conn.NewStdNetBind() // Open bind on specific port (0 = random port) receiveFuncs, actualPort, err := bind.Open(51820) if err != nil { fmt.Printf("Failed to open bind: %v\n", err) return } fmt.Printf("Listening on port %d\n", actualPort) // Parse endpoint string endpoint, err := bind.ParseEndpoint("203.0.113.1:51820") if err != nil { fmt.Printf("Failed to parse endpoint: %v\n", err) return } fmt.Printf("Endpoint: %s\n", endpoint.DstToString()) // Set firewall mark (Linux only) bind.SetMark(0x1234) // Get batch size for optimal performance batchSize := bind.BatchSize() fmt.Printf("Batch size: %d\n", batchSize) // Usually 128 // Send packets packets := [][]byte{ []byte("packet1"), []byte("packet2"), } if err := bind.Send(packets, endpoint); err != nil { fmt.Printf("Send error: %v\n", err) } // Receive packets (typically done in goroutines) for _, recvFn := range receiveFuncs { go func(fn conn.ReceiveFunc) { packets := make([][]byte, batchSize) sizes := make([]int, batchSize) endpoints := make([]conn.Endpoint, batchSize) for i := range packets { packets[i] = make([]byte, 2048) } for { n, err := fn(packets, sizes, endpoints) if err != nil { return } for i := 0; i < n; i++ { if sizes[i] > 0 { fmt.Printf("Received %d bytes from %s\n", sizes[i], endpoints[i].DstToString()) } } } }(recvFn) } // Cleanup bind.Close() } ``` -------------------------------- ### Create AmneziaWG Device Programmatically Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt This Go code demonstrates how to create and manage an AmneziaWG device programmatically. It includes setting up a TUN device, logger, and UDP bind, then bringing the device up and handling shutdown signals. ```go package main import ( "fmt" "os" "os/signal" "syscall" "github.com/amnezia-vpn/amneziawg-go/conn" "github.com/amnezia-vpn/amneziawg-go/device" "github.com/amnezia-vpn/amneziawg-go/tun" ) func main() { // Create TUN device with name and MTU tunDevice, err := tun.CreateTUN("awg0", device.DefaultMTU) if err != nil { fmt.Printf("Failed to create TUN device: %v\n", err) os.Exit(1) } // Create logger (LogLevelSilent, LogLevelError, LogLevelVerbose) logger := device.NewLogger(device.LogLevelVerbose, "(awg0) ") // Create network bind for UDP connections bind := conn.NewDefaultBind() // Create the device dev := device.NewDevice(tunDevice, bind, logger) // Bring the device up if err := dev.Up(); err != nil { fmt.Printf("Failed to bring device up: %v\n", err) os.Exit(1) } fmt.Println("Device started successfully") // Wait for shutdown signal term := make(chan os.Signal, 1) signal.Notify(term, syscall.SIGTERM, os.Interrupt) select { case <-term: fmt.Println("Received shutdown signal") case <-dev.Wait(): fmt.Println("Device closed") } // Cleanup dev.Close() } ``` -------------------------------- ### Implement Custom Loggers in Go Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Demonstrates creating various logger instances, including a silent logger, a custom formatted logger, and a logger that writes to a file. Use these to control debug and error message output. ```go package main import ( "fmt" "log" "os" "time" "github.com/amnezia-vpn/amneziawg-go/conn" "github.com/amnezia-vpn/amneziawg-go/device" "github.com/amnezia-vpn/amneziawg-go/tun" ) func customLoggerExample() { // Use built-in logger with log level logger := device.NewLogger(device.LogLevelVerbose, "(awg0) ") // Create silent logger silentLogger := &device.Logger{ Verbosef: device.DiscardLogf, Errorf: device.DiscardLogf, } // Create custom logger customLogger := &device.Logger{ Verbosef: func(format string, args ...any) { msg := fmt.Sprintf(format, args...) fmt.Printf("[DEBUG %s] %s\n", time.Now().Format(time.RFC3339), msg) }, Errorf: func(format string, args ...any) { msg := fmt.Sprintf(format, args...) fmt.Fprintf(os.Stderr, "[ERROR %s] %s\n", time.Now().Format(time.RFC3339), msg) }, } // Logger that writes to file logFile, _ := os.OpenFile("/var/log/amneziawg.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) fileLog := log.New(logFile, "", log.Ldate|log.Ltime) fileLogger := &device.Logger{ Verbosef: fileLog.Printf, Errorf: fileLog.Printf, } // Use with device tunDev, _ := tun.CreateTUN("awg0", device.DefaultMTU) _ = device.NewDevice(tunDev, conn.NewDefaultBind(), logger) _ = silentLogger _ = customLogger _ = fileLogger } ``` -------------------------------- ### Run AmneziaWG Source: https://github.com/amnezia-vpn/amneziawg-go/blob/master/README.md Execute amneziawg-go to create a network interface and run in the background. Use `ip link del wg0` to remove the interface. ```bash $ amneziawg-go wg0 ``` -------------------------------- ### Retrieve Device Configuration using IpcGet Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt The IpcGet helper function provides a simpler way to retrieve the device configuration as a string. It handles the underlying IPC call and returns the configuration or an error. ```go func getConfigSimple(dev *device.Device) { config, err := dev.IpcGet() if err != nil { fmt.Printf("Error: %v\n", err) return } // Parse the output // Example output: // private_key=a8dac1d8a70a751f0f699fb14ba1cee7... // listen_port=51820 // jc=8 // jmin=50 // jmax=1000 // s1=96 // s2=96 // h1=1234567890 // h2=1234567891-1234567899 // public_key=b85996fecc9c7f1fc6d2572a76bbe9f8... // endpoint=203.0.113.1:51820 // last_handshake_time_sec=1699123456 // last_handshake_time_nsec=789012345 // tx_bytes=1048576 // rx_bytes=2097152 // allowed_ip=10.0.0.0/24 for _, line := range strings.Split(config, "\n") { if line != "" { fmt.Println(line) } } } ``` -------------------------------- ### Set Device Private Key via IPC Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Demonstrates setting the device's private key using the IPC interface with a hex-encoded key. This is crucial for establishing cryptographic identity before peer connections. ```go package main import ( "crypto/rand" "encoding/hex" "fmt" "strings" "github.com/amnezia-vpn/amneziawg-go/conn" "github.com/amnezia-vpn/amneziawg-go/device" "github.com/amnezia-vpn/amneziawg-go/tun" ) func setPrivateKey(dev *device.Device) error { // Method 1: Via IPC (hex-encoded 32-byte key) config := `private_key=a8dac1d8a70a751f0f699fb14ba1cee7d89efb1bfe5f4b12e1a60c8f1e5d3b4a ` return dev.IpcSetOperation(strings.NewReader(config)) } func generateAndSetKey() { tunDev, _ := tun.CreateTUN("awg0", device.DefaultMTU) logger := device.NewLogger(device.LogLevelError, "") dev := device.NewDevice(tunDev, conn.NewDefaultBind(), logger) defer dev.Close() // Generate random 32-byte private key var privateKey [32]byte rand.Read(privateKey[:]) // Set via IPC config := fmt.Sprintf("private_key=%s\n", hex.EncodeToString(privateKey[:])) if err := dev.IpcSetOperation(strings.NewReader(config)); err != nil { fmt.Printf("Failed to set private key: %v\n", err) } } ``` -------------------------------- ### Manage Device Lifecycle Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Illustrates controlling the state of a WireGuard device, including bringing it up and down, checking load, and performing cleanup. Ensure the TUN device and bind are correctly initialized. ```go package main import ( "fmt" "time" "github.com/amnezia-vpn/amneziawg-go/conn" "github.com/amnezia-vpn/amneziawg-go/device" "github.com/amnezia-vpn/amneziawg-go/tun" ) func deviceLifecycle() { tunDev, _ := tun.CreateTUN("awg0", device.DefaultMTU) logger := device.NewLogger(device.LogLevelVerbose, "(awg0) ") dev := device.NewDevice(tunDev, conn.NewDefaultBind(), logger) // Bring device up if err := dev.Up(); err != nil { fmt.Printf("Up failed: %v\n", err) } // Check if under load (handshake queue filling up) if dev.IsUnderLoad() { fmt.Println("Device is under heavy load") } // Get batch size fmt.Printf("Batch size: %d\n", dev.BatchSize()) // Bring device down (stops peers, closes bind) if err := dev.Down(); err != nil { fmt.Printf("Down failed: %v\n", err) } // Bring back up dev.Up() // Send keepalives to peers with active sessions dev.SendKeepalivesToPeersWithCurrentKeypair() // Wait channel for graceful shutdown go func() { <-dev.Wait() fmt.Println("Device has been closed") }() // Close device (final cleanup) time.Sleep(time.Second) dev.Close() } ``` -------------------------------- ### Retrieve Device Configuration using IpcGetOperation Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Use IpcGetOperation to fetch the complete device configuration, including peers, statistics, and obfuscation settings. This method writes the configuration to a provided buffer. ```go package main import ( "bytes" "fmt" "strings" "github.com/amnezia-vpn/amneziawg-go/conn" "github.com/amnezia-vpn/amneziawg-go/device" "github.com/amnezia-vpn/amneziawg-go/tun" ) func getDeviceConfig(dev *device.Device) (string, error) { var buf bytes.Buffer if err := dev.IpcGetOperation(&buf); err != nil { return "", err } return buf.String(), nil } ``` -------------------------------- ### Apply and Verify AmneziaWG Configuration Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Commands to apply a complete AmneziaWG configuration using `awg-quick` or manual steps, and to verify the applied settings. This includes bringing the interface up, setting the configuration, and checking the interface status. ```bash # Apply configuration awg-quick up awg0 # Or manually: amneziawg-go awg0 ``` ```bash awg setconf awg0 /etc/amneziawg/awg0.conf ip addr add 10.0.0.2/24 dev awg0 ip link set awg0 up ip route add default dev awg0 ``` ```bash # Verify configuration awg show awg0 # Output example: # interface: awg0 # public key: xTIBA5rboUvnH4htodjb60Y7YAf21J7YQMlNGC8HQ14= # private key: (hidden) # listening port: 51820 # jc: 8 # jmin: 50 # jmax: 1000 # s1: 96 # s2: 96 # h1: 1234567890 ``` -------------------------------- ### Manage Peers with AmneziaWG-Go Device API Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Demonstrates adding, looking up, removing, and replacing peers using the device API. Peers can be managed via IPC or direct method calls. ```go package main import ( "encoding/hex" "fmt" "strings" "github.com/amnezia-vpn/amneziawg-go/device" ) // Convert hex string to NoisePublicKey func hexToPublicKey(hexStr string) (device.NoisePublicKey, error) { var pk device.NoisePublicKey bytes, err := hex.DecodeString(hexStr) if err != nil { return pk, err } copy(pk[:], bytes) return pk, nil } func managePeers(dev *device.Device) { // Add peer via IPC addPeerConfig := `public_key=b85996fecc9c7f1fc6d2572a76bbe9f8b1e2d4c6a8f0e2d4c6a8f0e2d4c6a8f0 endpoint=203.0.113.1:51820 allowed_ip=10.0.0.0/24 persistent_keepalive_interval=25 ` dev.IpcSetOperation(strings.NewReader(addPeerConfig)) // Lookup peer by public key pk, _ := hexToPublicKey("b85996fecc9c7f1fc6d2572a76bbe9f8b1e2d4c6a8f0e2d4c6a8f0e2d4c6a8f0") peer := dev.LookupPeer(pk) if peer != nil { fmt.Printf("Found peer: %v\n", peer) } // Remove specific peer dev.RemovePeer(pk) // Remove all peers dev.RemoveAllPeers() // Replace all peers (via IPC) replaceConfig := `replace_peers=true public_key=newpublickeyhere... endpoint=203.0.113.2:51820 allowed_ip=10.0.1.0/24 ` dev.IpcSetOperation(strings.NewReader(replaceConfig)) } ``` ```go func hexToPublicKey(hexStr string) (device.NoisePublicKey, error) { var pk device.NoisePublicKey bytes, err := hex.DecodeString(hexStr) if err != nil { return pk, err } copy(pk[:], bytes) return pk, nil } ``` -------------------------------- ### Configure Junk Packets for DPI Evasion Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Configure junk packets by setting the number of packets (jc), minimum size (jmin), and maximum size (jmax). Ensure jmax is less than the system MTU to prevent fragmentation. ```go package main import ( "strings" "github.com/amnezia-vpn/amneziawg-go/device" ) func configureJunkPackets(dev *device.Device) error { // jc: number of junk packets (recommended: 4-12) // jmin: minimum junk packet size // jmax: maximum junk packet size (must be < system MTU to avoid fragmentation) config := `jc=8 jmin=50 jmax=1000 ` return dev.IpcSetOperation(strings.NewReader(config)) } ``` ```bash # Command-line configuration using amneziawg-tools (awg command) # awg set awg0 jc 8 jmin 50 jmax 1000 ``` -------------------------------- ### Configure Message Padding Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Set message padding for handshake initiation (s1), handshake response (s2), cookie messages (s3), and transport messages (s4) to evade size-based DPI detection. ```go package main import ( "strings" "github.com/amnezia-vpn/amneziawg-go/device" ) func configureMessagePadding(dev *device.Device) error { // s1: padding for handshake initiation message // s2: padding for handshake response message // s3: padding for cookie message // s4: padding for transport messages config := `s1=96 s2=96 s3=32 s4=0 ` return dev.IpcSetOperation(strings.NewReader(config)) } ``` -------------------------------- ### Configure Custom Signature Packets Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Obfuscate the protocol by sending custom signature packets before handshakes. Configure packets I1 through I5 using static bytes, random data, random digits, random characters, or timestamps. Unspecified packets are skipped. ```go package main import ( "strings" "github.com/amnezia-vpn/amneziawg-go/device" ) func configureSignaturePackets(dev *device.Device) error { // Tag syntax: // - static bytes (hex-encoded) // - random bytes // - random digits (0-9) // - random chars (a-zA-Z) // - 4-byte UNIX timestamp // // Packets are sent in order: I1, I2, I3, I4, I5 // Unspecified packets are skipped config := `i1= i2= i3= ` // i1: "HELLO" + 10 random bytes // i2: timestamp + 8 random letters + 4 random digits // i3: static 4-byte sequence 0xdeadbeef // i4, i5: not sent (not configured) return dev.IpcSetOperation(strings.NewReader(config)) } ``` -------------------------------- ### Configure AmneziaWG Device via IPC Set Operation Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt This Go code configures an AmneziaWG device using a string that follows the WireGuard protocol format, including AmneziaWG-specific obfuscation parameters like junk packet settings (`jc`, `jmin`, `jmax`) and header/signature settings (`s1`-`s4`, `h1`-`h4`). ```go package main import ( "strings" "github.com/amnezia-vpn/amneziawg-go/conn" "github.com/amnezia-vpn/amneziawg-go/device" "github.com/amnezia-vpn/amneziawg-go/tun" ) func configureDevice(dev *device.Device) error { // Configuration format follows WireGuard protocol with AWG extensions config := `private_key=a8dac1d8a70a751f0f699fb14ba1cee7d89efb1bfe5f4b12e1a60c8f1e5d3b4a listen_port=51820 fwmark=0 jc=8 jmin=50 jmax=1000 s1=96 s2=96 s3=32 s4=0 h1=1234567890 h2=1234567891-1234567899 h3=1234567900 h4=1234568000-1234569000 public_key=b85996fecc9c7f1fc6d2572a76bbe9f8b1e2d4c6a8f0e2d4c6a8f0e2d4c6a8f0 endpoint=203.0.113.1:51820 allowed_ip=10.0.0.0/24 allowed_ip=192.168.1.0/24 persistent_keepalive_interval=25 ` return dev.IpcSetOperation(strings.NewReader(config)) } func main() { tunDevice, _ := tun.CreateTUN("awg0", device.DefaultMTU) logger := device.NewLogger(device.LogLevelError, "(awg0) ") dev := device.NewDevice(tunDevice, conn.NewDefaultBind(), logger) if err := configureDevice(dev); err != nil { panic(err) } dev.Up() // ... use device dev.Close() } ``` -------------------------------- ### Run AmneziaWG in Foreground Source: https://github.com/amnezia-vpn/amneziawg-go/blob/master/README.md Run amneziawg-go in the foreground by using the `-f` or `--foreground` flag. This is useful for debugging or when backgrounding is not desired. ```bash $ amneziawg-go -f wg0 ``` -------------------------------- ### Configure Custom Message Headers Source: https://context7.com/amnezia-vpn/amneziawg-go/llms.txt Replace WireGuard's default message type identifiers with custom values or ranges for handshake initiation (h1), handshake response (h2), cookie reply (h3), and transport data (h4) to prevent protocol fingerprinting. Ensure headers do not overlap. ```go package main import ( "strings" "github.com/amnezia-vpn/amneziawg-go/device" ) func configureCustomHeaders(dev *device.Device) error { // h1: header for handshake initiation (default: 1) // h2: header for handshake response (default: 2) // h3: header for cookie reply (default: 3) // h4: header for transport data (default: 4) // // Format: single value "1234" or range "1234-5678" // Headers must not overlap! config := `h1=1000000001 h2=1000000002-1000000099 h3=1000000100 h4=1000000200-1000000999 ` return dev.IpcSetOperation(strings.NewReader(config)) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.