Skip to content

Instantly share code, notes, and snippets.

@LanceMcCarthy
Last active September 30, 2024 13:28
Show Gist options
  • Save LanceMcCarthy/1298dca711984ef77d1035a66b7210ac to your computer and use it in GitHub Desktop.
Save LanceMcCarthy/1298dca711984ef77d1035a66b7210ac to your computer and use it in GitHub Desktop.
UDM Pro IPsec VPN Configuration Updater
#!/bin/sh
# ***** warning ***** warning ***** warning ***** warning ***** warning ***** warning *****
# THIS IS NOT LONGER A GOOD APPROACH TO USE. SCROLL DOWN TO THE COMMENTS TO SEE HOW YOU CAN USE WIREGUARD WITH A DDNS FQDN INSTEAD
# ***** warning ***** warning ***** warning ***** warning ***** warning ***** warning *****
# ___ ____ _ _ _ _
# |_ _| _ \ ___ ___ ___ | | | |_ __ __| | __ _| |_ ___ _ __
# | || |_) / __|/ _ \/ __| | | | | '_ \ / _` |/ _` | __/ _ \ '__|
# | || __/\__ \ __/ (__ | |_| | |_) | (_| | (_| | || __/ |
# |___|_| |___/\___|\___| \___/| .__/ \__,_|\__,_|\__\___|_|
# |_|
# CLI parameters
# $1 - path to the config file (e.g. /run/strongswan/ipsec.d/tunnels/6c1b_6f95_d0be_8a4d.ipsec.s2s.config)
# $2 - FQDN of the UDM Pro (e.g. mysite.com)
# $3 - DNS nameserver (e.g. ns69.domaincontrol.com)
echo "-------- VPN Configuration Updater - v0.0.1 by Lance McCarthy --------"
reload_needed=false
config_file=$1
udmpro_fqdn=$2
dns_nameserver=$3
################################################################
# Phase 1. Check the left-side values and update if neccessary #
################################################################
echo "***** Checking left IP address *****"
# Get the IP address of the local UDM Pro from ppp0 and store it in $local_wan_ip
# ------ IMPORTANT -----
# - Check that you're using the correct network adapter name using 'ifconfig' command
# - if you're using PPPoE, then it's probably 'ppp0'
# - if you're using ethernet in port 8, then it's probbaly 'eth8' (or 'eth10' for SFP in port 10)
local_wan_ip="$(ifconfig | grep -A 1 'eth8' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
# prepare the current and expected IP address values
echo expected_left=" left=$local_wan_ip"
echo current_left=$(sed -n '17p' $config_file)
# Check to see if the config has the expected left value (using the regex operator)
if [ "$current_left" == "$expected_left" ]; then
echo "LEFT OK - left does not need an update"
else
echo "!!! left mismatch !!! Updating config..."
sed -i "/left/s/=.*/=$local_wan_ip/" $config_file
echo " -- Done. Config successfully updated with new left value."
reload_needed=true
fi
#################################################################
# Phase 2. Check the right-side values and update if neccessary #
#################################################################
echo "***** Checking right IP address *****"
# Get the IP address of the remote UDM Pro and store it in $remote_wan_ip
remote_wan_ip="$(nslookup -type=A $udmpro_fqdn $dns_nameserver | grep "Address" | awk '{print $2}' | sed -n 2p)"
echo expected_right=" right=$remote_wan_ip"
echo current_right=$(sed -n '18p' $config_file)
# Check to see if the config has the expected right valie
if [ "$current_right" == "$expected_right" ]; then
echo "RIGHT OK - right does not need an update."
else
echo "!!! right mismatch !!! Updating config..."
sed -i "/right/s/=.*/=$remote_wan_ip/" $config_file
echo " -- Done. Config successfully updated with new right value."
reload_needed=true
fi
##################################################
# PHASE 3. Invoke any required swanctrl commands #
##################################################
echo "***** Validate VPN Setting Reload *****"
if [ "$reload_needed" = true ]; then
ipsec reload
echo ' ----> Reloaded IPsec <----'
else
echo 'No configuration changes were made, skipping swanctl settings reload.'
fi
echo "Done."
@LanceMcCarthy
Copy link
Author

@pgregg88 Good news... there is now a better option since Ubiquiti added support for WireGuard natively on the UDM Pro (UniFi OS v3+)

this means you can actually use a FQDN for the server, here's an example os a client wireguard config file.

