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 benchsend 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 mildTo 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 .envNow 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 serverINFO server > Started stun server on 0.0.0.0:8082Running the client will instantly send a Binding Request message (UDP packet):
RUST_LOG=info cargo run --example clientINFO 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_serverINFO 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: [] }