Artificial truth

The more you see, the less you believe.

[archives] [latest] | [homepage] | [atom/rss/twitter]

A simple multiports VPN with ferm and OpenVPN
Fri 11 November 2016 — download

OpenVPN's standard port is 1194, unfortunately, it's rarely open on shitty networks, where you actually do want to use a VPN, precisely because you're on a shitty network that you don't trust.

Now you have to pick a port to run your VPN on it, but there is no right choice, since you may want to use several: 53-udp, 80-tcp, 443-tcp, 22-tcp, 53-tcp, 123-udp, … But running one OpenVPN instance per port sounds is idiotic.

Fortunately, by using DNAT and SNAT, you can use something like the following ferm rules, make your TCP instead of OpenVPN listen on 1194 and the UDP one on 1195, and connect to them using whatever port you specify:

@hook post  "echo 1 >| /proc/sys/net/ipv4/ip_forward";
@hook flush "echo 0 >| /proc/sys/net/ipv4/ip_forward";

@def $ADDR_WAN = (W.X.Y.Z);
@def $ADDR_VPN = (A.B.C.D);

@def $NET_VPN = (;

table filter {
    chain INPUT {
        interface tun+ ACCEPT;

        mod state state NEW daddr @ipfilter($ADDR_VPN) proto (tcp udp) dport (1194 1195) ACCEPT;

    chain FORWARD {
        outerface eth0 saddr $NET_VPN ACCEPT;

domain ip table nat {
    chain PREROUTING daddr $ADDR_VPN proto tcp dport (ftp ssh telnet smtp http https pop3 openvpn) DNAT to "$ADDR_VPN:1194";
    chain PREROUTING daddr $ADDR_VPN proto udp dport (ntp domain) DNAT to "$ADDR_VPN:1195";

    chain POSTROUTING saddr $NET_VPN outerface eth0 SNAT to $ADDR_WAN;