Skip to content
taptapPublic

About

A lightweight DNS server that resolves any IP address embedded in the hostname — with automatic TLS certificates and DNS over HTTPS.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Latest commit

 

History

37 Commits

Folders and files

Repository files navigation

AnyIP

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.

The Problem

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/hosts on every machine
  • Give up and test on localhost only

AnyIP solves all three: any developer can instantly get a valid HTTPS hostname for any IP address, zero config.

How It Works

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:

  1. DNS server — resolves <name>-<ip>.yourdomain (and <prefix>.<ip>.yourdomain) to the embedded IP address
  2. ACME DNS-01 responder — automatically answers Let's Encrypt challenges for root and subdomain wildcard certificates
  3. 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.

Usage

Public Services

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.

When to use lanip.dev

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 address

When 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.

DNS Resolution

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:3000

See Hostname Format for IPv4, IPv6, and nested subdomain rules.

HTTPS Certificate

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.pem

Then 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.

Subdomain Certificate

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.pem

Now all *.127-0-0-1.anyip.dev hostnames have valid HTTPS. See Wildcard Certificate Coverage for details.

DNS over HTTPS (DoH)

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"}]}

Hostname Format

All names are single-label subdomains (to stay within *.yourdomain wildcard coverage):

IPv4

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).

IPv6

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

Nested Subdomains

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).

Wildcard Certificate Coverage

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.

Features

  • 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 GET and POST (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

Self-Hosting

Deploy your own AnyIP instance.

1. Prerequisites

  • 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

2. DNS Setup

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>

3. Run the Server

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:latest

From source:

cp .env.example .env
# Edit .env

go build -o bin/anyip ./src
sudo bin/anyip

Configuration is loaded from .env file, environment variables, or CLI flags (in that order of precedence: flags > env > .env file).

On first run, AnyIP will:

  1. Start the DNS server on port 53
  2. Request a wildcard certificate from Let's Encrypt via DNS-01
  3. Start the HTTPS server on port 443 (DoH + cert distribution)

Configuration

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

API Reference

Root Wildcard (*.anyip.dev)

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.

Subdomain Certificates

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.dev

Rate limit: Let's Encrypt allows 50 certificates per registered domain per week. Use ANYIP_CERT_SUBS to control which IPs can request certs: exact labels (127-0-0-1), CIDRs (10.0.0.0/8), private for all private/reserved IPs, or all for any IP.

DNS over HTTPS (DoH)

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

Docker

# 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

Architecture

                    ┌──────────────────────────────────────────┐
                    │              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)        │
                    └──────────────────────────────────────────┘

Security

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) ⚠️ Encrypted, but public key = MITM possible. Secure context ✅
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

Restricting to Private IPs

To restrict DNS answers for IP-encoded hostnames, use -only-private, as on the public lanip.dev service:

anyip -domain anyip.dev -only-private

This 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.

Tech Stack

  • 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

Comparison

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)

Use Cases

  • 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.dev with 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

License

MIT

About

A lightweight DNS server that resolves any IP address embedded in the hostname — with automatic TLS certificates and DNS over HTTPS.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages