IPv6 OpenVPN Tunneling with Asus MerlinWRT and Postfix Smarthost over v6 Tunnels

Hey All, It’s been a while and I finally got around to updating my postfix cluster to send email over my OpenVPN tunnel with standard ports to my local zimbra server instead of using a non-standard port over the wan.  While I was at it, I figured I’d trying pushing IPv6 and here’s how that went.  A little backstory, my Zimbra server has always been IPv6 only, which is fine for my phone (imap/smtps) which has been dual stacked for a few years now.

With the newest release of Merlin’s AsusWRT, I received the newest version of OpenVPN 2.4, which has a number of fixes, always start with the latest software.

Part 1) VPN

OpenVPN Config on the server

Start with a working IPv4 OpenVPN configuration, and add these lines to the Custom Configuration block.

tun-ipv6
server-ipv6 2001:db8:100::/64
push "route-ipv6 2001:db8:200::/64"
push "route-ipv6 2001:db8:100::/48"

I’m still using a HE.net tunnel at home, so 2001:db8:200::/64 is my LAN subnet, and 2001:db8:100::/48 is my routed /48, I wanted to use this subnet to also access the internet from v4 only hosts so I used a publicly routed network from my /48 delegated from HE.net, you could also use whatever subnets you have delegate from your upstream ISP.

Additional Settings:

Username/Password Authentication – Yes
Manage Client-Specific Options – Yes

OpenVPN Client Config (on client)

I set a static IP for my VPS servers, as well as my windows clients, this isn’t required but I don’t ( and avoid) have an enterprise level infrastructure at home, so static IPs are best for me.  Export the config and use it on each endpoint, add the option auth-user-pass login.conf. The login.conf looks like this.

username
PassW0rD

with your literal, username and password.

drop these files in your /etc/openvpn/ folder, make sure the login is read only by root.

chmod 0400 /etc/openvpn/login.conf; chown root: /etc/openvpn/*;

OpenVPN Client Config (on server)

Since you have a username, you can push custom config to the endpoints, the config for server1 for username is located in /jffs/configs/openvpn/ccd1/username and looks like this

ifconfig-push 192.168.2.101 255.255.255.0
ifconfig-ipv6-push 2001:db8:100::101/64
push "route 192.168.1.0 255.255.255.0"
push "route 192.168.2.0 255.255.255.0"
push "dhcp-option DNS 192.168.1.1

where 192.168.1.1 is my LAN, and 192.168.2.0 is the vpn subnet for IPv4,

Now restart the openvpn server and client services, (apply in the web console) If you don’t have it already, you can setup linux to autostart & join the vpn with standard service scripts.

systemctl enable openvpn@configname
systemctl start openvpn@configname

OpenVPN Client Config (on server) for IPv6 internet over the VPN.

If you, like me, work at a place where they have not deployed IPv6 but need access to IPv6 services (I like to check my mail over my lunch break). You can create a profile that provides IPv6 Access over the VPN with your public IP.

again the config is in /jffs/configs/openvpn/ccd1/username and looks like this, and only applies to this username.

push "redirect-gateway-ipv6 def1 bypass-dhcp-ipv6"
push tun-ipv6
push "route-ipv6 2000::/3"

If you wanted to make a IPv6 VPN “tunnel broker”, and purpose build it for that, you could make this the default options and apply them to everyone, but that was not my intent.

Part 2) IPv6 Firewall

Since IPv6 is all public IPs, I’ll need to add some firewall rules to let me VPN subnet communicate with my LAN subnet and the internet.

Service Name Remote IP/CIDR Local IP Port Range Proto
VPN-HTTP 2001:db8:100::/64 2000::/3 80 TCP
VPN-HTTPS 2001:db8:100::/64 2000::/3 443 BOTH
VPN-SMTP 2001:db8:100::/64 2000::/3 25 TCP
LAN-SMTP 2001:db8:200::/64 2001:db8:100::/64 25 TCP

You can be as open/closed as you want with your Local/Remote IP and ranges (as these are your VPN subnets), you can even specify range 1:65535 which would be all possible ports.

Part 3) Transport route over VPN for SMTP

So at this point we have IPv4 and IPv6 addreses for both the public and tunnel interfaces, but I want to ensure my outbound email uses the wan and my relay to the zimbra server uses my tunnel IPs, so I will make some changes.

First, TEST, make sure you can open a socket before you go changing your mail settings.  I know I’m on the tunnel if I can open port 25 as HE.net blocks smtp ports.

nc zimbra.jacobdevans.com 25
220 zimbra.jacobdevans.com ESMTP Postfix

Looking good, let’s continue…

Configure new transport

Note, I already bind my public IPs in the main.cf

smtp_bind_address = 104.244.74.27
smtp_bind_address6 = 2605:6400:30:fb26::10

Add binding for the VPN interface IPs (tun0)

smtp inet n - n - - smtpd
vpn unix - - n - - smtp
 -o smtp_helo_name=inbound.jacobdevans.com
 -o smtp_bind_address=192.168.2.101
 -o smtp_bind_address6=2001:db8:100::101

First, I added a second transport here, with different helo, ipv4 and ipv6 addresses.

Update the transport map (was smtp:, now vpn:)

jacobdevans.com vpn:[zimbra.jacobdevans.com]
.jacobdevans.com vpn:[zimbra.jacobdevans.com]

and of course run postmap transport to generate a new db hash

Restart the postfix services, and you’re good to go! Drop a line if you want some more details or found this helpful!

Final Thoughts:

Most of this I have in ansible playbooks, so managing multiple servers is very easy, a site effect seems to be I cannot ssh over IPv6 as I do not have NAT and my route for v6 to v6 is over the VPN now, something I still need to figure out.

Update1:

I was able to find this post on the openvpn forums and it solved my v6 to v6 issue!

ifconfig-push 192.168.2.101 255.255.255.0
ifconfig-ipv6-push 2001:db8:100::101/64
iroute-ipv6 2001:db8:abcd::/64
push "route 192.168.1.0 255.255.255.0"
push "route 192.168.2.0 255.255.255.0"
push "dhcp-option DNS 192.168.1.1

where 2001:db8:abcd::/64 would be the public IPv6 assigned to the VPS.

Say Something Nice