Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save nahall/6b23603ce9df2500a4053b280071d1ad to your computer and use it in GitHub Desktop.
Save nahall/6b23603ce9df2500a4053b280071d1ad to your computer and use it in GitHub Desktop.
Connecting to a Ubiquiti Unifi VPN with a Linux machine
This guide assumes that you have already set up a Ubiquiti Unifi VPN following the guide:
https://help.ubnt.com/hc/en-us/articles/115005445768-UniFi-L2TP-Remote-Access-VPN-with-USG-as-RADIUS-Server
To configure a Linux machine to be able to connect remotely I followed these steps. This guide was written for Debian 8.
- In Debian install the "xl2tpd" and "strongswan" packages.
- Edit /etc/ipsec.conf to add the connection:
conn YOURVPNCONNECTIONNAME
authby=secret
pfs=no
auto=start
keyexchange=ikev1
keyingtries=3
dpddelay=15
dpdtimeout=45
dpdaction=clear
rekey=no
ikelifetime=3600
keylife=3600
type=transport
left=%defaultroute
leftprotoport=17/1701
# Replace IP address with your VPN server's IP
right=IPADDRESSOFVPNSERVER
rightprotoport=17/%any
ike=aes128-sha1-modp2048,aes256-sha1-modp4096,aes128-sha1-modp1536,aes256-sha1-modp2048,aes128-sha1-modp1024,aes256-sha1-modp1536,aes256-sha1-modp1024,3des-sha1-modp1024!
esp=aes128-sha1-modp2048,aes256-sha1-modp4096,aes128-sha1-modp1536,aes256-sha1-modp2048,aes128-sha1-modp1024,aes256-sha1-modp1536,aes256-sha1-modp1024!
- Edit /etc/ipsec.secrets to add the secret key for this connection:
  IPADDRESSOFVPNSERVER : PSK "SECRETPRESHAREDKEY"
- Edit /etc/xl2tpd/xl2tpd.conf to add this connection:
[lac YOURVPNCONNECTIONNAME]
lns = IPADDRESSOFVPNSERVER
ppp debug = yes
pppoptfile = /etc/ppp/options.l2tpd.client-YOURVPNCONNECTIONNAME
length bit = yes
- Create the file /etc/ppp/options.l2tpd.client-YOURVPNCONNECTIONNAME:
ipcp-accept-local
ipcp-accept-remote
noccp
refuse-eap
refuse-chap
noauth
idle 1800
mtu 1410
mru 1410
defaultroute
# Uncomment if you want to use the DNS servers of the VPN host:
#usepeerdns
debug
logfile /var/log/xl2tpd.log
connect-delay 5000
proxyarp
name VPNUSERNAME
password "VPNPASSWORD"
- Now to connect to the VPN create a script:
#!/bin/bash
echo "Connecting to VPN..."
echo "c YOURVPNCONNECTIONNAME" > /var/run/xl2tpd/l2tp-control
sleep 10
# To have all internet traffic routed through the VPN uncomment:
#ip route add default dev ppp0
# To only have a remote subnet routed through the VPN uncomment
# (this line assumes the remote subnet you want routed is 192.168.0.0/24 and the remote VPN end is 10.11.0.1:
ip route add 192.168.0.0/24 via 10.11.0.1 dev ppp0
- And to disconnect to the VPN create a script:
#!/bin/bash
ip route del default dev ppp0
ip route del 192.168.0.0/24 dev ppp0
echo "d YOURVPNCONNECTIONNAME" > /var/run/xl2tpd/l2tp-control
service xl2tpd restart
- Note that for these scripts I am assuming that the remote subnet we are interested in is 192.168.0.0/24
and the remote VPN gateway address is 10.11.0.1.
- You can also decide which line to uncomment based on if you want all traffic to be routed through the VPN
or to just route connections to the 192.168.0.0/24 subnet.
- If you want all traffic routed through the VPN you may want to uncomment the "usepeerdns" line in
/etc/ppp/options.l2tpd.client-YOURVPNCONNECTIONNAME so that DNS traffic flows through the VPN rather
than going to the local DNS server.
@brett-kimball
Copy link

