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.
anyip.dev is the primary public service, supporting both
public and private IP addresses. The general usage examples in this README use
anyip.dev.
| Service | DNS policy for IP-encoded hostnames |
|---|---|
| anyip.dev | Resolves public and private IP addresses |
| lanip.dev | Resolves only permitted private, loopback, and reserved IP addresses; public IPs return no address |
Both services support IPv4, IPv6, prefixed and nested IP hostnames, ECDSA/RSA development certificates, on-demand subdomain certificates, and DNS over HTTPS.
Use lanip.dev when your workflow requires IP-encoded hostnames that will not resolve to public IP addresses, such as development callback policies that exclude public-IP destinations. It is publicly available to everyone and resolves only permitted private, loopback, and reserved addresses. See Restricting to Private IPs for the permitted ranges and OAuth guidance.
This restriction applies to IP-encoded hostnames; the bare domain and www remain
public service endpoints. The browser connects directly to the returned IP.
Address filtering alone does not establish application ownership or make every
subdomain a trusted OAuth callback.
For these use cases, substitute lanip.dev in the examples:
dig myapp-192-168-1-5.lanip.dev +short # 192.168.1.5
dig preview.127-0-0-1.lanip.dev +short # 127.0.0.1
dig 8-8-8-8.lanip.dev +short # no addressWhen migrating from tap.dev, replace the hostname suffix and obtain certificates
for the new domain; old-domain certificates cannot be reused. Both services support
on-demand subdomain issuance, but a specific certificate must be requested before
use. DNS support for a nested name does not imply that *.lanip.dev covers it;
see Wildcard Certificate Coverage.
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 restrict DNS answers for IP-encoded hostnames, use -only-private, as on the
public lanip.dev service:
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)
This is DNS address filtering, not access control or proof that an application is
trusted. Private addresses do not establish application ownership, and loopback
addresses refer to the visitor's own device. Certificate issuance is configured
separately with ANYIP_CERT_SUBS; -only-private does not restrict that policy.
For OAuth development callbacks, have the authorization server approve each
client's complete redirect URI rather than trusting every *.lanip.dev hostname.
Use authorization code flow with PKCE and appropriate request/session binding.
The shared development certificate keys are public and do not establish application
ownership. See OAuth 2.0 Security Best Current Practice, Section 2.1.
- 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