[Interface]
PrivateKey = ABCDTEHSKSUELSJSJSLSKSKSKSKSK=
# This is the IP address the client device will be assigned
Address = 10.10.0.12/24

# Notice the Endpoint FQDN, that's the DDNS setup on the UDM Pro, no need for IP address.
# Note the port number, that's the default port for wireguard, I would change it slightly.
[Peer]
PublicKey = JHSALKJSDAHLKASJHVLKSJVSLKJHVLK=
Endpoint = yoursubdomain.afraid.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

In case you haven't updated the UDM Pro and UniFi Network app yet, here's what the new WireGuard portal looks like

image

Since I have DDNS setup on all my UDM Pros, and I use that DDNS name as the remote host on the client configs, it's (almost) perfect. No need to worry when my ISP changes my WAN IP, because the clients are using the DDNS url (and not an IP address).

If you are not already using DDNS, I like afraid's DDNS service, because it allows up to 3 FQDNs for free without huge hoops ot jump through. You can choose any from the UniFi DDNS dropdown, or check out these popular free options.

image

@angusdavis2
Copy link

Hi, I see that you can use WireGuard with FQDNs for a VPN Server, but it does not appear to be an option for the Site-to-Site VPN setup in UDM Pro. Any tips on how to get a Site-to-Site VPN working with FQDNs?

@LanceMcCarthy
Copy link
Author

@angusdavis2 It's been a while since I've needed, I should take it private to avoid folks messing with their container environment :)

If you have two UDM Pros, there's a great new feature called "Magic site" which will setup the site-to-site VPN automatically for you and will handle any changes in WAN IP immediately... no need for DDNS or any preconfig for WAN IP.

image

Unfortiunately, if one of them is not a UDM machine, then you still need to use the WAN IP address of the other gateway. since I've written the script, I've used DDNS and static IP for an Azure gateway and Azure site-to-site VPN (because Azure supports using FQDN for a site-to-site gateway, that's where I use my DDNS's FQDN).

The site Magic is pretty amazing, and has removed nearly all my manual setup.

@LanceMcCarthy
Copy link
Author

I should have shared this, too... it's no joke https://www.youtube.com/watch?v=hqnl9awwYiM

@angusdavis2
Copy link

angusdavis2 commented Aug 24, 2023

That's amazing! Awesome. We have 2 UDMs and this solves our problem, but not quite ... for my next trick, I want to have certain hosts from Site B route their traffic over the VPN (or said another way, I want these select hosts on Site B to route their Internet traffic through the remote UDM Pro that's at Site A). With my old manually-configured Site-to-Site VPN, I was achieving this with https://github.com/peacey/split-vpn -- that approach worked with OpenVPN or IPSec site-to-site VPNs.

I see that with the new "Magic Site", Unifi has setup a new interface:

# ip route show 192.168.2.0/24
192.168.2.0/24 via 192.168.1.0 dev wgsts1000 proto ospf metric 20 onlink

Site B is 192.168.0.0/24, site A (the remote site) is 192.168.2.0/24 ... I want one or more of my local hosts (e.g. 192.168.0.161) to route its traffic over the VPN, i.e. to Site A.

Any thoughts on this? I am also going to go to the split-vpn author and see if maybe we can update the instructions to support this new Magic Site scenario.

@LanceMcCarthy
Copy link
Author

Aha, that's a bit more complicated and not what Magic sites was designed for.

Then in this case, wouldn't it be easier just to use WireGuard? Then you have full control over the tunnel (you can use FQDN in wireguard configs)

When creating a new VPN, you can now choose Wireguard!

image

@angusdavis2
Copy link

Yes, I see the option to create a WireGuard VPN server, but I don't believe the remote UDM Pro can be setup to act as a WireGuard VPN client to enable to a site-to-site VPN -- the only supported protocol for UDM Pro VPN Client is OpenVPN. Maybe I am misunderstanding.

@LanceMcCarthy
Copy link
Author

Hmm, I've never attempted to use wg as a client with UDM Pro, but my experience with wg is that each peer is just a node of the network, there really isn't a strict hub-spoke (Server-client) model... it's peer-to-peer. So I assumed this would work similarly with UDM Pro, regardless if they've put wireguard in the same menu as other "VPN Server" settings page.

@angusdavis2
Copy link

Unfortunately, I am not finding any examples of connecting two UDMs site-to-site using WireGuard (though under the covers, Magic Sites appears to be using WireGuard to create the site-to-site VPN).

