OpenWRT on GL-AR150 + Guest Wifi over OpenVPN (2023)

Written by pmd - - no comments

⚫ Installed last available OpenWRT on AR150

login as: xxxx
root@192.168.1.1's password:

BusyBox v1.35.0 (2023-04-27 20:28:15 UTC) built-in shell (ash)

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 OpenWrt 22.03.5, r20134-5f15225c1e
 -----------------------------------------------------
#

Source: [OpenWrt Wiki] GL.iNet GL-AR150

⚫ Expected configuration

The router will get access to internet by connecting to a Wifi network available around using wlan0 interface.
The router will spread two independant Wifi network :

  1. First Wifi will connect users on br-lan interface
    br-lan users will have access to internet through wlan0
  2. Second Wifi will connect users on br-lan2 interface
    br-lan2 users will have access to internet exclusively through tun0 interface (VPN)

⚫ Configuring Guest Wifi

Source: Guest Wi-Fi using LuCI (I didn't need to touch anything in Network > Firewall > Traffic Rules)

⚫ Installing OpenVPN and set first configuration

⚪ Installing OpenVPN

# opkg update
# opkg install openvpn-openssl ip-full luci-app-openvpn

Source: OpenWrt setup with NordVPN | NordVPN support

⚪ Configuring NordVPN

Download a NordVPN configuration : Server recommended by NordVPN | NordVPN


Go to VPN > OpenVPN

Under the “OVPN configuration file upload” section name the VPN connection in the “Instance name” field (I named it “nordvpn”.) After that, click on the Browse button, locate the downloaded server file and click Upload.

In the “OpenVPN instances” section, click the Edit button next to the instance you have just created.


Illustration #01 about previous steps


In the lower field, enter your NordVPN service credential username and password into separate lines.

username
password

Now, copy the path to the credentials file that is given right above the field containing the credentials and paste it next to the “auth-user-pass” line in the “Config file” section above. It should look like this: auth-user-pass /etc/openvpn/nordvpn.auth

Click on the Save button at the bottom.


Illustration #02 about previous steps


Go to Network > Interfaces

Select the Add new interface… button and name it “nordvpntun”.
Click on the “Protocol” dropdown menu and choose “Unmanaged”.
In the “Interface” dropdown, enter the name “tun0” at the bottom -- custom -- field and press the Enter key.
Click the “Create interface” and Save buttons.


Go to Network > Firewall

Click the “Add” button and adjust it as follows:

  1. Name it “vpnfirewall”;
  2. Set the “Input” option as “Reject”;
  3. Leave “Output” as “Accept” and “Forward” as “Reject”;
  4. Check the “Masquerading” option;
  5. Check the “MSS clamping” option;
  6. From the “Covered Networks” dropdown menu choose “nordvpntun”;
  7. In the “Allow forward from source zones” dropdown menu, choose “lan”;
  8. Click the “Save” button.

In the “Zones” section, find the zone named “lan”, and click on the “Edit” button.

In the “Allow forward to destination zones” dropdown check the “nordvpntun” entry.


Go to Network > DHCP and DNS

In the “General Settings” tab, find the “DNS forwardings” option and enter DNS addresses there. Addresses could be:

  • NordVPN DNS : 103.86.96.100 and 103.86.99.100 | Source 1
  • OpenDNS : 208.67.222.222 and 208.67.220.220 | Source 1, 2
  • Google DNS : 8.8.8.8 and 8.8.4.4 | Source 1

Go to the “Resolv and Hosts Files” tab, check the “Ignore resolve file” checkbox, and click the “Save & Apply” button.

You can verify which DNS server you are actually requested data to by using ths website : DNS leak test


Go to VPN > OpenVPN

In the “OpenVPN instances” section, check the “Enable” option next to the NordVPN option in the list, and click the “Save & Apply” button.

See Illustration #01 for final setup.

Now all you internet paquets should go through the VPN link.

⚪ Creating route-up.sh to chose which paquets should go through VPN

In your OpenVPN configuration file, you need to add these both lines:

  • route-noexec
    => so OpenVPN will not modify main routing table itself
  • route-up /etc/openvpn/route-up.sh
    => so OpenVPN will execute this file where we will add some rules and routes for vpn routing table
#!/bin/sh
# /etc/openvpn/route-up.sh
# chmod +x /etc/openvpn/route-up.sh

# https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/#scripting-and-environmental-variables
# This website to know what environmental-variables are available.

# Inspiration :
# https://github.com/soehest/openvpn/blob/master/route-up.sh
# https://medium.com/@ingamedeo/openvpn-splittunneling-on-openwrt-e4302a1a4e12

echo "$dev : $ifconfig_local -> $ifconfig_remote gw: $route_vpn_gateway" | logger

# Checks to see if there is an IP routing table named 'vpn', create if missing
if [ $(cat /etc/iproute2/rt_tables | grep vpn | wc -l) -eq 0 ]; then
    echo "100     vpn" >> /etc/iproute2/rt_tables
    echo "IP routing table named 'vpn' created" | logger
fi

# Remove any previous rules in the 'vpn' routing table
#/sbin/ip rule | sed -n 's/.*\(from[ \t]*[0-9\.]*\).*vpn/\1/p' | while read RULE
/sbin/ip rule | grep vpn | sed -n 's@.*\(from[ \t]*[0-9\./]*\)@\1@p' | while read RULE
do
    echo "remove old rule:   /sbin/ip rule del ${RULE}" | logger
    /sbin/ip rule del ${RULE}
done
# Remove any previous routes in the 'vpn' routing table
echo "remove old routes: /sbin/ip route flush table vpn" | logger
/sbin/ip route flush table vpn

# Search route for traffic coming from 192.168.2.0/24 in table 'vpn'
# (unicast: This rule type simple causes the kernel to refer to the
# specified routing table in the search for a route.)
echo "adding rule:       /sbin/ip rule add from 192.168.2.0/24 table vpn" | logger
/sbin/ip rule add from 192.168.2.0/24 table vpn

# Search route for traffic going to 192.168.2.0/24 in table 'vpn'
echo "adding rule:       /sbin/ip rule add to 192.168.2.0/24 table vpn" | logger
/sbin/ip rule add to 192.168.2.0/24 table vpn

# Use 'vpn' table as default for tun0
echo "adding route:      /sbin/ip route add table vpn default dev ${dev}" | logger
/sbin/ip route add table vpn default dev ${dev}

# Route traffic from/to 192.168.2.0/24 on br-lan2 using the 'vpn'.
# table. (192.168.2.1 is the source address for outgoing packets)
echo "adding route:      /sbin/ip route add 192.168.2.0/24 dev br-lan2 proto kernel scope link src 192.168.2.1 table vpn" | logger
/sbin/ip route add 192.168.2.0/24 dev br-lan2 proto kernel scope link src 192.168.2.1 table vpn

# Logging default rules
echo "/sbin/ip rule -----------" | logger
/sbin/ip rule  | logger

# Logging default route table
echo "/sbin/ip route show -----------" | logger
/sbin/ip route show  | logger

# Logging vpn route table
echo "/sbin/ip route show table vpn ----------" | logger
/sbin/ip route show table vpn | logger

Thanks to logger, we can check what happened during execution of route-up.sh when OpenVPN connected to the server:

$ logread | tail -n 30

 

⚫ Updating NordVPN configuration

I made this shell script to easily update the configuration using recommended server by NordVPN :

#!/bin/sh
# chmod +x /etc/openvpn/update_conf.sh

# log et information visuel que le script est en cours d'exectution
logger "/etc/openvpn/update_conf.sh going to get a new NordVPN configuration..."
echo "heartbeat" >  /sys/class/leds/green:power/trigger

OpenVpnConfFile='/etc/openvpn/nordvpn.ovpn'

# l'accès au serveur recommandé par NordVPN est bloqué, donc il faut passer par une autre sortie internet
echo "Starting wg0 interface to get configuration..."
ifup raspberry
echo -n "Waiting for wg0 interface..."
while [ $(ifconfig | grep -c raspberry) == 0 ]
do
    echo -n "."
    sleep 1
done
sleep 1
echo
echo

echo "Going to update OpenVPN configuration..."

# récuperation du serveur recommandé par NordVPN
# voir https://sleeplessbeastie.eu/2019/01/14/how-to-use-terminal-to-display-servers-recommended-by-nordvpn/
#RecommendedServer=$(curl --silent --interface raspberry 'https://nordvpn.com/wp-admin/admin-ajax.php?action=servers_recommendations&filters=\{%22country_id%22:74\}' | jq --raw-output '.[0].hostname' | awk -F. '{print $1}')
# voir https://sleeplessbeastie.eu/2019/02/18/how-to-use-public-nordvpn-api/
RecommendedServer=$(curl --silent --interface raspberry 'https://api.nordvpn.com/v1/servers/recommendations?filters\[country_id\]=74&limit=1' | jq --raw-output '.[0].hostname' | awk -F. '{print $1}')
echo "Recommended server by NordVPN:"
echo $RecommendedServer
echo


# récupération de la configuration
echo "Trying to get server configuration https://downloads.nordcdn.com/configs/files/ovpn_udp/servers/$RecommendedServer.nordvpn.com.udp.ovpn ..."
DownloadingServerConfFile=$(curl --silent --interface raspberry --write-out "%{http_code}" -o $OpenVpnConfFile https://downloads.nordcdn.com/configs/files/ovpn_udp/servers/$RecommendedServer.nordvpn.com.udp.ovpn)
if [ $DownloadingServerConfFile -eq 200 ]
then
    echo "OK $DownloadingServerConfFile"
    echo "Conf retrieved. Shutting down wg0 interface..."
    ifdown raspberry
    echo
else
    echo "NOK $DownloadingServerConfFile"
    echo "Conf NOT retrieved. Shutting down wg0 interface..."
    ifdown raspberry
    # fin de l'information visuelle
    echo "timer" >  /sys/class/leds/green:power/trigger
    sleep 5
    echo "none" >  /sys/class/leds/green:power/trigger
    exit
fi


# modification de la configuration pour ajouter password + route no-exec + route-up
echo "Trying to modify $OpenVpnConfFile configuration file..."
echo "$OpenVpnConfFile before modification:"
echo "----------"
echo "[...]"
sed -n '/auth-user-pass/{p;n;p}' $OpenVpnConfFile
echo "[...]"
echo "----------"
echo "Trying to modify $OpenVpnConfFile configuration file..."
sed -i 's@auth-user-pass@auth-user-pass /etc/openvpn/nordvpn.auth\nauth-nocache\nroute-noexec\nroute-up /etc/openvpn/route-up.sh@g' $OpenVpnConfFile
echo "$OpenVpnConfFile after modification:"
echo "----------"
echo "[...]"
sed -n '/auth-user-pass/{p;n;p;n;p;n;p;n;p}' $OpenVpnConfFile
echo "[...]"
echo "----------"
echo


# redemarrage de openvpn
echo "Trying to restart OpenVPN..."
/etc/init.d/openvpn restart
sleep 1
echo -n "Waiting for tun0 interface..."
while [ $(ifconfig | grep -c tun0) == 0 ]
do
    echo -n "."
    sleep 1
done
echo
t=$(ping -c 10 -I tun0 8.8.8.8 | grep -o -E '[0-9]+ packets r' | grep -o -E '[0-9]+')
if [ $t != 0 ]; then
    echo "OK. Done."
    echo -n "Public IP: "
    curl --interface wlan0 ifconfig.co/
    echo -n "VPN IP:    "
    curl --interface tun0 ifconfig.co/
else
    echo "Something went wrong."
    echo "timer" >  /sys/class/leds/green:power/trigger
    sleep 5
fi
echo
echo "Last log:"
echo "----------"
logread | tail -n 30
echo "----------"

# fin de l'information visuelle
echo "none" >  /sys/class/leds/green:power/trigger

 

⚫ Launch above script using router button

The first step is to find out the internal name of the button we want to use.

opkg update
opkg install kmod-button-hotplug

mkdir -p /etc/hotplug.d/button

cat << "EOF" > /etc/hotplug.d/button/buttons
logger "the button was ${BUTTON} and the action was ${ACTION}"
EOF

Now press the button you want to use, then run logread:

Wed Jul 31 17:51:33 2024 user.notice root: the button was BTN_8 and the action was released
Wed Jul 31 17:51:37 2024 user.notice root: the button was BTN_8 and the action was pressed
Wed Jul 31 17:51:40 2024 user.notice root: the button was BTN_8 and the action was released
Wed Jul 31 17:51:44 2024 user.notice root: the button was BTN_8 and the action was pressed

Next we will setup the action associated to the button using Atheros' 00-button + UCI:

# cat << "EOF" > /etc/hotplug.d/button/00-button
> source /lib/functions.sh
>
> do_button () {
>     local button
>     local action
>     local handler
>     local min
>     local max
>
>     config_get button "${1}" button
>     config_get action "${1}" action
>     config_get handler "${1}" handler
>     config_get min "${1}" min
>     config_get max "${1}" max
>
>     [ "${ACTION}" = "${action}" -a "${BUTTON}" = "${button}" -a -n "${handler}" ] && {
>         [ -z "${min}" -o -z "${max}" ] && eval ${handler}
>         [ -n "${min}" -a -n "${max}" ] && {
>             [ "${min}" -le "${SEEN}" -a "${max}" -ge "${SEEN}" ] && eval ${handler}
>         }
>     }
> }
>
> config_load system
> config_foreach do_button button
> EOF
#
# uci add system button
cfg064d81
# uci set system.@button[-1].button="BTN_8"
# uci set system.@button[-1].action="released"
# uci set system.@button[-1].handler="/etc/openvpn/update_conf.sh"
# uci commit system
#

Now putting the button in the released position will launch the script associated to it.

Source for button detection, source for LED signalisation.

 

Comments are closed.