ip-discovery
Detect your public IP address using DNS, STUN, or HTTP — with built-in fallback across trusted providers.
Why ip-discovery?
Most machines don't know their own public IP. If you're behind NAT, a load balancer, or a cloud VPC, your OS only sees a private address like 10.x.x.x or 192.168.x.x. This library solves that — reliably, fast, and with zero configuration.
Common use cases:
-
Self-hosted servers with dynamic IPs — Your home server or office NAS gets a new IP every time the ISP rotates it. Use
ip-discoveryto detect the change and update your DNS record (dynamic DNS), notify clients, or refresh firewall rules — automatically. -
WebRTC / P2P connection setup — When building WebRTC applications, you need your public IP to generate SDP offers/answers and ICE candidates.
ip-discoveryuses the same STUN protocol that browsers use, giving you the public-facing address for direct peer connections without relying on a browser environment. -
NAT traversal & hole punching — Building a peer-to-peer system (game server, file sharing, VPN)? You need to know your public IP and the type of NAT you're behind before you can punch through it.
-
Server self-registration — Microservices or edge nodes that spin up in dynamic cloud environments (auto-scaling groups, spot instances) and need to register their public address with a service registry or coordination layer.
-
Security & audit logging — Record the public IP of the machine at the time of an event for compliance or forensics. Use
Consensusstrategy to cross-verify across multiple providers and guard against a single provider being spoofed. -
CLI diagnostics — Quickly check "what IP does the internet see me as?" during debugging, without opening a browser or remembering which
curlendpoint to hit.
Why not just curl an IP-echo service?
Calling a single HTTP endpoint works for a quick manual check, but falls short in production:
| HTTP IP-echo services | ip-discovery |
|
|---|---|---|
| Single point of failure | If that one service is down or slow, you get nothing | Automatic fallback across 9 providers and 3 protocols |
| Rate limiting | Many free services aggressively throttle or block automated requests | DNS and STUN are lightweight UDP queries — far less likely to be throttled than HTTP APIs |
| Latency | Full TCP + TLS handshake every time (~200–500ms) | DNS & STUN use raw UDP — typically <50ms, 2–3× faster |
| Result verification | You trust one provider blindly — it could return stale data or be spoofed | Consensus strategy cross-checks across multiple providers |
| IPv6 support | Depends on the endpoint; many only return IPv4 | First-class IPv4 and IPv6 support across DNS and STUN |
| Dependency in code | Needs shell-out or an HTTP client just to get an IP | Embeddable Rust library, no HTTP dependency needed (DNS + STUN only) |
| Offline-friendly | Requires an HTTP-capable environment / TLS stack | DNS and STUN work in minimal environments with just UDP |
💡 Note: Some strict enterprise networks block outbound UDP entirely. In those environments, DNS and STUN won't work. Enable the
httpfeature to add HTTP-based providers as a fallback — the library will automatically try them if UDP-based providers fail.
CLI Tool — ipd
A command-line tool powered by this library. Get your public IP in one command:
Install
Homebrew (macOS):
Shell (macOS & Linux):
|
PowerShell (Windows):
powershell -ExecutionPolicy Bypass -c "irm https://github.com/zer0horizon/ip-discovery/releases/latest/download/ipd-installer.ps1 | iex"
Cargo:
CLI Usage
Library
Features
- DNS and STUN via raw UDP sockets (zero network library dependencies)
- HTTP/HTTPS via reqwest (optional)
- Built-in providers from Google, Cloudflare, AWS, and OpenDNS
- IPv4 and IPv6
- Sequential fallback, race, or consensus strategies
- Custom providers via the
Providertrait - Async, built on tokio
Usage
Add to your Cargo.toml:
[]
= "0.2"
= { = "1", = ["full"] }
Then:
use get_ip;
async
You can also request a specific IP version:
use ;
let v4 = get_ipv4.await?;
let v6 = get_ipv6.await?;
Configuration
The defaults (Cloudflare STUN → Cloudflare DNS → Google STUN/DNS → OpenDNS; 10s timeout) work well for most cases. If you need more control:
use ;
use Duration;
// DNS only, race all DNS providers
let config = builder
.protocols
.strategy
.timeout
.build;
let result = get_ip_with.await?;
// Pick specific providers
let config = builder
.providers
.build;
// Consensus — require at least 2 providers to agree
let config = builder
.strategy
.build;
Strategies
| Strategy | Description |
|---|---|
First (default) |
Try providers in order, return first success |
Race |
Query all concurrently, return fastest |
Consensus { min_agree } |
Require N providers to agree on the same IP |
Providers
All built-in providers are from tier-1 infrastructure companies:
| Provider | Protocol | IPv4 | IPv6 |
|---|---|---|---|
Google STUN (stun.l.google.com) |
STUN | ✅ | ✅ |
Google STUN 1 (stun1.l.google.com) |
STUN | ✅ | ✅ |
Google STUN 2 (stun2.l.google.com) |
STUN | ✅ | ✅ |
Cloudflare STUN (stun.cloudflare.com) |
STUN | ✅ | ✅ |
Google DNS (o-o.myaddr.l.google.com) |
DNS | ✅ | ✅ |
Cloudflare DNS (whoami.cloudflare) |
DNS | ✅ | ✅ |
OpenDNS (myip.opendns.com) |
DNS | ✅ | ❌ |
Cloudflare HTTP (1.1.1.1/cdn-cgi/trace) |
HTTP | ✅ | ❌ |
AWS (checkip.amazonaws.com) |
HTTP | ✅ | ❌ |
Cargo Features
| Feature | Default | Description |
|---|---|---|
dns |
✅ | DNS detection (raw UDP, no extra deps) |
stun |
✅ | STUN detection (raw UDP, no extra deps) |
http |
❌ | HTTP detection (pulls in reqwest + rustls) |
all |
❌ | Enable all protocols (dns + stun + http) |
native-tls |
❌ | Use OS-native TLS instead of rustls (requires http) |
By default, only DNS and STUN are enabled — zero network library dependencies, fast compile times. To also use HTTP providers:
= { = "0.2", = ["http"] }
Or enable everything:
= { = "0.2", = ["all"] }
Performance
STUN and DNS use raw UDP — no TLS handshake — so they're typically 2–3× faster than HTTP. Default provider order prioritizes UDP-based protocols with IPv4 + IPv6 support first, then falls back to IPv4-only HTTP providers.
💡 Tip: Latency varies significantly by region and network environment. Run the benchmark on your own infrastructure to find the optimal provider and strategy for your use case.
# Run the benchmark to find the best config for your network
Logging
Uses tracing for diagnostics:
fmt
.with_env_filter
.init;
Examples
MSRV
Rust 1.85 or later.
License
Licensed under either of Apache License, Version 2.0 or MIT License, at your option.