# # My YARHT for Ubiquity EdgeRouter-X RH Lamb 2019 # OpenVPN w/ 2-factor authentication # # All from the following GREAT articles: # https://community.ui.com/questions/Secure-OpenVPN-server-setup-with-multi-factor-authentication-Google-Authenticator-step-by-step/8b42e255-bd50-41ff-88c6-ad4e0512be7c # https://openvpn.net/community-resources/hardening-openvpn-security/ # I did this since I found myself following this recipie for many of my friends. # So I thought I would share. # Assume eth0:192.168.0.1/24 (ssh login), eth1:dhcp (Internet), eth2:192.168.3.1/24 (Office LAN), eth3:192.168.2.1/24 (Misc,WiFi), eth4:NC From the ERX Web GUI upgrade firmware on ERX to at least 2.06 ssh ubnt@192.168.0.1 sudo -i delete system image # Get rid of old image to make space apt-get update # prepare for debian update. DO NOT "upgrade". This may brick. apt-get install libqrencode3 apt-get install libpam-google-authenticator cd /etc/pam.d cp common-account openvpn echo "auth required pam_google_authenticator.so" >> openvpn From the ERX Web GUI Add users user001, user002, ... with role Admin OR from ssh CLI set system login user user001 authentication plaintext-password "a very secure password" set system login user user001 level admin commit save From ssh connection for each user run google-authenticator like this (notes:*): su -c "google-authenticator --label=\"VPN user001\"" user001 Do you want authentication tokens to be time-based (y/n) y Scan the resultant ACSII QR code w/ Authy or Google Authenticator on your phone Do you want me to update your "/home/user001/.google_authenticator" file (y/n) y Do you want to disallow multiple uses of the same authentication token? This restricts you to one login about every 30s, but it increases your chances to notice or even prevent man-in-the-middle attacks (y/n) n By default, tokens are good for 30 seconds. In order to compensate for possible time-skew between the client and the server, we allow an extra token before and after the current time. If you experience problems with poor time synchronization, you can increase the window from its default size of +-1min (window size of 3) to about +-4min (window size of 17 acceptable tokens). Do you want to do so? (y/n) n If the computer that you are logging into isn't hardened against brute-force login attempts, you can enable rate-limiting for the authentication module. By default, this limits attackers to no more than 3 login attempts every 30s. Do you want to enable rate-limiting (y/n) n mkdir /config/openvpn cd /config/openvpn Copy my bundle of scripts/configs (mkca mkclient cleanup *.cnf) into this directory somehow (e.g., tar-scp-tar) openssl dhparam -out dh.pem -2 2048 # This will take hours so maybe do overnight or on another machine openvpn --genkey --secret ta.key ./mkca ./mkclient server vpn-server-name-OR-ip-address rm server.ovpn # not needed ./mkclient user001 vpn-server-name-OR-ip-address ./mkclient user002 vpn-server-name-OR-ip-address .. Securely copy user001.ovpn, user002.ovpn, .. to intended user devices (e.g., smime email, ownCloud, etc..) On those device, import the ovpn file. exit # exit out of "sudo -i" configure set firewall name WAN_LOCAL rule 30 action accept set firewall name WAN_LOCAL rule 30 description openvpn set firewall name WAN_LOCAL rule 30 destination port 1194 set firewall name WAN_LOCAL rule 30 protocol udp set interfaces openvpn vtun0 mode server set interfaces openvpn vtun0 server subnet 172.16.1.0/24 set interfaces openvpn vtun0 server push-route 192.168.3.0/24 # Your LAN set interfaces openvpn vtun0 tls ca-cert-file /config/openvpn/ca.crt set interfaces openvpn vtun0 tls cert-file /config/openvpn/server.crt set interfaces openvpn vtun0 tls key-file /config/openvpn/server.key set interfaces openvpn vtun0 tls dh-file /config/openvpn/dh.pem set interfaces openvpn vtun0 openvpn-option "--keepalive 8 30" set interfaces openvpn vtun0 openvpn-option "--comp-lzo" set interfaces openvpn vtun0 openvpn-option "--duplicate-cn" set interfaces openvpn vtun0 openvpn-option "--client-to-client" set interfaces openvpn vtun0 openvpn-option "--user nobody --group nogroup" set interfaces openvpn vtun0 openvpn-option "--persist-key" set interfaces openvpn vtun0 openvpn-option "--persist-tun" set interfaces openvpn vtun0 openvpn-option "--persist-local-ip" set interfaces openvpn vtun0 openvpn-option "--persist-remote-ip" set interfaces openvpn vtun0 openvpn-option "--verb 3" set interfaces openvpn vtun0 openvpn-option "--float" set interfaces openvpn vtun0 openvpn-option '--tls-auth /config/openvpn/ta.key 0' set interfaces openvpn vtun0 openvpn-option "--tls-server" set interfaces openvpn vtun0 openvpn-option "--reneg-sec 0" set interfaces openvpn vtun0 openvpn-option '--plugin /usr/lib/openvpn/openvpn-auth-pam.so openvpn' commit save The following is not related to OpenVPN but may be useful for email notifications from the router. Contents of /etc/ssmtp/ssmtp.conf: root=postmaster mailhub=mail.example.com:587 AuthMethod=CRAM-MD5 # Or whatever you use UseSTARTTLS=YES AuthUser=smtpuser AuthPass=smtppassword hostname=ubnt FromLineOverride=YES Contents of /home/ubnt/mymonitor: #!/bin/bash # tail -F /var/log/messages | while [ "1" ]; do rs="" subj="" read a if [ $? -ne 0 ]; then exit; fi rso=`echo $a | grep -E "openvpn\[[0-9]+\]: [0-9\.\:]* \[[A-Za-z0-9]*\] Peer Connection Initiated with"` if [ "$rso" ]; then rs="$rs\n$rso" subj="$subj OpenVPN Login" fi rso=`echo $a | grep -E "openvpn\[[0-9]+\]: [0-9\.\:]* SENT CONTROL \[[A-Za-z0-9]*\]: 'AUTH_FAILED'"` if [ "$rso" ]; then rs="$rs\n$rso" subj="$subj OpenVPN Login Failure" fi rso=`echo $a | grep -E "authentication failure"` if [ "$rso" ]; then rs="$rs\n$rso" subj="$subj Authentication Failure" fi if [ "$rs" ]; then adminemail="admin@example.com" now=`date -u` msgid=$$.`date -u +%Y%m%d%H%M%S`@`hostname` echo "From: devnull@example.com (EdgeRouter-X)" > $0.tmp echo "Date: $now" >> $0.tmp echo "Message-ID: <$msgid>" >> $0.tmp echo "To: $adminemail" >> $0.tmp echo "Subject: $subj" >> $0.tmp echo "Content-Type: text/plain" >> $0.tmp echo "" >> $0.tmp echo -e "$rs" >> $0.tmp echo "" >> $0.tmp /usr/sbin/ssmtp -t < $0.tmp rm -f $0.tmp fi done Contents of /config/scripts/post-config.d/startmymonitor: #!/bin/bash # cd /home/ubnt nohup ./mymonitor >/dev/null 2>&1 & Then do: chmod +x /home/ubnt/mymonitor /config/scripts/post-config.d/startmymonitor # # end # Notes: * If google authenticator stops working with "verification failed", NTP/DNS time may be off. To fix remove all non-numeric " lines except for " TOTP_AUTH from /home/user001/.google_authenticator. You may have to enable writing temporarily then put it back. e.g.: user001@caperouter:~$ sudo cat /home/user001/.google_authenticator djhff8398873894jfkjfkljwkj " RESETTING_TIME_SKEW 52392312-15 " TOTP_AUTH 89340858 98769789 97000007 30853058 23482978