Loseblatt-Sammlung

Dokumentation: Apache2 SSL-Konfiguration & Server-Härtung

1. Problem: ERR_SSL_PROTOCOL_ERROR / SSL_ERROR_RX_RECORD_TOO_LONG

Symptom: Beim Aufruf des Servers über HTTPS brach die Verbindung mit einem Protokollfehler ab. Ursache:

  1. Das selbstsignierte Zertifikat wurde ohne Subject Alternative Name (SAN) generiert. Moderne Browser erzwingen diesen Eintrag für IP-Adressen und ignorieren den alten Common Name (CN).
  2. Die Konfigurationsdatei default-ssl.conf war in Apache zwar bearbeitet, aber nicht aktiv geschaltet (sites-enabled). Dadurch lieferte Apache auf Port 443 unverschlüsselten HTTP-Klartext statt eines SSL-Handshakes aus.

2. Diagnose-Werkzeuge

Für die Fehlersuche bei VirtualHosts und Ports ist dieser Befehl der wichtigste Indikator:

sudo apache2ctl -S

Er zeigt die exakte Ladereihenfolge und Port-Zuweisung aller aktiven VirtualHosts an.


3. Lösung: Zertifikat mit SAN neu erstellen

Erstellung des selbstsignierten Zertifikats inklusive der zwingend erforderlichen IP-Deklaration im SAN-Block:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/apache-selfsigned.key \
  -out /etc/ssl/certs/apache-selfsigned.crt \
  -subj "/CN=5.45.104.139" \
  -addext "subjectAltName = IP:5.45.104.139"

4. Einrichtung des "Lumpensammlers" (Fallback VirtualHost)

Um unbefugte IP-Aufrufe oder unbekannte Domains ressourcenschonend abzufangen, wird die default-ssl.conf als erster VHost (alphabetisch priorisiert via 000-default-ssl.conf) geladen. Statt Daten auszuliefern, bricht sie die Verbindung sofort mit einem nackten 403 Forbidden ab.

Datei: /etc/apache2/sites-available/default-ssl.conf

<VirtualHost *:443>
    # Kein ServerName -> Greift als globaler Fallback

    DocumentRoot /var/www/html/nix

    SSLEngine on
    SSLCertificateFile      /etc/ssl/certs/apache-selfsigned.crt
    SSLCertificateKeyFile   /etc/ssl/private/apache-selfsigned.key

    # TLS-Protokolle: Nur moderne Standards erlauben
    SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1

    # Sichere Cipher-Suite (inklusive AES128)
    SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384

    SSLHonorCipherOrder     on
    SSLCompression          off

    # Sofortiger Abbruch mit HTTP 403 (Ressourcenschonend gegen Bot-Grundrauschen)
    Redirect 403 /
    ErrorDocument 403 "Forbidden"

    <Directory /var/www/html/nix>
        AllowOverride None
        Require all denied
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/ssl_fallback_error.log
    CustomLog ${APACHE_LOG_DIR}/ssl_fallback_access.log combined
</VirtualHost>

Konfiguration aktivieren:

sudo a2ensite default-ssl.conf
# Optional: Verknüpfung als 000-default-ssl erzwingen für Ladepriorität
sudo ln -sf /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-enabled/000-default-ssl.conf
sudo apache2ctl -t
sudo systemctl restart apache2

5. Globale Server-Härtung (Sicherheit)

Um potenziellen Angreifern keine Details über das Betriebssystem oder die Apache-Version zu verraten, werden die Header global minimiert.

Datei: /etc/apache2/conf-available/security.conf

# Nur noch "Server: Apache" im Header senden (keine Versionsnummern)
ServerTokens Prod

# Fußzeilen auf generierten Fehlerseiten ausblenden
ServerSignature Off

Aktivierung:

sudo a2enconf security
sudo systemctl reload apache2

6. Überprüfung des Setups

Ein Test via curl gegen die IP-Adresse muss aufgrund des selbstsignierten Zertifikats fehlschlagen (Sicherheitsfeature). Mit dem Parameter -k (insecure) lässt sich das Ergebnis verifizieren:

curl -Ik https://5.45.104.139

Erwartete Ausgabe:

HTTP/1.1 403 Forbidden
Server: Apache
Content-Type: text/html; charset=iso-8859-1
...

(Das Ergebnis zeigt: Der Server maskiert sich als reines "Apache" und blockiert den IP-Aufruf sofort mit einem minimalen 403-Header, ohne Festplatten- oder CPU-Last zu erzeugen).