Building an IPSec hub and spoke

 24.04.2021 -  Louis Kowolowski -  ~7 Minutes

Sort of a continuation of the last post. This still uses FreeBSD   , pfSense   , Juniper SRX   but it could fairly easily be adapted to OpnSense   (fork/clone of pfSense   ), and other network vendor appliances.

Versions used:

Software Version
Junos 12.3X48-D105.4
FreeBSD 12.2
StrongSwan 5.9.2
pfSense 2.4

Note If you are using Junos 15.1X49 >D100, you can use IKEv2 with the traffic selectors. If not, you have to either use IKEv1, or use proxy-identity and create multiple phase2, 1 for each subnet you want to pass traffic to/from.

Requirements

  • route-based tunnel on Junos, policy-based tunnel on StrongSwan (VTI may be an option in the future).
  • Suite-B(ish) crypto: JunOS requires certificates for Suite-B on phase-1, I’m not doing that. I am still using SHA256, AES-128-CBC for phase1, and SHA256 and AES-128-GCM (Suite-B) for phase2.

JunOS config

Interface:

louisk@srx.cmhome> show configuration interfaces st0
unit 0 {
    apply-groups ipsec_interfaces;
    description "DO Tunnel";
    family inet;
    family inet6;
}

louisk@srx.cmhome>

IKE (phase 1):

louisk@srx.cmhome> show configuration security ike
inactive: traceoptions {
    file ike-debug size 10m files 2;
    flag all;
    level 10;
}
proposal ike-proposal-digital-ocean {
    authentication-method pre-shared-keys;
    dh-group group19;
    authentication-algorithm sha-256;
    encryption-algorithm aes-128-cbc;
    lifetime-seconds 28800;
}
policy ike-policy-digital-ocean {
    mode main;
    proposals ike-proposal-digital-ocean;
    pre-shared-key ascii-text "insert secret here";
}
gateway ike-gate-digital-ocean {
    ike-policy ike-policy-digital-ocean;
    address 172.16.143.91;
    dead-peer-detection {
        optimized;
        interval 10;
        threshold 5;
    }
    local-identity hostname srx.cmhome;
    remote-identity inet 172.16.143.91;
    external-interface fe-0/0/7;
    version v1-only;
}

louisk@srx.cmhome>

IPSec (phase 2):

louisk@srx.cmhome> show configuration security ipsec
inactive: traceoptions {
    flag all;
}
vpn-monitor-options {
    interval 10;
    threshold 10;
}
proposal ipsec-proposal-digital-ocean {
    protocol esp;
    authentication-algorithm hmac-sha1-96;
    encryption-algorithm aes-128-cbc;
}
policy ipsec-policy-digital-ocean {
    perfect-forward-secrecy {
        keys group19;
    }
    proposal-set suiteb-gcm-128;
}
vpn ipsec-vpn-digital-ocean {
    bind-interface st0.0;
    ike {
        gateway ike-gate-digital-ocean;
        ipsec-policy ipsec-policy-digital-ocean;
    }
    traffic-selector t1 {
        local-ip 192.168.0.0/20;
        remote-ip 10.10.2.0/24;
    }
    traffic-selector t2 {
        local-ip 192.168.0.0/20;
        remote-ip 192.168.17.0/24;
    }
    establish-tunnels immediately;
}

louisk@srx.cmhome>

The traffic-selector (proxy-identity if you’re using IKEv2 before Junos 15.1X49-D100) parts are required if the other side is policy-based (StrongSwan).

Security policies:

louisk@srx.cmhome> show configuration security policies from-zone trust to-zone site-2-site
policy trust-site-2-site {
    match {
        source-address net-192.168_0_0_m20;
        destination-address [ net-192.168_17_0_m24 net-10_10_2_20_m32 ];
        application any;
    }
    then {
        permit;
        count;
    }
}

louisk@srx.cmhome> show configuration security policies from-zone site-2-site to-zone trust
policy site-2-site-trust {
    match {
        source-address [ net-192.168_17_0_m24 net-10_10_2_20_m32 ];
        destination-address net-192.168_0_0_m20;
        application junos-icmp-ping;
    }
    then {
        permit;
        count;
    }
}

louisk@srx.cmhome>

If you want to be more granular about what kind of traffic you allow through, You would want to create more policy statements, and/or provide a list of applications, ports, and protocols that you wish to allow.

Security zones:

louisk@srx.cmhome> show configuration security zones security-zone site-2-site
interfaces {
    st0.0;
}

louisk@srx.cmhome>

Addressbook:

louisk@srx.cmhome> show configuration security address-book
global {
    address net-192.168_0_0_m20 {
        description CMHome;
        192.168.0.0/20;
    }
    address net-192.168_17_0_m24 {
        description "Office";
        192.168.17.0/24;
    }
    address net-10_10_2_20_m32 {
        description "DO IPSec Hub";
        10.10.2.20/32;
    }
}

