Some months ago we bought a Barracuda firewall/VPN box to allow IT staff to connect and manage other IT devices securely. The idea was that the Barracuda would not only authenticate them against Active Directory and support two-factor authentication, but also carry out some Network Access Control and only allow devices that meets specific criteria connect to the network. Eg. Must be a domain member with a current Anti-virus and active firewall.
Well it turns out that the Barracuda couldn’t meet these needs. If you wanted to connect to the Barracuda using it’s web interface for portal type access it was fine. It used an agent based NAC and would allow two-factor auth using Google, but sadly not RADIUS.
However, if you wanted to use the network connection feature that is provided by using OpenVPN then you were going to be sadly disappointed.
Admittedly we are looking at the budget end of the market, sub £1,000. It need only support five concurrent users as it’s pretty much a get out of jail free card should the tasks you need to carry out be more than can be allowed through a remote desktop in a walled garden setup.
So the Barracuda went back and it left me thinking I can build my own based on the fact that OpenVPN is Open Source. So that’s exactly what I did.
It took a little bit of thinking about, but eventually we ended up with a solution that works across client platforms and although we sacrificed some of our goals, namely RADIUS auth and NAC, we got a two-factor solution that authenticates with certificates and Active Directory.
A user must be issued with a certificate, that certificate can have a password on it – which by default does. They also must be within a specific AD OU. The server is configured to proxy port 443/tcp so should play fairly nicely with outside connections. It’s also hooked in with fail2ban so anyone hammering will get the boot.
Key configuration points within server.conf:
dev tun proto tcpport 443 port-share 127.0.0.1 5545 user nobody group nogroup cipher AES-256-CBC auth SHA512 keysize 256 ca /usr/local/etc/ssl/ca.pem cert /etc/openvpn/keys/server.crt key /etc/openvpn/keys/server.key tls-auth /etc/openvpn/keys/tls-auth.key 0 server 10.9.8.0 255.255.255.0 topology subnet ifconfig-pool-persist ipp.txt push "route 192.168.0.0 255.255.255.0" push "redirect-gateway def1" push "dhcp-option DOMAIN mydomain.local" push "dhcp-option DNS 192.168.0.5" push "dhcp-option DNS 192.168.0.10" push "dhcp-option NTP 192.168.0.5" push "dhcp-option DISABLE-NBT" keepalive 10 120 comp-lzo persist-key persist-tun status /var/log/openvpn-status.log log /var/log/openvpn.log verb 3 #client-to-client plugin /usr/lib/openvpn/openvpn-auth-ldap.so /etc/openvpn/auth/auth-ldap.conf #client-cert-not-required
I’ve shown the options I don’t want commented out, namely the client-to-client and client-cert-not-required, because we don’t want clients seeing each other and we must have a client certificate.
The port share of 5545 isn’t a service that exists. I don’t really want to provide anything that looks like a web server on that port, although I could happily set Nginx up with a static page and present something.
This also needs to link to the auth/auth-ldap.conf:
<LDAP> # LDAP server URL URL ldaps://ldapserver # Bind DN (If your LDAP server doesn't support anonymous binds) BindDN "CN=Read Only,CN=Users,DC=mydomain,DC=local" # Bind Password Password SecretPassword # Network timeout (in seconds) Timeout 15 # Enable Start TLS TLSEnable yes # Follow LDAP Referrals (anonymously) FollowReferrals yes # TLS CA Certificate File TLSCACertFile /usr/local/etc/ssl/ca.pem # TLS CA Certificate Directory TLSCACertDir /etc/ssl/certs # Client Certificate and key # If TLS client authentication is required TLSCertFile /usr/local/etc/ssl/client-cert.pem TLSKeyFile /usr/local/etc/ssl/client-key.pem # Cipher Suite # The defaults are usually fine here # TLSCipherSuite ALL:!ADH:@STRENGTH </LDAP> <Authorization> # Base DN BaseDN "OU=Admin Accounts,DC=mydomain,DC=local" # User Search Filter SearchFilter "(sAMAccountName=%u)" # Require Group Membership RequireGroup false </Authorization>
Then to make things easier for the client I package the certificates into their client.ovpn config file. This way all they are given is one file they stick on their client machine in the ‘config’ folder.
dev tun client auth-user-pass remote [EXTERNAL IP OF SERVER] 443 tcp nobind cipher AES-256-CBC auth SHA512 keysize 256 remote-cert-tls server key-direction 1 comp-lzo persist-key persist-tun verb 3 <ca> -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- </ca> <tls-auth> # # 2048 bit OpenVPN static key # -----BEGIN OpenVPN Static key V1----- ... -----END OpenVPN Static key V1----- </tls-auth> <cert> -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- </cert> <key> -----BEGIN ENCRYPTED PRIVATE KEY----- ... -----END ENCRYPTED PRIVATE KEY----- </key>
I’ve obviously trimmed out the certs and keys to protect the innocent. Notice the key-direction is 1 and the server is 0. Doesn’t matter which way round they go, but they have to be different.