Thursday, November 17, 2022

IPSec Site-to-Site VPN Demo using Libreswan as CPE on OCI Free Tier

What is required to do this demo ?

=> OCI Free Tier Account. We will be using only always free resources, so it works even if the trial period ends and the account is not upgraded to paid one.

=> No installation is required on your laptop/PC

=> Putty to make SSH connections








For the purpose of this demo, I am creating 3 compute instances in OCI as below. 

instance1 :

=> named as "target" 

=> resides in VCN1 "test-vcn-001" with CIDR 192.168.0.0/16. 

=> this is the instance in OCI we are trying to connect from on-prem network through IPSec tunnel setup. 

=> the on-prem network here is none other than VCN2 "test-vcn-002" with CIDR 172.16.0.0/16

=> we can connect two VCN's within same region easily using LPG or DRG, but we are not doing it that way for the purpose of IPSec demonstration.


instance2 :

=> named as "source" 

=> resides in VCN2 "test-vcn-002" with CIDR 172.16.0.0/16

=> assume this as a computer sitting on on-prem network.

=> this is the instance from which we are trying to connect to OCI instance.


instance3 :

=> named as "router" 

=> resides in VCN2 "test-vcn-002" with CIDR 172.16.0.0/16

=> assume this as an on-prem router

=> notice that instance3 and instance2 are in same network or VCN2, this instance will act as router to instance2/source, i.e it will send the traffic initiated from instance2/source to instance1/target.

=> this must reside in public subnet due to two reasons, 

1. We will be assigning public IP to the instance3-router for communicating with ipsec tunnel end point.

2. We need to attach an internet gateway to this instance for internet access to install Libreswan through dnf repository. NAT is not supported in OCI Free Tier after the trail period is ended, so we should have a public ip assigned to this instance to access internet over internet gateway.


=> for instance3/router I am selecting free arm based processor with 3 OCPU and 18 GB RAM, which is always free, as 3000 hours of OCPU and 18000 GB hours of RAM per month is always free for arm based processors, with 3 OCPU's the actual consumption per month will be only 3*24*31 = 2232 hours and with 18 GB of RAM consumption per month will be 18*24*31 = 13392 GB hours








=> the reason for selecting arm based processor for instance3/router is, we already consumed 2 free instances of type "VM Standard 2.1 Micro" for instance1/target and instance2/source. So we cannot create any additional instance in free tier.


=> High Level Steps
 
01. Create target VCN / VCN1 "test-vcn-001" CIDR 192.168.0.0/16
02. Create source VCN / VCN2 "test-vcn-002" CIDR 172.16.0.0/16
03. Create a private subnet / subnet-01 for VCN1, to host target instance
04. Create a public subnet / subnet-02 for VCN2, to host source instance and router instance
05. Configure security list for subnet-01
06. Configure security list for subnet-02
07. Create instance1/target under subnet-01
08. Create instance2/source under subnet-02
09. Create instance3/router under subnet-02
10. Create a reserved public IP and add it to instance3/router
11. Create DRG
12. Attach DRG to target VCN / VCN1 "test-vcn-001"
13. Create a Route Table for VPN 
14. Create Customer Premise Equipment - CPE 
15. Create IPSec connecting CPE to DRG 
16. Install and Configure Libreswan on instance3/router
17. Verify connectivity to instance1/target from instance3/router
18. Configure instance3/router as router to instance2/source
19. Verify connectivity to instance1/target from instance2/source


=> Create VCN's

Networking => Virtual Cloud Networks => Create VCN







=> Create Subnets for each VCN

Networking => Virtual Cloud Networks => test-vcn-001 => Create Subnet

Name : subnet-01
CIDR : 192.168.0.0/22
Subnet Access : Private 










Networking => Virtual Cloud Networks => test-vcn-002 => Create Subnet

Name : subnet-02
CIDR : 172.16.0.0/22
Subnet Access : Public






=> Add Ingress and Egress rules under security lists for both subnets

For demo purpose I am allowing all IP's/Ports/Protocols under Ingress and Egress rules for both the subnets. So the below step has to be done 4 times. 












