I wanted to contribute something to the VyOS world, so here is a wireguard configuration and script pair
that deal with DHCP and dynamic IP’s for a VPN pair. This has been in production and works flawlessly
for over a year. I dont know how to submit contributions to this product but hopefully this makes its
way in the VyOS release toolset.
There is no firewall, routing or port forwarding information, as this is not a wireguard tutorial.
Both site A and B have Dynamic public IP addresses changed at random by ISP’s, configured via DHCP
on ETH0.
Site A is VyOS 1.5 and Site B is VyOS 1.4 (full versions shown below).
They Dynamic DNS site is afraid.org which allows dynamic hostname updates. I have configured two hostanes,
XXX_YOUR_PUBLIC_HOSTNAME_SITEA_AT_AFRAID_DOT_ORG_XXX and XXX_YOUR_PUBLIC_HOSTNAME_SITEB_AT_AFRAID_DOT_ORG_XXX
Dynamic updates of the Afraid website are done by the “service-dns-dynamic” VyOS configuration.
Once a minute, the VyOS “system-task-scheduler-task” runs the script /config/scripts/wg-peer-XXX_SCRIPTNAMESITEA_XXX
or /config/scripts/wg-peer-XXX_SCRIPTNAMESITEB_XXX on site B.
The script checks the current IP of the hostname shown using “dig” from the afraid nameservers. It then
extracts the current running IP address from the working configuration in VyOS. It checks to make sure
the IP’s are vaild (as dig can return strange things) and then compares the two. If they are different, it
will update the VyOS working configuration for the shown wireguard interface, commit, and save the configuration.
Wireguard should automatically resync.
FYI, there is a typo on the site B config and script (interface wg01 should be named wg02) but the script
and configuration work as shown. Also note the “service-dns-dnyamic” configuration is different between 1.5 and 1.4.
Again this is a working configuration as shown.
Site A (VyOS 1.5-rolling-202403250019):
wireguard wg01 {
address 10.1.0.1/30
description VPN-to-wg02
peer to-wg02 {
address XXX_PUBLICIP_XXX
allowed-ips 0.0.0.0/0
port 51820
public-key XXX_MyPublicKey_XXX
}
port 51820
private-key XXX_MyPrivateKey_XXX
}
system {
task-scheduler {
task update-wg01 {
executable {
path /config/scripts/wg-peer-XXX_SCRIPTNAMESITEA_XXX
}
interval 1m
}
}
}
service {
dns {
dynamic {
name service-afraid-eth0 {
address {
interface eth0
}
host-name XXX_YOUR_PUBLIC_HOSTNAME_SITEA_AT_AFRAID_DOT_ORG_XXX
password "XXX_AFRAID_ORG_PASSWORD_XXX"
protocol freedns
server freedns.afraid.org
username XXX_AFRAID_DOT_ORG_USERNAME_XXX
}
}
}
}
script wg-peer-XXX_SCRIPTNAMESITEA_XXX:
#!/bin/vbash
if [ "$(id -g -n)" != 'vyattacfg' ] ; then
exec sg vyattacfg -c "/bin/vbash $(readlink -f $0) $@"
fi
source /opt/vyatta/etc/functions/script-template
function valid_ip()
{
local ip=$1
local stat=1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
fi
return $stat
}
newIP="$(dig +short XXX_YOUR_PUBLIC_HOSTNAME_SITEA_AT_AFRAID_DOT_ORG_XXX @ns1.afraid.org)"
oldIP=$(run show configuration commands | grep wg01 | grep to-wg02 | grep address | awk '{print $8 }' | awk '{print substr($1,2); }' | awk '{print substr($1, 1, length($1)-1)}')
if ! valid_ip $newIP
then
echo "bad newIP: " $newIP
elif ! valid_ip $oldIP
then
echo "bad oldIP: " $oldIP
else
#echo "new ip" $newIP
#echo "old ip" $oldIP
if [ $newIP != $oldIP ]
then
echo "new ip" $newIP
echo "old ip" $oldIP
configure
set interfaces wireguard wg01 peer to-wg02 address $newIP
commit
save
fi
fi
exit
Site B (yOS 1.4-rolling-202304040317):
wireguard wg01 {
address 10.1.0.2/30
description VPN-to-wg01
peer to-wg01 {
address XXX_PUBLICIP_SITEB_XXX
allowed-ips 0.0.0.0/0
port 51820
public-key XXX_MyPublicKey_XXX
}
port 51820
private-key XXX_MyPrivateKey_XXX
}
system {
task-scheduler {
task update-wg01 {
executable {
path /config/scripts/wg-peer-XXX_SCRIPTNAMESITEB_XXX
}
interval 1m
}
}
}
service {
dns {
dynamic {
interface eth0 {
service afraid {
host-name XXX_YOUR_PUBLIC_HOSTNAME_SITEB_AT_AFRAID_DOT_ORG_XXX
login XXX_AFRAID_DOT_ORG_USERNAME_XXX
password "XXX_AFRAID_ORG_PASSWORD_XXX"
server freedns.afraid.org
}
use-web {
url http://ifconfig.me/ip
}
}
}
}
}
wg-peer-XXX_SCRIPTNAMESITEB_XXX:
#!/bin/vbash
if [ "$(id -g -n)" != 'vyattacfg' ] ; then
exec sg vyattacfg -c "/bin/vbash $(readlink -f $0) $@"
fi
source /opt/vyatta/etc/functions/script-template
function valid_ip()
{
local ip=$1
local stat=1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
fi
return $stat
}
newIP="$(dig +short XXX_YOUR_PUBLIC_HOSTNAME_SITEB_AT_AFRAID_DOT_ORG_XXX @ns1.afraid.org)"
oldIP=$(run show configuration commands | grep wg01 | grep to-wg01 | grep address | awk '{print $8 }' | awk '{print substr($1,2); }' | awk '{print substr($1, 1, length($1)-1)}')
if ! valid_ip $newIP
then
echo "bad newIP: " $newIP
elif ! valid_ip $oldIP
then
echo "bad oldIP: " $oldIP
else
#echo "new ip" $newIP
#echo "old ip" $oldIP
if [ $newIP != $oldIP ]
then
echo "new ip" $newIP
echo "old ip" $oldIP
configure
set interfaces wireguard wg01 peer to-wg01 address $newIP
commit
save
fi
fi
exit