I think I just need to continue investigating the best way to force certain routing. It's unusual because when you setup magic sites, the "gateway" for the wireguard VPN it creates is a .0 address, so it's not really clear what the real gateway IP address would be to direct traffic out over that interface:

# ip route show
...
192.168.1.0 dev wgsts1000 proto kernel scope link
192.168.2.0/24 via 192.168.1.0 dev wgsts1000 proto ospf metric 20 onlink

@saltorico
Copy link

Did you get this to work? I didn't realise Site Magic uses WireGuard.
I'm a newbie, trying to use Site Magic, below my adventure

newbie on Ubiquity, and networks so please bear with me.
Two sites. both managed by UDM Pro. Site 1: UDM Pro has a public IP, Site 2 is behind NAT. UniFi OS 3.2.12 on both.
Site 1 has 1 UDM ethernet port reserved for vlan 10.0.0.0/24, default network set to 192.168.168.0/24
Site 2, UDM behind NAT, default network set to 192.168.168.3/24 and no devices connected, vlan with same id is set up, with 10.0.1.0/24 (not used)

My Use case

funnel all of Site1's vlan traffic (internet, ipsex) to egress to internet in Site 2
Sites have been connected with Site Magic/Site Manager (connecting both default networks and both vlans), which sets the config up in seconds and doesn't mind Site 2 being behind NAT. I have not yet investigated putting its modem in bridge mode, not sure of the ISP will play nicely.

What works:

IP allocation to the VLAN, based on the ports, addressing (virtual) hosts e.g. 10.0.1.1 in Site 2 from Site 1's vlan'ed clients.
Internet traffic as you'd expect egresses in Site 1
'ip link show' confirms the SiteToSite link:
39: wgsts1000: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 (set up by wireguard as the name of the link suggests)

link/none

What's not so clear:

the IP of the link as per above doesn't appear set, appears to be 192.168.1.1 as .2 shows up for teleport in site magic, and the 192.168.1.1 can be pinged.
As Site manager and udm web console are limited, I'm not sure how to proceed, any views welcome.

What I have carefully tried, is to figure out what site magic has configured, as it shows FYI in the web console, using SSH i can see it's been busy creating a wgsts1000 vpn interface (using wgsts as identifier):

ip route list table all | grep wgsts

default dev wgsts1000 table 001.wgsts1000 proto kernel scope link

192.168.1.1 dev wgsts1000 proto kernel scope link

local 192.168.1.0 dev wgsts1000 table local proto kernel scope host src 192.168.1.0

ff00::/8 dev wgsts1000 table local metric 256 pref medium

ff00::/8 dev wgsts1000 table local metric 256 pref medium

So far as expected / using the web console.

Attempt to route all (internet+ipsec traffic) to the tunnel, as i can't select the tunnel as routing target from the web interface:

on udm pro site 1, i added the routing and rule, to send all (!!) traffic through the vpn and a rule to use a custom table (added to/etc/iproute2/rt_tables well knowing upgrades could wipe it ) and to route all traffic via de (assumed IP) of the VPN tunnel. It did not have the effect, in my trial and error earlier i got some traffic through the tunnel, but regardless of keeping notes, can't repeat it.

Scenic route (pun intended) follows

ip rule add from 10.0.0.0/24 table wgsts1000a

ip route add default via 192.168.1.1 dev wgsts1000 table wgsts1000a

This indeed seems to force the vlan traffic into the vpn, all of it.

On Site 2, updated NAT updated, as I believe this is needed. Eth8 is the right port for traffic that on site 2 hasn't been set up to be routed, as it's not assuming it SHOULD route 10.0.0.0/24 to its ethernet wan port:

iptables -t nat -I POSTROUTING 1 -s 10.0.0.0/24 -o eth8 -j MASQUERADE

iptables -t nat -L POSTROUTING --line-numbers -n

Chain POSTROUTING (policy ACCEPT)

num target prot opt source destination

1 MASQUERADE all -- 10.0.0.0/24 0.0.0.0/0

2 UBIOS_POSTROUTING_JUMP all -- 0.0.0.0/0 0.0.0.0/0

Is it possible to adapt the wireguard config? Even if it doesn't survive a reboot?

@LanceMcCarthy
Copy link
Author

@saltorico I've ditched this approach because of the headache from it not persisting. More importantly, it's become so much easier using IPSec for dedicated Site-To-Site VPN (which it's looking like you're trying to do?).

Alternatively, if you really want a wireguard connection, you can now configure a client setup right in the UI!

image

