Post

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: infra.png 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

AttributeValue
MethodImport an existing Certificate
Certificate Datacopy all content from ca.crt
Nameca.crt

ca.png

System -> Certificates -> Certificates

AttributeValue
MethodImport an existing Certificate
Certificate TypeX.509(PEM)
Certificate Datainput Certificate section only from client1.domain.tld.crt
Private key datacopy all content from client1.domain.tld.key
Nameclient-us-west-1

Configure OpenVPN Client

VPN -> OpenVPN -> Clients

AttributeValue
Descriptionus-west-1
Server modePeer to Peer (SSL/TLS)
Device modetun - Layer 3 Tunnel Mode
ProtocolUDP on IPv4 only
InterfaceWAN
Server host or addressserver.cvpn-endpoint-x.prod.clientvpn.us-west-1.amazonaws.com
Server port443
Peer certificate authorityca.crt
Client certificateclient-us-west-1
Data encryption algorithmAES-256-GCM
Fallback Data encryption algorithmAES-256-CBC (256 bit key, 128 biy block)
Auth digest algorithmSHA-256 (256-bit)
Allow compressionRefuse any non-stub compression
TopologySubnet - One IP address per client in a common subnet
Don’t pull routesUnchecked
Don’t add remote routesChecked
Pull DNSUnchecked
Custom optionsreneg-sec 0
Gateway creationIPv4 only
Verbosity Level3

client.png

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

Status -> OpenVPN vpn_status.png

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)

gw_probe.png

Check the status

gw_status.png

Check AWS console VPN Client status

Now we can check the status of VPN connection is AWS Console: img.png

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):

vpn-interface.png

All traffic is routed through WAN ISP main interface:

wan-interface.png

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:

nat.png

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)

vpn2wan.png

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):

img.png img_1.png

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:

img_2.png

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:

img.png

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.

This post is licensed under CC BY 4.0 by the author.