[strongSwan] NAT over VPN

Mirko Parthey mirko.parthey at informatik.tu-chemnitz.de
Sat Nov 23 14:29:30 CET 2013


On Fri, Nov 22, 2013 at 05:52:21PM +0000, Will Wykeham wrote:
> I've got a local subnet with statically assigned address - 10.65.112.0/22. One
> of the devices is a linux box acting as a gateway with a PPP connection, it has
> a normal ethernet controller with address 10.65.112.69, and when the PPP
> connection is up it has an assigned address of 10.1.20.19.
> 
> Also on the local subnet is another machine (Windows as it happens),
> 10.65.112.174, with gateway set to the .69 machine.
> 
> Prior to integrating the VPN, I had some normal NAT going on so that the
> Windows box could communicate with the outside world, but using the "public" IP
> of 10.1.20.19. A fairly standard sort of rule:
> iptables --table nat --append POSTROUTING --out-interface ppp0 -j MASQUERADE
> 
> This worked fine - I could ping other devices on the public net directly from
> the Windows box.
> 
> I've now got an IPSEC based VPN, with the following connection setup:
> 
> conn MYCONN
> left=%defaultroute
> leftsourceip=%config
> right=10.1.40.1
> rightsubnet=10.31.21.0/24
> auto=add
> 
> This VPN works fine and from the Linux gateway I can ping remote devices
> (10.31.21.XXX) without any problem. If I add in my NAT rule again though,
> everything breaks - I can't ping from the local machine or the Windows box. The
> packets go out on the PPP interface but without being encapsulated, whether
> they've been locally or remotely generated.
> 
> My understanding of the iptables NAT table is that it takes place before it
> gets to the xfrm lookup (http://upload.wikimedia.org/wikipedia/commons/3/37/
> Netfilter-packet-flow.svg), and so once the source has been rewritten to
> 10.1.20.19, it should get picked up by the vpn and encapsulated, but that is
> clearly not what's happening.

Your IPsec connection is set up as host-to-net, but behind that host
(the gateway) you have multiple machines which want to use the IPsec
tunnel. I see this as the reason why you are trying to set up NAT for
both unprotected and IPsec-protected traffic.

A cleaner solution in my opinion would be to use NAT only for non-IPsec
traffic, and set up IPsec with a net-to-net connection. This requires
that you are able to change the configuration of both gateways, and
that IP addresses from the 10.65.112.0/22 range are routable inside
the remote subnet.
On the local gateway, replace leftsourceip=%config with
leftsubnet=10.65.112.0/22, and on the remote gateway, do the same for
rightsourceip and rightsubnet.
Then, set up your NAT rule such that it applies only to non-IPsec traffic:
  iptables -t nat -A POSTROUTING -o ppp0 -m policy --dir out --pol none -j MASQUERADE
and you should be done.

If you cannot meet these requirements, we are back to your original
question how to set up NAT in conjunction with IPsec.
You have to make sure that outgoing packets match the IPsec policy after
NAT processing. In particular, the packet's sender IP address after NAT must
match the IPsec tunnel's internal source IP assigned by the %config mechanism.
If no policy matches, the packet is sent out in plain text.

> My understanding of the iptables NAT table is that it takes place before it
> gets to the xfrm lookup (http://upload.wikimedia.org/wikipedia/commons/3/37/
> Netfilter-packet-flow.svg), and so once the source has been rewritten to
> 10.1.20.19, it should get picked up by the vpn and encapsulated, but that is
> clearly not what's happening.

I would suggest to change your NAT rule as follows:
  iptables -t nat -A POSTROUTING -o ppp0 -j SNAT --to-source $ip_addr
where $ip_addr is the local internal source IP assigned by the remote
gateway. If that IP address comes from an address pool and changes
dynamically on connection establishment, the NAT rule needs to be
updated as well, for example inside an updown script.
Using "-j SNAT --to-source" instead of "-j MASQUERADE" gives you
control over the sender IP address after NAT, which may be needed to
match the IPsec policy.  I haven't used such a setup myself, but I am sure
others can correct any possible errors in my description.

By the way, you didn't say how you checked if outgoing packets are encrypted.
Using a packet sniffer on the gateway itself can give misleading results.
I'd recommend to either use a box separate from the gateway to monitor
the traffic, or read xfrm packet counters on the gateway with "ipsec
statusall".

Regards,
Mirko




More information about the Users mailing list