Sometimes you need to connect to VPN server where connection has been set up using multi factor
authentication, meaning you can’t save your password in a traditionally convenient(read lazy) way. On top of that
it is even more annoying when you need to reach your phone just to get the bloody time based token.
Today I am going to show how to automate this process if you are using Tunnelblick and standard
TOTP MFA like Google Authenticator for example.
So let’s look at how we can do that. First off all you need to locate you config file:
➜ ~ ls /Users/$USER/Library/Application\ Support/Tunnelblick/Configurations configtest.tblk ➜ ~
As you can see I have configuration called ‘configtest’, now if you go inside you should find your config:
➜ ~ cat /Users/$USER/Library/Application\ Support/Tunnelblick/Configurations/configtest.tblk/Contents/Resources/config.ovpn | head -25 client dev tun auth-user-pass persist-key persist-tun remote-cert-tls server blabla blabalaa ... <connection> remote your-vpn-server.com 2000 tcp float nobind </connection> <ca> -----BEGIN CERTIFICATE----- ➜ ~
Once you found you config, you need to replace string ‘auth-user-pass’ with ‘auth-user-pass your_auth_file”, for example as below:
➜ ~ cat /Users/$USER/Library/Application\ Support/Tunnelblick/Configurations/configtest.tblk/Contents/Resources/config.ovpn | head -5 client dev tun auth-user-pass /Users/your_user_name/auth.txt persist-key persist-tun
Now your password will be taken from file ‘/Users/your_user_name/auth.txt’. But because it dynamically
created we will need to update that file programmatically.
But before updating file let’s look at how we can generate one-time password with oathtool.
On MacOS you can install it with brew:
brew install oath-toolkit
Now you can use it with you secret:
➜ ~ oathtool --totp -b -d 6 ABCAB23455765 892455
Here are ABCAB23455765 is your Base32 secret string,
-d 6 means generate 6 digit long token,
-totp means use Time-based One-Time Password and
-b means use base32 secret key
Alternatively you can use Linux version from Docker container on Mac:
~ docker run --name oathtool_container -it ubuntu sh # apt-get update && apt-get install -y oathtool
and then execute the tool by running:
~ docker exec oathtool_container sh -c "oathtool --totp -b -d 6 ABCAB23455765" 778834
Either way, you can now generate your token, so le’t update the file now:
#!/bin/bash echo -e "your_vpn_user_name_here\n`oathtool \ --totp -b -d 6 ABCAB23455765`" > /Users/your_user_name/auth.txt
or docker version:
#!/bin/bash echo -e "your_vpn_user_name_here\n`docker exec -it oathtool_container sh -c "oathtool \ --totp -b -d 6 ABCAB23455765"`" > /Users/your_user_name/auth.txt
As you can see, the auth file should have 2 lines, where 1st line is for username and 2nd is for password.
We are almost there, one last thing is to automate tunnelblick connections and we will use osascript for that:
#!/bin/bash echo -e "your_vpn_user_name_here\n`oathtool \ --totp -b -d 6 ABCAB23455765`" > /Users/your_user_name/auth.txt osascript -e "tell application \"/Applications/Tunnelblick.app\"" -e\ "connect \"configtest\"" -e "end tell"
Please note ‘configtest’ is the connections name, so pick up the right one from Tunnelblick.
If you think saving the secret in the file won’t be secure enough (and you will be right!), you can go further and use vault for example.
You can also keep the file encrypted, and decrypt with passw when it is asked, then delete when connected:
echo 'enter dec pass:' read -s pass_to_decrypt echo -e $(openssl enc -aes-256-cbc -d -in ~/$path_2_enc_file.enc -k $pass_to_decrypt)" > /Users/your_user_name/auth.txt sleep 5 rm /Users/your_user_name/auth.txt
That is it, all you need now is just to call this script from your favourite cmd line tool and forget about your mobile or whatever tool you have been
using to generate the MFA token.
Best way would be adding it to your .zshrc/.bashrc file:
export PATH=$PATH:/path_to_your_vpn_connection_script
You can chill now!
This is interesting to me. However, as a windows user, I am looking for something similar in a windows world. Fortunately there is an answer. The idea is the same, but I use Devolutions RDM solution for a connection manager. Some connections, by default support this, but not all. Using the technique above, I think I can do similar to automate it (using their powershell cmdlets on Windows). Thanks!
Note: They do offer a Mac version as well, and their free offering is very full featured as well, so may be a viable alternative for those reading this who may be interested. And no, I have no connection to the company, other than as a user and advocate (aka fanboi, if you must – but this is about the only software I would accept that title to).