Session Traversal Utilities for NAT (STUN) is a protocol to discover a client's public ip address and determine any restrictions in the client's router/firewall that would prevent a direct peer connection. This implementation only focuses on the Binding Request and Binding Response portion.
This STUN server receives Binding Request messages, validates them, and replies with a Binding Response message. This STUN client sends Binding Request messages and cosumes/decodes a Binding Response from the server.
This is primarily a teaching tool for Rust systems programming (UDP, header encoding/decoding, ...etc.) in the WebRTC domain.
To run the Criterion benchmarks:
cargo bench
send and receive binding request and response
time: [180.04 ns 180.14 ns 180.22 ns]
change: [-0.0304% +0.1749% +0.4260%] (p = 0.15 > 0.05)
No change in performance detected.
Found 9 outliers among 100 measurements (9.00%)
5 (5.00%) low severe
4 (4.00%) low mild
To view the HTML reports, navigate to target/criterion/send-and-receive-binding-request-and-response/report/index.html.
Copy the .env.example file to .env
cp .env.example .env
Now update the values in .env as needed.
Running the server will listen for incoming UDP packets and accept Binding Request messages:
RUST_LOG=info cargo run --example server
INFO server > Started stun server on 0.0.0.0:8082
Running the client will instantly send a Binding Request message (UDP packet):
RUST_LOG=info cargo run --example client
INFO client > Started stun client on 0.0.0.0:8081, connected to a stun server on 0.0.0.0:8082
INFO client > sending binding request to the server: Message { class: Request, method: Binding, transaction_id: TransactionId([216, 15, 139, 140, 54, 166, 55, 187, 63, 53, 116, 133]), attributes: [] }
To run the client and server at the same time time, where a binding request is sent and a binding response is received:
RUST_LOG=info cargo run --example client_server
INFO client_server::server > Started stun server on 0.0.0.0:8082
INFO client_server::client > Started stun client on 0.0.0.0:8081, connected to a stun server on 0.0.0.0:8082
INFO client_server::client > sending binding request to the server: Message { class: Request, method: Binding, transaction_id: TransactionId([208, 75, 17, 165, 14, 198, 154, 57, 125, 86, 149, 161]), attributes: [] }
INFO client_server::server > received 20 bytes from 127.0.0.1:8081: Message { class: Request, method: Binding, transaction_id: TransactionId([208, 75, 17, 165, 14, 198, 154, 57, 125, 86, 149, 161]), attributes: [] }
INFO client_server::server > sending message to client: Message { class: SuccessResponse, method: Binding, transaction_id: TransactionId([185, 55, 136, 17, 149, 163, 157, 110, 142, 158, 190, 150]), attributes: [XorMappedAddress(Address { address: [127, 0, 0, 1], port: 8081, ip_kind: IPv4 })] }
INFO client_server::client > received 20 bytes from 127.0.0.1:8082: Message { class: SuccessResponse, method: Binding, transaction_id: TransactionId([185, 55, 136, 17, 149, 163, 157, 110, 142, 158, 190, 150]), attributes: [] }