Creating a site-to-site VPN with dynamic internet IP addresses with OPNSense - part01

Background

This is something that grind my gears: Limitations of the IPSec implementation, and lack of how-tos about the specifics at the title of this post.

That situation lead me to this “not so beautiful” solution, where i use client certificates do identify the peers.

Every time i’ve tried to create a site-to-site environment where the remote office had to forward everything to the main office (basically 0.0.0.0/0) before going to the internet i had to deal with these issues:

  • The internet IP Address had to be static.
    • This isn’t a reality on many places in Brazil. Not even CGNATs have fixed addresses that we could rely as Identifier of the remote office;
  • Deal with external dynamic DNS solutions, or implement it on bind;
  • Have a valid FQDN for server Certificates for Mutual RSA;
  • Some compatibility issues with Strongswan and proprietary players;

And after some days of lab, here is my recipe:

Scenario

My scenario while developing this solution was:

  • A main office with a static IP address and a FQDN (lets call it ipsec.example.net);
    • Let use 1.2.3.4 as external ip A entry for ipsec.example.net;
    • External ip at the remote office is dynamic;
  • An external nat for all known IPSec ports and icmp on a proprietary firewall to the server VM;
    • NAT will forward ipsec ports and icmp to my OPNSense main office VM;
  • All traffic MUST be redirected to the main office for deep inspection (https inspection, dlp, and all that stuff that the proprietary solution does pretty well) before goes to the internet;
  • Basically, there will be only 1 phase 2: 0.0.0.0/0 - 10.1.0.0/16. This /16 net will take care of all /24 networks inside the remote office;
  • OPNSense at the main office will have only one WAN interface, since it’s a ipsec box only.

Things i will not deal or explain on this article:

  • Masquerade/Hide Nat from the proprietary firewall to allow access to internet from the VPN;
  • Return route creation at the proprietary firewall: 10.1.0.0/16 - gw 172.16.2.1. so, internal services(intranet, webmail, etc) can be reached;
  • Take your time to create the firewall. I’ll not deal with this cause the main porpose of this setup is conectivity, not firewalling.
  • I’ll not teach you how to deploy OPNSense. Google it! There’s plenty of installation how-tos at the internet.

A little diagram

                   INTERNET
                       ^
  ISP LAN:             |
  192.168.1.0/24       |                     +--------------------+
+-----------+          |   +-----------+     |DATACENTER          |
| OPNSense  |          |   |Proprietary+---^-+172.16.0.0/16       |
| Remote    +----------+-->+    FW     |   | |(multiple /24 Vlans)|
| Office    |ipsec.example.net -1.2.3.4|   | +--------------------+
+-----+-----+         +    +-----------+172.16.2.254/24
      |               |                    |
+-----+-------+       v-----NAT------+WAN:172.16.2.1/24
|Internal NETS|            +------------+  |
|10.1.10.0/24 |            |  OPNSense  |  |
|10.1.11.0/24 |            |Main Office +--+
|10.1.12.0/24 |            +------------+
|10.1.13.0/24 |
|etc.         |
+-------------+

It’s chaotic but i hope you get it. If you can’t grok the /16 and /24 net-subnet relationship:

Configuration

Site A: Our main office. Site B: Our remote office.

These keywords/terms will be interchangeably used.

You will basically create a CA, Site A and Site B client certificates both signed by the same CA.

All these artifacts will be generated inside the Site A OPNSense trust management.

You will export the CA(without keys) and Site B certificate(with keys) and import both at the Site B.

Trust Management

Access your OPNSense Site A(main office) web management interface.

Creating the CA

  • System > Trust > Authorities - Click "+ADD"
  • Descriptive Name: Anything descriptive (duh) - CA_IPSEC_SITE2SITE seems to be good enough
  • Method: “Create an Internal Certificate Authority”
  • Key length (bits) and Digest Algorithm: I’ll keep the default. Change to anything you like if you want to
  • Lifetime (days): I have used 3650 days(almost 10 years), to avoid dealing with expired CAs
  • Country Code: BR Brazil
  • State or Province: Use your state code
  • City: Your city name
  • Organization: Your company name
  • Email Address: Any mail used by your IT department (noc@example.net or postmaster@example.net)
  • Common Name: ipsec-ca
  • Click “Save”