@saltorico
Copy link

Thanks @LanceMcCarthy for the answer. Also site magic does wonders. Once either are in place, I would like all site a vlan internet bound traffic (non default 10.0.0.x to be tunnelled and egress in site b (different country).

Any idea how to combine the standard web interface for site to site like above or using site magic, and….. configuring site a to route its vlan internet traffic to site b?

@saltorico
Copy link

Or… are you using above wirevueard solution to build a site 2 site vpn?

@LanceMcCarthy
Copy link
Author

I have a similar setup and use the IPsec VPN to handle all the traffic. The trick is you need to make sure those subnets are listed and you have all corners of the traffic connected.

For example, I no longer use my homes' IP addresses for my DNS, instead I have my public-facing things point ot Azure Linux VM. then that Linux VM is connected to site-to-site VPNs to both opf my UDM Pros.

Inside azure VM I am running https://nginxproxymanager.com (super easy reverse proxy with automatic Let's Encrypt), that redirects traffic down to 192.168.x.0/24 which send traffic down the correct VPN.

image

No wireguard at all, it's pure IP sec site-to-site VPN and using that other UDM Pro's WAN IP:

image

I would recommend hitting up https://networkengineering.stackexchange.com/questions to get help from real network engineers ;)

also Reddit is sometimes helpful

@saltorico
Copy link

Many thanks for taking the time to explain. let me see what works for me, I'm not keen on setting up other hardware next to the UDMs

@leonardpitzu
Copy link

I have a Unifi Cloud Gateway Max that connects over PPPoE to my ISP. The IP on WAN changes upon every connection or, otherwise, every a few days. I have set up a simple VPN server (IPSEC L2TP) for the iOS devices around. The connection works great until the WAN receives a new IP. Unless I manually adapt the VPN settings i am not able to set up the VPN tunnel any more.
I briefly looked over your script to adapt it to my constellation but i have no idea where the VPN connection file is stored on the system (nor if the same setup applies for VPN servers). Do you have some insight/hints how to try and solve this issue? (I’m new to UCG but not to networking or Linux). I already have a ticket and am waiting for feedback but given similar issues other have i do not hold my hopes high for a quick fix.

@saltorico
Copy link

I got a stable setup eventually without using the script. Rather than using site magic, I defined a VPN server with wire guard on the unify dream machine pro connected to a fixed IP. That I use for my normal IOS VPN needs to egress at that site.

The original need of forcing egress in another country wasn’t possible with site magic or the above script. Instead and only once I got a fixed IP (although it will change from time to time) the extended NAT applied by the provider was disabled, only leaving local NAT between my cable modem and the UDM pro. That was enough to define a normal wireguard VPN manually with the UDM interface for the other site to connect TO. Once I had a named connection from my remote site, the UDM on that site is configured to route certain clients through the named VPN tunnel. The trick was to set it up manually (in UDM console, not above script) because that allows the traffic to be directed by UDM based on say MAC addresses.

The setup works well and stable. At the remote site UDM Pro is my main router and it’s IP address isn’t NATted by a modem. It also doesn’t tend to change. But who knows how stable it will be if it would. In any case it can set up the vpn to the other UDM in another country, even though that UDM Pro is behind NAT of my router there. It only started working when the provider NAT was disabled and having a dynamic but fixed IP. The local NAT is skipped by exposing the UDM Pro as server, as it handles outside attacks elegantly, this is no issue. The VPN is set up quickly and the traffic gets routed to the UDM in the other country only for the few clients, regardless of wired or wireless connection as the UDM Pro handles dhcp and traffic routing.

Result is a stable connection where a few selected clients are routed to egress at my “other” UDM router, and this allows for a company IPsec VPN to be set up on top of the site to site VPN.

If I’m at the other end, I tend to set up client vpns to just be able to watch my streaming service of choice that’s not available in that country.

It took a while to figure it out, and I got my entire site cut off from the interwebs more than once. But I’m happy with this setup.

@LanceMcCarthy
Copy link
Author

I should probably put a note at the top of the script to say that it's largely outdated and it's not a great idea to play with the containers. UniFi OS/Network has come a long way and supports DDNS (which was my saving grace with IPsec) and Wireguard.

@leonardpitzu DDNS was the solution for me, go to https://freedns.afraid.org/signup/?plan=starter and get up to 3 free DDNS addresses. The UDM Pro will automatically update them when the WAN IP changes (one of my UDMs are on a fiber PPPoE and IP changes frequently)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment