ProxyDNSCache is a small, production-friendly TLS SNI proxy that routes inbound HTTPS connections to a backend discovered via DNS SRV records.
It terminates TLS (using your certificates via SNI), then forwards the raw TCP stream to the resolved target. For HTTP traffic, it also injects standard X-Forwarded-* headers so upstream apps (NGINX, PHP-FPM, etc.) can log the real client IP.
For an incoming SNI hostname example.com, ProxyDNSCache looks up:
_pdcache._tcp.example.com
The first SRV record returned is used as the proxy destination (target:port).
Cache entries are refreshed and cleaned on a 1-minute tick:
- If the domain was accessed within the last 1 hour, its SRV record is refreshed every minute.
- If the domain was accessed more than 1 hour ago (but within 24 hours), it is refreshed every 15 minutes.
- If the domain was not accessed for more than 24 hours, it is removed from
cache.json.
cache.json is backward-compatible: older entries without timestamps still work and will be upgraded as the service runs.
config.yml: certificate configuration (required; auto-created if missing)cache.json: SRV lookup cache (auto-created if missing)
Both files are hot-reloaded when they change.
Example config.yml:
certs:
- "example.com":
- cert: "/etc/letsencrypt/live/example.com/fullchain.pem"
key: "/etc/letsencrypt/live/example.com/privkey.pem"
- "*.example.com":
- cert: "/etc/letsencrypt/live/example.com/fullchain.pem"
key: "/etc/letsencrypt/live/example.com/privkey.pem"Optional settings (new, but not required):
# Which DNS resolvers to use (defaults to Cloudflare)
dnsServers:
- "1.1.1.1"
# TLS ports to listen on (defaults to [443, 441])
tlsPorts:
- 443
- 441
# HTTP redirect port (defaults to 80)
httpPort: 80Install:
npm installStart:
npm start- If you have certbot installed remove it (this is as it's most likley outdated)
sudo apt-get remove certbot sudo apt autoremove
- Follow these instructions to install certbot using python for linux (do the respective for windows and mac) https://certbot.eff.org/instructions?ws=other&os=pip
- Install cloudflare plugin
# Enter python vertual environment source /opt/certbot/bin/activate # Install plugin pip install certbot-dns-cloudflare # Exit by typing deactivate
- Generate a cloudflare API key that has read/write/delete access to the DNS records of the domain
- Create a cloudflare.ini file in a safe place
- File should look like
dns_cloudflare_api_token = KEY HERE
- Set the files permissions
sudo chmod 600 /path/to/cloudflare.ini
- Generate certificate, remember to change the cloudflare path and the domain.com
sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /path/to/cloudflare.ini --preferred-challenges dns -d domain.com -d '*.domain.com' - Autorenewal will work as long as you are only using this app the manage certificates.
- Create the unit file:
sudo nano /etc/systemd/system/ProxyDNSCache.service- Paste the following (minimal) service definition:
[Unit]
Description=ProxyDNSCache
After=network.target
[Service]
WorkingDirectory=/home/ProxyDNSCache
ExecStart=/home/ProxyDNSCache/ProxyDNSCache-linux
Restart=always
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.targetNotes:
config.ymlandcache.jsonare expected inWorkingDirectory(and will be auto-created if missing).- If you want to store them elsewhere, set
CONFIG_PATH/CACHE_PATHenvironment variables. - Binding to ports 80/443 typically requires root or capabilities. If you run as non-root, you can grant the binary permission to bind privileged ports:
sudo setcap 'cap_net_bind_service=+ep' /home/ProxyDNSCache/ProxyDNSCache-linux- Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable --now ProxyDNSCache- View logs:
sudo journalctl -u ProxyDNSCache -fEnvironment overrides (optional):
CONFIG_PATH: path toconfig.ymlCACHE_PATH: path tocache.jsonHTTP_PORT: redirect server port
If your upstream is behind NGINX and you want correct client IP logging:
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;For PHP backends, you may also want:
fastcgi_param HTTPS on;Unit tests cover the pure logic (wildcard hostname matching, header injection, cache policy). Network integration tests are intentionally not included.
npm testThis project supports building standalone executables using pkg.
Install dependencies:
npm installBuild all configured targets:
npm run buildBuild specific targets:
npm run build:mac
npm run build:linuxArtifacts are written to the dist/ folder.
Expected outputs:
dist/proxydnscache-macos-x64dist/proxydnscache-macos-arm64dist/proxydnscache-linux-x64dist/proxydnscache-linux-arm64
pkg can build for multiple targets, but cross-building is not always reliable for every platform/architecture combination (especially Linux arm64) depending on which prebuilt Node runtimes pkg can fetch.
If npm run build:linux fails on macOS for linux-arm64, the most reliable option is to build on a Linux machine/runner.
Recommended approach:
- Use GitHub Actions (or any CI) with a Linux runner to build Linux artifacts.
- Optionally build Linux
arm64on an ARM runner (or via QEMU), depending on your CI setup. 5. Generate a cloudflare API key that has read/write/delete access to the DNS records of the domain 6. Create a cloudflare.ini file in a safe place 7. File should look likeenv dns_cloudflare_api_token = KEY HERE8. Set the files permissionsbash sudo chmod 600 /path/to/cloudflare.ini9. Generate certificate, remember to change the cloudflare path and the domain.combash sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /path/to/cloudflare.ini --preferred-challenges dns -d domain.com -d '*.domain.com'10. Autorenewal will work as long as you are only using this app the manage certificates.
- ProxyDNSCache ensures that HTTP client IPs are forwarded through the X-Forwarded-For header. Forwarding IP's for non-http TCP connections are not currently supported.
- You can manage certificates for different domains in the config.yml file.
- If you are having issues with Windows, running the project directly via Node.js is recommended.
Ensure that:
- SRV records are correctly set up for your domain.
- The SSL certificates are valid and properly configured.
- You're using Node.js v16 to build or run the project.