Creating Site A Certificate

  • System > Trust > Certificates - Click "+ADD"
  • Method: “Create an Internal Certificate”
  • Descriptive Name: Again, anything descriptive - MAIN_OFFICE_IPSEC seems to be good enough
  • Type: Here is where one of the important detail lives. Select “Client Certificate” instead of server or server+client certificate
  • Key length (bits) and Digest Algorithm: I’ll keep the default. Change to anything you like if you want to
  • Lifetime (days): Again, 3650. You can revoke this certificate if anything wrong or a security incident happens.
  • Private key location: “Save on this firewall”
  • Country Code, State or Province, City, Organization : Same as the CA in this case(since it’s the main office)
  • Email Address: This one is also important. It’s the identifier. use site2site@example.net since doesn’t have to be a valid email address, but it will be used as identifier.
  • Common Name: COMPANY_CITY (CITY = IATA code) or anything you like
  • The most important one: Alternative Names - Type change to email and fill with the EXACT SAME value of Email Address (site2site@example.net in this case)
    • During my labs I’ve noticed that Alternative Names - email and Email Address have to be EXACTLY THE SAME to make this Mutual RSA scheme work withouth FQDNs or IP addresses as identifiers of the IPSec connection.
  • Click “Save”

Creating Site B Certificate

Still while accessing Site A Trust management(cause it’s where the CA resides)

  • System > Trust > Certificates - Click "+ADD"
  • Method: “Create an Internal Certificate”
  • Descriptive Name: Again, anything descriptive - OFFICE01_IPSEC seems to be good to me
  • Type: “Client Certificate”
  • Key length (bits) and Digest Algorithm: I’ll keep the default.
  • Lifetime (days): 3650
  • Private key location: Save on this firewall
  • Country Code, State or Province, City, Organization : State, City and Country Code of your remote office. Keep Organization the same(unless you have a remote office that is also another company… ah, you got it!)
  • Email Address: office01@example.net
  • Common Name: Again, COMPANY_CITY or anything you like
  • Alternative Names - Type change to email - Same value of Email Address (office01@example.net in this case)
  • Click “Save”.

Importing Site B Certificate and CA

Access your OPNSense Site B(Remote office) web management interface.

  • System > Trust > Authorities - Click "+ADD"
  • Descriptive Name: CA_IPSEC_SITE2SITE to keep information the same
  • Method: “Import existing Certificate Authority”
  • Certificate data: Paste the certificate data. You can export it accessing site A web interface, and clicking at the “export CA cert” right-side button of that certificate line. Open this exported certificate with the text editor you like and paste it here
  • Certificate Private Key Keep empty. No need to import CA keys here and it’s even recommended since only Site A will be able to revoke certificates created with this CA Cert.

Now, import the client certificate using the same logic(is not that hard…)

  • System > Trust > Certificates - Click "+ADD"
  • Method: “Import existing Certificate Authority”
  • Descriptive name: OFFICE01_IPSEC
  • Certificate data: Paste certificate data
  • Private key data: Paste private key data

IPSec Connection

Now we will setup the tunnels that will connect remote and main office. It’s pretty straightforward:

  • 10.1.0.0/16 will be your remote network to Site A and local network to Site B
  • 0.0.0.0/0will be your remote network to Site B and local network to Site A

Site A Connection

Access your Site A management interface.

