• VyOS Networks Blog
  • How to setup an IPsec connection between two NATed peers: using id's and RSA keys

VyOS Networks Blog

Building an open source network OS for the people, together.

How to setup an IPsec connection between two NATed peers: using id's and RSA keys

Daniil Baturin
Posted 12 Jan, 2018

In the previous post from this series, we've discussed setting up an IPsec tunnel from a NATed router to a non-NATed one. The key point is that in the presence of NAT, the non-NATed side cannot identify the NATed peer by its public address, so a manually configured id is required.

What if both peers are NATed though? Suppose you are setting up a tunnel between two EC2 instances. They are both NATed, and this creates its own unique challenges: neither of them know their public addresses or can identify their peers by their public address. So, we need to solve two problems.

In this post, we'll setup a tunnel between two routers, let's call them "east" and "west". The "east" router will be the initiator, and "west" will be the responder.


A note on pre-shared keys

While there are many issues with PSKs that public key cryptography solves in an elegant way, such as the problem of exchanging them securely, there's also a specific pitfall associated with them in VyOS: if the local-address of the peer is set to 'any' and the peer is identified by an id rather than public address, it won't allow you to use a pre-shared key for that peer. I have to admit I don't remember if this is a fundamental issue or an implementation detail, and perhaps we can lift this limitation at some point, but as of 1.1.8 and the current builds of 1.2.0, you have to use RSA keys or x.509 for authentication in this kind of setup.

Setting up RSA keys

We will not touch x.509 just yet and will focus on "certless" RSA keys in this post. They are very fast and easy to setup. The only real disadvantage is that some IPsec implementation do not support them and require either pre-shared keys or x.509 certificates, but in our example both sides are running VyOS and this is not an issue.

To generate an RSA key, use this command: "run generate vpn rsa-key bits 2048 random /dev/urandom".

Adjust the key length to match the size and style of your tinfoil hat. Mine looks fine with 2048, though setting it to 4096 won't harm. There is also an option to use /dev/random, but on virtual machines it can be impractical due to long blocking time, and contrary to the popular misconception, neither is /dev/random a source of "true" (information theoretically secure) random numbers, nor is /dev/urandom always inherently insecure. Let's generate a key on the West router.

vyos@west# run generate vpn rsa-key bits 2048 random /dev/urandom
Generating rsa-key to /config/ipsec.d/rsa-keys/localhost.key

Your new local RSA key has been generated
The public portion of the key is:

0sAQO8DJuyosdeE1VQnRUdsPGYFJ5gBsj4qYurjUv+/Jn5qSJJSvLYONNCDYfRDj/me5WGAtGwqmikD00oiLdCqR0FOZJTEQoEWeEh7YnOd4MEIWdeOLFRnGeETcoxGX63S7mxfol4/CVw/9n/kXRRHCnNsgYROsygZLlQIRK7hWAq3L6O1WT7Y3s7dHekXN+Ev6UbtZWQq8lejgmO0TR2ZAF3y6iBETW4Q93ARlhUva/ubBjg2oqtuX9u5UpxWTowuNycY44jm3+vjWczPtcYvvlXNt6nSGoORoHPdBeVyzU7yGIf+TcPKXTiro1JO20gwFv1dPTOLucmgEhjhuO86fFf

Save the public key somewhere. If you clear the screen before copying it, don't worry, you can always find the public key in /config/ipsec.d/rsa-keys/localhost.key file, in its "pubkey=..." section.

Now add the West key to the East router so that we can reference it in the IPsec settings:


vyos@east# set vpn rsa-keys rsa-key-name east rsa-key 0sAQO8DJuyosdeE1V...

Repeat the procedure on the second router.

IPsec setup

Now that both routers have each other's keys, we can setup the actual tunnel. The key points:

  1. Since both routers do not know their effective public addresses, we set the local-address of the peer to "any".
  2. On the initiator, we set the peer address to its public address, but on the responder we only set the id.
  3. On the initiator, we need to set the remote-id option so that it can identify IKE traffic from the responder correctly.
  4. On the responder, we need to set the local id so that initiator can know who's talking to it for the point #3 to work.
  5. Don't forget to enable NAT traversal on both sides, "set vpn ipsec nat-traversal enable".

