It has been a while since I’ve written about Information Technology so I figure it is time to revisit a few of my favorite technologies. In this post, I will cover the configuration required to put Duo multifactor authentication (using “Duo Push” and the Duo Mobile app) in front of the Apache webserver via the mod_authz_ldap Apache module.
I am a big fan of webserver based authentication - I have horror stories about unsecured “one-off” authentication mechanisms created in code (ask me in the Comments and I will share). As a result, I tend to sleep better knowing authentication is handled securely and centrally by the webserver itself.
Before I get into this, I want to iterate that this is a proof of concept or illustrative post. I am going to take shortcuts that you should never use in production. I will note such things with #neverinproduction.
To keep things simple, I opted to use Forum System’s test LDAP server as my user directory (very nice of Forum Systems to make this available). This eliminated the need for me to install and configure my own OpenLDAP or Microsoft Active Directory instance. In the real world, this would be pointed to your directory service (Active Directory, OpenLDAP, etc.).
Keeping with the simple theme, I also installed the Duo Auth Proxy (technically a Python-based RADIUS and LDAP proxy) and Apache on the same AWS EC2 nano instance (#neverinproduction). Always keep things separate for improved security.
The Apache module mod_authz_ldap will be configured to use the Duo Authentication Proxy as an LDAP server. The auth proxy is the glue that holds everything together - it authenticates users (first factor, username/password) by proxying them to Forum System’s LDAP server and facilitate Duo Push (second factor) using the Duo MFA cloud service.
Here is the process.
Configure Duo (console)
A few things need to happen in the Duo Administrator Console. These include adding a Duo Integration for LDAP, adding a Duo user that matches one from the test LDAP server, adding a device for that user, and activating the device for Duo Push.
Creating the Integration
The Authentication Proxy needs an Integration Key, API host, and Secret Key to interact with the Duo Cloud service. Search for and create an “LDAP Proxy” integration in the Duo Admin Console.
I named mine “Apache Duo MFA”. Take note of the Integration Key, API host, and Secret Key - these are needed later during the Authentication Proxy Configuration.
Adding a user
In real life, your Duo users would be populated with an Active Directory Sync, Bulk Import, or some other batch process. For this demo, I opted to manually add the user “euclid”. The username in Duo just needs to match a username (uid) in Forum System’s test LDAP server.
Adding a device and enrolling it for Duo Push
Manually enroll a device (with the Duo Mobile App installed) and associate it with the “euclid” user. This way, when “euclid” authenticates, you can respond to the Push on the device. In real life, this can be automated as well.
Install Apache (httpd)
I used Amazon Linux AMI 2018.03.0 for this setup and did not see the mod_authz_ldap module for Apache 2.4 in the repository yet (I was in a hurry and may have missed it). As a result, I opted for Apache 2.2 since the LDAP module can be installed via yum for that version. Your mileage may vary on other distributions.
To install, log in as a user with sudo privileges and run:
sudo yum -y update sudo yum -y install httpd sudo yum -y install mod_authz_ldap sudo service httpd start
Install the Duo Authentication Proxy
At the time of writing, the current version of the Duo Auth Proxy was 3.1.0. If you are replicating the install process line by line, you may need to update references the version. The Auth Proxy install is very easy (albeit time-consuming to compile on a t2.nano instance - around 5 minutes).
Log in as a user with sudo privileges and run:
sudo yum -y install gcc make python-devel libffi-devel perl zlib-devel wget https://dl.duosecurity.com/duoauthproxy-latest-src.tgz tar xzf duoauthproxy-latest-src.tgz cd duoauthproxy-3.1.0-rc.1--src/ make cd duoauthproxy-build sudo ./install
Accepting the default options during the install is generally fine.
Configure the Duo Authentication Proxy
The Duo Auth Proxy configuration options are very well documented. Note, the proxy’s default settings are aligned to Microsoft Active Directory. If you are using RedHat Directory Server, OpenLDAP, etc., some minor tweaks are required.
The Forum System’s test LDAP server runs OpenLDAP. I found this guide particularly helpful for configuring the Duo Authentication Proxy to work with OpenLDAP. If you find entries like the following in authproxy.log, it is possible the auth proxy is not configured properly for your directory service:
- Username lookup failed: ‘invalidDNSyntax: invalid DN’
- Received extraneous LDAP PDU while resolving a BindRequest
To configure the proxy, log in as a user with sudo privileges and run:
sudo vi /opt/duoauthproxy/conf/authproxy.cfg
Remove the default config and paste the following, saving the file once done (note: replace the ikey, skey and api_host with the values you copied when creating the LDAP Proxy integration in the Duo Console):
[ad_client] ;https://duo.com/docs/authproxy-reference#ad_client ;https://help.duo.com/s/article/2121?language=en_US ;https://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/ ; I am binding on port 389 (no encryption) - #neverinproduction ; Use 636 (LDAPS) instead host=ldap.forumsys.com auth_type=plain service_account_username=read-only-admin service_account_password=password bind_dn=cn=read-only-admin,dc=example,dc=com search_dn=dc=example,dc=com username_attribute=uid [ldap_server_auto] ;https://duo.com/docs/authproxy-reference#ldap-auto ikey=<<from integration in Duo Admin Console>> skey=<<from integration in Duo Admin Console>> api_host=<<from integration in Duo Admin Console>> failmode=secure client=ad_client factors=push
The auth proxy config is also available as a Gist if you prefer.
Once done, start the auth proxy:
sudo /opt/duoauthproxy/bin/authproxyctl start
Configure Apache (HTTPD)
Finally, configure Apache to use the LDAP module for authentication. I simply protected the default site (test page) as an example, but this can be applied at the vhost level as well (either in the main configuration files or via .htaccess).
I neglected to set up HTTPS for this test - #neverinproduction. Any authentication on the web should always occur via HTTPS.
To configure, log in as a user with sudo privileges and run:
sudo vi /etc/httpd/conf/httpd.conf
Locate the “<Directory “/var/www/html”>” section and append this to the beginning of the block:
AuthType Basic AuthBasicProvider ldap AuthName "LDAP Duo MFA" # I am binding on port 389 (no encryption) - #neverinproduction - use 636 (LDAPS) instead AuthLDAPURL ldap://localhost/dc=example,dc=com?uid AuthLDAPBindDN "cn=read-only-admin,dc=example,dc=com" AuthLDAPBindPassword "password" Require valid-user
# # This should be changed to whatever you set DocumentRoot to. # <Directory "/var/www/html"> #Duo LDAP configuration AuthType Basic AuthBasicProvider ldap AuthName "LDAP Duo MFA" # I am binding on port 389 (no encryption) - #neverinproduction # Use 636 (LDAPS) instead AuthLDAPURL ldap://localhost/dc=example,dc=com?uid AuthLDAPBindDN "cn=read-only-admin,dc=example,dc=com" AuthLDAPBindPassword "password" Require valid-user # # Possible values for the Options directive are "None", "All", # or any combination of . . .
Once done, start or restart Apache / httpd:
sudo service httpd restart
Test the setup
If all went well, you should have a functional MFA setup for Apache (httpd). If you access your webserver’s URL in a browser, you should be prompted for primary authentication:
And if successful, you should receive a Duo Push on the device you enrolled:
Once both phases of authentication are completed, you should see the Apache test page. Note that if you plan to test repeatedly, you may need to restart Apache in between tests. mod_ldap performs some caching that prevents the MFA push from being presented each authentication attempt (from the same device).
The ldap_server_auto option in the Duo Authentication Proxy is a somewhat hidden gem. There is a lot of documentation surrounding using RADIUS for a similar type of MFA setup for Apache, but I prefer LDAP. Almost all applications and devices (including legacy ones) support LDAP in some form, so this option makes Duo MFA possible on a multitude of devices and applications.
I also wanted to comment on Duo Security as a company. They are fantastic in every way (no, I was not compensated by Duo to say this). Their MFA solution is excellent technically: reliable, easy to implement, maintain and use. What sets them apart (in my opinion) are their business processes: Incident Management, Change Management, Support, and Documentation. It is rare to receive such prompt and professional Incident Management and Change Management communications from an organization, but Duo has excelled at this since I first adopted their solution years ago. Not many companies score high in my book across the board, but Duo shines.
If you are in the market for a robust MFA (2-factor authentication) provider, I highly recommend Duo Security.