A lightweight DNS server that resolves any IP address embedded in the hostname — with automatic TLS certificates and DNS over HTTPS.
dig 127-0-0-1.anyip.dev +short
# 127.0.0.1
dig myapp-192-168-1-100.anyip.dev +short
# 192.168.1.100
dig preview.127-0-0-1.anyip.dev +short
# 127.0.0.1 (nested subdomain — also works!)
curl https://myapp-127-0-0-1.anyip.dev # ✅ valid TLS, no browser warnings
Built for development teams who need HTTPS on local/staging services without touching /etc/hosts or managing certificates.
Modern browsers require secure contexts for many Web APIs — camera (getUserMedia), clipboard, notifications, service workers, WebRTC, etc. On local networks, this means you either:
- Wrestle with self-signed certificates and browser exceptions on every device
- Edit
/etc/hostson every machine - Give up and test on
localhostonly
AnyIP solves all three: any developer can instantly get a valid HTTPS hostname for any IP address, zero config.
Developer's browser AnyIP server (public)
│ │
├─ DNS query: myapp-192-168-1-5.anyip.dev ──►│
│◄── A record: 192.168.1.5 ──────────────────┤
│ │
├─ TLS handshake ───────────────────────────►│ (local service on 192.168.1.5,
│ cert: *.anyip.dev (Let's Encrypt) │ using downloaded wildcard cert)
│◄── valid certificate ──────────────────────┤
│ │
└─ secure context ✅ │
Three components work together:
- DNS server — resolves
<name>-<ip>.yourdomain(and<prefix>.<ip>.yourdomain) to the embedded IP address - ACME DNS-01 responder — automatically answers Let's Encrypt challenges for root and subdomain wildcard certificates
- Certificate distribution — serves certs (including private keys) over HTTPS for developers to download
Security note: The private key is intentionally public. This provides the same security as plain HTTP — it satisfies the browser's secure context requirement, not actual transport security. See Security for details.
Using the public anyip.dev service — no setup required.
Any <ip>.anyip.dev hostname resolves to the embedded IP address. Works immediately, no configuration needed:
ping myapp-192-168-1-5.anyip.dev # → 192.168.1.5
curl http://127-0-0-1.anyip.dev:3000 # → connects to localhost:3000See Hostname Format for IPv4, IPv6, and nested subdomain rules.
Download the wildcard certificate to enable HTTPS on your local dev server:
curl -o fullchain.pem https://anyip.dev/cert/fullchain.pem
curl -o privkey.pem https://anyip.dev/cert/privkey.pemThen use it in your framework:
# Node.js / Vite / Docusaurus (use RSA — webpack requires RSA keys)
HTTPS=true SSL_CRT_FILE=fullchain.pem SSL_KEY_FILE=privkey.pem yarn start
# Vite
vite --https --host \
--ssl-cert fullchain.pem \
--ssl-key privkey.pem
# Go
http.ListenAndServeTLS(":443", "fullchain.pem", "privkey.pem", handler)
# Nginx
ssl_certificate fullchain.pem;
ssl_certificate_key privkey.pem;This cert covers *.anyip.dev — any single-level subdomain like myapp-192-168-1-5.anyip.dev.
For nested subdomains like user1.127-0-0-1.anyip.dev (useful for per-user preview domains), request a per-IP wildcard cert. ECDSA is always issued; RSA is also issued when -cert-rsa-compat is enabled:
# Request cert issuance (first time takes ~10-30s)
curl -X POST https://anyip.dev/cert/sub/127-0-0-1
# Download ECDSA (default)
curl -o fullchain.pem https://anyip.dev/cert/sub/127-0-0-1/fullchain.pem
curl -o privkey.pem https://anyip.dev/cert/sub/127-0-0-1/privkey.pem
# Download RSA (for Node.js/webpack)
curl -o fullchain.pem https://anyip.dev/cert/sub/127-0-0-1/fullchain-rsa.pem
curl -o privkey.pem https://anyip.dev/cert/sub/127-0-0-1/privkey-rsa.pemNow all *.127-0-0-1.anyip.dev hostnames have valid HTTPS. See Wildcard Certificate Coverage for details.
Use AnyIP as an encrypted DNS resolver in your browser:
- Chrome/Edge: Settings → Security → Use secure DNS →
https://anyip.dev/dns-query - Firefox: Settings → DNS over HTTPS →
https://anyip.dev/dns-query
Or query directly:
curl "https://anyip.dev/dns-query?name=127-0-0-1.anyip.dev&type=A"
# {"Status":0,"Answer":[{"name":"127-0-0-1.anyip.dev.","type":1,"TTL":259200,"data":"127.0.0.1"}]}All names are single-label subdomains (to stay within *.yourdomain wildcard coverage):
Replace dots with dashes. Prefix anything you want:
| Hostname | Resolves to |
|---|---|
127-0-0-1.anyip.dev |
127.0.0.1 |
myapp-192-168-1-50.anyip.dev |
192.168.1.50 |
api-10-0-0-1.anyip.dev |
10.0.0.1 |
Rule: the rightmost 4 dash-separated decimal octets are parsed as IPv4. Everything before is ignored (used as a label for your service).
Replace colons with dashes. :: becomes --:
| Hostname | Resolves to |
|---|---|
2001-db8--1.anyip.dev |
2001:db8::1 |
fe80--1.anyip.dev |
fe80::1 |
myapp---1.anyip.dev |
::1 |
AnyIP also supports multi-level subdomains — the IP is extracted from the last label before the base domain:
| Hostname | Resolves to |
|---|---|
preview.127-0-0-1.anyip.dev |
127.0.0.1 |
user1.192-168-1-5.anyip.dev |
192.168.1.5 |
app.staging.10-0-0-1.anyip.dev |
10.0.0.1 |
This is useful for dev tools that create per-user or per-branch preview domains (e.g., user1.127-0-0-1.anyip.dev, user2.127-0-0-1.anyip.dev).
Let's Encrypt wildcard certs cover one level of subdomain only:
| Hostname | Covered by *.anyip.dev? |
Covered by *.127-0-0-1.anyip.dev? |
|---|---|---|
myapp-127-0-0-1.anyip.dev |
✅ | — |
user1.127-0-0-1.anyip.dev |
❌ | ✅ |
For single-label subdomains, the root wildcard cert (*.anyip.dev) works. For nested subdomains, request a per-IP subdomain cert via the Subdomain Certificate API.
- Embedded IP resolution —
<anything>-<ip>.<domain>→ IP address - Nested subdomains —
<name>.<ip>.<domain>also resolves, for per-user preview domains - IPv4 and IPv6 — full dual-stack support
- Automatic TLS certificates — Let's Encrypt wildcard via DNS-01, auto-renewal; ECDSA by default
- RSA certificate support — opt-in (
-cert-rsa-compat) for Node.js/webpack dev server compatibility - Subdomain certificates — on-demand
*.<ip>.<domain>certs for nested subdomain HTTPS - Certificate distribution — download endpoint for dev teams
- DNS over HTTPS (DoH) — encrypted DNS via
GETandPOST(RFC 8484) - Standard DNS — UDP and TCP on port 53
- ACME DNS-01 responder — built-in, no external certbot plugin needed
- Long TTL — 72-hour TTL for static IP mappings
- Single binary — zero dependencies, cross-platform
Deploy your own AnyIP instance.
- A domain (e.g.,
anyip.dev) with NS records pointing to your server - A server with a public IP and ports 53 (DNS) + 443 (HTTPS) open
- Go 1.24+ (to build) or Docker
At your domain registrar, create these records:
anyip.dev. NS ns1.anyip.dev.
anyip.dev. NS ns2.anyip.dev.
ns1.anyip.dev. A <your-server-ip>
ns2.anyip.dev. A <your-server-ip>
Docker (recommended):
cp .env.example .env
# Edit .env — set ANYIP_DOMAIN and ANYIP_ACME_EMAIL
docker run -d --name anyip \
--env-file .env \
-p 53:53/udp -p 53:53/tcp -p 443:443 \
-v anyip-certs:/certs \
ghcr.io/taptap/anyip:latestFrom source:
cp .env.example .env
# Edit .env
go build -o bin/anyip ./src
sudo bin/anyipConfiguration is loaded from .env file, environment variables, or CLI flags (in that order of precedence: flags > env > .env file).
On first run, AnyIP will:
- Start the DNS server on port 53
- Request a wildcard certificate from Let's Encrypt via DNS-01
- Start the HTTPS server on port 443 (DoH + cert distribution)
| Flag | Env | Default | Description |
|---|---|---|---|
-domain |
ANYIP_DOMAIN |
anyip.dev |
Base domain |
-domain-ip |
ANYIP_DOMAIN_IP |
IP address for bare domain (e.g., server IP) | |
-dns-addr |
ANYIP_DNS_ADDR |
:53 |
DNS listen address (UDP+TCP) |
-doh-addr |
ANYIP_DOH_ADDR |
:443 |
DoH + cert distribution (HTTPS) |
-doh-path |
ANYIP_DOH_PATH |
/dns-query |
DoH endpoint path |
-acme-email |
ANYIP_ACME_EMAIL |
Email for Let's Encrypt registration | |
-acme-staging |
ANYIP_ACME_STAGING |
false |
Use Let's Encrypt staging (for testing) |
-cert-dir |
ANYIP_CERT_DIR |
./certs |
Certificate storage directory |
-ttl |
ANYIP_TTL |
259200 |
DNS response TTL in seconds (72h) |
-only-private |
ANYIP_ONLY_PRIVATE |
false |
Only resolve private/reserved IPs |
-cert-rsa-compat |
ANYIP_CERT_RSA_COMPAT |
false |
Also issue RSA certificates alongside ECDSA (for Node.js/webpack compatibility) |
-cert-subs |
ANYIP_CERT_SUBS |
Allowed IP labels/CIDRs for subdomain certs (comma-separated; e.g. 127-0-0-1, 10.0.0.0/8, private, or all) |
|
-cname |
ANYIP_CNAME |
Static CNAME records (label=target,..., e.g. www=taptap.github.io) |
|
-verbose |
ANYIP_VERBOSE |
false |
Verbose logging |
| Endpoint | Description |
|---|---|
GET /cert/fullchain.pem |
ECDSA certificate chain |
GET /cert/privkey.pem |
ECDSA private key |
GET /cert/info |
ECDSA certificate metadata (JSON) |
GET /cert/fullchain-rsa.pem |
RSA certificate chain (requires -cert-rsa-compat) |
GET /cert/privkey-rsa.pem |
RSA private key (requires -cert-rsa-compat) |
GET /cert/info-rsa |
RSA certificate metadata (JSON) (requires -cert-rsa-compat) |
RSA certificates are opt-in (-cert-rsa-compat / ANYIP_CERT_RSA_COMPAT=true). Use them when your tooling requires RSA — Docusaurus validates certificates via crypto.publicEncrypt which only supports RSA keys, causing ERR_OSSL_EVP_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE with ECDSA certs.
On-demand wildcard certificates for nested subdomains (e.g., *.127-0-0-1.anyip.dev). A POST always issues an ECDSA cert; RSA is also issued when -cert-rsa-compat is enabled.
| Endpoint | Description |
|---|---|
POST /cert/sub/{label} |
Issue cert(s) (~10-30s, returns cert info) |
GET /cert/sub/{label}/fullchain.pem |
ECDSA certificate chain |
GET /cert/sub/{label}/privkey.pem |
ECDSA private key |
GET /cert/sub/{label}/info |
ECDSA certificate metadata (JSON) |
GET /cert/sub/{label}/fullchain-rsa.pem |
RSA certificate chain (requires -cert-rsa-compat) |
GET /cert/sub/{label}/privkey-rsa.pem |
RSA private key (requires -cert-rsa-compat) |
GET /cert/sub/{label}/info-rsa |
RSA certificate metadata (JSON) (requires -cert-rsa-compat) |
The {label} must be a valid IP pattern (e.g., 127-0-0-1) and allowed by the ANYIP_CERT_SUBS policy (exact label, CIDR, private, or all). Requests for disallowed labels return 403.
Example: request and use a subdomain cert
# Request cert (first time takes ~10-30s for ACME; issues both ECDSA and RSA)
curl -X POST https://anyip.dev/cert/sub/127-0-0-1
# {"domains":["127-0-0-1.anyip.dev","*.127-0-0-1.anyip.dev"],...}
# Download ECDSA cert + key (Go, Nginx, etc.)
curl -o cert.pem https://anyip.dev/cert/sub/127-0-0-1/fullchain.pem
curl -o key.pem https://anyip.dev/cert/sub/127-0-0-1/privkey.pem
# Download RSA cert + key (Node.js / webpack / Docusaurus)
curl -o cert.pem https://anyip.dev/cert/sub/127-0-0-1/fullchain-rsa.pem
curl -o key.pem https://anyip.dev/cert/sub/127-0-0-1/privkey-rsa.pem
# Use in your dev server — all *.127-0-0-1.anyip.dev names work
node server.js --cert cert.pem --key key.pem --host user1.127-0-0-1.anyip.devRate limit: Let's Encrypt allows 50 certificates per registered domain per week. Use
ANYIP_CERT_SUBSto control which IPs can request certs: exact labels (127-0-0-1), CIDRs (10.0.0.0/8),privatefor all private/reserved IPs, orallfor any IP.
RFC 8484 compatible endpoint at /dns-query.
# JSON format (GET)
curl "https://anyip.dev/dns-query?name=127-0-0-1.anyip.dev&type=A"
# Wire format (POST)
curl "https://anyip.dev/dns-query" \
-H "Content-Type: application/dns-message" \
--data-binary @query.bin# Build locally
docker build -t anyip .
# Run with .env file
docker run -d --name anyip \
--env-file .env \
-p 53:53/udp -p 53:53/tcp -p 443:443 \
-v anyip-certs:/certs \
anyip
# Or use the published image
docker run -d --name anyip \
--env-file .env \
-p 53:53/udp -p 53:53/tcp -p 443:443 \
-v anyip-certs:/certs \
ghcr.io/taptap/anyip:latest ┌──────────────────────────────────────────┐
│ AnyIP Server │
│ │
DNS :53 ───────►│ DNS Handler │
(UDP/TCP) │ ├─ IP queries → parse & respond │
│ ├─ _acme-challenge.* → TXT record │
│ └─ SOA/NS → authority records │
│ │
HTTPS :443 ─────►│ HTTPS Server (SNI-based cert selection) │
│ ├─ /dns-query → DoH (RFC 8484) │
│ ├─ /cert/* → root cert download │
│ ├─ /cert/sub/* → subdomain certs │
│ └─ / → info page │
│ │
│ ACME Manager │
│ ├─ root wildcard cert (*.anyip.dev) │
│ ├─ subdomain certs (*.{ip}.anyip.dev) │
│ ├─ DNS-01 challenge responder │
│ └─ auto-renewal (every 12h check) │
└──────────────────────────────────────────┘
The wildcard private key is intentionally public. This is by design.
AnyIP solves the browser secure context problem — not transport security. The threat model:
| Scenario | Security level |
|---|---|
Plain HTTP (http://192.168.1.5) |
❌ No encryption, no secure context |
AnyIP (https://myapp-192-168-1-5.anyip.dev) |
|
Private cert (https://myapp.internal) |
✅ Full TLS security |
When AnyIP is the right choice:
- Development and testing environments
- Local network services that need
getUserMedia, clipboard, service workers, etc. - Staging deployments where convenience > security
When it's NOT:
- Production with sensitive data
- Environments where MITM attacks are a real threat
To prevent abuse (e.g., phishing with public IP certs), use -only-private:
anyip -domain anyip.dev -only-privateThis restricts resolution to private/reserved addresses only:
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16(RFC 1918)127.0.0.0/8(loopback)100.64.0.0/10(RFC 6598 CGNAT, e.g. Tailscale)169.254.0.0/16(link-local)192.0.2.0/24,198.51.100.0/24,203.0.113.0/24(RFC 5737 documentation)198.18.0.0/15(RFC 2544 benchmarking)fc00::/7(IPv6 ULA),fe80::/10(link-local),::1(loopback),2001:db8::/32(RFC 3849 documentation)
- Go — single binary, excellent performance, easy cross-compilation
- miekg/dns — the de facto Go DNS library (8.6k+ ★), used by CoreDNS and Caddy
- golang.org/x/crypto/acme — Go standard ACME client for Let's Encrypt
- net/http — standard library for DoH + cert distribution
| AnyIP | sslip.io / nip.io | localtls | |
|---|---|---|---|
| IP-in-hostname DNS | ✅ | ✅ | ✅ |
| Nested subdomains | ✅ | ❌ | ❌ |
| Auto TLS certs | ✅ | ❌ | ✅ |
| Subdomain wildcard certs | ✅ | ❌ | ❌ |
| Cert distribution API | ✅ | ❌ | ✅ |
| DNS over HTTPS | ✅ | ❌ | ❌ |
| IPv6 | ✅ | ✅ | ✅ |
| Private IP restriction | ✅ | ❌ | ✅ |
| Language | Go | Go | Python |
| Performance | High | High | Low |
| Maintained | ✅ | ✅ | ❌ (2023) |
- Local development — HTTPS for camera, clipboard, service workers on
192.168.x.x - Preview domains — per-user/per-branch previews like
user1.127-0-0-1.anyip.devwith subdomain wildcard certs - Game development — test WebRTC/WebGL features requiring secure context (TapTap Maker)
- Mobile testing — access dev server from phone with valid HTTPS
- CI/CD — deterministic DNS without external dependencies
- Staging — give every service a real HTTPS hostname
MIT