Many organizations with a physical presence have a robust internet egress (outbound) strategy and want to continue using it, even when adding additional locations, such as a public cloud provider. A basic pfSense environment on-prem can establish a site-to-site VPN tunnel with Google Cloud and accept internet-bound traffic to use the on-prem internet connection with a simple configuration.
Several different components are involved:
- Google Cloud VPN (basic, route-based)
- Google Cloud VPC with one or more subnets
- pfSense Community Edition (Virtual Machine)
- Google Cloud Compute Engine (GCE) (Virtual Machine for testing)
- One or more internet providers for the on-prem environment.
Essentially, Google Cloud VPN will establish an IPSec tunnel to the WAN/external interface of pfSense. A static route of 0.0.0.0/0 will be created in the Google Cloud VPC to direct all egress traffic (such as from a GCE instance) to the VPN tunnel. pfSense will have its own VPN configuration to establish the on-prem end of the tunnel, as well as some firewall and NAT rules to properly pass GCP traffic to the Internet.
In my lab, I have a pfSense virtual machine (running on vSphere 7) with a virtual NIC connected to my LAN. My LAN uses a cable provider for Internet. I also have a Wireless 5G Internet provider which I have connected directly to the pfSense virtual machine using a USB Ethernet adapter in USB passthrough mode directly to the virtual machine.
The pfSense WAN interface is set to the USB adapter and has a public IP address from the Wireless 5G provider. It also has the LAN interface with a static IP from the 192.168.86.0/23 subnet of my internal network.
I do not use pfSense as my main router, it will only be used as a VPN Gateway for connecting to GCP.
In GCP, I have a single VPC with a single subnet: 10.252.1.0/24. I have several VPC firewall rules created:
- permit Identity-Aware Proxy so that I can use browser-based SSH to connect to GCE instances that have private IPs
- permit all traffic from my on-prem subnet 192.168.86.0/23.
There is a test GCE instance on the subnet at 10.252.1.30.
A Classic Cloud VPN was created with a public IP and IKEv2 tunnel with pre-shared key. This is a route-based tunnel (not BGP) and the remote network range was set to 0.0.0.0/0. This tells GCP that all IP addresses (the Internet) can be reached through the VPN tunnel. This automatically creates a route for 0.0.0.0/0 in the VPC with next hop of the VPN tunnel. The VPC’s default route for 0.0.0.0/0 with next hop of “default internet gateway” should be deleted.
Note that GCP Classic Cloud VPN configurations are not recommended. Instead, a Cloud VPN HA configuration with BGP should be used. pfSense is compatible with Cloud VPN HA and BGP. See Site to Site VPN between Google Cloud and pfSense on VMware at home for more details including how to install and configure pfSense from scratch as well as use pfSense with BGP.
From the VPN menu, choose IPsec. Create a new Phase1 (P1). Leave the Interface as WAN. In the Remote Gateway field, enter the public IP of the GCP Cloud VPN gateway. Provide the pre-shared key that was used to create the GCP Cloud VPN tunnel.
Set Encryption Algorithm to AES256-GCM and Life Time to 36000.
Save it and then Add a Phase2 (P2). Set Mode to Tunnel IPv4. Set Local Network to Network with address 0.0.0.0/0. This tells GCP that this tunnel accepts traffic destined for 0.0.0.0/0. Set the Remote Network to Network and put in the remote (GCP) subnet. In my case, I set it to 10.252.1.0/24.
Check the box for AES256-GCM and set it to 128 bits. Save it.
From the Status drop-down, choose IPsec. The tunnel should come up shortly. GCP should also show the tunnel as up.
From the Firewall menu, choose Rules and then IPsec. Add a new rule for IPv4 for any source/port to any destination/port, any protocol.
In my LAN I added a static route in my LAN router for 10.252.1.0/24 with next-hop of my pfSense LAN IP. Then I was able to ping the GCE instance from my computer. The GCE instance could also ping IPs in my 192.168.86.0/23 network through pfSense.
At this point, communication should be working between GCP and on-prem networks, but there is one more step to enable Internet egress.
From the Firewall menu, choose NAT and then Outbound. Set Outbound NAT mode to Hybrid (automatic + custom rules). Create a new Mapping. Set Interface to WAN and Source to 10.252.1.0/24. Save and apply the changes.
Now, the GCE instance can reach the Internet through pfSense. To verify, run
curl ifconfig.me and verify that the public IP address returned is the one assigned to the pfSense WAN interface.
Recall that I said I had two internet providers: Cable and Wireless 5G. With pfSense, I can easily toggle which provider is used by GCP for Internet access. From the System menu, choose Routing. The Gateways will be listed. By default, only the WAN_DHCP gateway was listed with the public IP for the Wireless 5G provider. I added a new gateway using the LAN interface and my LAN default gateway of 192.168.86.1.
When I change the default gateway to my LAN gateway and apply the changes, my GCE instance now accesses the internet through pfSense’s LAN interface using the cable internet provider instead of the WAN interface Wireless 5G. Technically at this point the Outbound NAT mapping created earlier is not required, but it doesn’t hurt to leave it in place. Toggling the pfSense default gateway back to WAN and applying the change causes the GCE instance to again access the internet using the Wireless 5G connection.
pfSense is a great environment to experiment with site-to-site VPNs, NAT, and routing, and is pretty robust and capable of accomplishing a lot of different lab activities.