HTTP/2.0 Ubuntu 16.04 mit Apache 2.4

Das Apache Modul mod_http2 gilt selbst noch auf apache.org als experimentell. Unter Ubuntu Launchpad wurde dies aufgeriffen und deshalb wird das http2 Modul nicht mit der LTS Version 16.04 ausgeliefert. Dem Workaround von Launchpad folgend hier meine Erfahrungen beim Kompilieren des Moduls aus den Ubuntu quellen. Es müssen einige Voraussetzungen getroffen werden.

deb-src in Apt-Sources.list auskommentieren.

:~# vim /etc/apt/sources.list
deb-src http://de.archive.ubuntu.com/ubuntu/ xenial main restricted
deb-src http://de.archive.ubuntu.com/ubuntu/ xenial-updates main restricted
deb-src http://security.ubuntu.com/ubuntu xenial-security main restricted

Paket libnghttp2-dev nachinstallieren.

:~# apt-get install libnghttp2-dev
Paketlisten werden gelesen... Fertig
Abhängigkeitsbaum wird aufgebaut.
Statusinformationen werden eingelesen.... Fertig
Die folgenden zusätzlichen Pakete werden Installiert
  build-essential dpkg-dev fakeroot g++ g++-5 libalgorithm-diff-perl libalgorithm-diff-xs-perl
  libalgorithm-merge-perl libdpkg-perl libfakeroot libfile-fcntllock-perl libnghttp2-14 libstdc++-5-dev
  pkg-config
Vorgeschlagene Pakete:
[...]

Build Umgebung für apache2 installieren.

:~# apt-get build-dep apache2
Paketlisten werden gelesen... Fertig
Paketlisten werden gelesen... Fertig
Abhängigkeitsbaum wird aufgebaut.
Statusinformationen werden eingelesen.... Fertig
Die folgenden NEUEN Pakete werden installiert:
  autotools-dev debhelper dh-strip-nondeterminism gettext icu-devtools intltool-debian libapr1 libapr1-dev libaprutil1 libaprutil1-dev libarchive-zip-perl libcroco3
  libexpat1-dev libfile-stripnondeterminism-perl libicu-dev libldap2-dev liblua5.1-0 liblua5.1-0-dev libpcre16-3 libpcre3-dev libpcre32-3 libpcrecpp0v5
  libreadline-dev libreadline6-dev libsctp-dev libsctp1 libssl-dev libtimedate-perl libtinfo-dev libunistring0 libxml2-dev po-debconf uuid-dev zlib1g-dev
0 aktualisiert, 34 neu installiert, 0 zu entfernen und 0 nicht aktualisiert.
Es müssen 16,5 MB an Archiven heruntergeladen werden.
Nach dieser Operation werden 82,8 MB Plattenplatz zusätzlich benutzt.
Möchten Sie fortfahren? [J/n]
[...]

Build Umgebung anlegen und die apache2 Sourcen holen.

:~$ mkdir apache2
:~$ cd apache2