=> Create instance1/target under subnet-01





=> Create instance2/source under subnet-02





















=> Create instance3/router under subnet-02
































=> Below is the setup for 3 instances 























=> Create Internet Gateway for VCN2 - test-vcn-002


Networking => Virtual Cloud Networks => test-vcn-002 => Internet Gateways => Create Internet Gateway 









































=> Add Internet Gateway to the route rule of subnet-02 of VCN2

Networking => Virtual Cloud Networks => test-vnc-002 => subnet-02 => Click on Default Route Table => Add Route Rule as below

Target Type : Internet Gateway
Destination CIDR : 0.0.0.0/0
Target Internet Gateway : IGW-001







































=> Create a reserved public IP and add it to instance3/router

Navigation : Networking => IP Management => Reserve Public IP

Give a name to the IP and select the compartment of your choice. It is best practice to place all network related components in one compartment, net-cmp 


















=> Assign this public IP to instance3/router

Navigation : Computer => Instances => router => Add Public IP






















=> Got below error after clicking on Add Public IP.














Since instance is created in test-cmp and public ip is in net-cmp, it is not allowing. If both the instance and network resources are is same compartment, this error wouldn't come. 

Workaround is to attach the public ip to the instance through VNIC

Click on Attached VNIC's under instance3/router. Click on VNIC name - router 













Click on IPv4 addresses. Notice that public ip is not yet assigned.









Click on 3 dots icon and Click Edit

Select the reserved IP and click on update

























Public address will be assigned to the router instance













=> Create DRG

Networking => Customer Connectivity => Dynamic Routing Gateways => Create Dynamic Routing Gateway 














Enter name for DRG and select compartment and click on create 







































=> Attach DRG to target VCN / VCN1 "test-vcn-001"

Select the DRG and click on Create Virtual Cloud Network Attachment





















Select the VCN1 and click on create. Attachment name is optional








































=> Create a Route Table for VPN 

A route table will now be created in target VCN, VCN1, to allow all the traffic is routed back to the on-prem network or instance2/source.

Once the VCN is created, it will create a default route table with no route rules. For the purpose of this demo lets create a new routing table.

Networking => Virtual Cloud Networks => test-vcn-001 => Route Tables => Create Route Table 



















Provide a meaningful name for route table and select the compartment for the resource to reside.

Click on add route rule 

Target Type => Dynamic Routing Gateway 
Destination => CIDR Block 
Destination CIDR Block => 172.16.0.0/16 => This is the CIDR block on on-prem network or source VCN in our case.

Select the target DRG : libreswan-demo-drg and click on create 






































































=> Assign the route table to subnet-01 of VCN1.

Networking => Virtual Cloud Networks => test-vcn-001 => subet-01 => Edit => Select the route table just created. => Save Changes









































=> Create Customer Premise Equipment - CPE 

Here we have to define what type of CPE device being used on customer side for managing networking. In this example we are using Libreswan an open source VPN tool. Find the list of all supported CPE devices and versions and configuration details from below Oracle documentation 


Networking => Customer Connectivity => Customer Premises Equipment => Create Customer Premises Equipment


Give it a name and select the compartment and provide the Public IP, the IP will be the Public IP of instance3/router where we will be configuring our CPE device Libreswan. Select the CPE information, Vendor and Version.

TIP: In real world scenario if your on-prem CPE device has no public IP then a static public ip has to be procured and attach it directly to the server where CPE is running or attach through NAT device. 

This public IP is the end point at customer end to communicate with public IP's at OCI end generated through IP sec tunnels in the next steps. 







































=> Create IPSec connecting CPE and DRG 

Here we will create as IPSec connection connecting CPE and DRG attached to VCN1, so the traffic from on-prem network/instance2-source will travel through intance3-router's Public IP and through Public IP's at IPSec tunnels and through DRG attached to VCN1 to VCN1 and finally to target instance1-target present in VCN1, provides firewall rules / ingress and egress rules are allowed in subnet of instance1-target / subet-01.

