Creating an IPSEC vpn from openwrt router using Strong Swan

Team,

I have a small GL-MT1300 router running openwrt. I am planning on using this device as an alternative to the raspberry pi for a guest wifi hotspot self service wifi access project.

I have configured an IPSEC tunnel using strongwan on the GL-MT1300 router running openwrt. The IPSEC tunnel comes up but I can't get specific source traffic to route through the tunnel.

The tunnel to the remote VPN device comes up but my guest wifi subnet doesn't get routed through the IPSEC tunnel, it gets routed out to the wan port.

I had the same issue years ago when I first configured IPSEC tunnels on the raspberry pi, and I was able to fix it by adding the following commands on the ipv4 tables to force guest wifi user traffic through the IPSEC tunnel by adding an explicit exemption rule before the MASQUERADE rule. See yellow highlighted line below.

# Generated by xtables-save v1.8.2 on Sat Jun 5 10:06:20 2021

*nat

:PREROUTING ACCEPT [0:0]

:INPUT ACCEPT [0:0]

:POSTROUTING ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

-A POSTROUTING -m policy --dir out --pol ipsec -j ACCEPT

-A POSTROUTING -j MASQUERADE

COMMIT

This way I can control what IP's get forced to the IPSEC tunnel using the /etc/ipsec.conf file. In the below example, on the range 10.3.141.128/25

gets routed to the vpn tunnel.

conn fra4-vpn.zscalerbeta.net

left=%any

leftsubnet=10.3.141.128/25

aggressive=yes

authby=secret

leftid=xxxx@yyyyyyyy

leftfirewall=no

right=x.x.x.x

rightsubnet=0.0.0.0/0

lifetime=60m

auto=add

In the above configuration, when the guests connect to the wifi SSID, they get an IP address in the range of 10.3.141.128/25, which I want to route to the IPSEC vpn tunnel. I only want this source IP /25 range to be routed via the IPSEC tunnel.

In the openwrt router, I don't see a file that is similar to the iptables file in the raspberry.

There is an /etc/config/firewall file but I am not sure how to configure it so it will force only the guest wifi IP range to the IPSEC tunnel.

I am wondering if any of you configured IPSEC tunnels using openwrt or have any ideas how to force wifi client IP's through the IPSEC tunnel, which does gets established when I bring it up.

Any suggestions?

Could you format console text using </> button
And post output of

ubus call system board

The modern way to do IPSEC is underneath XFRM tunnels also known as route-based. Unlike the original "policy based" IPSEC which buries everything in a special IPSEC section of the kernel, XFRM gives you a conventional interface that can be used with standard routing and firewall rules.

If you own the systems at both ends of the tunnel it would be much easier to leave IPSEC entirely and use WireGuard instead.

An ipsec status would also shed some light.

root@GL-MT1300:~# ipsec status
Security Associations (1 up, 0 connecting):
fra4-vpn.zscalerbeta.net[1]: ESTABLISHED 22 minutes ago, 192.168.13.105[ALTOIDS@lk.zscalerbeta.net]...165.225.72.39[165.225.72.39]
fra4-vpn.zscalerbeta.net{1}:  INSTALLED, TUNNEL, reqid 1, ESP in UDP SPIs: c7683616_i 0b8d29ba_o
fra4-vpn.zscalerbeta.net{1}:   192.168.9.128/25 === 0.0.0.0/0
root@GL-MT1300:~#

WireGuard or openVPN is not an option. Strong Swan IPSEC works great with the Raspberry Pi. I am trying to do the same using openwrt. I am almost there. The tunnel gets established but I can't figure out how to Force a source subnet into the IPSEC tunnel like I did on the Raspberry using this command in the iptables.
-A POSTROUTING -m policy --dir out --pol ipsec -j ACCEPT

Please post output of

ubus call system board

root@GL-MT1300:~# ubus call system board
{
        "kernel": "5.10.176",
        "hostname": "GL-MT1300",
        "system": "MediaTek MT7621 ver:1 eco:3",
        "model": "GL.iNet GL-MT1300",
        "board_name": "glinet,gl-mt1300",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "22.03.4",
                "revision": "r20123-38ccc47687",
                "target": "ramips/mt7621",
                "description": "OpenWrt 22.03.4 r20123-38ccc47687"
        }
}

Upgrade to 23.05.5 and migrate away from xtables. You are using iptables-legacy together with fw4 which will never work well aka "unpredictable results".

While busy considering read through this and review your ruleset. https://wiki.nftables.org/wiki-nftables/index.php/Supported_features_compared_to_xtables

Are you certain that this line is in the correct place before the general MASQUERADE?

iptables-legacy is not supposed to work together with nftables.

Is there a converter tool that I can use to convert the following iptables-legacy to nftables?


# Generated by xtables-save v1.8.2 on Sun Oct 20 21:25:45 2019
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -m policy --dir out --pol ipsec -j ACCEPT
-A POSTROUTING -j MASQUERADE
COMMIT
# Completed on Sun Oct 20 21:25:45 2019
# Generated by xtables-save v1.8.2 on Sun Oct 20 21:25:45 2019
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

Again I will point out that route-based IPSEC requires no direct kernel table rules, it can be set up using high-level configs in UCI. An XFRM interface works like any other L3 VPN tunnel-- attach an IP address to it (which inherently makes a route into it), give it a firewall zone, and set masq on that zone.

1 Like

In principle you can use iptables-translate from iptables-nft or on any desktop linux to get custom rule into nftables format where -m policy is replaced by nftables xfrm.
additionally pbr does the selective routing in more visual manner.

1 Like

Solved!

I was able to force any DHCP client with a source IP in the range of 
192.168.8.128/25 through the IPSEC tunnel, 
while all other traffic routes out the WAN interface by adding 
the following configuration in /etc/config/firewall 

config nat
        option name 'ipsec_out'
        option src_ip '192.168.8.128/25'
        option family 'ipv4'
        option dest_ip '0.0.0.0/0'
        option target 'ACCEPT'
        option src '*'
        list proto 'all'



1 Like

I have another issue after getting the VPN routing to work based on a source subnet. Without the VPN I get about 350Mbps throughput. When the VPN is up and traffic is traversing the Strong Swan IPSEC tunnel, I only get 25Mbps. Any ideas on how to increase the VPN bandwidth?

The limitation is very likely due to the weight of the encryption on the CPU. A more powerful router will help, or a VPN protocol that is more performant (such as WG, although you said it wasn't an option). Other than that, there's usually not much you can do to improve the VPN performance.

1 Like

I got a slight improvement by changing esp fom esp=aes-sha1 to esp=null-sha1 in /etc/ipsec.conf

With null encryption I get about 45Mbps.

But possibly at the expense of the security of the encryption. But this lends further credence to the fact that the bandwidth is CPU limited.

1 Like