:~/apache2$ apt-get source apache2
Paketlisten werden gelesen... Fertig
HINWEIS: »apache2«-Paketierung wird betreut im »Git«-Versionsverwaltungssystem auf:
git://anonscm.debian.org/pkg-apache/apache2.git
Bitte verwenden Sie:
git clone git://anonscm.debian.org/pkg-apache/apache2.git
um die neuesten (möglicherweise noch unveröffentlichten) Aktualisierungen
für das Paket abzurufen.
Es müssen 5.547 kB an Quellarchiven heruntergeladen werden.
Holen:1 http://de.archive.ubuntu.com/ubuntu xenial-updates/main apache2 2.4.18-2ubuntu3.1 (dsc) [2.773 B]
Holen:2 http://de.archive.ubuntu.com/ubuntu xenial-updates/main apache2 2.4.18-2ubuntu3.1 (tar) [5.181 kB]
Holen:3 http://de.archive.ubuntu.com/ubuntu xenial-updates/main apache2 2.4.18-2ubuntu3.1 (diff) [363 kB]
Es wurden 5.547 kB in 9 s geholt (597 kB/s).
gpgv: Unterschrift vom Fr 15 Jul 2016 16:38:13 CEST mittels RSA-Schlüssel ID A744BE93
gpgv: Unterschrift kann nicht geprüft werden: Öffentlicher Schlüssel nicht gefunden
dpkg-source: Warnung: Fehler beim Überprüfen der Signatur von ./apache2_2.4.18-2ubuntu3.1.dsc
dpkg-source: Information: apache2 wird nach apache2-2.4.18 extrahiert
dpkg-source: Information: apache2_2.4.18.orig.tar.bz2 wird entpackt
dpkg-source: Information: apache2_2.4.18-2ubuntu3.1.debian.tar.xz wird entpackt
dpkg-source: Information: fhs_compliance.patch wird angewandt
dpkg-source: Information: no_LD_LIBRARY_PATH.patch wird angewandt
dpkg-source: Information: suexec-CVE-2007-1742.patch wird angewandt
dpkg-source: Information: customize_apxs.patch wird angewandt
dpkg-source: Information: build_suexec-custom.patch wird angewandt
dpkg-source: Information: reproducible_builds.diff wird angewandt
dpkg-source: Information: prefork_single_process_crash.patch wird angewandt
dpkg-source: Information: 086_svn_cross_compiles wird angewandt
dpkg-source: Information: CVE-2016-5387.patch wird angewandt

:~/apache2$ ll
insgesamt 5432
drwxrwxr-x  3 vagrant vagrant    4096 Mär 18 12:30 ./
drwxr-xr-x  5 vagrant vagrant    4096 Mär 18 12:28 ../
drwxrwxr-x 13 vagrant vagrant    4096 Mär 18 12:30 apache2-2.4.18/
-rw-r--r--  1 vagrant vagrant  362532 Jul 18  2016 apache2_2.4.18-2ubuntu3.1.debian.tar.xz
-rw-r--r--  1 vagrant vagrant    2773 Jul 18  2016 apache2_2.4.18-2ubuntu3.1.dsc
-rw-r--r--  1 vagrant vagrant 5181291 Jan 22  2016 apache2_2.4.18.orig.tar.bz2

Im Prinzip werden mit den nächsten Schritten komplette Debian Pakete des Apaches gebaut. Sie werden in den weiteren Schritten ignoriert und nur das kompilierte http2 Modul verwendet.

:~/apache2$ cd apache2-2.4.18/
:~$ fakeroot debian/rules binary
[...]
dpkg-shlibdeps: Warnung: 30 andere, ähnliche Warnungen wurden übersprungen (verwenden Sie -v, um alle zu sehen)
   dh_installdeb
   dh_gencontrol
dpkg-gencontrol: Warnung: Feld Depends von Paket apache2-utils: unbekannte Substitutionsvariable ${perl:Depends}
   dh_md5sums
   debian/rules override_dh_builddeb
make[1]: Verzeichnis „/home/vagrant/apache2/apache2-2.4.18“ wird betreten
dh_builddeb -- -Zxz
dpkg-deb: Paket »apache2« wird in »../apache2_2.4.18-2ubuntu3.1_amd64.deb« gebaut.
dpkg-deb: Paket »apache2-data« wird in »../apache2-data_2.4.18-2ubuntu3.1_all.deb« gebaut.
dpkg-deb: Paket »apache2-bin« wird in »../apache2-bin_2.4.18-2ubuntu3.1_amd64.deb« gebaut.
dpkg-deb: Paket »apache2-utils« wird in »../apache2-utils_2.4.18-2ubuntu3.1_amd64.deb« gebaut.
dpkg-deb: Paket »apache2-suexec-pristine« wird in »../apache2-suexec-pristine_2.4.18-2ubuntu3.1_amd64.deb« gebaut.
dpkg-deb: Paket »apache2-suexec-custom« wird in »../apache2-suexec-custom_2.4.18-2ubuntu3.1_amd64.deb« gebaut.
dpkg-deb: Paket »apache2-doc« wird in »../apache2-doc_2.4.18-2ubuntu3.1_all.deb« gebaut.
dpkg-deb: Paket »apache2-dev« wird in »../apache2-dev_2.4.18-2ubuntu3.1_amd64.deb« gebaut.
dpkg-deb: Paket »apache2-dbg« wird in »../apache2-dbg_2.4.18-2ubuntu3.1_amd64.deb« gebaut.
make[1]: Verzeichnis „/home/vagrant/apache2/apache2-2.4.18“ wird verlassen

