Integrating AWS Client VPN with pfSense (most popular OpenSource Router and Firewall)
Abstract
This Post explores integration of AWS Client VPN with pfSense, streamlining operations to utilize a single VPN connection per pfSense router.
Furthermore, it dives into the potential for establishing internal Firewall Rules, enabling precise control over traffic flow by specifying source entities and target destinations to leverage either the standard WAN ISP or the VPN channel.
This integration not only optimizes network efficiency but also enhances security measures.
Target Architecture Diagram
Here is a Deployed Client VPN ecosystem from previous Post Latest AWS Managed Client VPN Connection but much more extended with additional components: In current scope we will add:
- pfSense OpenSource Firewall Router
- Setup OpenVPN Client
- Add Network interface on top of WAN from OpenVPN port
- configure NAT and Firewall Rules for traffic routing
- check AWS monitoring tools for AWS Client VPN for troubleshooting and setup
Registering Certificates in pfSense
System -> Certificates -> Authorities
Attribute | Value |
---|---|
Method | Import an existing Certificate |
Certificate Data | copy all content from ca.crt |
Name | ca.crt |
System -> Certificates -> Certificates
Attribute | Value |
---|---|
Method | Import an existing Certificate |
Certificate Type | X.509(PEM) |
Certificate Data | input Certificate section only from client1.domain.tld.crt |
Private key data | copy all content from client1.domain.tld.key |
Name | client-us-west-1 |
Configure OpenVPN Client
VPN -> OpenVPN -> Clients
Attribute | Value |
---|---|
Description | us-west-1 |
Server mode | Peer to Peer (SSL/TLS) |
Device mode | tun - Layer 3 Tunnel Mode |
Protocol | UDP on IPv4 only |
Interface | WAN |
Server host or address | server.cvpn-endpoint-x.prod.clientvpn.us-west-1.amazonaws.com |
Server port | 443 |
Peer certificate authority | ca.crt |
Client certificate | client-us-west-1 |
Data encryption algorithm | AES-256-GCM |
Fallback Data encryption algorithm | AES-256-CBC (256 bit key, 128 biy block) |
Auth digest algorithm | SHA-256 (256-bit) |
Allow compression | Refuse any non-stub compression |
Topology | Subnet - One IP address per client in a common subnet |
Don’t pull routes | Unchecked |
Don’t add remote routes | Checked |
Pull DNS | Unchecked |
Custom options | reneg-sec 0 |
Gateway creation | IPv4 only |
Verbosity Level | 3 |
Compression currently is not supported in AWS VPN Client (LZO), so it should be turned off. It took time for me to troubleshoot why link was failing to establish.
Check that connection is established
Create Network Interface on top of VPN Client
Interfaces -> Assignments
Create a new Network interface WAN_VPN
on top of ovpnclient port
Update Monitoring IP
System -> Routing -> Gateway
Change monitor IP of Gateway to some known publicly available address (8.8.8.8)
Check the status
Check AWS console VPN Client status
Now we can check the status of VPN connection is AWS Console:
Traffic still goes over WAN ISP
Now we can see that Interface is create but traffic is not going through it (only health checks data):
All traffic is routed through WAN ISP main interface:
NAT configuration
To allow traffic going through VPN NW interface we need configure the NAT:
Firewall -> NAT -> Outbound
We should switch OutBound NAT Mode from Automatic into Hybrid or Manual rule generation and add 2 more mappings that will allow pass traffic to VPN:
Define the Firewall Rules to route traffic over VPN interface
Firewall -> Rules
At this point all the heavy-lifting setup is done, and now it is time to define what traffic will flow through VPN interface. Here we have a bunch of options, including:
- all traffic (by changing Default WAN Gateway to VPN Gateway)
- particular Network Subnet (Firewall Rule)
- dedicated VLAN only (Firewall Rule)
- isolated machine/IP (Firewall Rule)
- limited list of sites (Firewall Rule and Aliases)
Once Changes are done check Firewall logs that application completed with to issues:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Setting up pass/block rules pfB_PS_v4 auto rule
Creating rule pfB_PS_v4 auto rule
Pre-caching ...
Creating filter rule ...
Creating filter rules ...
Setting up pass/block rules
Setting up pass/block rules
Creating rule
Creating IPsec rules...
Generating ALTQ queues
Loading filter rules
Setting up logging information
Setting up SCRUB information
Processing down interface states
Running plugins
Done
Monitor the Traffic On pfSense
After NAT configuration, all traffic is routed through VPN interface (that is created on to of WAN). We can see perfect mirroring effect between these 2 interfaces):
CloudWatch Metrics Status:
AWS CloudWatch provides exposed metrics to monitor quality of our VPN connections (Egress, Ingress Bytes, connections count and errors are among them:
pfSense VPN status Logs:
Status -> System Logs -> OpenVPN
1
2
3
4
5
6
7
8
9
10
openvpn 90544 Using peer cipher 'AES-256-GCM'
ROUTE_GATEWAY xx.xx.xx.xx/xx.xx.xx.xx IFACE=xx0 HWADDR=00:xx:xx:xx:xx:xx
penvpn 90544 TUN/TAP device ovpnc1 exists previously, keep at program end
openvpn 90544 TUN/TAP device /dev/xx1 opened
openvpn 90544 /sbin/ifconfig ovpnc1 xx.xx.xx.xx/xx mtu xxxx up
openvpn 90544 /usr/local/sbin/ovpn-linkup xxx xxx 0 xx.xx.xx.xx xx.xxx.xxx.xxx init
openvpn 90544 Initialization Sequence Completed
openvpn 90544 Data Channel: cipher 'AES-256-GCM', peer-id: 0
openvpn 90544 Timers: ping 1, ping-restart 20
openvpn 90544 Protocol options: explicit-exit-notify 1
CloudWatch Logs:
Based on CloudWatch log entry we can easily troubleshoot remote devices peering, check OS, IP ranges and status, here is CloudWatch Log entry with all fields in the payload:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"connection-log-type": "connection-attempt",
"connection-attempt-status": "successful",
"connection-attempt-failure-reason": "NA",
"connection-id": "cvpn-connection-xxx",
"client-vpn-endpoint-id": "cvpn-endpoint-xxx",
"transport-protocol": "udp",
"connection-start-time": "2023-xx-xx ",
"client-ip": "xx.xx.xx.xx",
"common-name": "client1.domain.tld",
"device-type": "freebsd",
"device-ip": "xx.xx.xx.xx",
"port": "xxxx",
"ingress-bytes": "0",
"egress-bytes": "0",
"ingress-packets": "0",
"egress-packets": "0",
"connection-end-time": "NA",
"connection-duration-seconds": "0"
}
Conclusions:
This non-trivial setup offers extensive capabilities for finely-tuned traffic routing across both WAN and VPN interfaces, driven by multiple predicates. The advantages are that there is no need to create multiple connections (each of them is additionally billed) - just allow pfSense route the traffic using NAT.
Keep in mind that Internet speed per 1 client in Client VPN is limited to 10Mbits for single channel. A viable strategy to boost throughput is to establish diverse endpoints in distinct regions or engage in geospatial traffic distribution, preventing all traffic from being funneled through a single VPN.
Also, once compression algorithms will be extended on AWS Client VPN - it will allow additionally increase the channel throughput. This presents an additional avenue for enhancing overall network performance.