What's new

OpenVPN server with 2 factor authentication

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

manovel

New Around Here
Hi all,
I wanted to see if it is possible to enable 2 factor authentication with the OpenVPN server on a RT-AC68U.

I found an old topic about that:
https://www.snbforums.com/threads/guide-openvpn-server-with-2-factor-authentication.23928/

In there, the steps involved:
- compiling and installing the OpenVPN server with the following flag "--enable-pam-dlopen"
- compiling and installing google-authenticator
- compiling and installing libqrencode
- etc

Does somebody know if all those steps are still needed?
I know for example that today, google-authenticator-libpam and libqrencode could be installed via entware.
But what about the OpenVPN server flag?

Has somebody a more up to date instruction for firmware 384.16?

Thank you,
manovel
 
I decided to try something different, to avoid having to substitute OpenVPN on the router.
Changing the configuration of the OpenVPN server, it is possible to use a custom script to perform the username/password verification. The custom verification script then uses oathtool to check the token.
oathtool is availalbe as openwrt package, but at the end I decided to compile it using a docker container.

The steps to be performed are the following:
1 - Compile oathtool for the target (in this case RT-AC68U)
2 - Configure OpenVPN via the Asuswrt-Merlin web interface
3 - Create the verify.sh shell script
4 - Create the script to modify the OpenVPN server configuration
5 - Copy files to the router
6 - Create your google authenticator secret
7 - Reboot router

Instruction to compile oathtool with docker:
Code:
# Pull the docker image and run the container with a shared folder in the host system
docker pull acrisliu/asuswrt-merlin-build
docker run -dt -v C:\path\to\your\transfer\folder:/mnt/transfer --name asuswrt-merlin-build acrisliu/asuswrt-merlin-build

# Open a shell in docker
docker exec -it asuswrt-merlin-build bash

# Setup the environment for my RT-AC68U
. /root/env/bcm-sdk.sh
export CC=arm-brcm-linux-uclibcgnueabi-gcc

#Compile oathtool
cd /usr/src
wget https://fossies.org/linux/privat/oath-toolkit-2.6.2.tar.gz
gunzip oath-toolkit-2.6.2.tar.gz
tar -xf oath-toolkit-2.6.2.tar
cd oath-toolkit-2.6.2
./configure --disable-xmltest --disable-pskc --host=armv7
make

# Copy oathtool executable to the transfer folder

In the router GUI go to VPN>VPN Server and enable the OpenVPN Server.
Make sure the following is set:
Code:
Username/Password Authentication = Yes
Autenticazione solo con Nome utente / Password = No
Export the Configuration for the client

I used the following script to verify the username/password provided.
Note that username/password list is available and readable in the nvram.
I stored a list of username/secret also in the same way in the nvram (see step 6)
verify.sh:
Code:
#!/bin/sh
#Location: /jffs/openvpn/verify.sh
#This script was made with via-file in mind
PATH=/usr/bin:/bin

#users/passwords
users=`/usr/sbin/nvram get vpn_serverx_clientlist`
users="$users<"

#users/secrets
secrets=`/usr/sbin/nvram get vpn_serverx_secretlist`
secrets="$secrets<"

#1st line is the username
username=`/usr/bin/awk 'NR==1' "$1"`
#2nd line is the password
password=`/usr/bin/awk 'NR==2' "$1"`

#username consist only of alphanumerics_-.@
if [[ `echo "$username" | sed 's/[0-9A-Za-z_\-\.@]*//'` ]];
then
        echo "Invalid character in username." >&2
        exit 1
fi

if echo "$password" | grep -q "<" ;
then
        echo "Invalid character in password." >&2
        exit 1
fi

if ! echo "$users" | grep -q "<$username>" ;
then
        echo "Username invalid." >&2
        exit 1
fi

if ! echo "$secrets" | grep -q "<$username>" ;
then
        echo "Username has no secret." >&2
        exit 1
fi

#get correct password and secret and code
pass=`echo "$users" | sed 's/^.*<'"$username"'>\([^<]*\)<.*$/\1/'`
secret=`echo "$secrets" | sed 's/^.*<'"$username"'>\([^<]*\)<.*$/\1/'`
code=`/jffs/openvpn/oathtool -b --totp "$secret"`

if [[ "$password" == "$pass$code" ]];
then
        echo "$username User Authenticated."
        exit 0
fi

echo "$username Login credentials failed." >&2
exit 1

Then the script to modify the configuration of OpenVPN
openvpnserver1.postconf:
Code:
#!/bin/sh
#Location: /jffs/scripts/openvpnserver1.postconf
CONFIG=$1
source /usr/sbin/helper.sh
pc_delete "plugin /usr/lib/openvpn-plugin-auth-pam.so openvpn" $CONFIG
pc_append "script-security 2" $CONFIG
pc_append "auth-user-pass-verify /jffs/openvpn/verify.sh via-file" $CONFIG
#pc_append "reneg-sec 60" $CONFIG
pc_append "auth-gen-token" $CONFIG


Copy files to the router:
Code:
scp oathtool admin@IP:/jffs/openvpn/oathtool
scp verify.sh admin@IP:/jffs/openvpn/verify.sh
scp openvpnserver1.postconf admin@IP:/jffs/scritps/openvpnserver1.postconf
chmod +x /jffs/openvpn/oathtool
chmod +x /jffs/openvpn/verify.sh
chmod +x /jffs/scritps/openvpnserver1.postconf

Create a Google Authenticator secret (base32) with any tool you want
Try it (should gave same result as your Google Authenticator or Authy App)
Code:
/jffs/openvpn/oathtool -b --totp YOURGASECRETHERE
nvram set "vpn_serverx_secretlist=<yourusername>YOURGASECRETHERE"
nvram commit

reboot the router
Once up, you can connect to the VPN using username and password and the token:
username=yourusername
password=yourpassword######
where ###### is the token appended to your password

I have to say, I am not an expert of shell scripts and any input to improve the verify.sh script are welcome, together with any comment or concern about security of the solution.

manovel
 
Manovel, That is awesome. Are you able to share the binaries? I tried to compile is, but didnt work. Love to enable 2FA with Asus.
 
reboot the router
Once up, you can connect to the VPN using username and password and the token:
username=yourusername
password=yourpassword######
where ###### is the token appended to your password
Manovel,
I check "nvram get vpn_serverx_clientlist"
before reboot router shows "<username>password"
and can connect to router via VPN without any issue
However after reboot router, somehow
"nvram get vpn_serverx_clientlist" will show
"<username>somebinary" and when I try to connect to router,
get authentication error.
I have to do "nvram set vpn_serverx_clientlist=<username>password" and "nvram commit" then VPN can connect again.
It seems reboot router will change password to some binary
causing authentication error.
 

Similar threads

Latest threads

Support SNBForums w/ Amazon

If you'd like to support SNBForums, just use this link and buy anything on Amazon. Thanks!

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top