Things I'd do if I ever have time
Wish list
Please help a man further his career by donating expensive hardware. Cash works too.
OpenBSD and OpenVPN Quickstart Guide
Published: 09/06/2009
Everyone needs a personal VPN server because 1) crypto is cool, 2) public 802.11 (Wi-Fi) networks almost never implement WPA-anything, and if they do it's that "pre-shared key" stuff, and 3) bragging rights. Who cares if your next door neighbor upgraded their cheap Linksys router to DD-WRT? You have OpenBSD, OpenVPN, and some mystery called client certificate authentication. It sounds cool, so it must be good.
And if you're a business that already spent the entire budget on marketing but still need a VPN solution and can't afford any commercial-brand stuff from Cisco, F5, Check Point, Nortel, Juniper, etc. (or you don't want to pay for another Microsoft server license to run PPTP, L2TP with IPsec, or can't support SSTP because you have "legacy clients"), then have we got a solution for you that's free and the server-side can be deployed in about 10 minutes.
This article gives you the shortest path to achieving this. In other words, a command sequence cheat sheet. It assumes you've already set up OpenBSD and you're capable of copying / pasting the configs outlined here (and updating them to reflect your specific network configuration). The example in this article is based on OpenBSD 4.5 (i386) and OpenVPN 2.1_rc15 for the server.
SSH In and Let The Copy / Paste Begin...
More InformationSo let's assume that you're a good admin and observe fundamental security best-practices such as "least privilege." In other words, not logging in as root but with an account that has sudo privileges. As a general rule, you should have already ensured that sshd does not permit remote root logins (which can be configured under /etc/ssh/sshd_config). If that's already the case, then copy / paste the following commands into your terminal window. The machine will require access to the Internet, has one interface in this article example, and is located behind a firewall.
$ sudo pkg_add ftp://ftp.openbsd.org/pub/OpenBSD/4.5/packages/i386/openvpn-2.1rc15.tgz $ sudo mkdir -p /etc/openvpn/keys $ sudo mkdir -p /var/log/openvpn $ sudo touch /etc/hostname.tun0 $ sudo vi /etc/hostname.tun0 up $ sudo chmod 640 /etc/hostname.tun0 $ sudo sh /etc/netstart $ sudo touch /var/log/openvpn/openvpn.log $ sudo touch /var/log/openvpn/ipp.txt $ sudo touch /var/log/openvpn/server-tcp.log $ sudo chown root:nobody /var/log/openvpn/ $ sudo chmod 655 /var/log/openvpn/ $ sudo mkdir -p /etc/openvpn/easy-rsa/1.0/keys |
Use the easy-rsa package to create a certificate authority, server RSA keys, and client RSA keys. Bonus points if you use certificates from an existing PKI that you already run. Note that the ". ./vars" command has a space between the two dots. The items in red should be altered to reflect your network's values.
$ cp -R /usr/local/share/examples/openvpn/easy-rsa ~ $ cd ~/easy-rsa/1.0 $ vi vars export KEY_COUNTRY=US export KEY_PROVINCE=California export KEY_CITY="My City" export KEY_ORG="My Company" export KEY_EMAIL="admin@mycompany.com" $ . ./vars $ ./clean-all $ ./build-ca Generating a 1024 bit RSA private key .................++++++ ....................++++++ writing new private key to 'ca.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [US]: State or Province Name (full name) [California]: Locality Name (eg, city) [My City]: Organization Name (eg, company) [My Company]: Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:certauth.mycompany.com Email Address [admin@mycompany.com]: $ ./build-key-server server Generating a 1024 bit RSA private key .......................................................++++++ ..........................................................++++++ writing new private key to 'server.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [US]: State or Province Name (full name) [California]: Locality Name (eg, city) [My City]: Organization Name (eg, company) [My Company]: Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:myvpn.mycompany.com Email Address [admin@mycompany.com]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /home/adminguy/easy-rsa/1.0/openssl.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'US' stateOrProvinceName :PRINTABLE:'California' localityName :PRINTABLE:'My City' organizationName :PRINTABLE:'My Company' commonName :PRINTABLE:'myvpn.mycompany.com' emailAddress :IA5STRING:'admin@mycompany.com' Certificate is to be certified until Sep 4 09:56:41 2019 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated $ ./build-key client001 Generating a 1024 bit RSA private key ........................++++++ ....++++++ writing new private key to 'client001.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [US]: State or Province Name (full name) [California]: Locality Name (eg, city) [My City]: Organization Name (eg, company) [My Company]: Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:client001.mycompany.com Email Address [admin@mycompany.com]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /home/adminguy/easy-rsa/1.0/openssl.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'US' stateOrProvinceName :PRINTABLE:'California' localityName :PRINTABLE:'My City' organizationName :PRINTABLE:'My Company' commonName :PRINTABLE:'client001.mycompany.com' emailAddress :IA5STRING:'admin@mycompany.com' Certificate is to be certified until Sep 4 10:03:17 2019 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated $ ./build-dh Generating DH parameters, 1024 bit long safe prime, generator 2 This is going to take a long time ............................................................................... ...............................+.....................+......................... ....................................+.................................+........ ....................+............................+............................. .......+.+..................................................................... ................................++*++*++* $ sudo cp keys/ca.crt /etc/openvpn/keys/ $ sudo cp keys/dh1024.pem /etc/openvpn/keys/ $ sudo cp keys/server.crt /etc/openvpn/keys/ $ sudo cp keys/server.key /etc/openvpn/keys/ $ sudo chmod 600 /etc/openvpn/keys/server.key |
Create the OpenVPN server config file /etc/openvpn/server.conf.
port 1194 proto udp dev tun0 ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/server.crt key /etc/openvpn/keys/server.key dh /etc/openvpn/keys/dh1024.pem server 10.1.2.0 255.255.255.0 client-config-dir ccd push "dhcp-option DNS 208.67.222.222" push "dhcp-option DNS 208.67.220.220" push "dhcp-option DISABLE-NBT" push "dhcp-option DOMAIN corp.mycompany.com" push "route 10.1.1.0 255.255.255.0" push "redirect-gateway def1" keepalive 10 120 comp-lzo persist-key persist-tun status /var/log/openvpn/server-tcp.log ifconfig-pool-persist /var/log/openvpn/ipp.txt log-append /var/log/openvpn/openvpn.log verb 4 user nobody group nobody |
Enable routing by uncommenting the following line in /etc/sysctl.conf:
net.inet.ip.forwarding=1 |
Configure OpenVPN to start during system boot by editing /etc/rc.local:
if [ -x /usr/local/sbin/openvpn ]; then echo -n ' openvpn' /usr/local/sbin/openvpn --daemon --config /etc/openvpn/server.conf >/dev/null 2>&1 fi |
Configure /etc/pf.conf to perform basic NAT from within the virtual client subnet to the physical network where the server resides.
if_ext="dc0" if_tunnel="tun0" table <net_vpn_clients> { 10.1.2.0/24 } table <net_corp_inside> { 10.1.1.0/24 } scrub in nat on $if_ext from <net_vpn_clients> to any -> $if_ext pass in quick on $if_ext proto udp from any to $if_ext port 1194 pass in quick on $if_ext from <net_corp_inside> pass in quick on $if_tunnel from <net_vpn_clients> to any block in log all |
Edit /etc/rc.conf.local to allow pf to start a machine boot:
pf=YES |
Reboot your server.
A Server Isn't Much Without a Client...
More InformationDownload and install the software appropriate to the client platform. For Windows, this article uses version 2.1_rc19.
Copy the CA certificate file, client certificate, and client private key generated earlier on the server. Use WinSCP for a direct path to copy files off the server. In this case, this would be the files:
- ca.crt
- client001.crt
- client001.key
OpenVPN for Windows by default installs under %ProgramFiles%\OpenVPN and the three files above should be put under the config subdirectory. Then create a text file in this same subdirectory with an .ovpn extension (such as vpn-server.ovpn). The contents of the text file should be:
client proto udp dev tun remote myserver.somewhere.com 1194 resolv-retry infinite nobind persist-key persist-tun ca ca.crt cert client001.crt key client001.key comp-lzo verb 3 |
The address in red above refers to the public address of the server (replace with yours). When the GUI for OpenVPN is launched (and in Windows Vista and 7 with UAC enabled this process will need to be elevated), the icon for the application will be displayed in the system task tray. Right-clicking will allow the user to connect.
Since the server is placed behind a firewall, configure the firewall to port-forward UDP 1194 to the OpenVPN server. Before sure to test the client-to-server connection from outside the firewall unless your firewall allows connections from the corporate LAN to go outside and then come back in again. Some appliances (such as Cisco ASA devices) won't permit this as it violates default policy.
When the user initiates a connection to the server and is successfully authenticated, the following should appear in the /var/log/openvpn/openvpn.log with the default debug level of 3 (as set by the "verb" statement in the server config file):
Show example server log
Sun Sep 6 21:33:25 2009 us=714801 MULTI: multi_create_instance called Sun Sep 6 21:33:25 2009 us=715276 11.22.33.44:1060 Re-using SSL/TLS context Sun Sep 6 21:33:25 2009 us=715323 11.22.33.44:1060 LZO compression initialized Sun Sep 6 21:33:25 2009 us=716007 11.22.33.44:1060 Control Channel MTU parms [ L:1542 D:138 EF:38 EB:0 ET:0 EL:0 ] Sun Sep 6 21:33:25 2009 us=716066 11.22.33.44:1060 Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:135 ET:0 EL:0 AF:3/1 ] Sun Sep 6 21:33:25 2009 us=716395 11.22.33.44:1060 Local Options String: 'V4,dev-type tun,link-mtu 1542,tun-mtu 1500,proto UDPv4,comp-lzo,cipher BF-CBC,auth SHA1,keysize 128,key-method 2,tls-server' Sun Sep 6 21:33:25 2009 us=716417 11.22.33.44:1060 Expected Remote Options String: 'V4,dev-type tun,link-mtu 1542,tun-mtu 1500,proto UDPv4,comp-lzo,cipher BF-CBC,auth SHA1,keysize 128,key-method 2,tls-client' Sun Sep 6 21:33:25 2009 us=716449 11.22.33.44:1060 Local Options hash (VER=V4): '530fdded' Sun Sep 6 21:33:25 2009 us=716513 11.22.33.44:1060 Expected Remote Options hash (VER=V4): '41690919' Sun Sep 6 21:33:25 2009 us=716582 11.22.33.44:1060 TLS: Initial packet from 11.22.33.44:1060, sid=4928952d 1b431e62 Sun Sep 6 21:33:25 2009 us=779338 11.22.33.44:1060 VERIFY OK: depth=1, /C=US/ST=California/L=My_City/O=My_Company/CN=certauth.mycompany.com/emailAddress=admin@mycompany.com Sun Sep 6 21:33:25 2009 us=779944 11.22.33.44:1060 VERIFY OK: depth=0, /C=US/ST=California/O=My_Company/CN=client001.mycompany.com/emailAddress=admin@mycompany.com Sun Sep 6 21:33:25 2009 us=821075 11.22.33.44:1060 Data Channel Encrypt: Cipher 'BF-CBC' initialized with 128 bit key Sun Sep 6 21:33:25 2009 us=821290 11.22.33.44:1060 Data Channel Encrypt: Using 160 bit message hash 'SHA1' for HMAC authentication Sun Sep 6 21:33:25 2009 us=821359 11.22.33.44:1060 Data Channel Decrypt: Cipher 'BF-CBC' initialized with 128 bit key Sun Sep 6 21:33:25 2009 us=821385 11.22.33.44:1060 Data Channel Decrypt: Using 160 bit message hash 'SHA1' for HMAC authentication Sun Sep 6 21:33:25 2009 us=822364 11.22.33.44:1060 Control Channel: TLSv1, cipher TLSv1/SSLv3 DHE-RSA-AES256-SHA, 1024 bit RSA Sun Sep 6 21:33:25 2009 us=822410 11.22.33.44:1060 [client001.mycompany.com] Peer Connection Initiated with 11.22.33.44:1060 Sun Sep 6 21:33:25 2009 us=823126 MULTI: new connection by client 'client001.mycompany.com' will cause previous active sessions by this client to be dropped. Remember to use the --duplicate-cn option if you want multiple clients using the same certificate or username to concurrently connect. Sun Sep 6 21:33:25 2009 us=823262 MULTI: Learn: 10.1.2.6 -> client001.mycompany.com/11.22.33.44:1060 Sun Sep 6 21:33:25 2009 us=823290 MULTI: primary virtual IP for client001.mycompany.com/11.22.33.44:1060: 10.1.2.6 Sun Sep 6 21:33:27 2009 us=19620 client001.mycompany.com/11.22.33.44:1060 PUSH: Received control message: 'PUSH_REQUEST' Sun Sep 6 21:33:27 2009 us=19910 client001.mycompany.com/11.22.33.44:1060 SENT CONTROL [client001.mycompany.com]: 'PUSH_REPLY,dhcp-option DNS 208.67.222.222,dhcp-option DNS 208.67.220.220,dhcp-option DISABLE-NBT,dhcp-option DOMAIN corp.mycompany.com,route 10.1.1.0 255.255.255.0,redirect-gateway def1,route 10.1.2.1,topology net30,ping 10,ping-restart 120,ifconfig 10.1.2.6 10.1.2.5' (status=1) |
The client will also record a log file by default:
Show example client log
Sun Sep 06 21:33:29 2009 OpenVPN 2.1_rc19 i686-pc-mingw32 [SSL] [LZO2] [PKCS11] built on Jul 16 2009 Sun Sep 06 21:33:29 2009 WARNING: No server certificate verification method has been enabled. See http://openvpn.net/howto.html#mitm for more info. Sun Sep 06 21:33:29 2009 NOTE: OpenVPN 2.1 requires '--script-security 2' or higher to call user-defined scripts or executables Sun Sep 06 21:33:29 2009 LZO compression initialized Sun Sep 06 21:33:29 2009 Control Channel MTU parms [ L:1542 D:138 EF:38 EB:0 ET:0 EL:0 ] Sun Sep 06 21:33:29 2009 Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:135 ET:0 EL:0 AF:3/1 ] Sun Sep 06 21:33:29 2009 Local Options hash (VER=V4): '41690919' Sun Sep 06 21:33:29 2009 Expected Remote Options hash (VER=V4): '530fdded' Sun Sep 06 21:33:29 2009 Socket Buffers: R=[8192->8192] S=[8192->8192] Sun Sep 06 21:33:29 2009 UDPv4 link local: [undef] Sun Sep 06 21:33:29 2009 UDPv4 link remote: myserver.somewhere.com:1194 Sun Sep 06 21:33:29 2009 TLS: Initial packet from myserver.somewhere.com:1194, sid=b430adfb 54076df6 Sun Sep 06 21:33:29 2009 VERIFY OK: depth=1, /C=US/ST=California/L=My_City/O=My_Company/CN=certauth.mycompany.com/emailAddress=admin@mycompany.com Sun Sep 06 21:33:29 2009 VERIFY OK: depth=0, /C=US/ST=California/O=My_Company/CN=myvpn.mycompany.com/emailAddress=admin@mycompany.com Sun Sep 06 21:33:29 2009 Data Channel Encrypt: Cipher 'BF-CBC' initialized with 128 bit key Sun Sep 06 21:33:29 2009 Data Channel Encrypt: Using 160 bit message hash 'SHA1' for HMAC authentication Sun Sep 06 21:33:29 2009 Data Channel Decrypt: Cipher 'BF-CBC' initialized with 128 bit key Sun Sep 06 21:33:29 2009 Data Channel Decrypt: Using 160 bit message hash 'SHA1' for HMAC authentication Sun Sep 06 21:33:29 2009 Control Channel: TLSv1, cipher TLSv1/SSLv3 DHE-RSA-AES256-SHA, 1024 bit RSA Sun Sep 06 21:33:29 2009 [myvpn.mycompany.com] Peer Connection Initiated with myserver.somewhere.com:1194 Sun Sep 06 21:33:30 2009 SENT CONTROL [myvpn.mycompany.com]: 'PUSH_REQUEST' (status=1) Sun Sep 06 21:33:30 2009 PUSH: Received control message: 'PUSH_REPLY,dhcp-option DNS 208.67.222.222,dhcp-option DNS 208.67.220.220,dhcp-option DISABLE-NBT,dhcp-option DOMAIN corp.mycompany.com,route 10.1.1.0 255.255.255.0,redirect-gateway def1,route 10.1.2.1,topology net30,ping 10,ping-restart 120,ifconfig 10.1.2.6 10.1.2.5' Sun Sep 06 21:33:30 2009 OPTIONS IMPORT: timers and/or timeouts modified Sun Sep 06 21:33:30 2009 OPTIONS IMPORT: --ifconfig/up options modified Sun Sep 06 21:33:30 2009 OPTIONS IMPORT: route options modified Sun Sep 06 21:33:30 2009 OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified Sun Sep 06 21:33:30 2009 ROUTE default_gateway=11.22.33.45 Sun Sep 06 21:33:30 2009 TAP-WIN32 device [Local Area Connection 2] opened: \\.\Global\{54DE6C05-005D-49A9-8577-FA615D4902B4}.tap Sun Sep 06 21:33:30 2009 TAP-Win32 Driver Version 9.6 Sun Sep 06 21:33:30 2009 TAP-Win32 MTU=1500 Sun Sep 06 21:33:30 2009 Notified TAP-Win32 driver to set a DHCP IP/netmask of 10.1.2.6/255.255.255.252 on interface {54DE6C05-005D-49A9-8577-FA615D4902B4} [DHCP-serv: 10.1.2.5, lease-time: 31536000] Sun Sep 06 21:33:30 2009 Successful ARP Flush on interface [65540] {54DE6C05-005D-49A9-8577-FA615D4902B4} Sun Sep 06 21:33:35 2009 TEST ROUTES: 3/3 succeeded len=2 ret=1 a=0 u/d=up Sun Sep 06 21:33:35 2009 C:\WINDOWS\system32\route.exe ADD 11.22.33.0 MASK 255.255.255.255 11.22.33.45 Sun Sep 06 21:33:35 2009 Route addition via IPAPI succeeded [adaptive] Sun Sep 06 21:33:35 2009 C:\WINDOWS\system32\route.exe ADD 0.0.0.0 MASK 128.0.0.0 10.1.2.5 Sun Sep 06 21:33:35 2009 Route addition via IPAPI succeeded [adaptive] Sun Sep 06 21:33:35 2009 C:\WINDOWS\system32\route.exe ADD 128.0.0.0 MASK 128.0.0.0 10.1.2.5 Sun Sep 06 21:33:35 2009 Route addition via IPAPI succeeded [adaptive] Sun Sep 06 21:33:35 2009 WARNING: potential route subnet conflict between local LAN [10.1.1.0/255.255.255.0] and remote VPN [10.1.1.0/255.255.255.0] Sun Sep 06 21:33:35 2009 C:\WINDOWS\system32\route.exe ADD 10.1.1.0 MASK 255.255.255.0 10.1.2.5 Sun Sep 06 21:33:35 2009 Route addition via IPAPI succeeded [adaptive] Sun Sep 06 21:33:35 2009 C:\WINDOWS\system32\route.exe ADD 10.1.2.1 MASK 255.255.255.255 10.1.2.5 Sun Sep 06 21:33:35 2009 Route addition via IPAPI succeeded [adaptive] Sun Sep 06 21:33:35 2009 Initialization Sequence Completed |
If the user account running the OpenVPN client does not have administrative privileges nor the ability to elevate a process to that level, then there are other ways to allow restricted users (referred to as "standard users" in Vista lingo) to run the client and make a connection by granting access to the installed NT service of the application. Normally, most home users (unfortunately) use accounts with admin privileges for reasons of ignorance, but restricted accounts are more common in business environments. Check here for more information.
There are, of course, different variations to this environment setup such as multi-homed servers, a DMZ, a PKI that isn't rooted on the VPN server itself, stricter pf rules, etc.. This article provides a quick deployment guide for further evaluation of the OpenVPN implementation without needing to shell out big bucks for name-brand solutions.
Go back to the main articles list.