WireGuard has rapidly become a preferred VPN solution due to its simplicity, high performance, and robust security. While setting up WireGuard is often straightforward, configuring a resilient site-to-site VPN connection when one or both peers have dynamic IP addresses presents a common challenge. ISPs frequently assign dynamic IPs to residential and small business connections, which can break a VPN tunnel when an IP address changes.
This article provides a detailed, practical guide for establishing a reliable WireGuard site-to-site VPN where at least one peer uses a dynamic IP address. We’ll explore how to leverage Dynamic DNS (DDNS) services and scripting to maintain connectivity, ensuring your networks remain linked despite IP changes. This solution is ideal for connecting a home office to a central office, linking branch locations, or any scenario requiring a persistent VPN connection over dynamic IP infrastructure.
The Challenge: Dynamic IPs and WireGuard Endpoints
WireGuard’s core design relies on knowing the public IP address and port of its peers to establish encrypted tunnels. In a typical peer configuration, the Endpoint
directive specifies this static IP address.
|
|
When a peer’s public IP address changes (as is common with dynamic IP assignments), the Endpoint
information in the other peer’s configuration becomes outdated. The VPN tunnel will fail because packets are being sent to an old, incorrect IP address, effectively severing the site-to-site connection until the configuration is manually updated. This manual intervention is impractical for maintaining a stable VPN.
The Solution: DDNS and Endpoint Management
The most effective workaround involves two key components:
- Dynamic DNS (DDNS): A DDNS service maps a chosen hostname (e.g.,
site-b.yourddns.com
) to a dynamic IP address. When the IP address changes, a DDNS client on that network updates the DDNS provider, ensuring the hostname always resolves to the current public IP. - WireGuard Endpoint Configuration with Hostnames & Keepalives: WireGuard’s
Endpoint
directive can accept a hostname. However, WireGuard typically resolves this hostname to an IP only at interface startup or on configuration reload. - Persistent Keepalives: The
PersistentKeepalive
option in WireGuard helps maintain NAT traversal and can implicitly signal the current IP of a dynamic peer to a static one. - Automated Endpoint Updates: For scenarios where WireGuard doesn’t automatically re-resolve or update the endpoint IP after a DDNS change, or when both ends are dynamic, scripts are often necessary to monitor and update the peer endpoint information dynamically.
This article focuses on using a DDNS hostname in the Endpoint
field and strategies to ensure WireGuard uses the current IP address associated with that hostname.
Step 1: Setting Up DDNS
Before configuring WireGuard, the site(s) with dynamic IP addresses must set up DDNS.
Choose a DDNS Provider: Numerous providers offer free and paid DDNS services. Popular choices include:
- No-IP
- DuckDNS
- Dynu
- Cloudflare DDNS (if you manage your domain there)
- Many routers also have built-in DDNS services or support for common providers.
Create a DDNS Hostname: Sign up with your chosen provider and create a hostname (e.g.,
myoffice.ddns.net
).Configure a DDNS Update Client: This client software runs on a machine within the network that has the dynamic IP (often the router itself, or a server like the WireGuard host). Its job is to periodically check the network’s current public IP and notify the DDNS provider if it changes.
- Router-based: Check your router’s administration interface for DDNS settings. This is often the simplest method.
- Software Clients: Tools like
ddclient
(Linux) or provider-specific clients can be installed on a server. - Custom Scripts: You can use
curl
or other tools to interact with DDNS provider update APIs.
Ensure your DDNS hostname correctly resolves to your site’s current public IP address. You can verify this using nslookup your.ddns.hostname
or dig your.ddns.hostname
from an external network.
Step 2: Configuring WireGuard Peers
Let’s assume Site A has a static IP (or a very stable DDNS hostname) and Site B has a dynamic IP with DDNS configured (e.g., site-b.ddns.provider.com
). If both are dynamic, the principles are similar but require careful handling of which side initiates or using scripts on both ends.
Site A Configuration (wg0.conf
on Site A Server)
Site A’s WireGuard configuration will list Site B as a peer, using Site B’s DDNS hostname as the endpoint.
|
|
Site B Configuration (wg0.conf
on Site B Server)
Site B’s WireGuard configuration will list Site A as a peer. If Site A has a static IP, that’s straightforward. If Site A also uses DDNS, Site A’s DDNS hostname would be used here.
|
|
Key Configuration Notes:
Endpoint
: Use the DDNS hostname for the peer with the dynamic IP.PersistentKeepalive = 25
: This setting on Site B (the dynamic IP side, or any side behind NAT) causes it to send an encrypted keepalive packet to Site A every 25 seconds. This has two benefits:- It keeps the NAT mapping open on Site B’s router.
- It continuously informs Site A of Site B’s current public IP address and port, allowing Site A to reply even if Site B’s IP has changed since the tunnel was last active. This can often be enough for the “static” side to learn the new dynamic IP.
- Generate Keys: Use
wg genkey | tee privatekey | wg pubkey > publickey
to generate private and public key pairs for each site. See the WireGuard Quickstart Guide for details.
Step 3: Router and Firewall Configuration
Proper network configuration is essential.
Port Forwarding
On the site(s) that will receive initial incoming WireGuard connections (typically Site A, if it has a static IP, or any site designated as a “server”), you must configure port forwarding on the router.
- Forward UDP port
51820
(or your chosen WireGuard port) from your router’s public interface to the internal IP address of the WireGuard server on that site.
If both sites are dynamic and behind NAT, and one is expected to “listen,” it must have reliable port forwarding. PersistentKeepalive
from the “client” side helps punch through NAT.
Firewall Rules
Ensure that firewalls on both the routers and the WireGuard host machines allow:
- Incoming UDP traffic on port
51820
(or your custom port) to the WireGuard server. - Traffic forwarded through the WireGuard tunnel interface (e.g.,
wg0
). This often means allowing traffic from/to theAllowedIPs
subnets.
For iptables
on Linux, you might need rules like:
Allow UDP traffic to the WireGuard port:
|
|
Or, if using ufw
(Uncomplicated Firewall):
|
|
Allow traffic forwarding from WireGuard clients:
|
|
Remember to make iptables rules persistent (e.g., using iptables-persistent
).
Step 4: Automating WireGuard Endpoint Updates (The Scripting Solution)
While PersistentKeepalive
can often maintain connections when one side is dynamic and initiates, or if the “static” side’s WireGuard implementation re-resolves DNS effectively, some WireGuard implementations might only resolve the Endpoint
hostname at startup. If the DDNS IP changes, the connection can still break if the peer doesn’t update its understanding of the remote endpoint’s IP.
A script can be used on the peer that connects to the DDNS hostname to periodically check if the resolved IP for that hostname has changed and, if so, update WireGuard’s endpoint information using the wg set
command.
This script is typically run on the “more static” peer (Site A in our example) or on any peer that needs to ensure it’s connecting to the correct, most recently updated IP of a dynamic peer.
Below is a conceptual Bash script. You’d run this on Site A to monitor Site B’s DDNS.
|
|
Using the Script:
Customize: Replace placeholders (
<Site B's Public Key>
,site-b.ddns.provider.com
,wg0
,51820
) with your actual values.Permissions: Make the script executable:
chmod +x /path/to/update_wg_endpoint.sh
.Test: Run it manually to ensure it works.
Schedule: Run this script periodically using
cron
or asystemd
timer. For example, every 5 minutes:Crontab entry:
1
*/5 * * * * /path/to/update_wg_endpoint.sh >> /var/log/update_wg_endpoint.log 2>&1
Ensure the user running the cron job has
sudo
privileges for thewg set
command, or configure passwordlesssudo
for that specific command.
Note on DDNS Update Propagation: DNS changes take time to propagate (though DDNS services aim for low TTLs, e.g., 60-300 seconds). The script’s check interval should be balanced – too frequent might be excessive, too infrequent could lead to longer downtimes.
Alternative: Script to Update Local DDNS and Inform Peer
If this machine has the dynamic IP, a script could first update its own DDNS record and then, if it were acting as a “client” to a static peer, it might not need further action if PersistentKeepalive
is set. If it is the “server” with a dynamic IP, the above script on the “client” is more relevant.
Handling Both Ends Dynamic
If both Site A and Site B have dynamic IPs:
- Both use DDNS: Each site maintains its own DDNS hostname.
PersistentKeepalive
on Both Sides: ConfigurePersistentKeepalive
in both peer stanzas.- Endpoint Update Scripts on Both Sides: Each site would run a script similar to the one above to monitor and update the endpoint of the other site.
- One Site as “Initiator”: Even if both are dynamic, one often acts more like a “client” that is more aggressive in initiating/re-initiating the connection via its keepalives.
- Potential Race Conditions: This can be more complex to stabilize perfectly, as IP changes on both ends simultaneously can lead to brief discovery issues.
- Consider a Static “Hub”: For maximum reliability when multiple sites are dynamic, a cheap VPS with a static IP acting as a central WireGuard “hub” can simplify things. Each dynamic site connects to this static hub.
Troubleshooting Common Issues
wg show
: Your primary diagnostic tool. Thewg
command documentation provides full details.Check:1
sudo wg show
endpoint
: Is the IP address and port correct and current for peers?latest handshake
: If recent, the connection is likely active. If old or(none)
, there’s a problem.transfer
: Shows data sent/received.
- DDNS Resolution:Verify this from both inside your network and externally (e.g., using an online
1 2
nslookup your.ddns.hostname dig your.ddns.hostname
nslookup
tool) to ensure the DDNS record is updated and has propagated. - Port Forwarding: Use an online port checker tool (e.g., YouGetSignal Port Checker or similar) to confirm your WireGuard UDP port is open on the public IP of the listening peer.
- Firewall Logs: Check system and router firewall logs for dropped packets on the WireGuard port or related to the tunnel IPs.
- DDNS Client Logs: Ensure your DDNS update client is running and successfully updating the IP with your DDNS provider.
- Packet Captures: Use
tcpdump
or Wireshark on the WAN and WireGuard interfaces to inspect traffic.1 2
# Listen for WireGuard traffic on your WAN interface (e.g., eth0) sudo tcpdump -i eth0 udp port 51820 -n
Security Considerations
- Strong Keys: Use strong, unique private/public key pairs for each WireGuard peer.
- Pre-shared Keys: For an added layer of symmetric-key security against potential future quantum computing threats, consider using
PresharedKey
in your peer configurations.Then add1 2
# Generate a preshared key using wg genpsk wg genpsk > preshared.key
PresharedKey = <contents of preshared.key>
to the[Peer]
section on both sides (must be the same key for that peer pair). - DDNS Account Security: Protect your DDNS account credentials. Use strong passwords and two-factor authentication if offered.
- DDNS Update Security: If using scripts with API keys for DDNS updates, ensure the script and keys are secured with appropriate file permissions. Use HTTPS for update URLs.
- Least Privilege: Run update scripts with the minimum necessary privileges.
Alternatives to DDNS Workaround
- Static IP Address: The simplest, most reliable solution is to obtain a static IP address from your ISP for at least one of the sites.
- VPS as a Hub: Deploy a WireGuard server on a low-cost Virtual Private Server (VPS) with a static IP. Both dynamic sites connect to this central hub. This is common for hub-and-spoke topologies.
- Other VPN Protocols: OpenVPN or IPsec (IKEv2) have their own methods for handling dynamic IPs, but WireGuard’s performance and simplicity are often preferred if the DDNS workaround can be implemented effectively.
- Managed VPN/SD-WAN Services: Solutions like Tailscale (uses WireGuard) or ZeroTier abstract away NAT traversal and dynamic IP complexities, often by using relay servers. They are easier to set up but rely on a third-party service.
Conclusion
Configuring a WireGuard site-to-site VPN with dynamic IP addresses requires a reliable DDNS service and a strategy for keeping WireGuard’s peer endpoint information current. By using DDNS hostnames in Endpoint
configurations, leveraging PersistentKeepalive
, and implementing simple scripts for endpoint updates, you can create a robust and stable VPN connection that automatically adapts to IP address changes. This approach harnesses WireGuard’s strengths while overcoming the common hurdle of dynamic IP addressing, providing a cost-effective and high-performance solution for connecting your networks.