OpenVPN and Active Directory (Kerberos without user certificates)

A lot of guides have been written about OpenVPN, including authorization through Active Directory. Most of them boil down to using LDAP; I did not find an approach using Kerberos, which is written in a full-fledged article. However, something new will not be invented here, I just compiled what has already been done before me, PAM works fine with Kerberos, and OpenVPN has a native PAM plugin. I also decided to abandon user certificates and advice, where they simply recommend that all users issue one certificate, they did not suit me, so another solution was found that worked on all clients.







A bit about NSS



In my case, I used Centos 7 in conjunction with sssd. However, nothing prevents using winbind. The main thing is to have a car in the domain and a Kerberos ticket. I will not write about how this is done, because I will not say anything new, the network has a lot of good manuals.



It will be necessary to change the settings of /etc/nsswitch.conf



if this has not been done before. Depending on which module was used, you need to enter sss or winbind instead of module_name, respectively. Parameter descriptions can be read using man nsswitch.conf



.



The following settings should be sufficient:



 passwd: files module_name shadow: files module_name group: files module_name
      
      





In the case of sssd, we do not forget, among other things, that in /etc/sssd/sssd.conf



in the [sssd] block, nss should be mentioned:



 services = nss, pam
      
      





As for winbind, it's hard for me to say something, I did not use it.



The ultimate goal is to get the right result from getent. Check that the machine can receive information about domain users and groups:



 > getent passwd kanlas kanlas:*:14123583:1257570:Kanlas Kanlasovich:/home/kanlas@example.com:/bin/bash > getent group VPN vpn:*:13821391:kanlas,igor,marina
      
      





Note
If you used sssd and user data is obtained only with the full name (i.e. kanlas@example.com), add the use_fully_qualified_names = False



parameter in sssd.conf in the domain block



Configure PAM



Now you need to create your own PAM module. In order not to use the system access.conf, we will create a separate file from where the access group will be read. I'm not so good at PAM modules, so I can’t say if all the lines are needed in the example below. In general, we are only interested in the line account required pam_listfile.so onerr=fail item=group sense=allow file=/etc/openvpn/auth/access-groups



.



The easiest option is to take, for example, the login module and add the desired line to it. Which was done.



We get:



 #%PAM-1.0 auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so auth substack system-auth auth include postlogin account required pam_listfile.so onerr=fail item=group sense=allow file=/etc/openvpn/auth/access-groups account include system-auth password include system-auth session required pam_selinux.so close session required pam_loginuid.so session optional pam_console.so session required pam_selinux.so open session required pam_namespace.so session optional pam_keyinit.so force revoke session include system-auth session include postlogin -session optional pam_ck_connector.so
      
      





We put it in /etc/pam.d



, naming it at our discretion.



In /etc/openvpn/auth/access-groups



, specified in the module, the access group will be written here, you can specify your path if you wish. You will need to specify the name of the group (Common Name) with the domain. In my case, I wrote VPN@example.com there.



It remains to explain to OpenVPN that it needs to use PAM. We put the following lines in the server configuration:



 plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so __pam username-as-common-name
      
      





Different distributions may have different paths! Check for a file by the path, or use find.



The use of the username-as-common-name parameter is due to the fact that, otherwise, after the client has auth-user-pass, the name specified in the certificate will be sent to the server.



In the client config, add the line



 auth-user-pass
      
      





On this setup is finished, you can test.



We remove the user certificate



Now we have authorization through the domain and the user certificate is useless, abandoning it seems like a logical decision. But mobile clients have problems with this, simply not accepting such a configuration, while desktop ones, although they work, curse viciously. First, we’ll reconfigure the server so that it no longer requires a certificate.



 verify-client-cert none
      
      





Next, we add to the client configuration



 setenv CLIENT_CERT 0
      
      





That's it, now customers will not swear on a certificate. It's funny that this option is hidden in the question and answer section for iOS . I have not tested on iOS, but Android, as well as MacOS ( beta client ) and Windows accept these settings with a bang. Only a third-party OpenVPN client on Android can not do this yet (by the time this article was being written, they could already fix it).



All Articles