Nice example, it worked great. One additional option I found useful, especially if multiple VPN connections are required, is to specify the ppp interface name manually by adding the following to /etc/ppp/options.l2tpd.client-YOURVPNCONNECTIONNAME:

ifname YOURIFACENAME

Then modify the connect/disconnect scripts to utilize the interface name instead of the default "ppp0".

@JnMik
Copy link

JnMik commented Feb 19, 2019

Hello guys,

In connect.sh file, on that line :

ip route add default dev ppp0

I end up with Cannot find device "ppp0".
Not quite sure what to do from here, does it have anything to do with pptp software ?

  • Ubuntu 16.04.3

@pjbisset
Copy link

I have the same issue as JnMik - for us newbies there must be something missing here. How is the interface ppp0 created?

@nahall
Copy link
Author

nahall commented May 11, 2020

It will give the error message "Cannot find device ppp0" if it was not successful connecting to the VPN. Check syslog for the messages about establishing the VPN link. If you want to reset everything and try again, run:

/etc/init.d/ipsec restart
/etc/init.d/xl2tpd restart

and then watch the log as you bring the VPN up.

But, I will also tell you that the VPN software on Unifi continues to be really flaky. Sometimes it gets in a weird state on the Unifi end where you need to SSH on to the Unifi and run "restart vpn" and then reconnect from your client. So if you used to be able to connect OK but are now getting this "Cannot find device ppp0" error, reset the vpn on Unifi's side and see if it can reconnect. This seems to happen a lot more often when there are Windows clients involved, and I've had much better success when only Linux clients connect to the VPN. But personally I've kind of given up on Ubiquiti fixing it and have switched my main VPN to use Wireguard instead. It is so much better and I highly recommend it. It is a little work to set up but once it is set up, it just works. I know you can get it to work on the Unifi device but I just have mine running on that end on a Raspberry Pi that also runs PiHole.

@pjbisset
Copy link

pjbisset commented May 11, 2020

Thanks - tried using networkmanager and strongswan and still get failed connection. Complains about encryption algorithm 3des_CBC not supported. I'm following the Ubiquiti doco page, but it does look like there is something wrong with their end. It is a little beyond my troubleshooting ability, so might investigate your suggestion. Thanks again.

One last update done the day after. Just tried connecting using my android phone's VPN service and it worked. So issue is on my Linux PC. Thanks again.

@llang629
Copy link

llang629 commented Feb 24, 2021

First of all, thank you to Nahall for assembling this guide! Best available for the task of configuring L2TP via command line on Ubuntu. Is any task more fraught with mystery and frustration than attempting to configure a VPN correctly?

My goal was to create an L2TP VPN linking a Ubiquiti USG and a Google Cloud Platform virtual machine instance running Ubuntu 18.04. These steps guided me to success. Let me share how I surmounted some obstacles particular to my journey, in the interest of paying forward the help.

A key observation is that two steps are involved: bringing up the IPsec tunnel, then bringing up L2TP inside that tunnel. Both steps must be successful, or you won't end up with a working VPN.

When debugging the IPsec connection, sudo swanctl --log on the USG command line is immensely helpful, as described in the main L2TP client configuration guide.

Finally you enter:
sudo ipsec down your-vpn
and see:
connection 'your-vpn' established successfully
Congratulations, your IPsec tunnel is up! But you're only half way through.

Hopefully, L2TP should just connect when instructed by the command:
echo "c your-vpn" > /var/run/xl2tpd/l2tp-control
However, if it fails for some reason, the diagnostic symptom is that ppp0 will not have been added to the list of active interfaces, as seen with ifconfig. The subsequent commands to add routes will also fail, as experienced by JnMik and pjbisset. (As an aside, probably wise to add a route just for the subnet, because adding a default route for everything could unintentionally include your ssh connection and lock you out. Ouch.)

