7.1 KiB
Securing Your Critical Server: Starting/Stopping acme-dns & Opening/Closing Port 53 with Certbot
On a critical server, leaving port 53 (DNS) open unnecessarily is a security risk. DNS servers are frequent targets for attacks (e.g., DDoS amplification, DNS hijacking).
The best practice is to only open port 53 and run acme-dns while Certbot is executing a DNS challenge, then immediately close port 53 and stop acme-dns afterward.
Below is a complete, production‑ready solution using systemd to automate this safely.
Why Systemd?
Systemd allows you to define dependencies, pre/post actions, and clean lifecycle management — perfect for this use case!
✅ Step-by-Step Implementation
1. Modify acme-dns.service (DO NOT enable it at boot!)
We disable acme-dns from starting automatically. It will only run when Certbot needs it.
Edit the service file:
sudo nano /etc/systemd/system/acme-dns.service
Replace its content with this (security‑hardened version):
#/etc/systemd/system/acme-dns.service
[Unit]
Description=Limited DNS server for ACME DNS challenges
After=network.target
# ONLY start when explicitly requested (never at boot)
RefuseManualStart=no # Allow manual start (for testing)
# DO NOT start on boot!
[Service]
# Run as a NON-ROOT user (HIGHLY RECOMMENDED!)
User=acme-dns # Create this user first (see Step 2)
Group=acme-dns
# Prevent the service from gaining extra privileges
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
NoNewPrivileges=yes
RestrictAddressFamilies=AF_INET AF_INET6 # Only allow IPv4/IPv6
# Bind to port 53 WITHOUT root (requires kernel >= 4.11)
AmbientCapabilities=CAP_NET_BIND_SERVICE
ExecStart=/usr/local/bin/acme-dns -c /etc/acme-dns/config.cfg
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target # BUT WE WILL DISABLE THIS!
⚠️ Critical: DO NOT enable this service!
Run:sudo systemctl disable acme-dns.service
2. Create a Dedicated Non-Root User for acme-dns
sudo useradd --system --no-create-home --shell /usr/sbin/nologin acme-dns
sudo mkdir -p /var/lib/acme-dns /etc/acme-dns
sudo chown -R acme-dns:acme-dns /var/lib/acme-dns /etc/acme-dns
Ensure your /etc/acme-dns/config.cfg has correct permissions:
sudo chown acme-dns:acme-dns /etc/acme-dns/config.cfg
sudo chmod 600 /etc/acme-dns/config.cfg
3. Create a NEW Systemd Service: certbot-acme-dns.service
This service orchestrates:
- Open UDP port 53 in
ufw - Start
acme-dns.service - Run Certbot
- Stop
acme-dns.service - Close UDP port 53
Create the file:
sudo nano /etc/systemd/system/certbot-acme-dns.service
Paste the following (replace <yoursite> with your domain):
#/etc/systemd/system/certbot-acme-dns.service
[Unit]
Description=Run Certbot with acme-dns (opens/closes port 53)
After=network.target network-online.target
Wants=network-online.target
# Start ONLY when triggered (by timer or manual)
RefuseManualStart=no
[Service]
# ----- OPEN PORT 53 & START acme-dns BEFORE Certbot -----
ExecStartPre=/usr/sbin/ufw allow 53/udp
ExecStartPre=/usr/bin/systemctl start acme-dns.service
# ----- RUN CERTBOT -----
# • Use 'renew' for automatic renewals
# • Add domains as needed
ExecStart=/usr/bin/certbot renew \
--quiet \
--post-hook "/usr/bin/systemctl restart nginx" # <-- CHANGE "nginx" to "apache2" if you use Apache
# ----- STOP acme-dns & CLOSE PORT 53 AFTER Certbot FINISHES (EVEN ON FAILURE!) -----
ExecStopPost=/usr/bin/systemctl stop acme-dns.service
ExecStopPost=/usr/sbin/ufw delete allow 53/udp
# Critical: Clean up even if Certbot FAILS!
Restart=on-failure
RestartSec=10
# Never run this service manually! It's triggered by the timer.
RefuseManualStart=yes
[Install]
WantedBy=multi-user.target
✅
ExecStopPostruns after the service stops — even if Certbot fails!
This guarantees port 53 is always closed.
4. Create a Timer to Run Renewals Weekly
Create /etc/systemd/system/certbot-acme-dns.timer:
sudo nano /etc/systemd/system/certbot-acme-dns.timer
#/etc/systemd/system/certbot-acme-dns.timer
[Unit]
Description=Weekly Certbot Renewal (with acme-dns)
[Timer]
# Wait 5 minutes after boot (to avoid race conditions)
OnBootSec=5min
# Run every week
OnUnitActiveSec=1w
# Randomize delay ±30 min to avoid "thundering herd"
RandomizedDelaySec=1800s
[Install]
WantedBy=timers.target
Enable & Start the Timer:
sudo systemctl enable --now certbot-acme-dns.timer
✅ Now Certbot will run automatically every week — and port 53 is ONLY open for a few seconds!
5. Test It!
🔍 Check Timer Status
systemctl status certbot-acme-dns.timer
🔧 Dry-Run Renewal (NO real changes!)
sudo certbot renew --dry-run
▶️ Manually Trigger the Service (for testing)
sudo systemctl start certbot-acme-dns.service
Watch the logs:
journalctl -u certbot-acme-dns.service -f
You should see:
ufw allow 53/udpsystemctl start acme-dns.service- Certbot running
systemctl stop acme-dns.serviceufw delete allow 53/udp
✅ Port 53 is closed again!
Verify UFW after the run:
sudo ufw status verbose
You should NOT see 53/udp allowed.
📌 Additional Security Tips
-
Firewall Lockdown
Ensure no other service listens on port 53!sudo ss -tulpn | grep ':53'Only
acme-dnsshould appear — and only when the service is running. -
acme-dnsConfiguration Hardening
In/etc/acme-dns/config.cfg:[general] debug = false # <<-- TURN OFF DEBUG IN PRODUCTION! listen = ":53" protocol = "udp" [api] disable_registration = true # <<-- PREVENT NEW ACCOUNTS! tls = "none" # API runs on localhost:8081 (safe) -
Backups
Backup:/etc/acme-dns/config.cfg/var/lib/acme-dns/acme-dns.db- Your Let's Encrypt certificates (
/etc/letsencrypt)
Use
cronto backup daily.
❓ What About Manual Certificate Issuance (e.g., adding a new domain)?
Use this one‑liner (it auto-opens/closes port 53):
sudo systemctl start certbot-acme-dns.service --no-block
Or create a helper script (/usr/local/bin/certbot-with-acme-dns):
#!/usr/bin/env bash
sudo systemctl start certbot-acme-dns.service --no-block "$@"
Make it executable:
sudo chmod +x /usr/local/bin/certbot-with-acme-dns
Then run:
sudo certbot-with-acme-dns certonly \
-d newdomain.com \
--manual \
--manual-auth-hook /etc/letsencrypt/acme-dns-auth.py \
--preferred-challenges dns
The script will handle opening/closing port 53 automatically!
💚 You’re now running a critical server with MINIMAL exposure!
Port 53 is only open for seconds while Certbot runs — drastically reducing your attack surface. 🎯