Phase 1:

  • VPN > IPSec > Tunel Settings - Click “add phase 1”
  • Connection method: “Respond only”, cause it’s the server side of this tunnel
  • Key Exchange version: “v2”. No need to use old v1 ipsec here
  • Internet Protocol: IPv4
  • Interface: Select your wan interface. Remember, we have an external nat from ipsec.example.net(1.2.3.4) pointing to our wan IP (172.16.2.1).
  • Remote gateway: 0.0.0.0(means, anyone)
  • Dynamic gateway: Check
  • Description: Again, up to you. SITE2SITE_OFFICE01 is my suggestion since each Phase 1 will correspond to one office
  • Authentication method: “Mutual RSA”
  • My identifier: User distinguished name - site2site@example.net
  • Peer identifier: User distinguished name - office01@example.net
    • This tuple (my+peer identifiers) will be responsible for identifying the remote connection. If you have problems when connecting, pretty much those values differ from what is written on the certificates
  • My Certificate: “MAIN_OFFICE_IPSEC”
  • My Certificate Authority: “CA_IPSEC_SITE2SITE”
  • Encryption algorithm, Hash algorithm and DH key group: Anything you like. Remember to keep the SAME VALUES across IPSec peers.
    • I have used “AES 256”, “SHA1” and “Group 14” while making this lab
  • Lifetime: 28800
  • Advanced Options: Check only Install policy and Disable Rekey. Keep NAT Transversal Enabled.
  • Click “Save”

Phase 2:

  • VPN > IPSec > Tunel Settings, below the recently created phase 1, Click “add phase 2 entry”
  • Mode: “Tunnel IPv4”
  • Description: Up to you!
  • Local Network - Type: “Network”
  • Local Network - Address: 0.0.0.0/0
  • Remote Network - Type: “Network”
  • Remote Network - Address: 10.1.0.0/16
  • Protocol - “ESP”
  • Encryption Algorithms: Anything you like. Remember to keep the SAME VALUES across IPSec peers and their phases 2.
    • I have used “AES 256” only, Hash algorithms “SHA1” only and PFS key group 14 on my lab.
  • Click “Save”
  • Click “Apply”

Thats it. The server is listening to connections and waiting someone to connect using a valid certificate.

Site B Connection

Access your Site B management interface.

Phase 1:

  • VPN > IPSec > Tunel Settings - Click “add phase 1”
  • Connection method: “Start immediate”
  • Key Exchange version: “v2”
  • Internet Protocol: IPv4
  • Interface: Select your wan interface if you have only one internet link, or “Any” if you have 2 or more internet links.
  • Remote gateway: ipsec.example.net
  • Dynamic gateway: Uncheck
  • Description: Again, up to you. OFFICE01_SITE2SITE is my suggestion.
  • Authentication method: “Mutual RSA”
  • My identifier: User distinguished name - office01@example.net
  • Peer identifier: User distinguished name - site2site@example.net
  • My Certificate: “OFFICE01_IPSEC”
  • My Certificate Authority: “CA_IPSEC_SITE2SITE”
  • Encryption algorithm, Hash algorithm and DH key group: Anything you like. Remember to keep the SAME VALUES across IPSec peers.
    • I have used “AES 256”, “SHA1” and “Group 14” while making my lab
  • Lifetime: 28800
  • Advanced Options: Check only Install policy and Disable Rekey. Keep NAT Transversal Enabled.
  • Enable Dead Peer Detection: 30 seconds 3 retries. This will make IPSec reconnect in case of connectivity loss.
  • Click “Save”

Phase 2:

  • VPN > IPSec > Tunel Settings, below the recently created phase 1, Click “add phase 2 entry”
  • Mode: “Tunnel IPv4”
  • Description: Up to you!
  • Local Network - Type: “Network”
  • Local Network - Address: 10.1.0.0/16
  • Remote Network - Type: “Network”
  • Remote Network - Address: 0.0.0.0/0
  • Protocol - “ESP”
  • Encryption Algorithms: Anything you like. Remember to keep the SAME VALUES across IPSec peers and their phases 2.
    • I have used “AES 256” only, Hash algorithms “SHA1” only and PFS key group 14 on my lab.
  • Click “Save”

Important: Do not apply settings yet. First, we will tweak the local lans

Access IPSec advanced settings:

  • VPN > IPSec > Advanced Settings
  • Passthrough networks: Here, you will declare all your /24 internal networks on your remote office plus, the LAN network connected to your ISP. This will make local traffic use a pass ipsec connection type on, keeping local traffic inside your remote office.
    • 10.1.10.0/24 10.1.11.0/24 10.1.12.0/24 10.1.13.0/24192.168.1.0/24
  • Click “Save”
  • Click “Apply”

