Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@terrillmoore
Last active June 10, 2023 14:50
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save terrillmoore/dfccff9ef8bffacdb9eb39264f6b341f to your computer and use it in GitHub Desktop.
Save terrillmoore/dfccff9ef8bffacdb9eb39264f6b341f to your computer and use it in GitHub Desktop.
Adapting IPFire net-to-net client config for OpenVPN in ASUS WRT routers

Adapting IPFire net-to-net client config for OpenVPN in ASUS WRT routers

IPFire supports net-to-net connections.

Part of setting up the connection with non-IPFire peers often involves generating a .ovpn file from the client package.

There are some client docs about how to do this, but not net-to-net.

For net-to-net clients, IPFire generates a zip file containing two files. Both files are named based on the name you choose for the VPN.

  • vpnname.conf is the configuration file for OpenVPN.
  • vpnname.p12 is a PKCS12 file containing the certs and the private key to be used by the client.

The ASUS router wants a combined OpenVPN config file (which we'll call vpnname.ovpn). This file has the certificates and the private key embedded, using XML-like notation.

First issue: what's the password on the vpnname.p12 file? You can't read it without knowing the password. It turns out that for net-to-net connections, the private key in the vpnname.p12 file has an empty password. Next question: what password shoud we use on the private key When setting up an ASUS OpenWRT router, you will want to generate the private key without any encryption (possibly different than an empty password).

Armed with this info, we can get the info manually:

$ openssl pkcs12 -in vpnname.p12 -passin pass: -nodes -info
MAC: sha1, Iteration 2048
MAC length: 20, salt length: 8
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2048
Certificate bag
Bag Attributes
    localKeyID: ..redacted..
    friendlyName: ..redacted..
subject=C = US, ST = NY, O = Example Corp., CN = ..redacted..
issuer=C = US, ST = NY, L = Anytown, O = Example Corp., OU = sysadmin, CN = Example Corp. CA, emailAddress = sysadmin-request@example.com

-----BEGIN CERTIFICATE-----
..redacted..
-----END CERTIFICATE-----
Certificate bag
Bag Attributes
    friendlyName: Example Corp. CA
subject=C = US, ST = NY, L = Anytown, O = Example Corp., OU = sysadmin, CN = Example Corp. CA, emailAddress = sysadmin-request@example.com

issuer=C = US, ST = NY, L = Anytown, O = Example Corp., OU = sysadmin, CN = Example Corp. CA, emailAddress = sysadmin-request@example.com

-----BEGIN CERTIFICATE-----
..redacted..
-----END CERTIFICATE-----
PKCS7 Data
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2048
Bag Attributes
    localKeyID: ..redacted..
    friendlyName: ..redacted..
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
..redacted..
-----END PRIVATE KEY-----

With this info, and the info on the net (e.g., wiki.ipfire.org iOS manual configuration, wiki.ipfire.org iOS scripted configuration, and Magnus Wedberg's IpCop config for OpenVPN and iOS, it's not too hard to create a combined .ovpn file that will authenticate properly.

Some editing of the configuration portion of the script is needed.

Unzip the client zip file in a temporary directory, cd to that directory, and use the following commands to generate the .ovpn file.

BASENAME=vpnname
function _wrap { awk -vkey="$1" '/^----/ { if (f == 0) printf("<%s>\n", key); f = 1; } { if (f) print } END { if(f) printf( "</%s>\n", key); }' ; }
sed -e '/^status/d' -e '/^pkcs12/d' -e '/^management/d' ${BASENAME}.conf >${BASENAME}.ovpn
openssl pkcs12 -in ${BASENAME}.p12 -passin pass: -nodes -cacerts -nokeys | _wrap ca >> ${BASENAME}.ovpn
openssl pkcs12 -in ${BASENAME}.p12 -passin pass: -nodes -clcerts -nokeys | _wrap cert >> ${BASENAME}.ovpn
openssl pkcs12 -in ${BASENAME}.p12 -passin pass: -nodes -nocerts | _wrap key >> ${BASENAME}.ovpn

The above command deletes the management port command, if present, because there's no way to give it a password in the Asus setup.

If you're doing this on Windows, get git bash; that includes a suitable version of the openssl command.

You'll get something like this:

# IPFire n2n Open VPN Client Config by ummeegge und m.a.d
# 
# User Security
user nobody
group nobody
persist-tun
persist-key
script-security 2
# IP/DNS for remote Server Gateway
remote XX.XX.XX.XX
float
# IP adresses of the VPN Subnet
ifconfig YY.YY.YY.2 YY.YY.YY.1
# Server Gateway Network
route ZZ.ZZ.ZZ.0 255.255.255.0
# tun Device
dev tun
#Logfile for statistics
# Port and Protokoll
port 1195
proto udp
# Paketsize
tun-mtu 1500
fragment 1300
mssfix
remote-cert-tls server
# Auth. Client
tls-client
# Cipher
cipher AES-256-CBC
# HMAC algorithm
auth SHA512
# Debug Level
verb 3
# Tunnel check
keepalive 10 60
# Start as daemon
daemon VPNNAMEn2n
writepid /var/run/VPNNAMEn2n.pid
# Activate Management Interface and Port
# remsub WW.WW.WW.0/255.255.255.0
<ca>
-----BEGIN CERTIFICATE-----
..redacted..
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
..redacted..
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
..redacted..
-----END PRIVATE KEY-----
</key>

Asus AC68U setup

Log into the router's web-admin page.

Select VPN (on left), then VPN client.

Add a profile.

Import the .ovpn profile you chose above. Leave username and password blank. Save. Don't start yet.

IPFire setup

Add rules allowing inbound and outbound traffic from the new openVPN net-to-net connection.

Enable the VPN.

For some reason, the IPFire program /usr/local/openvpnctrl always explicitly blocks traffic from net-to-net communications as part of its setup, in rule OVPNBLOCK. This makes things not work for inbound traffic. At time of writing, I'd not investigated why this is. The solution is to edit /etc/sysconfig/firewall.local and add a CUSTOMFORWARD rule that accepts traffic from the remote side. A simple solution, but arguably not terribly secure, is For example, if you're using 10.1.2.0/24 as your remote, you could say:

#!/bin/sh
# Used for private firewall rules

function _start {
    # allow all packets from VPN address group over any tunnel to be forwarded.
    iptables -A CUSTOMFORWARD -s 10.1.2.0/24 -i tun+ -j ACCEPT
}

function _stop {
    # remove the custom rules.
    iptables -F CUSTOMFORWARD
}

# See how we were called.
case "$1" in
  start)
        ## add your 'start' rules here
        _start
        ;;
  stop)
        ## add your 'stop' rules here
        _stop
        ;;
  reload)
        $0 stop
        $0 start
        ## add your 'reload' rules here
        ;;
  *)
        echo "Usage: $0 {start|stop|reload}"
        ;;
esac

Asus

Now enable the VPN.

Notes on setting things up

It is very much easier to do this if you have a system on the remote network that can be accessed via Splashtop, RDP, etc. This will let you access the AC68U configuration web page.

I've only tried this using public IP addresses on each end.

Work was done with IPFire 2.25 (x86_64) - Core Update 147, and AC68U firmware version 3.0.0.4.385_20630.

@benjamin-9T
Copy link

Hi @terrillmoore , thanks for the inquiry. Yes, I we got it working after a lot of trial and error.
This is a great guide, and helped us get started.

Now we just struggle with DNS forwarding, so that a VPN cliend also gets to use the DNS from the ZenWifi router.

@terrillmoore
Copy link
Author

Great. In my use case, the default DNS settings were fine, so didn't have to figure that out. Good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment