After buying a Yubikey 4, I wanted to see what this little sucker could do, besides being used as U2F two-factor thingy for Gmail and so on, so I found out it could be used as a smartcard, meaning I could save X.509/PEM keys and certificates inside it, which I again could use for my OpenVPN connections! Happiness was in my face, until I found out that OpenVPN and PKCS11 with PIN codes is currently somewhat broken on some systems (including my Ubuntu 16.04), as I need to enter the PIN via the OpenVPN Management interface due to some broken systemd-ask-password thing. This severely complicates my setup, as I usually just start the OpenVPN connection via the terminal by something like “sudo openvpn <configfile>” which was suddenly not possible, or at least I then needed to do a lot more… So after thinking (whoa) and googling some, I came up with this small bash script utilizing netcat and some piping to automate this whole shebang. The script requires that the OpenVPN client configuration has these lines:
auth-retry nointeract management 127.0.0.1 8888 management-query-passwords
So we start a management interface locally on port 8888 and query passwords here. The script then looks like this:
#!/bin/bash USER=`whoami` MGM_PORT=8888 if [ "$USER" != 'root' ]; then echo "Must be run with superuser priviledges" fi if [ -z $1 ]; then echo "Usage: $0 < vpn-config >" exit 1 fi printf "OpenVPN PKCS11 PIN wrapper\n" read -s -p "Enter PIN: " PINCODE printf "\nStarting OpenVPN\n" /usr/sbin/openvpn $1 > /dev/null & OPENVPN_PID=$! # Give OpenVPN a chance to get somewhere sleep 2 PIPE=/tmp/ovpn_pkcs11_fifo trap "rm -f $PIPE" EXIT if [[ ! -p $PIPE ]]; then mkfifo $PIPE fi # Start nc with a 2 second delay (sleep 2 && nc localhost $MGM_PORT) > $PIPE & SUBSTRING= while true do if read LINE < $PIPE; then if [[ $LINE == *"PASSWORD"* ]]; then SUBSTRING=$(echo $LINE | cut -d "'" -f 2) break fi fi done echo "password '$SUBSTRING' '$PINCODE'" | nc localhost $MGM_PORT > /dev/null printf "Write 'quit' to kill OpenVPN instance: " while read LINE; do if [ "$LINE" == "quit" ]; then kill $OPENVPN_PID exit 0 fi done