If you don’t create those passthrough networks, all local traffic (example, 10.1.12.100 is a voip phone, 10.1.13.200 is an asterisk server) will be redirected to your main office.

Another example: If your OPNSense remote office box is also a dhcp-relay to a Active Directory VM on that office, all traffic will be forwarded through ipsec if no passthrough network is declared.

Checking the tunnel status:

After all this configuration, you should be able to connect both offices.

Taking a look at Site B logs(VPN > IPSec > Log File), you should find something like this:

charon: 04[IKE] <con1|1> peer supports MOBIKE
charon: 04[IKE] <con1|1> CHILD_SA con1{1} established with SPIs c69c3961_i ceca7713_o and TS 10.1.0.0/16 === 0.0.0.0/0
charon: 04[CFG] <con1|1> selected proposal: ESP:AES_CBC_256/HMAC_SHA1_96/NO_EXT_SEQ
charon: 04[IKE] <con1|1> received ESP_TFC_PADDING_NOT_SUPPORTED, not using ESPv3 TFC padding
charon: 04[IKE] <con1|1> IKE_SA con1[1] established between 192.168.1.9[office01@example.net]...MAIN.OFFICE.IP.ADDR[site2site@example.net]
charon: 04[IKE] <con1|1> authentication of 'site2site@example.net' with RSA_EMSA_PKCS1_SHA2_256 successful
charon: 16[IKE] <con1|2> peer supports MOBIKE
charon: 16[IKE] <con1|2> received ESP_TFC_PADDING_NOT_SUPPORTED, not using ESPv3 TFC padding
charon: 16[IKE] <con1|2> authentication of 'office01@example.net' with RSA_EMSA_PKCS1_SHA2_256 successful

Site A logs as soon as you start ipsec.

charon: 14[CFG] added configuration 'con1'
charon: 14[CFG] loaded certificate "C=BR, ST=STATE, L=City, O=My Org, E=site2site@example.net, CN=COMPANY_CITY, subjectAltName=email:site2site@example.net" from '/usr/local/etc/ipsec.d/certs/cert-1.crt'
charon: 14[CFG] received stroke: add connection 'con1'
charon: 00[JOB] spawning 16 worker threads

Can you see that subjectAltName=email: and E= are exactly the same?

Site A logs right after Site B connects(supressing sensitive and Certificate specific info with ... since is too much to replace):

charon: 16[IKE] <con1|2> CHILD_SA con1{2} established with SPIs cacde5b5_i c8397929_o and TS 0.0.0.0/0 === 10.1.0.0/16
charon: 16[CFG] <con1|2> selected proposal: ESP:AES_CBC_256/HMAC_SHA1_96/NO_EXT_SEQ
charon: 16[IKE] <con1|2> sending end entity cert "..."
charon: 16[IKE] <con1|2> IKE_SA con1[2] established between MAIN.OFFICE.IP.ADDR[site2site@example.net]...REMOTE.OFFICE.IP.ADDR[office01@example.net]
charon: 16[IKE] <con1|2> authentication of 'site2site@example.net' (myself) with RSA_EMSA_PKCS1_SHA2_256 successful
charon: 16[IKE] <con1|2> peer supports MOBIKE
charon: 16[IKE] <con1|2> received ESP_TFC_PADDING_NOT_SUPPORTED, not using ESPv3 TFC padding
charon: 16[IKE] <con1|2> authentication of 'office01@example.net' with RSA_EMSA_PKCS1_SHA2_256 successful
charon: 16[CFG] <con1|2> using trusted ca certificate "..."
charon: 16[CFG] <con1|2> using certificate "..."
charon: 16[CFG] <con1|2> selected peer config 'con1'
charon: 16[CFG] <2> looking for peer configs matching MAIN.OFFICE.IP.ADDR[site2site@example.net]...REMOTE.OFFICE.IP.ADDR[office01@example.net]
charon: 16[IKE] <2> received end entity cert "C=BR, ST=State, L=Remote Office City, O=My Org, E=office01@example.net, CN=COMPANY_SITEB_CITY, subjectAltName=email:office01@example.net"

Pretty simple eh?

That’s all. Hope you have enjoyed.