On my GCP instance, the L2TP connection command failed because the default user has insufficient permissions. The failure message is:
-bash: /var/run/xl2tpd/l2tp-control: Permission denied
Naturally, I tried:
sudo echo "c your-vpn" > /var/run/xl2tpd/l2tp-control
But that doesn’t work, because the permission problem is with l2tp-control, not echo.
The solution:
echo "c your-vpn" | sudo tee /var/run/xl2tpd/l2tp-control
And just like that, the L2TP tunnel came up and ppp0 appears in the interface list.
(Perhaps someone wiser in the arcana of named pipes could explain how to change the permissions of l2tp-control. And why couldn't xl2tp just use up/down commands like ipsec?)

One last thought: rather than adding routes in your connection script, the system can do it automatically. Edit /etc/ppp/ip-up.d/route-traffic to include:

#!/bin/bash
NET="192.168.0.0/16" # set to your remote subnet(s)
IFACE="ppp0" # probably, but might be different on your system
route add -net ${NET} dev ${IFACE}

This script will be invoked when ppp0 comes up, adding the needed route. (Shout out to Vivek Gite for this nifty trick.)

Best of luck getting pings to flow through whatever VPN you're creating!

@nahall
Copy link
Author

nahall commented Feb 25, 2021

That's great, thanks for sharing that info! I'm sure someone will find your guide very helpful.

@jstlouis-psd
Copy link

Just used this to finally get my VPN connection working as well

@llang629 's follow up here is definitely recommended so the routes get started and removed automatically as you connect and disconnect.
Just don't be dumb like me and forget to add execute permissions to it :)

The only thing else that I needed to do was take out all the other methods for IKE but the one that the server is using in /etc/ipsec.conf
The esp list didn't seem to matter

To determine this I used ike-scan <server-ip> to check what the server is expecting.

$ ike-scan <Server-IP>

Starting ike-scan 1.9.4 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/)
<Server-IP>  Main Mode Handshake returned HDR=(CKY-R=ae242aea68e18d7a) SA=(Enc=3DES Hash=SHA1 Group=2:modp1024 Auth=PSK LifeType=Seconds LifeDuration=28800)....

Ending ike-scan 1.9.4: 1 hosts scanned in 0.010 seconds (104.72 hosts/sec).  1 returned handshake; 0 returned notify

Enc=3DES Hash=SHA1 Group=2:modp1024 = 3des-sha1-modp1024

I had to do this before the ipsec tunnel would even begin.

@nahall
Copy link
Author

nahall commented Oct 1, 2021

I hadn't tried this VPN in a while, and today when I tried it I was unable to connect (latest USG, client is running Debian Bullseye). The issue was that strongswan was rejecting some of the protocols that I originally had in there, which came from USG's version of strongswan which is older than what is running on Debian Bullseye.

I updated the gist to reflect what worked for me:

ike=aes128-sha1-modp2048,aes256-sha1-modp4096,aes128-sha1-modp1536,aes256-sha1-modp2048,aes128-sha1-modp1024,aes256-sha1-modp1536,aes256-sha1-modp1024,3des-sha1-modp1024!
esp=aes128-sha1-modp2048,aes256-sha1-modp4096,aes128-sha1-modp1536,aes256-sha1-modp2048,aes128-sha1-modp1024,aes256-sha1-modp1536,aes256-sha1-modp1024!

I previously had aes256-sha1 and 3des-sha1 in there, but newer strongswan doesn't like those anymore.

So if you have problems, make sure to check the charon.log carefully as the error messages aren't always very clear.

@jomomz
Copy link

jomomz commented Oct 1, 2021

I can confirm this worked for me as well

I hadn't tried this VPN in a while, and today when I tried it I was unable to connect (latest USG, client is running Debian Bullseye). The issue was that strongswan was rejecting some of the protocols that I originally had in there, which came from USG's version of strongswan which is older than what is running on Debian Bullseye.

I updated the gist to reflect what worked for me:

ike=aes128-sha1-modp2048,aes256-sha1-modp4096,aes128-sha1-modp1536,aes256-sha1-modp2048,aes128-sha1-modp1024,aes256-sha1-modp1536,aes256-sha1-modp1024,3des-sha1-modp1024!
esp=aes128-sha1-modp2048,aes256-sha1-modp4096,aes128-sha1-modp1536,aes256-sha1-modp2048,aes128-sha1-modp1024,aes256-sha1-modp1536,aes256-sha1-modp1024!

I previously had aes256-sha1 and 3des-sha1 in there, but newer strongswan doesn't like those anymore.

So if you have problems, make sure to check the charon.log carefully as the error messages aren't always very clear.

@maximede
Copy link

