Skip to content

phracek/mod_md

 
 

Repository files navigation

mod_md - Everybody Spies

Copyright 2017-2019 greenbytes GmbH

This repository contains mod_md, a module for Apache httpd that adds support for Let's Encrypt (and other ACME CAs).

This code here is to help people review and comment and test early versions. Issues you can raise here, general discussion is probably best at the httpd dev mailing list. The module is, in Apache terms, experimental, meaning features might change based on feedback by the community. It is however a complete implementation of the ACMEv1 protocol and used in production in many locations.

NEWS: Experimental! Again! Wildcards!

The current releases, v1.99.x, contain new support for the ACMEv2 protocol and can NOT be considered as stable as the previous releases. Please help me test this, but do expect things to go pling now and then.

From v1.99.5 onwards mod_md supports wildcard certificates. See the section below about details.

For the new tls-alpn-01 challenge method to work, you need a patched mod_ssl. The patches for trunk and 2.4.x versions of the Apache httpd are available in the patches directory. When you have that, you also need to extend the protocols you allow on your server:

Protocols h2 http/1.1 acme-tls/1

The last one, acme-tls/1, is the new one that needs adding. You do not need h2.

Documentation

For Versions before v1.1.x and earlier, look on the wiki for directions on how to use mod_md.

For Versions 1.99.x here are a summary of the changes which will be merged into the wiki once this version becomes stable:

Base Setup in 1.99.x

  • For now, the ACMEv2 endpoint of Let's Encrypt is not enabled by default. If you want to test it on your server, you need to explicitly set:
MDCertificateAuthority https://acme-staging-v02.api.letsencrypt.org/directory

This is the "staging" end point for testing. The certificates it hands out will not be accepted by browsers. But it's a good test.

  • If the ACMEv2 staging endpoint works for you, you can enable the real end point:
MDCertificateAuthority https://acme-v02.api.letsencrypt.org/directory

to your configuration. mod_md will in version 2.0 do that as the new default. This means, when you do not set this URL explicitly somewhere, your next certificates will come from the ACMEv2 endpoint of Let's Encrypt.

  • Changing the MDCertificateAuthority configuration will not invalidate the certificates you have. It only affects certificate renewal when it is time.

Challenges in v1.99.x

Challenges are the method how Let's Encrypt (LE) verfifies that the domain is controlled by you. Only if you (or your Apache server) answers such a challenge correctly, LE will sign a new ceritficate.

ACMEv1 and ACMEv2 have different challenge methods they allow:

  • http-01: the server needs to answer a special http: request correctly. Supported on ACME v1+v2, your Apache server needs to be reachable on port 80.
  • dns-01: the DNS server for your domain needs to contain a special record. Supported on ACME v1+v2, but not supported by Apache (yet).
  • tls-sni-01: the Apache server needs to answer a https: connection in a certain way. Supported initialy on ACME v1, but disabled for security reasons.
  • tls-alpn-01: the Apache server needs to answer a https: connection in a certain way. Supported on ACME v2, server needs to be reachable on port 443.

To summarize: with mod_md version 1.x you needed port 80 to be open to get LE certificates. With version 2.x you can continue to do that. But you can also configure the new challenge method and no longer need port 80. See below how this works.

Challenge Type tls-alpn-01

This ACME v2 challenge type is designed to fix the weaknesses of the former tls-sni-01 challenge type. For that, amongst other changes, it opens a TLS connection to you Apache for the protocol named 'acme-tls/1'.

This protocol string is send in the application layer protocol names (ALPN) extensions of SSL. No server that is not prepared for ACME challenges will ever answer that protocol. That makes it harder for cheaters so somehow fake the challenge answer.

The protocols that your Apache server allows are configured with the Protocols directive. It has as default http/1.1, but if you already run the HTTP/2 protocol, you will have added h2 already. Now, for your server to answer the new ACMEv2 challenges, you would then add it simply:

Protocols h2 http/1.1 acme-tls/1

mod_md will see that and use the new challenge type.

