Nat – strongSwan setup where both sides are behind NAT

ipsecnat;strongswanvpn

I'm trying to setup a strongSwan server in my home and connect to it from another network. Let's say sun is the VPN server and venus is the client. Both sun and venus are behind NAT networks. sun is not the gateway of my home networks. However, ports 4500, 500 and 50 (UDP) are forwarded to sun.

ipsec.conf (sun)

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
    charonstart=yes
    plutostart=no

conn venus
     left=%any
     leftcert=sunCert.pem
     right=%any
     leftsubnet=10.135.1.0/24
     rightid="C=IL, O=KrustyKrab, CN=venus"
     keyexchange=ikev2
     auto=add
     type=tunnel
     mobike=no

include /var/lib/strongswan/ipsec.conf.inc

ipsec.conf (venus)

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
    charonstart=yes
    plutostart=no

conn krustykrab
     left=%defaultroute
     leftsourceip=%config
     leftid="C=IL, O=KrustyKrab, CN=venus"
     leftcert=venusCert.pem
     right=x.x.x.x # My home public IP 
     rightsubnet=10.135.1.0/24
     rightid="C=IL, O=KrustyKrab, CN=sun"
     keyexchange=ikev2
     auto=start
     type=tunnel
     mobike=no

# include /var/lib/strongswan/ipsec.conf.inc

Sun's private IP is 10.135.1.200 and Venus's private IP is 192.168.10.200
This is what happens when I try to connect:

Sun (y.y.y.y is Venus's public IP):

13[NET] received packet: from y.y.y.y[500] to 10.135.1.200[500]
13[ENC] parsed IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) ]
13[IKE] y.y.y.y is initiating an IKE_SA
13[IKE] local host is behind NAT, sending keep alives
13[IKE] remote host is behind NAT
13[IKE] sending cert request for "C=IL, O=KrustyKrab, CN=KrustyKrab CA"
13[ENC] generating IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) CERTREQ N(MULT_AUTH) ]
13[NET] sending packet: from 10.135.1.200[500] to y.y.y.y[500]
14[IKE] sending keep alive
14[NET] sending packet: from 10.135.1.200[500] to y.y.y.y[500]
15[JOB] deleting half open IKE_SA after timeout

Venus (x.x.x.x is Sun's public IP)

13[IKE] initiating IKE_SA krustykrab[1] to x.x.x.x
13[ENC] generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) ]
13[NET] sending packet: from 192.168.10.200[500] to x.x.x.x[500]
14[NET] received packet: from x.x.x.x[500] to 192.168.10.200[500]
14[ENC] parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) CERTREQ N(MULT_AUTH) ]
14[IKE] local host is behind NAT, sending keep alives
14[IKE] remote host is behind NAT
14[IKE] received cert request for "C=IL, O=KrustyKrab, CN=KrustyKrab CA"
14[IKE] sending cert request for "C=IL, O=KrustyKrab, CN=KrustyKrab CA"
14[IKE] authentication of 'C=IL, O=KrustyKrab, CN=venus' (myself) with RSA signature successful
14[IKE] sending end entity cert "C=IL, O=KrustyKrab, CN=venus"
14[IKE] establishing CHILD_SA krustykrab
14[ENC] generating IKE_AUTH request 1 [ IDi CERT N(INIT_CONTACT) CERTREQ IDr AUTH CP(ADDR DNS) SA TSi TSr N(MULT_AUTH) N(EAP_ONLY) ]
14[NET] sending packet: from 192.168.10.200[4500] to x.x.x.x[4500]
09[IKE] retransmit 1 of request with message ID 1
09[NET] sending packet: from 192.168.10.200[4500] to x.x.x.x[4500]
10[IKE] retransmit 2 of request with message ID 1
10[NET] sending packet: from 192.168.10.200[4500] to x.x.x.x[4500]
11[IKE] retransmit 3 of request with message ID 1
11[NET] sending packet: from 192.168.10.200[4500] to x.x.x.x[4500]
14[IKE] sending keep alive
14[NET] sending packet: from 192.168.10.200[4500] to x.x.x.x[4500]
15[IKE] retransmit 4 of request with message ID 1
15[NET] sending packet: from 192.168.10.200[4500] to x.x.x.x[4500]
10[IKE] sending keep alive
10[NET] sending packet: from 192.168.10.200[4500] to x.x.x.x[4500]
12[IKE] sending keep alive
12[NET] sending packet: from 192.168.10.200[4500] to x.x.x.x[4500]
11[IKE] retransmit 5 of request with message ID 1
11[NET] sending packet: from 192.168.10.200[4500] to x.x.x.x[4500]

