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).