Let's look at the configs:

The East side:

vyos@east# show vpn
ipsec {
[SNIP, IKE/ESP groups are irrelevant]
ipsec-interfaces {
interface eth0
}
nat-traversal enable
site-to-site {
peer 192.0.2.60 {
authentication {
id @east
mode rsa
remote-id west
rsa-key-name west
}
connection-type initiate
default-esp-group Foo
ike-group Foo
local-address any
tunnel 1 {
local {
prefix 10.36.63.0/24
}
remote {
prefix 10.45.54.0/24
}
}
}
}
}
rsa-keys {
rsa-key-name west {
rsa-key 0sAQO8DJuyosdeE1VQnRUdsPGYFJ5gBsj4qYurjUv+/Jn5qSJJSvLYONNCDYfRDj/me5WGAtGwqmikD00oiLdCqR0FOZJTEQoEWeEh7YnOd4MEIWdeOLFRnGeETcoxGX63S7mxfol4/CVw/9n/kXRRHCnNsgYROsygZLlQIRK7hWAq3L6O1WT7Y3s7dHekXN+Ev6UbtZWQq8lejgmO0TR2ZAF3y6iBETW4Q93ARlhUva/ubBjg2oqtuX9u5UpxWTowuNycY44jm3+vjWczPtcYvvlXNt6nSGoORoHPdBeVyzU7yGIf+TcPKXTiro1JO20gwFv1dPTOLucmgEhjhuO86fFf
}
}

The West side:

vyos@west# show vpn
ipsec {
[SNIP]
ipsec-interfaces {
interface eth0
}
nat-traversal enable
site-to-site {
peer @east {
authentication {
id west
mode rsa
rsa-key-name east
}
connection-type respond
default-esp-group Foo
ike-group Foo
local-address any
tunnel 1 {
local {
prefix 10.45.54.0/24
}
remote {
prefix 10.36.63.0/24
}
}
}
}
}
rsa-keys {
rsa-key-name east {
rsa-key 0sAQO7OF/FKgx33E5I29HSy2cqLnL9hNZ6CMbR8kVRIKhqAowIAskh13+gJN2QKOvLfbjN29uy94W02tty5G7+S+xOPeMsCJyz+ofD/v5tJpqIUughngCAGEoB6uveRRfqF15sOetEgjUGPmcVU+neOJ822E2T1sYbnEVfd+vilNPFopzlY61gtWgq7m7ANe2logwSB5XWyQkgCDNi+8IqVyFhNTVbmxDyfJQ1T4/3sRgcEh5XdZhSqRIwxI7/m2jH1FfIGg0FX5+5ok0bBmRU3tMkUKMB1A4QqgXPXR5P0SMDEkfo6zkbsueAX1NEOKXO443r5aKzA1qAGKV0Zp0sriuR
}
}

Now if we look in the logs, we will see the following picture:

Jan 12 06:24:23 east pluto[28278]: "peer-192.0.2.60-tunnel-1" #1: enabling possible NAT-traversal with method 3
Jan 12 06:24:23 east pluto[28278]: "peer-192.0.2.60-tunnel-1" #1: NAT-Traversal: Result using RFC 3947: both are NATed
Jan 12 06:24:23 east pluto[28278]: "peer-192.0.2.60-tunnel-1" #1: we don't have a cert
Jan 12 06:24:23 east pluto[28278]: "peer-192.0.2.60-tunnel-1" #1: Peer ID is ID_FQDN: 'west'
Jan 12 06:24:23 east pluto[28278]: "peer-192.0.2.60-tunnel-1" #1: ISAKMP SA established
Jan 12 06:24:23 east pluto[28278]: "peer-192.0.2.60-tunnel-1" #2: initiating Quick Mode PUBKEY+ENCRYPT+TUNNEL+PFS+UP {using isakmp#1}
Jan 12 06:24:23 east pluto[28278]: "peer-192.0.2.60-tunnel-1" #2: sent QI2, IPsec SA established {ESP=>0xc9bf71e1 <0xc32e1a3a NATOA=0.0.0.0}

This concludes the all-NATed IPsec setup.

The post categories:

Comments