louisk@srx.cmhome>

StrongSwan config

Most of this is pretty straight forward. I did find that nothing wanted to work until I changed the strongswan_interface variable to stroke. It currently defaults to vici (new configs from scratch should probably be done this way, but getting the existing configs working was faster this time).

rc.conf

strongswan_enable="YES"
strongswan_interface="stroke"
gateway_enable="YES"
ipv6_gateway_enable="YES"

ipsec.conf

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
	uniqueids=yes
	# strictcrlpolicy=yes

# Add connections here.
conn %default
	ikelifetime=28800s
	keylife=3600s
	rekeymargin=3m
	keyingtries=1
	authby=secret
	keyexchange=ikev2
	mobike=no
	rekey=yes

conn to-office
	fragmentation=yes
	reauth=yes
	forceencaps=no
	mobike=yes

	installpolicy=yes
	type=tunnel
	dpddelay=10s
	dpdtimeout=60s
	dpdaction=restart
	auto=add
	authby=secret
	ike=aes128-sha256-ecp256!
	esp=aes128gcm128-sha256-ecp256,aes128gcm96-sha256-ecp256,aes128gcm64-sha256-ecp256!

	leftauth=psk
	leftsubnet=10.10.2.20/24,192.168.0.0/20
	left=172.16.143.91
	leftid=172.16.143.91

	rightauth=psk
	rightsubnet=192.168.17.0/24
	right=%any
	rightid=@office

conn to-cmhome
	keyexchange=ikev1
	fragmentation=yes
	reauth=yes
	forceencaps=no
	mobike=yes

	installpolicy=yes
	type=tunnel
	dpddelay=10s
	dpdtimeout=60s
	dpdaction=restart
	auto=add
	authby=secret
	ike=aes128-sha256-ecp256!
	esp=aes128gcm128-sha256-ecp256,aes128gcm96-sha256-ecp256,aes128gcm64-sha256-ecp256!

	leftauth=psk
	leftsubnet=10.10.2.20/24,192.168.17.0/24
	left=172.16.143.91
	leftid=172.16.143.91

	rightauth=psk
	rightsubnet=192.168.0.0/20
	right=%any
	rightid=@srx.cmhome

You can provide a comma separated list of prefixes for the left/right subnet instead of having to define new stanzas for each P2. That was nice.

Because all of the spokes in this configuration have dynamic addresses, the right needs to be set to %any. Make sure you set your identifier the same on both sides or it won’t connect.

ipsec.secrets

@srx.cmhome : PSK "insert password here"
@office : PSK "insert other password here"

You can use certs instead of PSK if you like them better. You can find examples here   .

pfSense config

Overview: SHA256, AES128 CBC/GCM

Phase 1: 2 screenshots because its too long for 1

Phase 2: 2 screenshots because its too long for 1

NOTE: Ensure you allow traffic in/out the IPSec interface. With out this, you won’t get traffic to go where you want.

You can be granular, or not, up to you. Probably best to use the same applications, ports, and protocols that were defined in the SRX policy, just to keep things from being more confusing when it comes time to debug things.

Verification and testing

Tunnel is up:

louisk@srx.cmhome> show security ike sa
Index   State  Initiator cookie  Responder cookie  Mode           Remote Address
4286058 UP     4e4839c9f5cf00e7  5b4197e463eefd51  Main           172.16.143.91

louisk@srx.cmhome> show security ipsec sa
  Total active tunnels: 2
  ID    Algorithm       SPI      Life:sec/kb  Mon lsys Port  Gateway
  <67108865 ESP:aes-gcm-128/None e36683fb 1626/ unlim - root 500 172.16.143.91
  >67108865 ESP:aes-gcm-128/None c7e91c4f 1626/ unlim - root 500 172.16.143.91
  <67108866 ESP:aes-gcm-128/None c5880593 1726/ unlim - root 500 172.16.143.91
  >67108866 ESP:aes-gcm-128/None c233855f 1726/ unlim - root 500 172.16.143.91

louisk@srx.cmhome> ping count 1 192.168.17.6
PING 192.168.17.6 (192.168.17.6): 56 data bytes
64 bytes from 192.168.17.6: icmp_seq=0 ttl=63 time=131.445 ms

--- 192.168.17.6 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 131.445/131.445/131.445/0.000 ms

louisk@srx.cmhome>

Showing policy counters/statistics after the tunnel has been up for a little bit. You should see numbers > 0 for almost everything here.

