Score:1

StrongSwan swanctl/xfrm: How to masquerade tunneled traffic?

cn flag
  • Ubuntu 20.04LTS
  • strongSwan swanctl 5.8.2
  • Linux 5.8.0-1035-gcp

I'm trying to setup an IKEv2 "roadwarrior" VPN that defers radius authentication to our upstream server. The good news is, I can get clients to connect and pass RADIUS auth. But, I've tried about a million things, but I cannot get packets to forward. I do see traffic arriving in the tunnel, but it will not NAT outbound. Notice my attempts to in the updown script to attempt to NAT traffic to no avail (currently commented out).

Here's the configuration:

sudo tee /etc/strongswan.d/charon-systemd.conf  << "EOF"
charon-systemd {
#  install_virtual_ip=no
#  install_routes=0
  load=random nonce aes sha1 sha2 hmac pem pkcs1 x509 revocation curve25519 gmp curl kernel-netlink socket-default updown vici eap-radius eap-identity
  journal {
   # Loglevel for a specific subsystem.
   # <subsystem> = <default>
   # Default loglevel.
   default=2
   enc=1
   asn=1
  }

  plugins {
    eap-radius {
      servers {
        primary {
          address=10.128.0.13
          secret=super-duper-secret
          auth_port=21812
        }
      }
    }
  }
}
EOF

sudo tee /etc/swanctl/conf.d/vpn.conf << "EOF"
connections {
  rw-eap {
    version=2
    proposals=aes128gcm16-sha256-modp2048
    local_addrs=10.128.0.14
    send_cert=always
    pools=dhcp_ipv4
    local {
      auth=pubkey
      certs=vpn.pem
      id=vpn.xxx.com
    }
    remote {
      auth=eap-radius
      id=*
    }
    children {
      net {
        local_ts=0.0.0.0/0
        remote_ts=172.16.20.64/26
        if_id_in=%unique
        if_id_out=%unique
        mark_in=%unique
        mark_out=%unique
        updown=/usr/local/bin/rw-updown.sh
        esp_proposals=aes128gcm16-sha256-modp2048
      }
    }
  }
}
pools {
  dhcp_ipv4 {
    addrs=172.16.20.64/26
    dns=10.128.0.9
  }
}
EOF

tee /usr/local/bin/rw-updown.sh << "EOF"
#!/bin/bash

set -o nounset
set -o errexit

XFRM_IF="xfrm${PLUTO_UNIQUEID}"

case "${PLUTO_VERB}" in
    up-client)
        logger -t "vpn rw-updown" ${PLUTO_VERB} ${PLUTO_UNIQUEID} ${XFRM_IF} ${PLUTO_ME} ${PLUTO_PEER} ${PLUTO_MARK_OUT%%/*} ${PLUTO_PEER_SOURCEIP}
        ip link add ${XFRM_IF} type xfrm dev ens4 if_id ${PLUTO_UNIQUEID}
        ip link set ${XFRM_IF} up
#        iptables -A FORWARD --in-interface ${XFRM_IF} -j ACCEPT
#        iptables --table nat -A POSTROUTING --out-interface ens4 -j MASQUERADE
        ;;
    down-client)
#        iptables -D FORWARD --in-interface ${XFRM_IF} -j ACCEPT
#        iptables --table nat -D POSTROUTING --out-interface ens4 -j MASQUERADE
        ip link del ${XFRM_IF}
        ;;
esac
EOF
chmod +x /usr/local/bin/rw-updown.sh

So after a client connects, we do see the interface created:

root@vpn-iowa:~# ip xfrm policy 
src 0.0.0.0/0 dst 172.16.20.64/26 
    dir out priority 386687 
    mark 0x2/0xffffffff 
    tmpl src 10.128.0.14 dst 173.197.16.118
        proto esp spi 0x08547b23 reqid 2 mode tunnel
    if_id 0x2
src 172.16.20.64/26 dst 0.0.0.0/0 
    dir fwd priority 386687 
    mark 0x2/0xffffffff 
    tmpl src 173.197.16.118 dst 10.128.0.14
        proto esp reqid 2 mode tunnel
    if_id 0x2
src 172.16.20.64/26 dst 0.0.0.0/0 
    dir in priority 386687 
    mark 0x2/0xffffffff 
    tmpl src 173.197.16.118 dst 10.128.0.14
        proto esp reqid 2 mode tunnel
    if_id 0x2
src 0.0.0.0/0 dst 0.0.0.0/0 
    socket in priority 0 
src 0.0.0.0/0 dst 0.0.0.0/0 
    socket out priority 0 
src 0.0.0.0/0 dst 0.0.0.0/0 
    socket in priority 0

... more

And running a steady ping 1.1.1.1 on the client causes traffic to arrive RX packets 246:

root@vpn-iowa:~# ifconfig
ens4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1460
        inet 10.128.0.14  netmask 255.255.255.255  broadcast 0.0.0.0
        inet6 fe80::4001:aff:fe80:e  prefixlen 64  scopeid 0x20<link>
        ether 42:01:0a:80:00:0e  txqueuelen 1000  (Ethernet)
        RX packets 2668  bytes 444824 (444.8 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1907  bytes 586712 (586.7 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 140  bytes 13208 (13.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 140  bytes 13208 (13.2 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

xfrm2: flags=193<UP,RUNNING,NOARP>  mtu 1500
        inet6 fe80::85d9:2aa5:841:803f  prefixlen 64  scopeid 0x20<link>
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 1000  (UNSPEC)
        RX packets 246  bytes 18819 (18.8 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

I will forever be in your debt if you can help me with this. I've read a million resources and still cannot figure this out. Thank you!

cn flag
Why would you assign interface IDs AND marks? (The latter actually requires marking the traffic manually.) Did you read the page on [route-based VPN](https://wiki.strongswan.org/projects/strongswan/wiki/RouteBasedVPN) on the strongSwan wiki? And regarding the forwarding, did you read [this wiki page](https://wiki.strongswan.org/projects/strongswan/wiki/ForwardingAndSplitTunneling)?
Jonathan S. Fisher avatar
cn flag
First thanks for taking the time to respond :) The marks were leftover from when I was trying to use vti instead of xfrm. I can remove them, but it doesn't make a difference. I've read both pages. I have IP Forwarding enabled in sysctl. I've tried both route based and policy based and I can't get either working. I'd rather have a route based vpn, but at this point I just need _anything_ to work
cn flag
Definitely remove the marks. You'll need a NAT (no need to install it in an updown script, in particular if you expect multiple clients). You also need a route to the client's virtual IP via XFRM interface (check the VTI example script on the first page I linked above, you can do this similarly for XFRM interfaces). However, you could also just use a single interface and route (for the whole `172.16.20.64/26` subnet) and get rid of the updown script (configure the static interface ID in the config instead of `%unique`).
Jonathan S. Fisher avatar
cn flag
awesome, thank you
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.