Trojan Rust

Dynamic DNS

Automatically update DNS records when your server's public IP changes

trojan-rs includes a built-in DDNS client that detects public IP changes and updates DNS records automatically. This is useful when running a server on a dynamic IP address (home network, some VPS providers).

How It Works

trojan-server

    ├── [every 300s] GET https://api.ipify.org → current IP

    ├── IP changed?
    │   ├── No  → skip
    │   └── Yes → update DNS records via Cloudflare API

    └── continue serving connections

The DDNS updater runs as a background task inside the server process. It shares the same graceful shutdown mechanism — when the server stops, the DDNS loop stops too.

Cloudflare Setup

1. Create an API Token

  1. Go to Cloudflare Dashboard
  2. Click Create Token
  3. Use the Edit zone DNS template, or create a custom token with:
    • Permissions: Zone → DNS → Edit
    • Zone Resources: Include → Specific zone → your domain
  4. Copy the generated token

2. Configure the Server

[ddns]
enabled = true
interval = 300

[ddns.cloudflare]
api_token = "your-api-token-here"
zone = "example.com"
records = ["example.com", "*.example.com"]
proxied = false
ttl = 1

3. Start the Server

trojan server -c server.toml

On startup you will see:

INFO starting DDNS update task
INFO DDNS update loop started zone="example.com" records=["example.com", "*.example.com"]
INFO detected IPv4 address ip=203.0.113.42
INFO DNS record updated name="example.com"
INFO DNS record created name="*.example.com"

Configuration Reference

[ddns]

OptionTypeDefaultDescription
enabledboolfalseEnable DDNS updates
intervalint300Seconds between IP checks
ipv4_urlsstring[]["https://api.ipify.org", ...]URLs to detect public IPv4 address
ipv6_urlsstring[][]URLs to detect public IPv6 address (empty = disabled)

[ddns.cloudflare]

OptionTypeDefaultDescription
api_tokenstringrequiredCloudflare API token with DNS edit permission
zonestringrequiredDomain name (Cloudflare zone)
recordsstring[]requiredDNS record names to create/update
proxiedboolfalseEnable Cloudflare CDN proxy (orange cloud)
ttlint1DNS record TTL in seconds. 1 = automatic

IP Detection

The DDNS client detects your public IP by querying external HTTP endpoints. URLs are tried in order — the first successful response is used.

Default IPv4 detection URLs:

ipv4_urls = [
  "https://api.ipify.org",
  "https://ifconfig.me/ip",
  "https://ip.sb",
]

You can customize or replace these:

[ddns]
ipv4_urls = ["https://checkip.amazonaws.com"]

IPv6 Support

IPv6 is disabled by default. To enable it, configure IPv6 detection URLs:

[ddns]
ipv6_urls = ["https://api6.ipify.org", "https://ifconfig.me/ip"]

When enabled, both A (IPv4) and AAAA (IPv6) records are managed for each configured record name.

Update Behavior

  • First run: Detects IP and creates or updates all configured records
  • Subsequent runs: Only calls the Cloudflare API when the IP actually changes
  • Partial failures: Successfully updated records are skipped on retry; only failed records are retried on the next cycle
  • Zone ID caching: The Cloudflare zone ID is resolved once and cached for the lifetime of the process
  • Record existence: If a record does not exist, it is created automatically. If it already exists with the correct IP, no API call is made

Example: Full Server with DDNS

[server]
listen = "0.0.0.0:443"
fallback = "127.0.0.1:80"

[tls]
cert = "/etc/trojan/cert.pem"
key = "/etc/trojan/key.pem"
alpn = ["h2", "http/1.1"]

[auth]
passwords = ["my-secret-password"]

[ddns]
enabled = true
interval = 300

[ddns.cloudflare]
api_token = "cf-api-token"
zone = "example.com"
records = ["trojan.example.com"]
proxied = false
ttl = 1

[logging]
level = "info"

On this page