louisk@srx.cmhome> show security policies from-zone trust to-zone site-2-site detail
Policy: trust-site-2-site, action-type: permit, State: enabled, Index: 13, Scope Policy: 0
  Policy Type: Configured
  Sequence number: 1
  From zone: trust, To zone: site-2-site
  Source addresses:
    net-192.168_0_0_m20(global): 192.168.0.0/20
  Destination addresses:
    net-10_10_2_20_m32(global): 10.10.2.20/32
    net-192.168_17_0_m24(global): 192.168.17.0/24
  Application: any
    IP protocol: 0, ALG: 0, Inactivity timeout: 0
      Source port range: [0-0]
      Destination port range: [0-0]
  Per policy TCP Options: SYN check: No, SEQ check: No
  Policy statistics:
    Input  bytes       :              9794924                   29 bps
      Initial direction:              1933478                   14 bps
      Reply direction  :              7861446                   14 bps
    Output bytes       :              9795478                   29 bps
      Initial direction:              1932016                   14 bps
      Reply direction  :              7863462                   14 bps
    Input  packets     :                24114                    0 pps
      Initial direction:                11438                    0 pps
      Reply direction  :                12676                    0 pps
    Output packets     :                24149                    0 pps
      Initial direction:                11437                    0 pps
      Reply direction  :                12712                    0 pps
    Session rate       :                 3155                    0 sps
    Active sessions    :                    1
    Session deletions  :                 3154
    Policy lookups     :                 3167

louisk@srx.cmhome>
[louisk@hub louisk 125 ]$ ipsec statusall
Status of IKE charon daemon (strongSwan 5.9.2, FreeBSD 12.2-RELEASE-p6, amd64):
  uptime: 3 hours, since Apr 24 19:25:50 2021
  worker threads: 11 of 16 idle, 5/0/0/0 working, job queue: 0/0/0/0, scheduled: 6
  loaded plugins: charon aes des blowfish rc2 sha2 sha1 md4 md5 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem openssl fips-prf curve25519 xcbc cmac hmac gcm drbg curl attr kernel-pfkey kernel-pfroute resolve socket-default stroke vici updown eap-identity eap-md5 eap-mschapv2 eap-tls eap-ttls eap-peap xauth-generic whitelist addrblock counters
Listening IP addresses:
  172.16.143.91
Connections:
       to-office:  172.16.143.91...%any  IKEv2, dpddelay=10s
       to-office:   local:  [172.16.143.91] uses pre-shared key authentication
       to-office:   remote: [office] uses pre-shared key authentication
       to-office:   child:  10.10.2.0/24 192.168.0.0/20 === 192.168.17.0/24 TUNNEL, dpdaction=restart
   to-cmhome:  172.16.143.91...%any  IKEv1, dpddelay=10s
   to-cmhome:   local:  [172.16.143.91] uses pre-shared key authentication
   to-cmhome:   remote: [srx.cmhome] uses pre-shared key authentication
   to-cmhome:   child:  10.10.2.0/24 192.168.17.0/24 === 192.168.0.0/20 TUNNEL, dpdaction=restart
Security Associations (2 up, 0 connecting):
   to-cmhome[3]: ESTABLISHED 3 hours ago, 172.16.143.91[172.16.143.91]...98.198.238.127[srx.cmhome]
   to-cmhome[3]: IKEv1 SPIs: 4e4839c9f5cf00e7_i 5b4197e463eefd51_r*, pre-shared key reauthentication in 4 hours
   to-cmhome[3]: IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256
   to-cmhome{11}:  INSTALLED, TUNNEL, reqid 2, ESP SPIs: c7e91c4f_i e36683fb_o
   to-cmhome{11}:  AES_GCM_16_128/ECP_256, 9108 bytes_i (207 pkts, 2s ago), 20700 bytes_o (207 pkts, 2s ago), rekeying in 19 minutes
   to-cmhome{11}:   10.10.2.0/24 === 192.168.0.0/20
   to-cmhome{12}:  INSTALLED, TUNNEL, reqid 3, ESP SPIs: c233855f_i c5880593_o
   to-cmhome{12}:  AES_GCM_16_128/ECP_256, 31888 bytes_i (692 pkts, 3s ago), 305548 bytes_o (2670 pkts, 1s ago), rekeying in 23 minutes
   to-cmhome{12}:   192.168.17.0/24 === 192.168.0.0/20
       to-office[1]: ESTABLISHED 3 hours ago, 172.16.143.91[172.16.143.91]...66.220.110.60[office]
       to-office[1]: IKEv2 SPIs: 77f55c79c761bb62_i 855552af159b5132_r*, pre-shared key reauthentication in 4 hours
       to-office[1]: IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256
       to-office{10}:  INSTALLED, TUNNEL, reqid 1, ESP SPIs: c12588fa_i cc7b0f52_o
       to-office{10}:  AES_GCM_16_128/ECP_256, 248788 bytes_i (4327 pkts, 1s ago), 134880 bytes_o (1328 pkts, 2s ago), rekeying in 4 minutes
       to-office{10}:   10.10.2.0/24 192.168.0.0/20 === 192.168.17.0/24
[louisk@hub louisk 126 ]$

pfSense ICMP test:

pfSense should also show traffic flowing across the tunnel

Footnotes and References