Skip to content

Instantly share code, notes, and snippets.

@dol
Forked from alexzorin/mod_acme_alpn.c
Created September 1, 2018 23:33
Show Gist options
  • Save dol/519f98d7c0d45d5b210f8753c05cf8b4 to your computer and use it in GitHub Desktop.
Save dol/519f98d7c0d45d5b210f8753c05cf8b4 to your computer and use it in GitHub Desktop.
docker network create --driver bridge httpd-acme-alpn
docker build . -t httpd-acme-alpn; docker run --rm -it --network=httpd-acme-alpn --name httpd-acme-alpn httpd-acme-alpn
cd test; docker build . -t httpd-acme-alpn-test; docker run --rm -it --network=httpd-acme-alpn httpd-acme-alpn-test perl /test.pl
FROM httpd
RUN apt-get update && apt-get install -y \
wget \
automake \
build-essential \
ssl-cert \
&& rm -rf /var/lib/apt/lists/*
RUN make-ssl-cert generate-default-snakeoil
COPY vhost.conf /usr/local/apache2/conf
RUN echo 'Include conf/vhost.conf' >> /usr/local/apache2/conf/httpd.conf
COPY mod_acme_alpn.c /usr/local/apache2
RUN apxs -i -a -c mod_acme_alpn.c
FROM perl
RUN cpanm -n \
Crypt::OpenSSL::X509 \
IO::Socket::SSL
COPY test.pl /
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include <http_log.h>
#include "ap_config.h"
#define AP_PROTOCOL_ACME_ALPN "acme-tls/1"
static int acme_alpn_protocol_propose(conn_rec *c, request_rec *r,
server_rec *s,
const apr_array_header_t *offers,
apr_array_header_t *proposals)
{
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "In protocol_propose");
if (!offers)
{
return DECLINED;
}
const char *offer = AP_PROTOCOL_ACME_ALPN;
if (ap_array_str_contains(offers, offer))
{
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "protocol_propose: Proposing %s", offer);
APR_ARRAY_PUSH(proposals, const char*) = offer;
return OK;
}
return DECLINED;
}
static int acme_alpn_protocol_switch(conn_rec *c, request_rec *r, server_rec *s,
const char *protocol)
{
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "In protocol_switch");
/* Can't override the ServerHello lol! */
return OK;
}
static const char *acme_alpn_protocol_get(const conn_rec *c)
{
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "In protocol_get: NULL");
return NULL;
}
void acme_alpn_register_hooks(apr_pool_t *pool)
{
ap_hook_protocol_propose(acme_alpn_protocol_propose, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_protocol_switch(acme_alpn_protocol_switch, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_protocol_get(acme_alpn_protocol_get, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA acme_alpn_module =
{
STANDARD20_MODULE_STUFF,
NULL, /* Per-directory configuration handler */
NULL, /* Merge handler for per-directory configurations */
NULL, /* Per-server configuration handler */
NULL, /* Merge handler for per-server configurations */
NULL, /* Any directives we may have for httpd */
acme_alpn_register_hooks /* Our hook registering function */
};
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
# This script imitates the ACME server’s validation process.
# It’s useful for testing your challenge setup independently of the
# actual ACME validation.
#
# See tls_alpn_01_server.pl for a corresponding server implementation.
use constant {
_DOMAIN => 'example.com',
};
use Crypt::OpenSSL::X509;
use IO::Socket::SSL;
die 'No ALPN support in Net::SSLeay!' if !Net::SSLeay->can('CTX_set_alpn_protos');
my $client = IO::Socket::SSL->new(
PeerAddr => 'httpd-acme-alpn',
PeerPort => '443',
ReuseAddr => 1,
SSL_alpn_protocols => [ 'acme-tls/1' ],
SSL_hostname => _DOMAIN(),
SSL_verify_callback => sub {
my ($ossl_o, $cert_store, $attrs_str, $errs_str, $cert_addr) = @_;
my $pem = Net::SSLeay::PEM_get_string_X509($cert_addr);
my $x509 = Crypt::OpenSSL::X509->new_from_string($pem, Crypt::OpenSSL::X509::FORMAT_PEM());
my $exts_hr = $x509->extensions_by_oid();
my $extn_obj = $exts_hr->{ '1.3.6.1.5.5.7.1.31' };
die "No acmeValidation-v1 extension!" if !$extn_obj;
if (!$extn_obj->critical()) {
die "acmeValidation-v1 is not marked critical!";
}
my $val = pack 'H*', substr( $extn_obj->value(), 1 );
print "This certificate’s acmeValidation-v1 extension has this value:$/$/";
printf "\t%v.02x$/$/", $val;
return 1;
},
);
die "SSL client failure: $! ($@)\n" if !$client;
Listen *:443
LoadModule ssl_module modules/mod_ssl.so
LogLevel debug
Protocols acme-tls/1 http/1.1
<VirtualHost *:443>
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
ServerName "example.com"
</VirtualHost>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment