### Encrypt IP Packet Example (Kotlin) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Example demonstrating the use of `wireguardWrite` to encrypt an IP packet. It prepares input and output buffers and handles the returned packet size. ```kotlin val ipPacket = ByteArray(1500) val output = ByteBuffer.allocateDirect(1600) val op = ByteBuffer.allocateDirect(4) val size = BoringTunJNI.wireguardWrite(tunnel, ipPacket, ipPacket.size, output, output.capacity(), op) if (size > 0) { // Send `output[0..size]` to peer sendToNetwork(output.array(), size) } ``` -------------------------------- ### Install boringtun-cli with Cargo Source: https://github.com/cloudflare/boringtun/blob/master/README.md Install the command-line interface for BoringTun using Cargo. This is the primary method for installing the executable. ```bash cargo install boringtun-cli ``` -------------------------------- ### Rust DeviceConfig Initialization Example Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-device.md Demonstrates how to create an instance of DeviceConfig with custom settings for worker threads and socket usage. ```rust let config = DeviceConfig { n_threads: 8, use_connected_socket: true, use_multi_queue: true, uapi_fd: -1, }; ``` -------------------------------- ### Rust Tunn::new() Example Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/configuration.md Provides a practical example of how to use the `Tunn::new()` constructor in Rust. It demonstrates initializing a tunnel with a private key, peer's public key, keepalive interval, and index. The `persistent_keepalive` is set to 25 seconds, suitable for mobile environments. The `index` is set to 1 for identification. ```rust use boringtun::noise::Tunn; use boringtun::x25519::{StaticSecret, PublicKey}; use rand_core::OsRng; let my_secret = StaticSecret::random_from_rng(OsRng); let peer_public = PublicKey::from_bytes(&[/* 32 bytes */]).unwrap(); let tunnel = Tunn::new( my_secret, peer_public, None, // no preshared key Some(25), // keepalive every 25 seconds 1, // index 1 None, // default rate limiter ); ``` -------------------------------- ### Create and Initialize DeviceConfig Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/configuration.md Example of creating a `DeviceConfig` instance with custom settings and initializing a `DeviceHandle`. Ensure `use_multi_queue` and `uapi_fd` are appropriate for your Linux environment. ```rust use boringtun::device::{DeviceHandle, DeviceConfig}; let config = DeviceConfig { n_threads: 8, use_connected_socket: true, use_multi_queue: true, uapi_fd: -1, }; let handle = DeviceHandle::new("wg0", config)?; ``` -------------------------------- ### Create New Tunnel Example (Kotlin) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Example of how to call the `newTunnel` JNI function in Kotlin. Includes error handling for invalid tunnel creation. ```kotlin val tunnel = BoringTunJNI.newTunnel( "WJlhX0DrLS26zBzpd9p+/ZzIqMlzG0+91scksKjwO2A=", "NJgcyYyJ7xfX+7M89Lq4/0Y5NWlDWJqnJWcQ8eG8DlY=", null, 25, 1 ) if (tunnel == 0L) { throw IllegalStateException("Failed to create tunnel") } ``` -------------------------------- ### Get Current WireGuard Configuration Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/configuration.md Use the `wg show` command to display the current configuration of a WireGuard interface. ```bash # Get current config wg show wg0 ``` -------------------------------- ### Encode Key to Base64 String (Kotlin) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Example of converting an x25519 key to its base64 string representation using `x25519KeyToBase64`. ```kotlin val secret = BoringTunJNI.x25519SecretKey() val b64String = BoringTunJNI.x25519KeyToBase64(secret) println("Secret (base64): $b64String") ``` -------------------------------- ### Derive x25519 Public Key (Kotlin) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Example demonstrating how to derive an x25519 public key from a secret key using the `x25519PublicKey` native method. ```kotlin val secret = BoringTunJNI.x25519SecretKey() val public = BoringTunJNI.x25519PublicKey(secret) ``` -------------------------------- ### Periodic Tunnel Maintenance Example (Kotlin) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Example of how to use `wireguardTick` within an event loop to handle tunnel maintenance and send keepalive packets when necessary. ```kotlin // In event loop, every 100ms: val output = ByteBuffer.allocateDirect(150) val op = ByteBuffer.allocateDirect(4) val size = BoringTunJNI.wireguardTick(tunnel, output, output.capacity(), op) if (size > 0) { sendToNetwork(output.array(), size) } ``` -------------------------------- ### Configure BoringTun Device via uAPI Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-device.md Use this command to set device configurations such as private key, listen port, peer details, and allowed IPs. Ensure socat is installed and the WireGuard socket is accessible. ```bash echo "set=1 private_key=WJlhX0DrLS26zBzpd9p+/ZzIqMlzG0+91scksKjwO2A= listen_port=51820 public_key=NJgcyYyJ7xfX+7M89Lq4/0Y5NWlDWJqnJWcQ8eG8DlY= endpoint=192.0.2.1:51820 allowed_ip=10.0.0.2/32 persistent_keepalive_interval=25 preshared_key=zOEmXKNpCKM7PGhV0eFhHlL5qKQXQWH0rOwNaKzUgnQ= " | socat - UNIX-CONNECT:/var/run/wireguard/wg0.sock ``` -------------------------------- ### Run boringtun-cli Source: https://github.com/cloudflare/boringtun/blob/master/README.md Start a WireGuard tunnel using the boringtun-cli executable. The tunnel can be configured using standard WireGuard tools. ```bash boringtun-cli [-f/--foreground] INTERFACE-NAME ``` -------------------------------- ### AllowedIP Parsing Example Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/types.md Demonstrates how to parse a string representation of an IP address with a CIDR prefix into an `AllowedIP` struct. Requires the `std::str::FromStr` trait. ```rust use boringtun::device::AllowedIP; use std::str::FromStr; let allowed = AllowedIP::from_str("10.0.0.2/32")?; assert_eq!(allowed.cidr, 32); ``` -------------------------------- ### Encode Key to Hex String (Kotlin) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Example of converting an x25519 key to its hex string representation using `x25519KeyToHex`. ```kotlin val secret = BoringTunJNI.x25519SecretKey() val hexString = BoringTunJNI.x25519KeyToHex(secret) println("Secret (hex): $hexString") ``` -------------------------------- ### Example: Display WireGuard Tunnel Statistics in Kotlin Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md This Kotlin code demonstrates how to call the `wireguardStats` function and print the retrieved statistics in a human-readable format. Ensure the BoringTun library is loaded. ```kotlin val stats = BoringTunJNI.wireguardStats(tunnel) println(""" Handshake: ${stats.timeSinceLastHandshake}s ago TX: ${stats.txBytes} bytes RX: ${stats.rxBytes} bytes Loss: ${stats.estimatedLoss * 100}% RTT: ${stats.estimatedRtt}ms """.trimIndent()) ``` -------------------------------- ### WireGuard Tunnel Integration Example Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Demonstrates how to create and manage a WireGuard tunnel using the BoringTun JNI API. Ensure DirectBuffers are used for JNI buffers and check for null return values to handle errors. ```kotlin class WireGuardTunnel( private val secret: ByteArray, private val peerPublic: ByteArray, private val presharedKey: ByteArray? = null, private val keepAlive: Short = 25 ) { private val tunnel: Long private val sendBuffer = ByteBuffer.allocateDirect(1600) private val recvBuffer = ByteBuffer.allocateDirect(2048) private val opBuffer = ByteBuffer.allocateDirect(4) init { val privStr = BoringTunJNI.x25519KeyToBase64(secret) val pubStr = BoringTunJNI.x25519KeyToBase64(peerPublic) val pskStr = presharedKey?.let { BoringTunJNI.x25519KeyToBase64(it) } tunnel = BoringTunJNI.newTunnel(privStr, pubStr, pskStr, keepAlive, 1) if (tunnel == 0L) throw IllegalStateException("Failed to create tunnel") } fun encapsulate(ipPacket: ByteArray): ByteArray? { sendBuffer.clear() opBuffer.clear() val size = BoringTunJNI.wireguardWrite( tunnel, ipPacket, ipPacket.size, sendBuffer, sendBuffer.capacity(), opBuffer ) return if (size > 0) { ByteArray(size).also { sendBuffer.get(0, it) } } else null } fun decapsulate(datagram: ByteArray): Pair? { recvBuffer.clear() opBuffer.clear() val size = BoringTunJNI.wireguardRead( tunnel, datagram, datagram.size, recvBuffer, recvBuffer.capacity(), opBuffer ) val op = opBuffer.int return when { size > 0 && (op == 4 || op == 6) -> { Pair(ByteArray(size).also { recvBuffer.get(0, it) }, op) } else -> null } } fun tick(): ByteArray? { sendBuffer.clear() opBuffer.clear() val size = BoringTunJNI.wireguardTick( tunnel, sendBuffer, sendBuffer.capacity(), opBuffer ) return if (size > 0) { ByteArray(size).also { sendBuffer.get(0, it) } } else null } fun stats(): WireGuardStats? { return BoringTunJNI.wireguardStats(tunnel) } } ``` -------------------------------- ### Generate x25519 Secret Key (Kotlin) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Example of how to call the `x25519SecretKey` native method in Kotlin and print the size of the generated key. ```kotlin val secretKey = BoringTunJNI.x25519SecretKey() println("Generated ${secretKey.size}-byte secret key") ``` -------------------------------- ### Format Handshake Initiation Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-tunn.md Use `format_handshake_initiation` to create a WireGuard handshake initiation message. This is called when starting a connection or re-keying. The destination buffer must be at least 148 bytes. ```rust let mut handshake_pkt = [0u8; 148]; match tunnel.format_handshake_initiation(&mut handshake_pkt, false) { TunnResult::WriteToNetwork(pkt) => { send_to_network(pkt); } TunnResult::Done => println!("Handshake in progress"), TunnResult::Err(e) => eprintln!("Failed: {:?}", e), _ => {} // Handle other potential TunnResult variants if necessary } ``` -------------------------------- ### Handshake Rate Limiting Example Timeline Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-rate-limiter.md Illustrates the sequence of handshake responses based on a rate limit of 100 per second. Shows how the system differentiates between initial handshakes and subsequent attempts with a cookie. ```text t=0.0s: Handshake init 1 → Handshake response t=0.1s: Handshake init 2 → Handshake response ... t=0.99s: Handshake init 100 → Handshake response t=1.0s: Reset counter to 0 t=1.05s: Handshake init 101 (no cookie) → Cookie reply t=1.06s: Handshake init 102 (with cookie) → Handshake response ``` -------------------------------- ### Handle DropPrivileges Error on Linux Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/errors.md Handle `DropPrivileges` errors, which occur on Linux if dropping privileges after device setup fails. This might be acceptable if the process is not running as root. ```rust match DeviceHandle::new("wg0", config) { Err(Error::DropPrivileges(msg)) => { eprintln!("Privilege drop failed: {}", msg); // May be OK if not root; check context } _ => {} } ``` -------------------------------- ### DeviceConfig Struct Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/types.md Configuration for DeviceHandle::new(). ```APIDOC ## DeviceConfig Struct ### Description Configuration for `DeviceHandle::new()`. ### Fields - **n_threads** (usize) - Required - Number of worker threads. Default: 4 - **use_connected_socket** (bool) - Required - Use connected UDP for performance. Default: true - **use_multi_queue** (bool) - Optional (Linux) - Enable per-thread TUN queue. Default: true - **uapi_fd** (i32) - Optional (Linux) - Existing uAPI socket fd, or -1 to create. Default: -1 ### Implements `Default` ``` -------------------------------- ### Rust - Create and Encapsulate Tunnel Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/quick-start.md Demonstrates generating keys, creating a tunnel instance, and encapsulating an IP packet for transmission. Requires the boringtun crate. ```rust use boringtun::noise::Tunn; use boringtun::x25519::{StaticSecret, PublicKey}; use rand_core::OsRng; fn main() { // Generate or load keys let my_secret = StaticSecret::random_from_rng(OsRng); let my_public = PublicKey::from(&my_secret); let peer_public = PublicKey::from(&StaticSecret::random_from_rng(OsRng)); // Create tunnel let mut tunnel = Tunn::new( my_secret, peer_public, None, // no preshared key Some(25), // 25-second keepalive 1, // peer index None, // default rate limiter ); // Send a packet let ip_packet = [0u8; 100]; // Example packet let mut output = vec![0u8; ip_packet.len() + 32]; loop { match tunnel.encapsulate(&ip_packet, &mut output) { boringtun::noise::TunnResult::WriteToNetwork(pkt) => { // Send pkt to peer via UDP println!("Sending {} bytes", pkt.len()); } boringtun::noise::TunnResult::Done => { println!("Packet queued, handshake in progress"); break; } _ => break, } } } ``` -------------------------------- ### Run boringtun-cli with wg-quick Source: https://github.com/cloudflare/boringtun/blob/master/README.md Use boringtun-cli with wg-quick by setting the WG_QUICK_USERSPACE_IMPLEMENTATION environment variable. WG_SUDO=1 is used to allow wg-quick to run with sudo. ```bash sudo WG_QUICK_USERSPACE_IMPLEMENTATION=boringtun-cli WG_SUDO=1 wg-quick up CONFIGURATION ``` -------------------------------- ### Configure Boringtun via CLI on Linux Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/quick-start.md Use this bash script to set up a WireGuard interface, configure peers, assign IPs, and manage routes using the boringtun-cli. ```bash # Create interface sudo boringtun-cli wg0 & # Configure with wg wg set wg0 private-key <(wg genkey) wg set wg0 listen-port 51820 # Add peer wg set wg0 peer \ NJgcyYyJ7xfX+7M89Lq4/0Y5NWlDWJqnJWcQ8eG8DlY= \ endpoint 203.0.113.1:51820 \ allowed-ips 10.0.0.0/8 \ persistent-keepalive 25 # Assign IP and route sudo ip addr add 10.0.0.1/24 dev wg0 sudo ip route add 10.0.0.0/8 dev wg0 # View status wg show wg0 # Stop pkill boringtun ``` -------------------------------- ### Configure Device and Peer via uAPI Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/configuration.md Use this command to configure the WireGuard device and add a peer through the uAPI socket. Ensure the socket path is correct for your interface. ```bash # Configure device and peer echo "set=1 private_key=WJlhX0DrLS26zBzpd9p+/ZzIqMlzG0+91scksKjwO2A= listen_port=51820 fwmark=1234 public_key=NJgcyYyJ7xfX+7M89Lq4/0Y5NWlDWJqnJWcQ8eG8DlY= endpoint=192.0.2.1:51820 allowed_ip=10.0.0.2/32 allowed_ip=10.0.1.0/24 persistent_keepalive_interval=25 preshared_key=zOEmXKNpCKM7PGhV0eFhHlL5qKQXQWH0rOwNaKzUgnQ=" | socat - UNIX-CONNECT:/var/run/wireguard/wg0.sock ``` -------------------------------- ### Build boringtun-cli Executable Source: https://github.com/cloudflare/boringtun/blob/master/README.md Build the boringtun-cli executable in release mode. The output will be in the ./target/release folder. ```bash cargo build --bin boringtun-cli --release [--target $(TARGET_TRIPLE)] ``` -------------------------------- ### Get Tunnel Statistics Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-tunn.md Retrieves tunnel statistics including time since last handshake, transmitted and received bytes, packet loss rate, and estimated round-trip time. ```rust pub fn stats(&self) -> (Option, usize, usize, f32, Option) ``` ```rust let (handshake_age, tx_bytes, rx_bytes, loss, rtt) = tunnel.stats(); println!( "Handshake: {:?}, TX: {}, RX: {}, Loss: {:.1}%, RTT: {:?}ms", handshake_age, tx_bytes, rx_bytes, loss * 100.0, rtt ); ``` -------------------------------- ### DeviceConfig Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-device.md Configuration for device creation, including thread count, socket usage, and platform-specific options. ```APIDOC ## DeviceConfig Configuration for device creation. ### Fields - **n_threads** (usize) - Default: 4 - Number of worker threads for packet processing. - **use_connected_socket** (bool) - Default: true - Use connected UDP socket for better performance (platform-dependent). - **use_multi_queue** (bool) - Default: true - Enable multi-queue TUN for per-thread queue (Linux only). - **uapi_fd** (i32) - Default: -1 - Pre-opened file descriptor for uAPI socket (Linux only, -1 = auto). ### Example ```rust let config = DeviceConfig { n_threads: 8, use_connected_socket: true, use_multi_queue: true, uapi_fd: -1, }; ``` ``` -------------------------------- ### Default DeviceConfig Implementation Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/configuration.md Provides the default configuration for `DeviceConfig`, setting a default thread count and enabling connected socket usage. Linux-specific defaults are also included. ```rust impl Default for DeviceConfig { fn default() -> Self { DeviceConfig { n_threads: 4, use_connected_socket: true, #[cfg(target_os = "linux")] use_multi_queue: true, #[cfg(target_os = "linux")] uapi_fd: -1, } } } ``` -------------------------------- ### Retrieve Tunnel Statistics (C) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-ffi.md Retrieves tunnel statistics for monitoring and diagnostics. Use this function to get current metrics like handshake time, transmitted and received bytes, and estimated network loss and RTT. ```c typedef struct { int64_t time_since_last_handshake; // seconds (-1 if never) size_t tx_bytes; // bytes encrypted size_t rx_bytes; // bytes decrypted float estimated_loss; // 0.0 to 1.0 int32_t estimated_rtt; // milliseconds (-1 if unknown) uint8_t reserved[56]; // reserved for future fields } stats; ``` ```c stats st = wireguard_stats(tunnel); printf("Handshake: %ld sec ago, TX: %zu, RX: %zu, Loss: %.1f%%\n", st.time_since_last_handshake, st.tx_bytes, st.rx_bytes, st.estimated_loss * 100.0); ``` -------------------------------- ### Create RateLimiter Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/configuration.md Instantiate a RateLimiter to control DoS protection per peer. The limit specifies handshakes per second before sending cookie challenges. MAC1 keys are derived from peer public keys for independent limits. ```rust pub fn new(public_key: &x25519::PublicKey, limit: u64) -> Self ``` ```rust use boringtun::noise::RateLimiter; use std::sync::Arc; let rate_limiter = Arc::new(RateLimiter::new(&peer_public_key, 100)); let tunnel1 = Tunn::new(secret1, peer_pub1, None, None, 1, Some(Arc::clone(&rate_limiter))); let tunnel2 = Tunn::new(secret2, peer_pub2, None, None, 2, Some(Arc::clone(&rate_limiter))); ``` -------------------------------- ### Retrieve WireGuard Tunnel Statistics Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Use this native function to get statistics for a specific WireGuard tunnel. The returned object contains handshake timing, data transfer bytes, and estimated network quality metrics. ```java public static native WireGuardStats wireguardStats(long tunnel); ``` -------------------------------- ### C - FFI Tunnel Creation and Encryption Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/quick-start.md Shows how to use boringtun's C FFI to create a tunnel and encrypt an IP packet. Requires linking against libboringtun.so and including the FFI header. ```c #include #include // Include boringtun FFI header (boringtun/wireguard_ffi.h) // Link against libboringtun.so (or .dylib/.dll) extern wireguard_result wireguard_write( const Tunnel* tunnel, const uint8_t* src, uint32_t src_size, uint8_t* dst, uint32_t dst_size ); extern Tunnel* new_tunnel( const char* static_private, const char* server_static_public, const char* preshared_key, uint16_t keep_alive, uint32_t index ); extern void tunnel_free(Tunnel* tunnel); int main() { // Create tunnel with base64-encoded keys Tunnel* tunnel = new_tunnel( "WJlhX0DrLS26zBzpd9p+/ZzIqMlzG0+91scksKjwO2A=", "NJgcyYyJ7xfX+7M89Lq4/0Y5NWlDWJqnJWcQ8eG8DlY=", NULL, 25, 1 ); if (!tunnel) { fprintf(stderr, "Failed to create tunnel\n"); return 1; } // Encrypt packet uint8_t ip_packet[100]; uint8_t output[200]; wireguard_result res = wireguard_write(tunnel, ip_packet, sizeof(ip_packet), output, sizeof(output)); if (res.op == WRITE_TO_NETWORK) { printf("Sending %zu bytes\n", res.size); // sendto(sock, output, res.size, ...); } tunnel_free(tunnel); return 0; } ``` -------------------------------- ### Create New Tunn Instance Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-tunn.md Initializes a new Tunn instance for a peer connection. Configure optional parameters like preshared keys and keepalive intervals. If no rate limiter is provided, a default one is created. ```rust use boringtun::noise::Tunn; use boringtun::x25519::{PublicKey, StaticSecret}; use rand_core::OsRng; let my_secret = StaticSecret::random_from_rng(OsRng); let peer_public = PublicKey::from(&StaticSecret::random_from_rng(OsRng)); let tunnel = Tunn::new( my_secret, peer_public, None, // no preshared key Some(25), // keepalive every 25 seconds 1, // index 1 None, // use default rate limiter ); ``` -------------------------------- ### Configure BoringTun Logging Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-ffi.md Configures the global tracing output to a user-defined C function. This function should be called only once, as subsequent calls will fail. ```c void my_logger(const char* msg) { fprintf(stderr, "[BoringTun] %s\n", msg); } bool ok = set_logging_function(my_logger); if (!ok) printf("Logging already initialized\n"); ``` -------------------------------- ### Create a new WireGuard tunnel interface Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-device.md Use this constructor to create and initialize a new WireGuard tunnel interface. It requires a tunnel name and a DeviceConfig. Ensure you have the necessary permissions (e.g., CAP_NET_ADMIN on Linux) as it creates a TUN device and binds a UDP socket. ```rust use boringtun::device::{DeviceHandle, DeviceConfig}; let config = DeviceConfig::default(); let mut handle = DeviceHandle::new("wg0", config)?; // Device is now live, configure via wg CLI or API socket // ... // Later: handle.wait(); // Block until interface is shut down handle.clean(); // Remove socket files ``` -------------------------------- ### Build BoringTun Library Source: https://github.com/cloudflare/boringtun/blob/master/README.md Build only the BoringTun library without default features. Specify a target triple if needed for cross-compilation. ```bash cargo build --lib --no-default-features --release [--target $(TARGET_TRIPLE)] ``` -------------------------------- ### DeviceHandle::new Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-device.md Creates and initializes a new WireGuard tunnel interface with the specified name and configuration. ```APIDOC ## DeviceHandle::new ### Description Creates and initializes a new WireGuard tunnel interface. ### Signature ```rust pub fn new(name: &str, config: DeviceConfig) -> Result ``` ### Parameters #### Path Parameters - **name** (str) - Required - Tunnel interface name (e.g., "wg0" on Linux, "utun1" on macOS) - **config** (DeviceConfig) - Required - Configuration for thread count and socket options ### Response #### Success Response - **DeviceHandle** - A new, initialized WireGuard tunnel interface. - **Error** - An error if the tunnel creation fails. ### Errors - `Error::InvalidTunnelName` — name format invalid for platform - `Error::IoError` — socket creation failed - `Error::EventQueue` — event loop setup failed - Other platform-specific errors ### Effects - Creates TUN device (requires `CAP_NET_ADMIN` on Linux) - Binds UDP socket to random port - Spawns `n_threads` worker threads in background - Listens on `/var/run/wireguard/{name}.sock` for configuration commands ### Example ```rust use boringtun::device::{DeviceHandle, DeviceConfig}; let config = DeviceConfig::default(); let mut handle = DeviceHandle::new("wg0", config)?; // Device is now live, configure via wg CLI or API socket // ... // Later: handle.wait(); // Block until interface is shut down handle.clean(); // Remove socket files ``` ``` -------------------------------- ### Device-Level Rate Limiting with DeviceHandle Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-rate-limiter.md Illustrates how device-level rate limiting is automatically applied when using DeviceHandle. All peers managed by a single device share a common rate limiter, ensuring independent limits for separate interfaces. ```rust // Device-level rate limiting is applied automatically // All peers managed by this device share the limit let handle = DeviceHandle::new("wg0", config)?; ``` -------------------------------- ### Clean up temporary device files Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-device.md Use the `clean` method to remove temporary files, such as the socket and configuration files, that were created when the device was initialized. This should typically be called after `wait`. ```rust handle.wait(); handle.clean(); ``` -------------------------------- ### Enable Multi-Queue TUN for High Throughput (Linux) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/README.md Enable the multi-queue feature for the TUN device on Linux systems to enhance performance for high throughput. ```rust use_multi_queue: true ``` -------------------------------- ### Android VPN Service with BoringTun Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/quick-start.md This Kotlin code demonstrates a basic Android VpnService implementation using BoringTun. It covers loading the native library, creating a tunnel with WireGuard keys, allocating direct ByteBuffers for packet handling, and processing incoming IP packets for sending and receiving network data. ```kotlin class VpnService : VpnService() { private var tunnel: Long = 0 private lateinit var sendBuffer: ByteBuffer private lateinit var recvBuffer: ByteBuffer private lateinit var opBuffer: ByteBuffer override fun onCreate() { super.onCreate() // Load native library System.loadLibrary("boringtun") // Create tunnel with base64 keys tunnel = BoringTunJNI.newTunnel( "WJlhX0DrLS26zBzpd9p+/ZzIqMlzG0+91scksKjwO2A=", "NJgcyYyJ7xfX+7M89Lq4/0Y5NWlDWJqnJWcQ8eG8DlY=", null, 25, 1 ) if (tunnel == 0L) { throw IllegalStateException("Failed to create tunnel") } // Allocate buffers (must be direct) sendBuffer = ByteBuffer.allocateDirect(1600) recvBuffer = ByteBuffer.allocateDirect(2048) opBuffer = ByteBuffer.allocateDirect(4) } fun handleTunPacket(ipPacket: ByteArray) { sendBuffer.clear() opBuffer.clear() val size = BoringTunJNI.wireguardWrite( tunnel, ipPacket, ipPacket.size, sendBuffer, sendBuffer.capacity(), opBuffer ) if (size > 0) { val encrypted = ByteArray(size) sendBuffer.get(0, encrypted) sendToNetwork(encrypted) } } fun handleNetworkPacket(datagram: ByteArray) { recvBuffer.clear() opBuffer.clear() var src = datagram while (true) { val size = BoringTunJNI.wireguardRead( tunnel, src, src.size, recvBuffer, recvBuffer.capacity(), opBuffer ) when (opBuffer.int) { 4, 6 -> { // IPv4 or IPv6 val packet = ByteArray(size) recvBuffer.get(0, packet) writeTUN(packet) src = ByteArray(0) // Continue with empty } 1 -> { // WRITE_TO_NETWORK val packet = ByteArray(size) recvBuffer.get(0, packet) sendToNetwork(packet) src = ByteArray(0) } 0 -> break // DONE else -> break } } } private fun sendToNetwork(pkt: ByteArray) { // Send via UDP socket to peer endpoint } private fun writeTUN(pkt: ByteArray) { // Write to Android VPN interface } } ``` -------------------------------- ### Create New RateLimiter Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-rate-limiter.md Initializes a new RateLimiter for a specific peer's public key and sets the handshake attempt limit per second. A limit of 100 is recommended for DoS protection. Requires `Arc` for sharing across multiple `Tunn` instances. ```rust use boringtun::noise::RateLimiter; use std::sync::Arc; let rate_limiter = Arc::new(RateLimiter::new(&peer_public_key, 100)); ``` -------------------------------- ### C/C++ Linking with BoringTun Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/quick-start.md Compile your C/C++ application and link against the BoringTun Rust library. Ensure correct include paths and library locations are specified. ```makefile LIBS = -L./target/release -lboringtun -ldl CFLAGS = -I./boringtun/src/ffi app: main.c gcc -o app main.c $(LIBS) $(CFLAGS) -Wl,-rpath,./target/release ``` -------------------------------- ### Generate Static Secret and PublicKey in Rust Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/types.md Demonstrates how to generate a static x25519 secret key using a random number generator and derive its corresponding public key. Ensure `rand_core::OsRng` is available for secure random number generation. ```rust use boringtun::x25519::{StaticSecret, PublicKey}; use rand_core::OsRng; let secret = StaticSecret::random_from_rng(OsRng); let public = PublicKey::from(&secret); ``` -------------------------------- ### FFI Bindings Header Source: https://github.com/cloudflare/boringtun/blob/master/README.md The C ABI bindings for the BoringTun library are defined in this header file. These can be used with C/C++, Swift, or C#. ```c #include "wireguard_ffi.h" ``` -------------------------------- ### Rust DeviceConfig Struct Definition Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-device.md Defines the configuration structure for creating a device. Includes settings for worker threads, connected sockets, and Linux-specific multi-queue and uAPI socket options. ```rust pub struct DeviceConfig { pub n_threads: usize, pub use_connected_socket: bool, #[cfg(target_os = "linux")] pub use_multi_queue: bool, #[cfg(target_os = "linux")] pub uapi_fd: i32, } ``` -------------------------------- ### Tunn with Default Rate Limiter Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-rate-limiter.md Instantiate a Tunn without providing a RateLimiter. Tunn will create a default limiter with a rate of 100 handshakes per second. ```rust let tunnel = Tunn::new( static_secret, peer_public, None, None, index, None, // Tunn creates limiter with default 100/sec ); ``` -------------------------------- ### x25519_key_to_base64 Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-ffi.md Encodes an x25519 key into a base64 null-terminated C string. ```APIDOC ## x25519_key_to_base64 ### Description Encodes a 32-byte x25519 key into a base64 null-terminated C string. ### Signature ```c const char* x25519_key_to_base64(x25519_key key) ``` ### Parameters - **key** (`x25519_key`): The 32-byte x25519 key to encode. ### Returns - `const char*`: A pointer to a dynamically allocated C string containing the base64 encoded key. This string must be freed using `x25519_key_to_str_free()`. ### Example (C) ```c x25519_key secret = x25519_secret_key(); const char* encoded = x25519_key_to_base64(secret); printf("Secret (base64): %s\n", encoded); x25519_key_to_str_free((char*)encoded); ``` ``` -------------------------------- ### Force Handshake with wireguard_force_handshake (C) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-ffi.md Immediately initiates a new handshake for rekeying purposes. The output buffer must be at least 148 bytes. ```c uint8_t pkt[150]; wireguard_result res = wireguard_force_handshake(tunnel, pkt, sizeof(pkt)); if (res.op == WRITE_TO_NETWORK) { sendto(udp_sock, pkt, res.size, 0, &peer_addr, sizeof(peer_addr)); } ``` -------------------------------- ### Android Build Configuration Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/quick-start.md Configure your Android project to use CMake for native builds, pointing to your CMakeLists.txt file. ```gradle android { externalNativeBuild { cmake { path "CMakeLists.txt" } } } ``` -------------------------------- ### Create a new tunnel object Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-ffi.md Use `new_tunnel` to create a tunnel. Keys must be base64-encoded 32-byte values. The `preshared_key` can be NULL if none is used. A non-NULL return value indicates success. ```c Tunnel* new_tunnel( const char* static_private, const char* server_static_public, const char* preshared_key, uint16_t keep_alive, uint32_t index ) ``` ```c Tunnel* tunnel = new_tunnel( "WJlhX0DrLS26zBzpd9p+/ZzIqMlzG0+91scksKjwO2A=", "NJgcyYyJ7xfX+7M89Lq4/0Y5NWlDWJqnJWcQ8eG8DlY=", NULL, 25, 1 ); if (!tunnel) { fprintf(stderr, "Failed to create tunnel\n"); return -1; } ``` -------------------------------- ### Generate X25519 Key in Rust, Use in C Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-ffi.md Demonstrates generating a base64 encoded X25519 static secret in Rust and then validating it in C. Ensure the key format matches expected base64 encoding. ```rust use boringtun::x25519::StaticSecret; use rand_core::OsRng; use base64::encode; let secret = StaticSecret::random_from_rng(OsRng); let base64_key = encode(secret.to_bytes()); println!("Key: {}", base64_key); ``` ```c const char* key_str = "WJlhX0DrLS26zBzpd9p+/ZzIqMlzG0+91scksKjwO2A="; if (check_base64_encoded_x25519_key(key_str)) { printf("Valid key\n"); } ``` -------------------------------- ### Set WireGuard Private Key Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/configuration.md This command sets the private key for a WireGuard interface using a generated key. Ensure you have write permissions for the interface. ```bash # Set key wg set wg0 private-key <(wg genkey) ``` -------------------------------- ### `format_handshake_initiation` Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-tunn.md Formats a new Noise handshake initiation message. Called when initiating a connection or re-keying. ```APIDOC ## `format_handshake_initiation` ### Description Formats a new Noise handshake initiation message (148 bytes). Called when initiating a connection or re-keying. ### Method `format_handshake_initiation` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **dst** (&'a mut [u8]) - Required - Output buffer, must be at least 148 bytes - **force_resend** (bool) - Required - If true, send new handshake even if one is in progress ### Response #### Success Response (`TunnResult<'a>`) - `WriteToNetwork(&'a mut [u8])` — handshake initiation packet ready to send - `Done` — handshake already in progress and force_resend is false - `Err(WireGuardError)` — buffer too small or other error ### Example ```rust let mut handshake_pkt = [0u8; 148]; match tunnel.format_handshake_initiation(&mut handshake_pkt, false) { TunnResult::WriteToNetwork(pkt) => { send_to_network(pkt); } TunnResult::Done => println!("Handshake in progress"), TunnResult::Err(e) => eprintln!("Failed: {:?}", e), _ => {} } ``` ``` -------------------------------- ### Handle Socket Errors During Device Creation Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/errors.md Handle `Socket` errors that occur when setting up a UDP socket for a device. This can be due to port conflicts, permission issues, or firewall restrictions. ```rust match DeviceHandle::new("wg0", config) { Err(Error::Socket(e)) => { eprintln!("Socket error: {}", e); // Check permissions, firewall, or port availability } _ => {} } ``` -------------------------------- ### Create New Tunnel (Java) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Creates a new tunnel instance. Requires base64-encoded keys and specifies keepalive intervals and peer index. Returns an opaque handle or 0 on error. ```java public static native long newTunnel( String privateKey, String publicKey, String presharedKey, short keepAlive, int index ); ``` -------------------------------- ### newTunnel(privateKey, publicKey, presharedKey, keepAlive, index) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Creates a new WireGuard tunnel with the specified configuration. ```APIDOC ## newTunnel(privateKey, publicKey, presharedKey, keepAlive, index) ### Description Creates a new WireGuard tunnel. ### Method `external fun newTunnel( privateKey: String, publicKey: String, presharedKey: String?, keepAlive: Short, index: Int ): Long` ### Parameters #### Path Parameters - **privateKey** (String) - The tunnel's private key. - **publicKey** (String) - The peer's public key. - **presharedKey** (String?) - Optional preshared key for enhanced security. - **keepAlive** (Short) - Interval in seconds for keep-alive packets. - **index** (Int) - An index to identify the tunnel. ### Response #### Success Response - **Long** - A handle representing the newly created tunnel. ``` -------------------------------- ### newTunnel Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Creates a new WireGuard tunnel instance. It initializes the tunnel with provided keys and configuration, returning an opaque handle for subsequent operations. Returns 0 on error. ```APIDOC ## newTunnel ### Description Creates a new tunnel. All keys are base64-encoded strings. ### Method Signature ```java public static native long newTunnel( String privateKey, String publicKey, String presharedKey, short keepAlive, int index ); ``` ### Parameters - **privateKey** (String) - Base64-encoded 32-byte local secret key - **publicKey** (String) - Base64-encoded 32-byte peer public key - **presharedKey** (String) - Base64-encoded 32-byte symmetric key, or null for none - **keepAlive** (short) - Keepalive interval in seconds (0 to disable) - **index** (int) - Unique peer index (0-255) ### Returns - `long` — opaque tunnel handle (0 on error) ``` -------------------------------- ### HandshakeInit Struct for WireGuard Handshake Initiation Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/types.md Represents the first message in a WireGuard handshake. Contains the sender's index, ephemeral public key, static key, and timestamp, with some fields sent in cleartext. ```rust pub struct HandshakeInit<'a> { sender_idx: u32, unencrypted_ephemeral: &'a [u8; 32], encrypted_static: &'a [u8], encrypted_timestamp: &'a [u8], } ``` -------------------------------- ### Encode Key to Base64 String (Java) Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-jni.md Encodes a 32-byte x25519 key into a base64 string. Returns null on error. ```java public static native String x25519KeyToBase64(byte[] key); ``` -------------------------------- ### Tunn with Explicit Rate Limiter Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-rate-limiter.md Instantiate a Tunn with an explicitly created RateLimiter. The rate limiter is configured with a public key and a limit of 100 handshakes per second. ```rust let tunnel = Tunn::new( static_secret, peer_public, None, None, index, Some(Arc::new(RateLimiter::new(&peer_public, 100))), ); ``` -------------------------------- ### Handle Cookie Challenges Under Load Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/errors.md In the event loop, recognize and handle incoming cookie challenges, which are sent by the tunnel under denial-of-service load. This is expected behavior. ```rust // In event loop: match tunnel.decapsulate(src_addr, &pkt, &mut dst) { TunnResult::WriteToNetwork(cookie) if pkt_size == 148 => { // This is a cookie reply; send it back send_to_network(cookie); } // ... other cases } ``` -------------------------------- ### Configure Boringtun via API Socket Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/quick-start.md This bash script configures Boringtun using its Unix socket, allowing programmatic control over interface settings, peers, and network configurations. ```bash #!/bin/bash # Configure via Unix socket (same as wg tool) { echo "set=1" echo "private_key=$(wg genkey | base64)" echo "listen_port=51820" echo "public_key=NJgcyYyJ7xfX+7M89Lq4/0Y5NWlDWJqnJWcQ8eG8DlY=" echo "endpoint=203.0.113.1:51820" echo "allowed_ip=10.0.0.2/32" echo "allowed_ip=10.0.1.0/24" echo "persistent_keepalive_interval=25" echo "preshared_key=$(base64 -w0 < /dev/urandom | head -c 44)" } | socat - UNIX-CONNECT:/var/run/wireguard/wg0.sock ``` -------------------------------- ### Custom Rate Limit Per Endpoint Type Source: https://github.com/cloudflare/boringtun/blob/master/_autodocs/api-reference-rate-limiter.md Demonstrates setting different rate limits for different peers by creating separate RateLimiter instances for each. This is useful for differentiating between types of clients or partners. ```rust use boringtun::noise::{Tunn, RateLimiter}; use std::sync::Arc; // Different limits for different peers let business_partner = Arc::new(RateLimiter::new(&business_pub_key, 50)); // Lower limit let mobile_client = Arc::new(RateLimiter::new(&mobile_pub_key, 200)); // Higher limit let tunnel_business = Tunn::new(secret1, business_pub_key, None, None, 1, Some(business_partner)); let tunnel_mobile = Tunn::new(secret2, mobile_pub_key, None, None, 2, Some(mobile_client)); ```