Jump to: navigation, search

Apache SNI With Kerberos


Apache Namebased SSL VirtualHosts with optional kerberos login

Introduction

Apache 2.2.12 added SNI to the TLS support of mod_ssl and RHEL6 brought 2.2.15 which then includes this.

This technology allows for multiple sites utilising a single IP - with their own certificates ... basically name based virtual hosting for SSL enabled sites.

There are a couple of caveats however - this capability is client dependant as well as server dependant - an approximate list can be found here - and since this requires the host header in the initial request it leaves it open to packet inspection and logging unlike traditional SSL.

The dogtag part of IPA can be used to handle these certificates and optionally IPA can handle the login details afterwards.

This documentation is an example from my own implementations at my workplace.

IPA/SSSD Configuration

SSSD does not need any special configuration however if:

 ipa-getcert list

shows any errors such as CA_UNREACHABLE when there are multiple replicas in the topology it is worth checking

 /etc/ipa/default.conf

to see which server is being used for certificate requests. Ensure that the server is accepting requests against the IPA topology and kerberos tickets are being generated before continuing.

Apache Configuration

There are several parts to this. Initially the default host will be configured to ensure there are no basic issues before adding the complexity of SNI. This guide assumes selinux is enforcing with the default targeted type in RHEL6.

Default SSL apache config

Before carrying out configuration of the web server on a system with ipa-admintools:

 ipa service-add HTTP/<fqdn-of-webserver>

This adds the service to IPA for the purposes of adding an SSL certificate to it and then later on for a keytab to the kerberos principal.

As usual the only requirements to install an SSL capable web server are:

 yum install httpd mod_ssl

which will provide for a self signed standard HTTPS server with content served from /var/www/html.

Certmonger and Apache will need a common area to read and/or write certificates as such I'd recommend creating a directory for these such as /etc/httpd/certs.

Certmonger needs to be allowed to write to this area - although it runs as root selinux will restrict it:

 semanage fcontext -a -t cert_t '/etc/httpd/certs(/.*)?' && restorecon -v /etc/httpd/certs

The apache process is able to read directories of type cert_t to obtain its certificates and certmonger can then write to this safely.

A certificate/key pair can then be requested through certmonger on the web server for the default instance via:

 ipa-getcert request -r -f /etc/httpd/certs/default.crt -k /etc/httpd/certs/default.key -N CN=`uname -n` -D `uname -n` -K HTTP/`uname -n`

To check the status of the request use:

 ipa-getcert list

If all is well there should be output similar to:

  Request ID '20120618111406':
	  status: MONITORING
	  stuck: no
	  key pair storage: type=FILE,location='/etc/httpd/certs/default.key'
	  certificate: type=FILE,location='/etc/httpd/certs/default.crt'
	  CA: IPA
	  issuer: CN=Certificate Authority,O=<KERBEROS-REALM>
	  subject: CN=<fqdn-of-webserver>,O=<KERBEROS-REALM>
	  expires: 2014-06-19 11:14:07 UTC
	  eku: id-kp-serverAuth,id-kp-clientAuth
	  track: yes
	  auto-renew: yes

The files should be visible in /etc/httpd/certs - the owner should be changed to make them readable by apache.

Following this edit /etc/httpd/conf.d/ssl.conf to make sure the following entries read as so:

 SSLCertificateFile /etc/httpd/certs/default.crt
 SSLCertificateKeyFile /etc/httpd/certs/default.key

If you require client validation link or copy /etc/ipa/ca.crt to /etc/httpd/certs and include:

 SSLCACertificateFile /etc/httpd/certs/ca.crt

At the time of writing there is no GUI for client certificates in IPA so any further configuration down that avenue is left as an exercise to the reader.

Ensure that TCP/443 is open and then start httpd to give it a test. If all is well the browser should show a certificate chain starting at the IPA server and with the certificate requested being served. If there are any problems here then backtrack and amend before proceeding.

Adding NameBased Virtual Sites with SSL

To allow IPA to handle the certificates there's some work that needs to be carried out in the IPA topology before the web server is further configured.

IPA requires the hostname in the services to match the hostname in the hosts for permission reasons - without this certmonger will show a permissions error when submitting the certificate request.

So the first step is to add a dummy host in the 'hosts' tab of IPA.

My preference to make this clearer as a dummy host was to put 'dummy host' in the description to make it easy to search for in future and to put the location as the fully qualified domain name of the actual host. A DNS record should already be in place for this (or just use the --force option when adding the host).

To do this via the ipa-admin tools do as follows (or just use the GUI):

 ipa dnsrecord-add example.com dummyhost --a-rec=10.180.80.1
 ipa host-add dummyhost.example.com --desc="Dummy Host" --location="<fqdn-of-webserver>"
 ipa host-add-managedby dummyhost.example.com --hosts="<fqdn-of-webserver>"
 

Now that the dummy host is in place (no enrollment, keytabs or certificates needed for this bit) the service can be added.

 ipa service-add HTTP/dummyhost.example.com
 ipa service-add-host HTTP/dummyhost.example.com --hosts="<fqdn-of-webserver>"

The IPA topology is then ready to add this as a virtual host on the web server.

Back on the web server itself the new certificate can now be requested:

 ipa-getcert request -r -f /etc/httpd/certs/dummyhost.crt -k /etc/httpd/certs/dummyhost.key -N CN=dummyhost.example.com -D dummyhost.example.com -K HTTP/dummyhost.example.com