Das fertig kompilierte Modul befindet sich in dem weiteren Verzeichnisbaum unter

:~/apache2/apache2-2.4.18$ ll -ld debian/apache2-bin/usr/lib/apache2/modules/mod_http2.so
-rw-r--r-- 1 vagrant vagrant 178880 Mär 18 12:39 debian/apache2-bin/usr/lib/apache2/modules/mod_http2.so

:~/apache2/apache2-2.4.18$ file debian/apache2-bin/usr/lib/apache2/modules/mod_http2.so
debian/apache2-bin/usr/lib/apache2/modules/mod_http2.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=da4afcf4eeb02a436ba926ced52740820eb4aa43, stripped

Diese einzelne Modul Datei mod_http2.so auf einen anderen Rechner/Datenträger wegkopieren. Zum weiteren Testen des Moduls eine komplett neue Ubuntu 16.04 Maschine einrichten und apache2 nachinstallieren.

:~# apt-get update
:~# apt-get install apache2

[...]
apache2 (2.4.18-2ubuntu3.1) wird eingerichtet ...

Man beachte die nun installierte Version entspricht der Version vom obigen Download der Sourcen. Die Modul Datei mod_http2.so wird in das entsprechende Modul Verzeichnis des Apache kopiert, die Rechte angepasst, eine Load Datei erstellt und anschließend wird das Modul geladen.

:~# cp mod_http2.so /usr/lib/apache2/modules/
:~# chown root. /usr/lib/apache2/modules/mod_http2.so

:~# vim /etc/apache2/mods-available/http2.load
LoadModule http2_module /usr/lib/apache2/modules/mod_http2.so

:~# a2enmod http2
Enabling module http2.
To activate the new configuration, you need to run:
  service apache2 restart

Ein erster Test zeigt, dass noch die Abhängikeit zu libnghttp2 fehlt. Das Paket wird nachinstalliert und der Test erneut ausgeführt.

:~# source /etc/apache2/envvars
:~# apache2 -M
apache2: Syntax error on line 140 of /etc/apache2/apache2.conf: Syntax error on line 1 of /etc/apache2/mods-enabled/http2.load: Cannot load /usr/lib/apache2/modules/mod_http2.so into server: libnghttp2.so.14: cannot open shared object file: No such file or directory

:~# apt-get install libnghttp2-14
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  libnghttp2-14
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
[...]

:~# source /etc/apache2/envvars
:~# apache2 -M
[...]
 http2_module (shared)
[...]

Die weitere Konfiguration enthält nur exemplarisch das Einschalten von SSL und das Aktivieren des HTTP/2.0 Protokolls.

:~# a2enmod ssl
:~# a2ensite default-ssl

:~# vim /etc/apache2/sites-enabled/default-ssl.conf
[...]
                SSLEngine on
                Protocols h2 http/1.1
[...]

:~# service apache2 restart

Beim Aufruf von https://192.168.202.20/ zeigt sich im Firefox mit eingeschalteten Entwicklertools der Zugriff mit HTTP/2.0

screenshot firefox h2
screenshot firefox HTTP/2.0

und wie aus dem Nginx Artikel bekannt mit der aus Kali Linux zur Verfügung stehenden curl Version.

:~# curl -k -v --http2 https://192.168.202.20/
*   Trying 192.168.202.20...
* TCP_NODELAY set
* Connected to 192.168.202.20 (192.168.202.20) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=devubu
*  start date: Mar 18 11:51:51 2017 GMT
*  expire date: Mar 16 11:51:51 2027 GMT
*  issuer: CN=devubu
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55c1476fdd60)
> GET / HTTP/1.1
> Host: 192.168.202.20
> User-Agent: curl/7.52.1
> Accept: */*
[...]