HOWEVER (there is always a catch, is there not?): for now, you 'll also need a patched mod_sslto make this work. The patch is included here, but patching and compiling mod_ssl might not be everyone's cup of tea. If you do not have a patched mod_ssl, you can still run the new mod_md, but do not enable the tls-alpn-01 challenge protocol.

Wildcard Certificates in v1.99.x

Since v1.99.5 you can request wildcard certificates, e.g. *.mod_md.org. These can be combined with other names for Managed Domains, just as before:

 MDomain mod_md.org *.mod_md.org www.mod_md.org

HOWEVER, Let's Encrypt will hand out certificates with a wildcard domain only on its ACMEv2 service and only when verified via the dns-01 challenge method.

dns-01 means that Let's Encrypt (or another ACME CA) checks a DNS record for your domain at the DNS server that handles your domain. Read: Apache cannot answer such queries and there is no standardized interface to manipulate a DNS server, so the details of how to do this are very much up to you.

So, how does this work in general? mod_md has a new configuration directive:

MDChallengeDns01 <exectute-command>    
# example:
# MDChallengeDns01 /usr/sbin/dns01-handler

If you configure such a command, it will get called by mod_md with one of the two options:

# setup the answer to a dns-01 challenge, a TXT DNS record for 
# _acme-challenge.<domain> with the given challenge.
> dns01-handler setup <domain> <challenge-base64>

# clear a challenge answer
> dns01-handler teardown <domain>

This command needs then to talk to the DNS server you use. How it does this work, I have no idea! Upon success, it needs to return 0. All other return codes are considered as failure and the signup for the certificate will either try another challenge method (if available) or fail.

One more detail: the command will, on most installations, not be executed as root but was www-data. Plan that into your security/authentication model.

So, no ready-made solution here. Sorry! But! There are many possible scenarios on how to set this up and I am sure that Linux distribution will think of nice ways to integrate this into their server setups.

Status

The module has been backported to Apache 2.4.x branch and was released in version 2.4.33 (in the release notes, you will see it listed as change in 2.4.30 - a release that never saw the light of day. So, in a sane world, all changes since 2.4.29 would be listed as change in 2.4.33. But release managers already carry a heavy burden. One always treats them with respect and bows thankfully and does not mentions one's unimportant annoyances ;).

For the impatient and danger seekers: what you find here is a copy of what lives inside the Apache httpd trunk repository. While people find an occasional hickup - mostly due to some unique aspect in the setups - several people, including myself, are running this inside a patched 2.4 Apache for months now. And successfully.

However, this is not checkout, configure and shoot. For it to work, you need a patched mod_ssl (patch is provided in directory patches), but that is about the only complication.

There is an ever expanding test suite included against a local boulder server, using the excellent pytest. Also, thanks to Jacob Champion, we have unit tests available when check is installed.

The Apache2 PPA for ubuntu by @oerdnj, see here, has a patched mod_ssl just as mod_md needs it! Thanks! So, in such a server you just need to drop mod_md from here.

Test Status

Tests have been verified to run on MacOS and Ubuntu 16.04 under the following conditions:

  • the *SSL library you compile with supports SNI
  • curl is linked against this recent *SSL lib
  • your Apache httpd installation has a patched mod_ssl
  • you have a local boulder server installed and it resolved host names against your httpd (see below)

So, it's a bit tricky when your OS does not support features like SNI in its standard config.

Install

See 2.4.x Installation on the wiki.

See ChangeLog for details.

Licensing

Please see the file called LICENSE.

Credits

This work is supported by an Award from MOSS, the Mozilla Open Source Support project. Many thanks to these excellent people! You are awesome!

Test cases mostly written by my colleague @michael-koeller who made this to a good part really a test driven development. Thanks!

Münster, 07.01.2019

Stefan Eissing, greenbytes GmbH

Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. See LICENSE for details.

About

Let's Encrypt (ACME) support for Apache httpd

Resources

License

Apache-2.0, Unknown licenses found

Licenses found

Apache-2.0
LICENSE
Unknown
COPYING

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 66.5%
  • Python 30.5%
  • M4 2.0%
  • Other 1.0%