Networking => Customer Connectivity => Site-to-Site VPN => Create IPSec Connection 















Give a name for ipsec connection and select the CPE and DRG 



















Provide on-prem CIDR under Route










Select Static Routing for Tunnel1 and Tunnel2




















































Leave the remaining optional settings and click on Create IPSec connection.

This will create two tunnels with a public ip for each tunnel. Tunnels status will be down, they will come up once the on-prem router is configured/security associations - SA's are established.





















=> Install and Configure Libreswan on instance3/router


Login to instance3/router. Since it has public IP assigned, you can login directly using public ip - 129.154.44.236 and the private key generated during instance creation.












=> Install Libreswan using below command as root user

Oracle Documentation





[root@router ~]# dnf install -y libreswan
Last metadata expiration check: 1:39:19 ago on Thu 17 Nov 2022 04:53:40 AM GMT.
Dependencies resolved.
======================================================================================================================================
 Package                      Architecture               Version                               Repository                        Size
======================================================================================================================================
Installing:
 libreswan                    aarch64                    4.5-1.0.1.el8                         ol8_appstream                    1.3 M
Installing dependencies:
 ldns                         aarch64                    1.7.0-21.el8                          ol8_appstream                    155 k
 nss-tools                    aarch64                    3.79.0-10.el8_6                       ol8_appstream                    579 k

Transaction Summary
======================================================================================================================================
Install  3 Packages

Total download size: 2.0 M
Installed size: 8.5 M
Downloading Packages:
(1/3): libreswan-4.5-1.0.1.el8.aarch64.rpm                                                            6.0 MB/s | 1.3 MB     00:00
(2/3): ldns-1.7.0-21.el8.aarch64.rpm                                                                  503 kB/s | 155 kB     00:00
(3/3): nss-tools-3.79.0-10.el8_6.aarch64.rpm                                                          1.6 MB/s | 579 kB     00:00
--------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                 5.4 MB/s | 2.0 MB     00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                              1/1
  Installing       : nss-tools-3.79.0-10.el8_6.aarch64                                                                            1/3
  Installing       : ldns-1.7.0-21.el8.aarch64                                                                                    2/3
  Installing       : libreswan-4.5-1.0.1.el8.aarch64                                                                              3/3
  Running scriptlet: libreswan-4.5-1.0.1.el8.aarch64                                                                              3/3
  Verifying        : ldns-1.7.0-21.el8.aarch64                                                                                    1/3
  Verifying        : libreswan-4.5-1.0.1.el8.aarch64                                                                              2/3
  Verifying        : nss-tools-3.79.0-10.el8_6.aarch64                                                                            3/3

Installed:
  ldns-1.7.0-21.el8.aarch64              libreswan-4.5-1.0.1.el8.aarch64              nss-tools-3.79.0-10.el8_6.aarch64

Complete!
[root@router ~]#



=> Verify Installation

[root@router ~]# ipsec version
Linux Libreswan 4.5 (XFRM) on 5.4.17-2136.311.6.1.el8uek.aarch64
[root@router ~]#


=> Configure Libreswan 

There are 3 files you have to configure for this version - 4.5 of Libreswan 

/etc/sysctl.conf => Configures instance3 as router, i.e to forward the traffic from instance2-source to instance1-target and vice-versa

/etc/ipsec.d/oci-ipsec.conf => Contains the on-prem end points/public & private IP's and OCI end points/ipsec tunnel public IP's and network packets encryption algorithms supported by OCI and other timeout parameters

/etc/ipsec.d/oci-ipsec.secrets => Contains secret keys for OCI tunnel public IP's


=> Identify the network device name of router instance - enp0s3

