📜 ⬆️ ⬇️

Web authorization of the domain user through nginx and HTTP Negotiate

The other day there was a task - to provide transparent authorization of domain users in CRM, Microsoft itself had long ago developed the Negotiate HTTP authentication method for this purpose, it all works fine on IIS and Windows Server, and we have Samba4 as Primary Domain Controller and proxy web server nginx. How to be?

The network has a lot of information on the organization of such a scheme for Apache2 & AD based on Windows, but nginx users have to collect everything bit by bit, the cat cried out. In the basic delivery of Nginx there is no such functionality. Fortunately, people didn’t lose heart and the story began in the nginx mailings in 2009 , where one American friend from Ohio hired a developer on RentACoder to download a module with similar functionality. The guys forked a similar module for Apache, screwed it to nginx and posted the results of the work on github, where the module was occasionally doped by different people and eventually took on a robotic look. The latest version is available on github .


In this tutorial, I’ll show you how to make nginx work with the SPNEGO module and samba4.


The first thing you need is to build nginx with the module we need. Ubuntu 16.04 will be used as an example.
')
For a start we put nginx
apt-get install nginx -V 

Next, download the latest version of the source code from the official site.
 wget http://nginx.org/download/nginx-1.11.2.tar.gz 

Ok, unzip the source folder and put our spnego-http-auth-nginx-module in it
 tar xvzf nginx-1.11.2.tar.gz cd nginx-1.11.2 git clone https://github.com/stnoonan/spnego-http-auth-nginx-module 

We look with what options we have now assembled nginx from the basic delivery and get a footwoman
 root@dc1:~# nginx -V nginx version: nginx/1.11.1 built by gcc 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2.1) built with OpenSSL 1.0.2g-fips 1 Mar 2016 TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_perl_module=dynamic --with-threads --with-stream --with-stream_ssl_module --with-http_slice_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_v2_module --with-debug --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,--as-needed' 

We copy a footwoman in a notebook and add it somewhere
 --add-module=spnego-http-auth-nginx-module 

We start the assembly with the necessary parameters
 ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_perl_module=dynamic --with-threads --with-stream --with-stream_ssl_module --add-module=spnego-http-auth-nginx-module --with-http_slice_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_v2_module --with-debug --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,--as-needed' 

Naturally, utilities for building should be installed on the system, and nginx should be extinguished.
 make make install 

After the procedure, we now end up with a working self-assembled nginx with the module we need. You can also check this - nginx -V and see the presence of the module in the parameters.


For example, use the url for authorization test.intranet.com, domain intranet.com


It's time to work a bit with samba, add a user to whom we hang the service principal name (spn) for authorization via Kerberos
 samba-tool user add HTTP samba-tool user setexpiry HTTP --noexpiry samba-tool spn add HTTP/test.intranet.com HTTP samba-tool spn add host/test.intranet.com HTTP 

Create a Kerberos keytab file for nginx
 samba-tool domain exportkeytab /etc/http.keytab --principal=HTTP/test.intranet.com samba-tool domain exportkeytab /etc/http.keytab --principal=host/test.intranet.com 

Check the generated keytab
 klist -ke /etc/http.keytab Keytab name: FILE:/etc/http.keytab KVNO Principal ---- -------------------------------------------------------------------------- 1 host/test.intranet.com@INTRANET.COM (des-cbc-crc) 1 host/test.intranet.com@INTRANET.COM (des-cbc-md5) 1 host/test.intranet.com@INTRANET.COM (arcfour-hmac) 1 HTTP/test.intranet.com@INTRANET.COM (des-cbc-crc) 1 HTTP/test.intranet.com@INTRANET.COM (des-cbc-md5) 1 HTTP/test.intranet.com@INTRANET.COM (arcfour-hmac) 

Log in to the domain controller via kerberos
 kinit administrator Password for administrator@INTRANET.COM: Warning: Your password will expire in 39 days on  30  2016 11:23:11 

We check domain authorization by spn using the keytab file:
 kinit -V -k -t /etc/http.keytab HTTP/test.intranet.com@INTRANET.COM Using default cache: /tmp/krb5cc_0 Using principal: HTTP/test.intranet.com@INTRANET.COM Using keytab: /etc/http.keytab Authenticated to Kerberos v5 

I had a problem at this stage, the authentication did not want to go through. Mistake:
kinit: Client not found in Kerberos database while getting initial credentials
I rummaged through the Internet, in the end there was a solution, it turned out that samba-tool does not work out the way Microsoft intended it, unexpectedly, right?
To solve the problem, go to the Windows machine and use the administrative console “Active Directory Users and Computers” to rule our HTTP user, namely, we edit the user login field on HTTP / test.intranet.com
After this procedure, everything works.

It's time to go to the nginx configuration, look at my virtual host config
  server { listen *:443 ssl; server_name test.intranet.com; # error_log /var/log/nginx/debug.log debug; ssl_certificate /etc/nginx/ssl/nginx.crt; ssl_certificate_key /etc/nginx/ssl/nginx.key; location / { proxy_pass http://********/$request_uri; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; auth_gss on; auth_gss_realm INTRANET.COM; auth_gss_keytab /etc/http.keytab; auth_gss_service_name HTTP/test.intranet.com; # auth_gss_allow_basic_fallback off; } } 


Parameter auth_gss_allow_basic_fallback off; allows you to turn off the request for basic authorization if something went wrong, let's say the user is not in the domain.


For a transparent authorization to work, certain conditions must be met:


It remains to be on the machine to bring our URL - test.intranet.com into the Intranet security zone in IE and try to access our link. If everything is configured correctly, then nginx should transparently skip the user to the site. On the server side, where we actually proxy the connection, the following information can be found in the packet headers.
[PHP_AUTH_USER] => Administrator [PHP_AUTH_PW] => bogus_auth_gss_passwd
It remains to finish the web application for transparent authentication a little, but that’s already a web programmer’s ...

In other browsers, this mechanism also works with minor modifications.


Actually, this is the whole setup process, I killed a couple of days for it, I decided to share it with the public. This mechanism allows you to save users in the office from entering a login \ password when accessing an internal web application.

Source: https://habr.com/ru/post/305098/


All Articles