Hi all !
I have my vpn working correctly following this step, except that the connection drop every hour. Seems like an issue with the key lifetime but I'm not exactly sure what's the best way to solve that. Any idea ?

@nahall
Copy link
Author

nahall commented Oct 26, 2022

Hmm, that's strange, I haven't seen that. Have you tried increasing ikelifetime and keylife in /etc/ipsec.conf to see if that stops the drop? In my example they are set to 3600 seconds which corresponds to 1 hour so you could increase them and see if it goes longer without dropping. But it's not actually supposed to drop when that lifetime expires.

@maximede
Copy link

I think I won't be able to go higher than this since 3600s is also what's configured on UDM side ( in /run/strongswan/ipsec.d/tunnels/lns-l2tp-server.ipsec.l2tp.config) but I can try :)
This is the sequence of events I see in my logs if that helps :

Oct 26 12:33:02 servername pppd[312446]: sent [LCP EchoReq id=0x78 magic=0xf47f4c94]
Oct 26 12:33:02 servername charon: 16[IKE] sending DPD request
Oct 26 12:33:02 servername charon: 16[ENC] generating INFORMATIONAL_V1 request 3876004764 [ HASH N(DPD) ]
Oct 26 12:33:02 servername charon: 16[NET] sending packet: from {serverIP}[500] to {udmIP}[500] (92 bytes)
Oct 26 12:33:10 servername charon: 05[NET] received packet: from {udmIP}[500] to {serverIP}[500] (540 bytes)
Oct 26 12:33:10 servername charon: 05[ENC] parsed ID_PROT request 0 [ SA V V V V V ]
Oct 26 12:33:10 servername charon: 05[IKE] received XAuth vendor ID
Oct 26 12:33:10 servername charon: 05[IKE] received DPD vendor ID
Oct 26 12:33:10 servername charon: 05[IKE] received FRAGMENTATION vendor ID
Oct 26 12:33:10 servername charon: 05[IKE] received NAT-T (RFC 3947) vendor ID
Oct 26 12:33:10 servername charon: 05[IKE] received draft-ietf-ipsec-nat-t-ike-02\n vendor ID
Oct 26 12:33:10 servername charon: 05[IKE] {udmIP} is initiating a Main Mode IKE_SA
Oct 26 12:33:10 servername charon: 05[CFG] selected proposal: IKE:AES_CBC_128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_2048
Oct 26 12:33:10 servername charon: 05[ENC] generating ID_PROT response 0 [ SA V V V V ]
Oct 26 12:33:10 servername charon: 05[NET] sending packet: from {serverIP}[500] to {udmIP}[500] (160 bytes)
Oct 26 12:33:10 servername charon: 12[NET] received packet: from {udmIP}[500] to {serverIP}[500] (372 bytes)
Oct 26 12:33:10 servername charon: 12[ENC] parsed ID_PROT request 0 [ KE No NAT-D NAT-D ]
Oct 26 12:33:10 servername charon: 12[ENC] generating ID_PROT response 0 [ KE No NAT-D NAT-D ]
Oct 26 12:33:10 servername charon: 12[NET] sending packet: from {serverIP}[500] to {udmIP}[500] (372 bytes)
Oct 26 12:33:10 servername charon: 09[NET] received packet: from {udmIP}[500] to {serverIP}[500] (76 bytes)
Oct 26 12:33:10 servername charon: 09[ENC] parsed ID_PROT request 0 [ ID HASH ]
Oct 26 12:33:10 servername charon: 09[CFG] looking for pre-shared key peer configs matching {serverIP}...{udmIP}[{udmIP}]
Oct 26 12:33:10 servername charon: 09[CFG] selected peer config "UDM"
Oct 26 12:33:10 servername charon: 09[IKE] detected reauth of existing IKE_SA, adopting 1 children and 0 virtual IPs
Oct 26 12:33:10 servername charon: 09[IKE] schedule delete of duplicate IKE_SA for peer '{udmIP}' due to uniqueness policy and suspected reauthentication
Oct 26 12:33:10 servername charon: 09[IKE] IKE_SA UDM[24] established between {serverIP}[{serverIP}]...{udmIP}[{udmIP}]
Oct 26 12:33:10 servername charon: 09[ENC] generating ID_PROT response 0 [ ID HASH ]
Oct 26 12:33:10 servername charon: 09[NET] sending packet: from {serverIP}[500] to {udmIP}[500] (76 bytes)
Oct 26 12:33:10 servername charon: 11[NET] received packet: from {udmIP}[500] to {serverIP}[500] (572 bytes)
Oct 26 12:33:10 servername charon: 11[ENC] parsed QUICK_MODE request 3923868918 [ HASH SA No KE ID ID ]
Oct 26 12:33:10 servername charon: 11[CFG] selected proposal: ESP:AES_CBC_128/HMAC_SHA1_96/MODP_2048/NO_EXT_SEQ
Oct 26 12:33:10 servername charon: 11[IKE] received 3600s lifetime, configured 0s
Oct 26 12:33:10 servername charon: 11[ENC] generating QUICK_MODE response 3923868918 [ HASH SA No KE ID ID ]
Oct 26 12:33:10 servername charon: 11[NET] sending packet: from {serverIP}[500] to {udmIP}[500] (444 bytes)
Oct 26 12:33:10 servername charon: 08[NET] received packet: from {udmIP}[500] to {serverIP}[500] (60 bytes)
Oct 26 12:33:10 servername charon: 08[ENC] parsed QUICK_MODE request 3923868918 [ HASH ]
Oct 26 12:33:10 servername charon: 08[IKE] CHILD_SA UDM{3} established with SPIs c0c1d95b_i cf703f9a_o and TS {serverIP}/32[udp/l2f] === {udmIP}/32[udp]
Oct 26 12:33:11 servername xl2tpd[845]: check_control: Received out of order control packet on tunnel 41163 (got 62, expected 61)
Oct 26 12:33:11 servername xl2tpd[845]: handle_packet: bad control packet!
Oct 26 12:33:17 servername charon: 13[IKE] sending DPD request
Oct 26 12:33:17 servername charon: 13[ENC] generating INFORMATIONAL_V1 request 1354316911 [ HASH N(DPD) ]
Oct 26 12:33:17 servername charon: 13[NET] sending packet: from {serverIP}[500] to {udmIP}[500] (92 bytes)
Oct 26 12:33:20 servername charon: 10[IKE] deleting IKE_SA UDM[23] between {serverIP}[{serverIP}]...{udmIP}[{udmIP}]
Oct 26 12:33:20 servername charon: 10[IKE] sending DELETE for IKE_SA UDM[23]
Oct 26 12:33:20 servername charon: 10[ENC] generating INFORMATIONAL_V1 request 705273687 [ HASH D ]
Oct 26 12:33:20 servername charon: 10[NET] sending packet: from {serverIP}[500] to {udmIP}[500] (92 bytes)
Oct 26 12:33:26 servername charon: 16[NET] received packet: from {udmIP}[500] to {serverIP}[500] (92 bytes)
Oct 26 12:33:26 servername charon: 16[ENC] parsed INFORMATIONAL_V1 request 3966655131 [ HASH N(DPD) ]
Oct 26 12:33:26 servername charon: 16[ENC] generating INFORMATIONAL_V1 request 2641383276 [ HASH N(DPD_ACK) ]
Oct 26 12:33:26 servername charon: 16[NET] sending packet: from {serverIP}[500] to {udmIP}[500] (92 bytes)
Oct 26 12:33:27 servername xl2tpd[845]: Maximum retries exceeded for tunnel 62873.  Closing.
Oct 26 12:33:27 servername xl2tpd[845]: Terminating pppd: sending TERM signal to pid 312446

@nahall
Copy link
Author

nahall commented Oct 26, 2022

Sorry, I don't really know what's going on. I haven't tried doing this kind of VPN in a few months so I'm not sure if Ubiquiti has changed something or not. Is there anyone else following this gist who has seen this, or has a VPN that continues to work fine for more than 1 hour?

@pjbisset
Copy link

pjbisset commented Oct 26, 2022 via email

@emiller233
Copy link

will this work on the Unifi UDM as well?

@nahall
Copy link
Author

nahall commented Feb 4, 2023

will this work on the Unifi UDM as well?

I would think so but I haven't tried that.

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