[root@router ~]# ifconfig

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9000
        inet 172.16.1.214  netmask 255.255.252.0  broadcast 172.16.3.255
        inet6 fe80::17ff:fe01:461c  prefixlen 64  scopeid 0x20<link>
        ether 02:00:17:01:46:1c  txqueuelen 1000  (Ethernet)
        RX packets 26462  bytes 180447172 (172.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 21936  bytes 6768866 (6.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 9724  bytes 595512 (581.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 9724  bytes 595512 (581.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@router ~]#


=> Edit /etc/sysctl.conf with below parameters and update the device name as per your servers device name - enp0s3

[root@router ~]# vi /etc/sysctl.conf

[root@router ~]# cat /etc/sysctl.conf
# sysctl settings are defined through files in
# /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
#
# Vendors settings live in /usr/lib/sysctl.d/.
# To override a whole file, create a new file with the same in
# /etc/sysctl.d/ and put new settings there. To override
# only specific settings, add a file with a lexically later
# name in /etc/sysctl.d/ and put new settings there.
#
# For more information, see sysctl.conf(5) and sysctl.d(5).

#Router Setup of OCI

net.ipv4.ip_forward=1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.enp0s3.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.enp0s3.accept_redirects = 0

=> Run sysctl -p for changes to take into effect without restarting the system

[root@router ~]# sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.enp0s3.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.enp0s3.accept_redirects = 0
[root@router ~]#


=> Create/Edit /etc/ipsec.d/oci-ipsec.conf

[root@router ~]# vi /etc/ipsec.d/oci-ipsec.conf
[root@router ~]#
[root@router ~]# cat /etc/ipsec.d/oci-ipsec.conf
conn oracle-tunnel-1
  left=172.16.1.214             # router private ip address
  leftid=129.154.44.236         # router public ip address
  leftsubnet=172.16.0.0/16      # on-prem CIDR / VCN2 CIDR
  right=152.67.177.141          # OCI VPN gateway / any one of ip sec tunnel public ip address
  rightsubnet=192.168.0.0/16    # OCI target VCN CIDR / VCN1 CIDR
  authby=secret
  auto=start
  ikev2=no
  ike=aes_cbc256-sha2_384;modp1536
  phase2alg=aes_gcm256;modp1536
  encapsulation=yes
  ikelifetime=28800s
  salifetime=3600s

[root@router ~]#


=> Create/Edit /etc/ipsec.d/oci-ipsec.secrets

This file will be in below format 

<Router Public IP> <OCI Tunnel Public IP> : PSK "Pre-Shared-Key-From-OCI"

You can get the PSK / Pre Shared Key of OCI Tunnel through below navigation 

Networking => Customer Connectivity => Site-to-Site VPN => libreswam-demo-ipsec => click on tunnel name => Shared Secret => Show





[root@router ~]# cat /etc/ipsec.d/oci-ipsec.secrets
129.154.44.236 152.67.177.141 : PSK "dsfskahjflkdsjfjdsafkljsajfadskljfkdlsjfslkadslkjfkdslfj"


=> Make it readable only by root user

[root@router ~]# chmod 0600 /etc/ipsec.d/oci-ipsec.secrets
[root@router ~]# ls -ltr /etc/ipsec.d/oci-ipsec.secrets
-rw-------. 1 root root 103 Nov 17 07:46 /etc/ipsec.d/oci-ipsec.secrets
[root@router ~]#


=> We need to allow ipsec traffic through firewall using below commands, but for the puropse of the demo, I am turning off the firewall so the below commands are not needed.

firewall-cmd --add-service="ipsec" 
firewall-cmd --runtime-to-permanent

[root@router ~]# service firewalld stop
Redirecting to /bin/systemctl stop firewalld.service
[root@router ~]#


=> Start ipsec 

Before starting verify the connection to target OCI server, you should not be able to connect.

[root@router ~]# ping 192.168.0.93
PING 192.168.0.93 (192.168.0.93) 56(84) bytes of data.
^C
--- 192.168.0.93 ping statistics ---
13 packets transmitted, 0 received, 100% packet loss, time 12289ms

[root@router ~]#



[root@router ~]# ipsec start
Redirecting to: systemctl start ipsec.service
[root@router ~]#

=> Verify the logfile to check if connection is established

If you see the message "IPsec SA established tunnel mode" then connection is established. You can verify the same from OCI tunnel as well.

[root@router ~]# tail -f /var/log/secure

Nov 17 07:53:44 router pluto[274752]: loading secrets from "/etc/ipsec.d/oci-ipsec.secrets"
Nov 17 07:53:44 router pluto[274752]: "oracle-tunnel-1" #1: initiating IKEv1 Main Mode connection
Nov 17 07:53:44 router pluto[274752]: "oracle-tunnel-1" #1: sent Main Mode request
Nov 17 07:53:44 router pluto[274752]: "oracle-tunnel-1" #1: sent Main Mode I2
Nov 17 07:53:44 router pluto[274752]: "oracle-tunnel-1" #1: sent Main Mode I3
Nov 17 07:53:44 router pluto[274752]: "oracle-tunnel-1" #1: Peer ID is ID_IPV4_ADDR: '152.67.177.141'
Nov 17 07:53:44 router pluto[274752]: "oracle-tunnel-1" #1: IKE SA established {auth=PRESHARED_KEY cipher=AES_CBC_256 integ=HMAC_SHA2_384 group=MODP1536}
Nov 17 07:53:44 router pluto[274752]: "oracle-tunnel-1" #2: initiating Quick Mode IKEv1+PSK+ENCRYPT+TUNNEL+PFS+UP+IKE_FRAG_ALLOW+ESN_NO {using isakmp#1 msgid:6fd3f3d2 proposal=AES_GCM_16_256-NONE-MODP1536 pfsgroup=MODP1536}
Nov 17 07:53:44 router pluto[274752]: "oracle-tunnel-1" #2: sent Quick Mode request
Nov 17 07:53:45 router pluto[274752]: "oracle-tunnel-1" #2: IPsec SA established tunnel mode {ESPinUDP=>0x05ba6258 <0xdff820b3 xfrm=AES_GCM_16_256-NONE NATOA=none NATD=152.67.177.141:4500 DPD=passive}


=> Now the tunnel status will be UP. Since we configured only one tunnel, other tunnel will be down


















=> Check ipsec status 

[root@router ~]# ipsec status
000 using kernel interface: xfrm
000
.
.
000 Total IPsec connections: loaded 1, active 1
000
.
000 IKE SAs: total(1), half-open(0), open(0), authenticated(1), anonymous(0)
000 IPsec SAs: total(1), authenticated(1), anonymous(0)
000
.
.
.
.
000
[root@router ~]#


=> Verify connectivity to instance1/target from instance3/router

ping and ssh to the target instance in OCI / VCN1. 

Stop the ipsec and verify the connection. You should not be able to connect.



































=> Connect to source instance from router and try to ping to target instance, it won't work as routing is not yet configured for source instance.

















=> Configure instance3/router as router to instance2/source

Now we have to redirect traffic originating from instance2/source to the target OCI CIDR 192.168.0.0/16 through instance3/router.

This can be done in 2 steps

Step - 1 : Disable Skip Source/Destination Check for the VNIC attached to router

Computer => Instances => router => Attached VNIC's => Edit VNIC  (three dots) => Check the option for Skip Source/Destination Check








 



















=> Step - 2 : Add a route rule to route table of subnet-02 of VCN2 to route traffic for 192.168.0.0/16 subnet though private IP of router 172.16.1.214

Networking => Virtual Cloud Networks => test-vcn-002 => Subnets => subnet-02 => Click on Route Table : 

Click on Add Route Rule 




























































=> Verify connectivity to instance1/target from instance2/source and vice-versa





































This completes IPSec Demo.

This way we can establish connectivity with ZERO cost using Libreswan between any of the following end points.

=> Two/More VCN's within same region in OCI
=> Two/More VCN's in different regions in OCI
=> Two/More VCN's in different tenancies in OCI
=> Azure VCN's and OCI VCN's
=> AWS VCN's and OCI VCN's
=> Google Cloud VCN's and OCI VCN's
=> Any Server residing on any cloud/on-prem network with a public IP assigned to it and OCI VCN's



THE END


No comments:

Post a Comment