tcpdump in Venus:

16:57:42.389799 IP 192.168.10.200.500 > x.x.x.x.500: isakmp: parent_sa ikev2_init[I]
16:57:42.465073 IP x.x.x.x.500 > 192.168.10.200.500: isakmp: parent_sa ikev2_init[R]
16:57:42.712016 IP 192.168.10.200.4500 > x.x.x.x.4500: NONESP-encap: isakmp: child_sa  ikev2_auth[I]
16:57:42.712057 IP 192.168.10.200 > x.x.x.x: ip-proto-17
16:57:46.712854 IP 192.168.10.200.4500 > x.x.x.x.4500: NONESP-encap: isakmp: child_sa  ikev2_auth[I]
16:57:46.712911 IP 192.168.10.200 > x.x.x.x: ip-proto-17
16:57:53.913742 IP 192.168.10.200.4500 > x.x.x.x.4500: NONESP-encap: isakmp: child_sa  ikev2_auth[I]
16:57:53.913799 IP 192.168.10.200 > x.x.x.x: ip-proto-17
16:58:02.458669 IP x.x.x.x.500 > 192.168.10.200.500: [|isakmp]
16:58:06.874834 IP 192.168.10.200.4500 > x.x.x.x.4500: NONESP-encap: isakmp: child_sa  ikev2_auth[I]
16:58:06.874884 IP 192.168.10.200 > x.x.x.x: ip-proto-17

tcpdump in Sun:

16:59:06.521762 IP y.y.y.y.500 > 10.135.1.200.500: isakmp: parent_sa ikev2_init[I]
16:59:06.556423 IP 10.135.1.200.500 > y.y.y.y.500: isakmp: parent_sa ikev2_init[R]
16:59:26.556324 IP 10.135.1.200.500 > y.y.y.y.500: [|isakmp]

It seems that sun doesn't get packets in port 4500, which is odd, since I opened up a Python interpreter in venus and typed:

In [1]: from socket import *
In [2]: x = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
In [3]: x.sendto('', ('x.x.x.x', 4500))
Out[3]: 0

And the packet was received:

17:02:45.246769 IP y.y.y.y.44335 > 10.135.1.200.4500: [|isakmp]

I also tried setting

port_nat_t = 6000

In charon section in both sides, but they still try to use port 4500

Best Answer

Due to the certificates and certificate requests IKE_AUTH messages can get quite large, so much so that they have to be fragmented on the IP layer (you can see those fragments in the tcpdump capture at venus). Perhaps the NAT box at sun has problems reassembling fragmented packets or just drops them.

As a workaround, you can try installing the two peer's certificates on both sides, then configure rightcert accordingly so that it points to the file containing the certificate of the other peer.

With that done, you can configure rightsendcert=never on both ends, to avoid that certificate requests are being sent. Because leftsendcert defaults to ifasked the peers ultimately won't send their certificates and the message size should be small enough to avoid IP fragments.

By the way, you don't have to open UDP port 50. Without NAT traversal you'd need to allow IP protocol 50 (ESP), but if a NAT is involved ESP packets get UDP encapsulated so opening UDP ports 500 and 4500 is sufficient.