Checking the /etc/httpd/certs directory should show the new certificate/key pair and as before these should be made readable to apache.

Now that the backend is in place to support the virtual host apache itself can be configured for it.

Configure Apache to use name based virtual hosts on port 443 (in addition to the standard 80):

 NameVirtualHost *:80
 NameVirtualHost *:443

Optionally add a redirect from non-SSL to SSL if you want it as a requirement:

  <VirtualHost *:80>
  ServerName dummyhost.example.com
  ServerAlias dummyhost
  RewriteEngine on
  RewriteRule ^/(.*)$ https://dummyhost.example.com/$1
  </VirtualHost>

And then add the SSL enabled virtual host:

  <VirtualHost *:443>
  ServerName dummyhost.example.com
  ServerAlias dummyhost
  SSLEngine on
  SSLProtocol all -SSLv2
  SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
  SSLCertificateFile /etc/httpd/certs/dummyhost.crt
  SSLCertificateKeyFile /etc/httpd/certs/dummyhost.key
  SSLOptions +StdEnvVars
  <Location />
  SSLRequireSSL
  </Location>
  </Virtualhost>

All the usual SSL/VirtualHost possibilities exist - just ensure the ServerName is present in the configuration.

If a client does not support SNI then the first virtual host defined will be used for any SSL session - similar to a non HTTP/1.1 client requesting a site from a name based virtual host system.

The exception to this is using SSLStrictSNIVHostCheck to alter the behaviour as described in the Apache documentation.

Restart the httpd service and check the logs - if all is working the following should appear in error_log:

 [Mon Jun 18 13:25:44 2012] [warn] Init: Name-based SSL virtual hosts only work for clients with TLS server name indication support (RFC 4366)

At this point https://dummyhost.example.com should then work to show the virtual host as defined and the certificate chain should be IPA->dummyhost when checked. If the IPA root certificate is trusted by the browser then there should be no certificate errors (name mismatches etc)... if there are any errors double check the logs and permissions on the certificates.

This procedure can be repeated for additional virtual hosts off the same server as required.

Adding kerberos authentication to the sites

With the sites having communication to the clients encrypted with SSL authentication can then be added. This authentication can be added without SSL but be aware that if fallback is enabled in mod_auth_kerb this will be basic authentication (ie insecure) without SSL in place.

Add the appropriate module for kerberos authentication on the web server:

 yum install mod_auth_kerb

Create a directory to store keytabs for authenticating against IPA:

 mkdir /etc/httpd/keytabs
 semanage fcontext -a -t httpd_keytab_t '/etc/httpd/keytabs/(.*)?'

Note that with the selinux context the directory should maintain the httpd_config_t type (default for anything in /etc/httpd/) but only the contents has the httpd_keytabs_t type.

The default keytab for the host (for any 'default' site requests) can be obtained via:

 ipa-getkeytab -s <fqdn-of-an-ipa-server> -p HTTP/`uname -n` -k /etc/httpd/keytabs/default

To get a site specific keytab use:

 ipa-getkeytab -s <fqdn-of-an-ipa-server> -p HTTP/dummyhost.example.com -k /etc/httpd/keytabs/dummyhost

Although segregation of keytabs isn't necessarily required (all hosts could use the default keytab in principle) separation allows for fine grained controls later on when integrating with other systems.

Check the contents of the keytab to ensure the expected principals are present:

  klist -k /etc/httpd/keytabs/default
  Keytab name: WRFILE:/etc/httpd/keytabs/default
  KVNO Principal
  ---- --------------------------------------------------------------------------
     1 HTTP/<fqdn-of-webserver>@<KERBEROS-REALM>
     1 HTTP/<fqdn-of-webserver>@<KERBEROS-REALM>
     1 HTTP/<fqdn-of-webserver>@<KERBEROS-REALM>
     1 HTTP/<fqdn-of-webserver>@<KERBEROS-REALM>

  klist -k /etc/httpd/keytabs/dummyhost
  KVNO Principal
  ---- --------------------------------------------------------------------------
     1 HTTP/dummyhost.example.com@<KERBEROS-REALM>
     1 HTTP/dummyhost.example.com@<KERBEROS-REALM>
     1 HTTP/dummyhost.example.com@<KERBEROS-REALM>
     1 HTTP/dummyhost.example.com@<KERBEROS-REALM>

To require login for all pages in a virtual host add:

  <Location />
    AuthType Kerberos
    AuthName "Web Server Login"
    KrbMethodNegotiate On
    KrbMethodK5Passwd On
    Krb5KeyTab /etc/httpd/keytabs/default
    require valid-user
  </Location>

For a non-default keytab (eg the dummyhost above) add/amend as appropriate:

 KrbServiceName HTTP/dummyhost.example.com
 Krb5KeyTab /etc/httpd/keytabs/dummyhost

The REMOTE_USER environment variable will be set to username@<KERBEROS-REALM> by default. For some systems it's preferable to just have the shorter 'username'. This behaviour is obtainable by adding:

 KrbLocalUserMapping On

If it is desirable to disable the basic authentication fallback and restrict the system to kerberos tokens only change KrbMethodK5Passwd to off and leave KrbMethodNegotiate on.

Conclusion

If all the steps above have been followed and everything is working properly the server should then be configured in such a way new virtual hosts can easily be added to present new sites each with their own SSL certificates (being tracked and renewed via certmonger) and the IPA infrastructure being utilised for all authentication on a standard RHEL6 install with nothing outside of the standard RHEL repositories.