I really like openWRT routers software. It is a brilliant piece of software easy to manage and very powerful. Compatible with thousands of routers but also with a lot of ARM boards and others (GL-B1300, raspberry Pi4, raspberry Pi3, raspberry Pi2, X86 virtual machines, bananaPi Pro, nanopi, etc..)
digging a bit in internet, I could not find any documentation about how to configure openWRT to work with PPTP/L2TP/iKev2 instead of openVPN as client.
Whether obviously openVPN is more integrated in openWRT, the next configuration involves manual tasks and configurations to be done manually. You need to have some basic skill (SSH, edit files, understanding of VPNs, etc) out of the scope on this document.
Let’s start.
login through SSH on your openWRT installation and then run the following:
# opkg update # opkg install opkg install xl2tpd strongswan-default
That will install a huge set of packages, just ensure you have space enough before.
Packages likely to be installedConfiguring kmod-udptunnel6.
Configuring kmod-l2tp.
Configuring opkg.
Configuring kmod-crypto-hash.
Configuring kmod-crypto-null.
Configuring kmod-crypto-aead.
Configuring kmod-crypto-pcompress.
Configuring kmod-crypto-manager.
Configuring libmnl.
Configuring ip-tiny.
Configuring kmod-crypto-authenc.
Configuring kmod-crypto-cbc.
Configuring kmod-lib-zlib-inflate.
Configuring kmod-lib-zlib-deflate.
Configuring kmod-crypto-acompress.
Configuring kmod-crypto-deflate.
Configuring kmod-crypto-des.
Configuring kmod-crypto-echainiv.
Configuring kmod-crypto-hmac.
Configuring kmod-crypto-sha256.
Configuring kmod-crypto-rng.
Configuring kmod-crypto-wq.
Configuring kmod-crypto-iv.
Configuring kmod-crypto-md5.
Configuring kmod-crypto-sha1.
Configuring kmod-ipsec.
Configuring kmod-iptunnel4.
Configuring kmod-ipsec4.
Configuring kmod-iptunnel6.
Configuring kmod-ipsec6.
Configuring kmod-ipt-ipsec.
Configuring iptables-mod-ipsec.
Configuring strongswan.
Configuring strongswan-mod-constraints.
Configuring strongswan-mod-sha1.
Configuring strongswan-mod-sha2.
Configuring strongswan-mod-connmark.
Configuring strongswan-mod-pem.
Configuring strongswan-mod-rc2.
Configuring resolveip.
Configuring strongswan-mod-aes.
Configuring strongswan-mod-pgp.
Configuring strongswan-mod-sshkey.
Configuring strongswan-mod-xcbc.
Configuring strongswan-mod-random.
Configuring strongswan-mod-pkcs1.
Configuring strongswan-mod-dnskey.
Configuring strongswan-mod-hmac.
Configuring kmod-pppol2tp.
Configuring ppp-mod-pppol2tp.
Configuring xl2tpd.
Configuring strongswan-charon.
Configuring strongswan-mod-des.
Configuring strongswan-mod-fips-prf.
Configuring strongswan-mod-socket-default.
Configuring strongswan-mod-resolve.
Configuring strongswan-mod-pubkey.
Configuring strongswan-mod-kernel-netlink.
Configuring strongswan-ipsec.
Configuring strongswan-mod-attr.
Configuring strongswan-mod-gmp.
Configuring strongswan-mod-md5.
Configuring strongswan-mod-nonce.
Configuring strongswan-mod-revocation.
Configuring strongswan-mod-stroke.
Configuring strongswan-mod-updown.
Configuring strongswan-mod-x509.
Configuring strongswan-mod-xauth-generic.
Configuring strongswan-default.
Now we will edit the following files and we will empty them replacing any content with the following.
/etc/ipsec.conf /etc/ipsec.secrets /etc/xl2tpd/xl2tpd.conf /etc/ppp/options.l2tpd.client
let’s start:
- file: /etc/ipsec.conf
#note the spaces are on purpose and must remain. config setup strictcrlpolicy=yes uniqueids = no charondebug=all conn %default ikelifetime=60m keylife=20m rekeymargin=3m keyingtries=1 keyexchange=ikev2 #you can play with the encryption. The default is a good choice. #ike=aes128-sha1-modp1024,3des-sha1-modp1024! #esp=aes128-sha1-modp1024,3des-sha1-modp1024! conn L2TP-PSK authby=secret #you can play with the encryption. The default is a good choice. #ike=aes256-sha1-modp1024! #esp=aes256-sha1! leftauth=psk auto=add keyingtries=3 dpddelay=30 dpdtimeout=120 dpdaction=clear rekey=yes ikelifetime=8h keylife=1h type=transport # Replace IP address with your current default gateway IP or just let %defaultroute left=%defaultroute leftprotoport=17/1701 # Replace IP address with your VPN server's IP right=<VPN SERVER IP> (i.e IP of xxx-yyyy.strongconnectivity.com) rightauth=psk rightid=<VPN SERVER IP> (i.e IP of xxx-yyyy.strongconnectivity.com) rightprotoport=17/1701 auto=start dpddelay=40 dpdtimeout=130 dpdaction=clear
- /etc/ipsec.secrets (note, below values must be adapted to your own setup and to the VPN server IP.
#strongSwan IPsec secrets file <host_public_ip> <VPN_Server_IP> PSK "shared_key" 192.168.1.25 1.2.3.4 : PSK "xxxxxxxxxxxxxxx"
- /etc/xl2tpd/xl2tpd.conf (note: <VPN server IP> is the IP of your VPN server) (debug is not enabled by default)
[lac strong-vpn] lns = <VPN server IP> ;ppp debug = yes pppoptfile = /etc/ppp/options.l2tpd.client length bit = yes bps = 1000000
- /etc/ppp/options.l2tpd.client (username and password can be obtained in the customer area)(debug is also not enabled by default).
ipcp-accept-local ipcp-accept-remote require-mschap-v2 noccp noauth idle 1800 mtu 1410 mru 1410 defaultroute replacedefaultroute usepeerdns #debug connect-delay 5000 name <login (username/account name)> password <password to be confirmed with StrongVPN provider> lcp-echo-interval 20 lcp-echo-failure 5
- Restart services:
# /etc/init.d/ipsec enable # /etc/init.d/xl2tpd enable # /etc/init.d/ipsec restart # /etc/init.d/xl2tpd restart # ipsec restart # ipsec up L2TP-PSK # ipsec statusall
- to check the logs:
# logread
We have setup already everything to make it work. Now we just need some routing details to properly run it.
- Create a route to VPN server IP via your current default gateway (or ppp device if applicable).
Example: Add route using the below command (where x.y.z.w is the IP of the VPN server)
ip ro ad x.y.z.w via 192.168.1.1
- To connect the VPN (remember you are going to lose you connectivity with the host, unless you are locally in the same subnet as the server. Do not run remotely unless you have another way of connecting to the local network IP of your router”!!)
# echo "c strong-vpn" > /var/run/xl2tpd/l2tp-control
- To disconnect the VPN:
# echo "d strong-vpn" > /var/run/xl2tpd/l2tp-control
Once you have first time created the interface (it will be ppp0), you have to define the interface within luci tool to properly set up the Firewall rules and allow masquerading in that new network.
To do so, it is time to create the interfaces for the Firewall.
- Go to your openWRT server ip.
- Go to the menu –> Network –> interface
Select “Add new interface”
Create the interface with the following details. Note: keep the protocol in Unmanaged, and if you have already started it up (not recommended yet), select ppp0 in “Cover the following interface”, or just write ppp0 in the selection box
Remember to keep the Assign firewall empty, we will create it later:
Now go to your Firewall settings and create a new Firewall zone:
Fill only Allow forward from source, including the interfaces you want to allow masquerading from (i.e local lan, any other local interface, and, if you have it as me, any other VPN server interface you have running in your router if so.
When finished click on Save and Apply
After the Firewal has been applied, the following command has been run (yo do not have to do it).
# fw3 -q reload
so your interface would be now without IP setup. Just, stop it and run it again as explained before.
# echo "d strong-vpn" > /var/run/xl2tpd/l2tp-control # echo "c strong-vpn" > /var/run/xl2tpd/l2tp-control
Now you are done!!. If you continue reading, you will need deep knowledge of routing tables, what happens after you are in a VPN, or just how to deal with more than just one interface (i.e having an OpenVPN server in the same hosts which is accessing to another VPN as client, or just how to login in your public ISP IP when you are redirecting all the traffic into the VPN).
If at this point, you do not know what I am talking about. Please stop reading here, and do not continue doing any other change, just take the below script, remove all the things related to the routing outside of the VPN, and use adapt it for your needs).
If you need some automated way of enabling disabling and also include some routes outside of the VPN (i.e to update your public IP in duckdns for instance, instead of the public IP of your VPN, you have to redirect some traffic outside of the VPN in two ways.
- Just adding a package sign to some source or destination hosts.
- Just redirecting hosts outiside of the VPN (i.e your TV to watch Netflix outside of the VPN).
I will show you how to do it in both ways with just one script. You will have to understand it by your own….
Let’s commence.
- To redirect traffic outside of the VPN (if you do not know what is this, most probably yo do not need it!!)
# echo 201 novpn >> /etc/iproute2/rt_tables # echo 200 duckdns >> /etc/iproute2/rt_tables
Now the script, which is not a script, but a bash function. I prefer this option as it is quick and easier.
Note: you need additional software installed in your router like curl, bash, awk, wget, nslookup, etc…
Now load your shell to be bash
# bash
After enabling bash, you need a bash variable with the name of the VPN server you are trying to connect to:
# server=your.vpn.server.com
Edit your preferable file (.bashrc or .profile) and add the following (note, it is important having created the alias IP with the below content).
To be used as bash function. Add it in your .profile or .bashrc file, and reload the file with:
# . /root/.bashrc
Now te function and the alias:
alias IP='wget -qO- http://ipv4.icanhazip.com; echo -n' function rutas () { [[ -z $server ]] && { echo no variable server defined.Please, define bash variable with server=vpn.host.server; return 1; } host=`nslookup ${server} | awk '/^Address 1:/ { print $3 }'`; if [[ "$1" == "conecta" ]]; then if [[ ! $( ip ro | grep $host) ]]; then ip ro ad $host via 192.168.1.1 ip rule add from $( ip route get 1 |grep src | awk {'print $7'}) table novpn ip route add table novpn to $(ip route get 1 | grep src | awk '{print $7 "/32 dev"}') $(ip -4 route ls | grep default | awk {'print $5}') ip route add table novpn default via $(ip -4 route ls | grep default | awk {'print $3}') echo adding routes ip ro | grep $host ipsec restart sleep 5 fi elif [[ "$1" == "desconecta" ]]; then if [[ $( ip ro | grep $host) ]]; then ip ro del $host via 192.168.1.1 ip rule del from $( ip route get 1 |grep src | awk {'print $7'}) table novpn ip route del table novpn to $(ip route get 1 | grep src | awk '{print $7 "/32 dev"}') $(ip -4 route ls | grep default | awk {'print $5}') ip route del table novpn default via $(ip -4 route ls | grep default | awk {'print $3}') echo deleting routes ip ro | grep $host fi elif [[ "$1" == "ok" ]]; then # next lines will make some hosts to be sent outside of the VPN network. # If you need this, comment out the following lines # #novpn="list of IPs that will be sent out of the VPN separated by space" ###### comment out after this line for the feature of allowing hosts to be sent out of VPN # novpn="172.16.8.14 172.16.8.137 10.0.1.137 10.0.1.2" # for client in $novpn; # do # echo "Routing client $client traffic out of the VPN" # echo "ip rule add from $client priority 10 table novpn" # ip rule add from $client priority 10 table novpn # echo "ip route add $client dev eth1 table novpn" # ip route add $client dev eth1 table novpn # done ###### end comment out for the feature of allowing hosts to be sent out of VPN # if you are routing networks (i.e as VPN server too), # the hosts redirected out of the VPN will not have access to them. # If you want to allow those hosts out of VPN to access those networks too create the file # /etc/openvpn/network.txt containing those networks in the network/mask notation, i.e: 10.0.2.0/24) # now comment out the following line, and adapt the interface (tun0) to any local interface, # it can be br-lan, or any other ###### comment out after this line for the feature of allowing networks to be accessible in novpn # for i in `cat /etc/openvpn/network.txt`; do ip route add $i dev tun0 src 172.16.15.1 table novpn; done # ip route flush cache ###### end comment out for the feature of allowing networks to be accessible in novpn # this is to be able to sync duckdns with your public IP. # Check with wget http://whatismyip.host && wget adsl4ever.com/ip # here is where you need to have the line "200 duckdns" in the /etc/iproute2/rt_tables # on this way (marking packages) you can run your duck.sh script and it will update duckdns # with your real public IP not the VPN one. # (remember you are redirecting all the traffic into the VPN after get connected) # if you do not understnad anything, do not enable the following lines!!! ###### comment out after this line for the feature of syncing your public IP with a DDNS # ip route add default via 192.168.1.1 table duckdns # update 192.168.1.1 with your default GW ###### end comment out for the feature of syncing your public IP with a DDNS # now we mark all the packages pointing to duckdns with the mark 65 # to be firewalled outside of the VPN. # if you have commented out the previous ip route line, you will need the next 6 ###### comment out after this line for the feature of syncing your public IP with a DDNS #ip rule add fwmark 65 table duckdns #iptables -t mangle -A OUTPUT -d 72.47.224.85 -j MARK --set-mark 65 #iptables -t mangle -A OUTPUT -d 35.167.241.52 -j MARK --set-mark 65 #iptables -t mangle -A OUTPUT -d 54.191.209.253 -j MARK --set-mark 65 #iptables -t nat -I PREROUTING -d 72.47.224.85 -j MARK --set-mark 65 #iptables -t nat -I PREROUTING -d 35.167.241.52 -j MARK --set-mark 65 #iptables -t nat -I PREROUTING -d 54.191.209.253 -j MARK --set-mark 65 ###### end comment out for the feature of syncing your public IP with a DDNS elif [[ "$1" == "nok" ]]; then ###### comment out after this line for the feature of allowing hosts to be sent out of VPN # #novpn="list of IPs that will be sent out of the VPN separated by space" # novpn="172.16.8.14 172.16.8.137 10.0.1.137 10.0.1.2" # for client in $novpn; # do # echo "Delete client $client from rule traffic routing through VPN" # ip rule del from $client lookup novpn # echo "Delete client $client from route" # ip route del $client dev eth1 table novpn # done ###### end comment out for the feature of allowing hosts to be sent out of VPN ###### comment out after this line for the feature of allowing networks to be accessible in novpn # for i in `cat /etc/openvpn/network.txt`; do ip route del $i dev tun0 src 172.16.15.1 table novpn 2> /dev/null; done # ip route flush cache ###### end comment out for the feature of allowing networks to be accessible in novpn # this is to be able to sync duckdns. Check with wget http://whatismyip.host & wget adsl4ever.com/ip ###### comment out after this line for the feature of syncing your public IP with a DDNS # ip route del default via 192.168.1.1 table duckdns # ip rule del fwmark 65 table duckdns # iptables -t mangle -D OUTPUT -d 72.47.224.85 -j MARK --set-mark 65 # iptables -t mangle -D OUTPUT -d 35.167.241.52 -j MARK --set-mark 65 # iptables -t mangle -D OUTPUT -d 54.191.209.253 -j MARK --set-mark 65 # iptables -t nat -D PREROUTING -d 72.47.224.85 -j MARK --set-mark 65 # iptables -t nat -D PREROUTING -d 35.167.241.52 -j MARK --set-mark 65 # iptables -t nat -D PREROUTING -d 54.191.209.253 -j MARK --set-mark 65 ###### end comment out for the feature of syncing your public IP with a DDNS fi } function conecta_ipsec () { [[ -z $server ]] && { echo no variable server defined!.Please, define bash variable with server=vpn.host.server; return 1; } echo route to StrongVPN does not exist, adding it. sleep 3; ip=$(IP) ip2=$(IP) while [ "$ip" == "$ip2" ]; do rutas conecta echo "c strong-vpn" > /var/run/xl2tpd/l2tp-control echo waiting 10 secs for the VPN sleep 10; ip2=$(IP) if [[ "$ip" == "$ip2" ]]; then echo Cleaning desconecta_ipsec restart fi done rutas ok echo VPN up and running } function desconecta_ipsec () { [[ -z $server ]] && { echo no variable server defined.Please, define bash variable with server=vpn.host.server; return 1; } echo "d strong-vpn" > /var/run/xl2tpd/l2tp-control; while [ ! -z $(ip link show ppp0 > /dev/null 2>&1 && echo $? ) ]; do echo interface still up, waiting... ;sleep 3 ; done sleep 2; if [[ "$1" == "restart" ]]; then rutas desconecta else rutas desconecta rutas nok fi echo End, ppp interface down }
Now you can connect to the VPN with : (note this script will retry the connection until it gets connected).
# conecta_ipsec
and to disconnect with
# deconecta_ipsec
All done folks!