I’ve been trying to establish a site-to-site VPN connection between my house and my parents’ for a couple years now. Each time I try I become frustrated and eventually give up. No longer! I’ve finally gotten a site to site VPN working between my pfSense router and my parents’ Netgear Nighthawk R8000 running DD-WRT v3.
It was quite the undertaking for me to get these two systems talking. I drew a lot of inspiration from here. In order to get this to work you need to keep these things in consideration:
- Protocol, port, device type, encryption cipher, hash algorithm, TLS authentication, and certificate settings all need to match
- VPN IP addresses need to be assigned to both the server and the client
- Routes for each network need to be established on both devices
- Firewalls need to be configured to allow traffic to/from each network through the VPN tunnel
I used the following settings to get things working between these two devices:
OpenVPN Server (pfSense)
If you haven’t already, generate a certificate authority and server certificate. Do this in System / Cert Manager and click Add. When generating the certificate make sure the Certificate Type is Server Certificate.
General
- Server mode: Peer to Peer (SSL / TLS)
- Protocol: UDP
- Device mode: tap
Cryptographic settings
- Enable authentication of TLS packets: checked
- Automatically generate a shared TLS authentication key: checked
- Peer certificate authority & Server Certificate: Select appropriate CA / certificate from the dropdowns here
- DH Parameter length: 2048
- Encryption algorithm: AES-256-CBC
- Auth digest algorithm: SHA256 (256 BIT)
- Certificate depth: One (Client + Server)
Tunnel Settings
- IPv4 Tunnel network: Enter a unique (not existing on either netwonk) network here in CIDR format, ex 10.1.1.0/24
- Ipv4 Local Network(s): Enter the networks you would like the remote network to access
- IPv4 Remote Network(s): Enter the networks you would like the local network to access
- Compression: Enabled with Adaptive Compression
Advanced Configuration
Optional? I found that for some reason the routing table wasn’t properly populated with the remote network on my pfSense server. I added a custom option to take care of that:
route <remote network> <remote subnet mask> <remote VPN IP>
In my example it ended up being “route 192.168.98.0 255.255.255.0 10.54.98.2”
Key export
You will need to export the Certificate Authority certificate as well as the client certificate & private key files for use with dd-wrt. Do this by going to System / Cert Manager. There are little icons to the right of the certificates where you can click to download them.
Export the CA certificate as well as both the certificate and key from whatever was specified in the Server Certificate section from the above OpenVPN configuration.
OpenVPN client (dd-wrt)
Go to Services / VPN and look for the OpenVPN Client section
- Start OpenVPN Client: Enable
- Tunnel Device: TAP
- Tunnel Protocol: UDP
- Encryption cipher: AES-256 CBC
- Hash Algorithm: SHA256
- User Pass Authentication: Disable
- Advanced Options: Enable
- LZO Compression: Adaptive
- NAT: Enable
- Firewall protection: Disable
- Bridge TAP to br0: Enable
- TLS Auth Key: <Paste the contents of the “Key” section under pfSense’s Cryptographic settings area of the OpenVPN server configuration>
- CA Cert: <Paste contents of downloaded CRT file from pfsense’s CA>
- Public Client Cert: <Paste contents of downloaded CRT file from pfsense’s certificate section>
- Private Client Key: <Paste contents of downloaded .key file from pfsense’s certificate section>
IN THEORY this should be all that you have to do. The tunnel should establish and traffic should flow between both networks. Sadly it wasn’t that simple for my setup.
Troubleshooting
One-way VPN
After setting up the tunnel I saw everything was connected but the traffic was unidirectional (remote could ping local network but not visa versa.)
On the pfsense router, I ran
netstat -r | grep 192.168
(change the grep to whatever your remote network is)
I noticed that there were no routes to the remote network. To fix this I appended a server option in the OpenVPN server config (adjust this to match your networks)
route 192.168.98.0 255.255.255.0 10.54.98.2
Blocked by iptables
Adding the route on the server helped but things still weren’t getting through. I enabled logging on the DD-WRT side, consoled into the router, and ran the following:
watch -n 1 "dmesg | grep 192.168.98"
This revealed a lot of dropped packets from my OpenVPN server’s network. After a lot of digging I found this forum post that suggested a couple custom iptables rules to allow traffic between the bridged network and the OpenVPN network (adjust interface names as necessary)
iptables -I FORWARD -i br0 -o tap1 -j ACCEPT
iptables -I FORWARD -i tap1 -o br0 -j ACCEPT
This doesn’t survive a reboot, so you’ll want to enter those two commands in the Administration / Commands section of the dd-wrt web configuration and click “Save Firewall”
Success
Finally, after a custom routing rule on the pfsense side and a custom iptables rule on the dd-wrt side, two way VPN has been established!