Intro/Background
I recently needed to configure an IPSec VPN tunnel between two Ubiquiti EdgeRouters. I did some searching, and the documentation was lacking or incomplete. I decided to write a post describing my setup process from start to finish.
In my test setup, I’ve got two Ubiquiti EdgeRouters. One is an EdgeRouter Lite, the other is an EdgeRotuer X, both on firmware 1.9.1 (the most current firmware as of when this was written). Both routers have external IPs on their WAN interfaces, and are not behind any other NAT. Both routers have been configured with the basic WAN+2LAN wizards, which adds a basic stateful firewall and NAT masquerade on the WAN interface. R1 has an external IP of 1.1.1.1 on eth0, and an internal subnet of 192.168.1.0/24. R2 has an external IP of 2.2.2.2 on eth1, and an internal subnet on 10.1.1.0/24. In the real world, you would ideally have static external IPs. This might work using hostnames with dynamic IPs, but I haven’t tested it.
Configuring the tunnel
I found this guide on Ubiquiti’s website, which shows some CLI commands to run. The screenshots of the configurations on that page must be dated though, because some of the commands aren’t correct.
I’m going to start by configuring the tunnels in the routers. SSH into the routers, and apply these commands:
For R1:
configure
set vpn ipsec esp-group vpntunnel
set vpn ipsec esp-group vpntunnel compression disable
set vpn ipsec esp-group vpntunnel proposal 1
set vpn ipsec esp-group vpntunnel proposal 1 encryption aes128
set vpn ipsec esp-group vpntunnel proposal 1 hash sha1
set vpn ipsec ike-group vpntunnel
set vpn ipsec ike-group vpntunnel proposal 1
set vpn ipsec ike-group vpntunnel proposal 1 encryption aes128
set vpn ipsec ike-group vpntunnel proposal 1 hash sha1
set vpn ipsec ipsec-interfaces interface eth0
set vpn ipsec site-to-site peer 2.2.2.2
set vpn ipsec site-to-site peer 2.2.2.2 local-address 1.1.1.1
set vpn ipsec site-to-site peer 2.2.2.2 authentication mode pre-shared-secret
set vpn ipsec site-to-site peer 2.2.2.2 authentication pre-shared-secret SuperSecretKey123
set vpn ipsec site-to-site peer 2.2.2.2 default-esp-group vpntunnel
set vpn ipsec site-to-site peer 2.2.2.2 ike-group vpntunnel
set vpn ipsec site-to-site peer 2.2.2.2 tunnel 1
set vpn ipsec site-to-site peer 2.2.2.2 tunnel 1 esp-group vpntunnel
set vpn ipsec site-to-site peer 2.2.2.2 tunnel 1 local prefix 192.168.1.0/24
set vpn ipsec site-to-site peer 2.2.2.2 tunnel 1 remote prefix 10.1.1.0/24
commit
exit
For R2:
configure
set vpn ipsec esp-group vpntunnel
set vpn ipsec esp-group vpntunnel compression disable
set vpn ipsec esp-group vpntunnel proposal 1
set vpn ipsec esp-group vpntunnel proposal 1 encryption aes128
set vpn ipsec esp-group vpntunnel proposal 1 hash sha1
set vpn ipsec ike-group vpntunnel
set vpn ipsec ike-group vpntunnel proposal 1
set vpn ipsec ike-group vpntunnel proposal 1 encryption aes128
set vpn ipsec ike-group vpntunnel proposal 1 hash sha1
set vpn ipsec ipsec-interfaces interface eth1
set vpn ipsec site-to-site peer 1.1.1.1
set vpn ipsec site-to-site peer 1.1.1.1 local-address 2.2.2.2
set vpn ipsec site-to-site peer 1.1.1.1 authentication mode pre-shared-secret
set vpn ipsec site-to-site peer 1.1.1.1 authentication pre-shared-secret SuperSecretKey123
set vpn ipsec site-to-site peer 1.1.1.1 default-esp-group vpntunnel
set vpn ipsec site-to-site peer 1.1.1.1 ike-group vpntunnel
set vpn ipsec site-to-site peer 1.1.1.1 tunnel 1
set vpn ipsec site-to-site peer 1.1.1.1 tunnel 1 esp-group vpntunnel
set vpn ipsec site-to-site peer 1.1.1.1 tunnel 1 local prefix 10.1.1.0/24
set vpn ipsec site-to-site peer 1.1.1.1 tunnel 1 remote prefix 192.168.1.0/24
commit
exit
Now that we have committed the changes and we have exited configuration mode, we’ll run show vpn ipsec status to check the status of the tunnel on R2.
show vpn ipsec status
IPSec Process Running PID: 11410
0 Active IPsec Tunnels
IPsec Interfaces :
Configuring the WAN_IN firewall to allow IPSec traffic
The tunnel isn’t up! What we have to do now is configure the WAN_LOCAL firewall on both routers to allow IPSec traffic in to the router. Make sure that the firewall rule numbers you configure are higher priority (smaller number) than the default “Drop invalid state” rule.
configure
set firewall name WAN_LOCAL rule 15
set firewall name WAN_LOCAL rule 15 action accept
set firewall name WAN_LOCAL rule 15 description AllowIPSec
set firewall name WAN_LOCAL rule 15 log disable
set firewall name WAN_LOCAL rule 15 protocol udp
set firewall name WAN_LOCAL rule 15 destination port 500,4500
set firewall name WAN_LOCAL rule 16
set firewall name WAN_LOCAL rule 16 action accept
set firewall name WAN_LOCAL rule 16 description AllowESP
set firewall name WAN_LOCAL rule 16 log disable
set firewall name WAN_LOCAL rule 16 protocol esp
commit
exit
Now that I’ve applied the above rules to both routers, let’s try that show vpn ipsec status command again.
show vpn ipsec status
IPSec Process Running PID: 11140
1 Active IPsec Tunnels
IPsec Interfaces :
The tunnel is now up! Let’s try to ping the local IP of R1 from R2.
ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
^C
--- 192.168.1.1 ping statistics ---
6 packets transmitted, 0 received, 100% packet loss, time 5008ms
No responses were received, so I interrupted the pings with control-c. The requests timed out. Let’s see if the traffic is actually traversing the tunnel. We’ll check this by running show vpn ipsec sa on R2.
show vpn ipsec sa
peer-1.1.1.1-tunnel-1: #2, ESTABLISHED, IKEv1, bb126d66e9ca4bdf:f2fccad0bcf04771
local '2.2.2.2' @ 2.2.2.2
remote '1.1.1.1' @ 1.1.1.1
AES_CBC-128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
established 246s ago, reauth in 27505s
peer-1.1.1.1-tunnel-1: #1, INSTALLED, TUNNEL, ESP:AES_CBC-128/HMAC_SHA1_96/MODP_1024
installed 246 ago, rekeying in 2298s, expires in 3354s
in caa4c413, 0 bytes, 0 packets
out ccaa54eb, 0 bytes, 0 packets
local 10.1.1.0/24
remote 192.168.1.0/24
Adding NAT Masquerade exclusion rules
Why are there 0 packets going out when I’m trying to ping across the tunnel? The packets need to be excluded from the NAT masquerade.
For R1:
configure
set service nat rule 5001
set service nat rule 5001 description ExcludeIPSecTunnel
set service nat rule 5001 inbound-interface eth0
set service nat rule 5001 log disable
set service nat rule 5001 protocol all
set service nat rule 5001 type masquerade
set service nat rule 5001 destination address 10.1.1.0/24
set service nat rule 5001 exclude
commit
exit
For R2:
configure
set service nat rule 5001
set service nat rule 5001 description ExcludeIPSecTunnel
set service nat rule 5001 inbound-interface eth1
set service nat rule 5001 log disable
set service nat rule 5001 protocol all
set service nat rule 5001 type masquerade
set service nat rule 5001 destination address 192.168.1.0/24
set service nat rule 5001 exclude
commit
exit
You may also have to recreate the default NAT masquerade with a lower priority (higher number) than this NAT exclusion rule. NAT masquerade rules need to be between 5000-10000. In this example, my default NAT masquerade on my WAN interface eth0 on R1 is rule 5000. I’m going to delete rule 5000 and recreate it as rule 5002, which is lower priority than the rule I created in the previous step.
For R1:
configure
delete service nat rule 5000
set service nat rule 5002
set service nat rule 5002 outbound-interface eth0
set service nat rule 5002 type masquerade
commit
exit
For R2:
configure
delete service nat rule 5000
set service nat rule 5002
set service nat rule 5002 outbound-interface eth1
set service nat rule 5002 type masquerade
commit
exit
Let’s try pinging the local IP of R1 from R2 again.
ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
^C
--- 192.168.1.1 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 4006ms
Pings still aren’t going through, so I interrupted the pings. Let’s check the VPN tunnel stats on R2 with show vpn ipsec sa.
show vpn ipsec sa
peer-1.1.1.1-tunnel-1: #2, ESTABLISHED, IKEv1, bb126d66e9ca4bdf:f2fccad0bcf04771
local '2.2.2.2' @ 2.2.2.2
remote '1.1.1.1' @ 1.1.1.1
AES_CBC-128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
established 2280s ago, reauth in 25471s
peer-1.1.1.1-tunnel-1: #1, INSTALLED, TUNNEL, ESP:AES_CBC-128/HMAC_SHA1_96/MODP_1024
installed 2280 ago, rekeying in 264s, expires in 1320s
in caa4c413, 0 bytes, 0 packets
out ccaa54eb, 420 bytes, 5 packets, 4s ago
local 10.1.1.0/24
remote 192.168.1.0/24
Allowing traffic from remote subnet through firewall
Progress! Pings are now traveling out the IPSec tunnel, but nothing is coming back. Now we’ll add rules to the WAN_IN and WAN_LOCAL firewalls on both routers to allow traffic in from the remote subnets. The WAN_LOCAL rule will allow us to communicate with the router on the other side of the tunnel, and the WAN_IN rule will allow us to communicate with the rest of the devices in that remote subnet. In the commands below, I’ve given the rules number 18. Make sure that 18 is higher priority (lower number) than the default drop invalid state rule.
For R1:
configure
set firewall name WAN_LOCAL rule 18
set firewall name WAN_LOCAL rule 18 action accept
set firewall name WAN_LOCAL rule 18 description AllowVPNsubnet
set firewall name WAN_LOCAL rule 18 log disable
set firewall name WAN_LOCAL rule 18 protocol all
set firewall name WAN_LOCAL rule 18 source address 10.1.1.0/24
set firewall name WAN_IN rule 18
set firewall name WAN_IN rule 18 action accept
set firewall name WAN_IN rule 18 description AllowVPNsubnet
set firewall name WAN_IN rule 18 log disable
set firewall name WAN_IN rule 18 protocol all
set firewall name WAN_IN rule 18 source address 10.1.1.0/24
commit
exit
For R2:
configure
set firewall name WAN_LOCAL rule 18
set firewall name WAN_LOCAL rule 18 action accept
set firewall name WAN_LOCAL rule 18 description AllowVPNsubnet
set firewall name WAN_LOCAL rule 18 log disable
set firewall name WAN_LOCAL rule 18 protocol all
set firewall name WAN_LOCAL rule 18 source address 192.168.1.0/24
set firewall name WAN_IN rule 18
set firewall name WAN_IN rule 18 action accept
set firewall name WAN_IN rule 18 description AllowVPNsubnet
set firewall name WAN_IN rule 18 log disable
set firewall name WAN_IN rule 18 protocol all
set firewall name WAN_IN rule 18 source address 192.168.1.0/24
commit
exit
Now I’m able to ping the router and a remote device across the IPSec tunnel. Here’s a test ping from R2 to a device in R1’s private subnet.
ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_req=1 ttl=127 time=16.5 ms
64 bytes from 192.168.1.2: icmp_req=2 ttl=127 time=19.9 ms
64 bytes from 192.168.1.2: icmp_req=3 ttl=127 time=18.9 ms
64 bytes from 192.168.1.2: icmp_req=4 ttl=127 time=17.1 ms
64 bytes from 192.168.1.2: icmp_req=5 ttl=127 time=20.5 ms
Conclusion
Finally, once everything is tested to be working properly, you’ll want to save your configs. I’ve intentionally not saved my configs, just in case I mess something up and need to revert back. When you save, your configurations will be retained after reboots. To save, enter:
configure
save
exit
For fun, I set up a continuous ping on the Windows machine (192.168.1.2) and pinged a network printer (10.1.1.2) in the remote subnet over the span of a few days.
Ping statistics for 10.1.1.2:
Packets: Sent = 311538, Received = 311242, Lost = 296 (0% loss),
Approximate round trip times in milli-seconds: Minimum = 9ms, Maximum = 1165ms, Average = 24ms
There were very few dropped packets, so I consider this tunnel to be pretty stable. Both sites have pretty stable internet connections.
You will need to modify the commands above accordingly to match your unique environment. Also, many/all of the above commands can be done in the GUI, too. The following is provided only as a reference. As always, test in a lab environment first!