.. -*- coding: utf-8; mode: rst -*- .. include:: ../apache_setup_refs.txt .. _xref_serverwide_cfg: ================================================================================ Serverweite Konfigurationen ================================================================================ Das Basis Konfiguration umfasst: * Konfiguration der Prozessumgebung der Apache-Serverprozesse. * Konfiguration der *geöffneten* Ports. * Serverweit einheitliche Einstellungen. * Basiseinstellungen zur *Sicherheit* und ein einfaches Zugriffskonzept * Rewrite um ``http`` Requests auf ``https`` (SSL) umzuleiten, so dass nur SSL-Anfragen möglich sind Abschluss bildet ein einfacher Test der vorgenommenen Settings. .. _xref_etc_apache2_envvars: /etc/apache2/envvars ==================== Diese Datei ist ein Shell Skript in dem die Umgebung für :man:`apache2ctl` eingestellt wird, dazu gehören auch die Benutzer- und Gruppenzugehörigkeit des Apache WEB-Server Prozesses. Bei der Installation des :deb:`apache2` Pakets wurde bereits ein Benutzer und eine Gruppe hierfür eingerichtet (``www-data``). .. code-block:: bash export APACHE_RUN_USER=www-data export APACHE_RUN_GROUP=www-data /etc/apache2/ports.conf ======================= In der Konfigration werden die Ports 80 und 443 konfiguriert auf denen der Apache Server *lauschen* soll. .. code-block:: apache Listen 80 Listen 443 .. _xref_apache2_conf: /etc/apache2/apache2.conf ========================= In der Konfiguration wird die `Apache Server-Wide Configuration`_ vorgenommen, dazu gehören beispielsweise ``ServerName``, ``ServerAdmin``, ``DocumentRoot`` (siehe `Apache Core Features`_). .. code-block:: apache ServerName server.example.com ServerAdmin noreply@mailinator.com DocumentRoot /var/www/html Der Benutzer und die Gruppe des Serverprozess werden aus den Umgebungsvariablen bezogen, die zuvor in der `/etc/apache2/envvars`_ eingerichtet wurden. .. code-block:: apache # These need to be set in /etc/apache2/envvars User ${APACHE_RUN_USER} Group ${APACHE_RUN_GROUP} Die ``apache2.conf`` Datei ist die *Hauptdatei* der Apache-Konfiguration, sie lädt alle weiteren Konfigurationen nach (siehe auch `Apache Core Features`_): .. code-block:: apache IncludeOptional mods-enabled/*.load IncludeOptional mods-enabled/*.conf ... Include ports.conf ... IncludeOptional conf-enabled/*.conf IncludeOptional sites-enabled/*.conf .. _xref_conf_security: /etc/apache2/conf-available/security.conf ========================================= Konfiguration zur **Absicherung** des WEB-Servers. Abhänging vom *Anwendungs- und Gefahrenkontext* sind die Anforderungen und Maßnahmen zur Absicherung ganz individuell. Die in dieser Datei vorgenommenen Einstellungen relaiseren das in Abschnitt :ref:`xref_setup_properties` vorgestellte Konzept: * **alles dicht machen** Diese Konfiguration muss ggf. angepasst werden. Erste Orientierung können die `Apache Security Tips`_ geben. Die hier vorzunehmenden Einstellungen sind jedoch nur die Grundlage zur *Absicherung* eines Apache Servers. In Abschnitt :ref:`xref_mod_security2` wird der Aspekt der Sicherheit dann noch etwas tiefer durchdrungen. Die Konfigurationen in dieser ``security.conf`` finden im globalen Kontext statt. Hierzu muss man wissen, dass die Apache Konfigurationen -- die **Direktiven** genannt werden -- entweder auf den gesammten Server (globaler Kontext) oder auf **Sections** angewendet werden können. Die Sections (Kontexte) sind z.B. Ordner, also die Pfadnamen auf **Resourcen** aus dem Dateisystem. Es gibt noch wesentlich mehr Kontexte, siehe `Apache Kontexte (Sections)`_. Um bei dem Beispiel der Ordner eines Dateisystems zu bleiben: Wird beispielsweise ein Ordner im Dateisystem als Resource definiert, so erfolgt dies, indem eine *Directory-Section* (der Kontext) definiert wird. Die Direktieven, die in diesem Kontext gesetzt werden vererben sich auf alle Unterordner in dieser Resource. Die Vererbung erfolgt solange, bis ein Unter-Ordner kommt, für den eine eigene *Directory-Section* definiert wird. Dieser Kontext ist sozusagen ein Unterabschnitt des übergeordneten Ordners / dessen Kontext. Auch in diesem Kontext gelten noch die Direktieven des übergeordneten Kontext, sie können dann aber angepasst werden. So wird beispielsweise mit dem :ref:`xref_deny_from_root` Konzept der Root-Ordner als Kontext eingerichtet der das gesammte Dateisystem einschliesst. Unter dem Root-Ordner befinden sich bekanntlich alle Resourcen, die auf dem Dateisystem (in der Root-Umgebung) existieren, auch die WEB-Anwendungen die man auf dem Host installiert. Durch ein :ref:`xref_deny_from_root` schliesst man somit alle Zugriffe auf die Resourcen aus dem Dateisystem aus. Zur Installation einer WEB-Anwendung gehört, dass neben der Resource im Dateisystem noch ein Kontext im Apache konfiguriertwerden muss. In dem (Unter-) Kontext muss dann der Zugriff entsprechend der WEB-Anwendung eingeräumt werden, indem Vererbtes *überschrieben* und/oder angepasst werden muss. .. _xref_deny_from_root: Deny from root -------------- Das in diesem Setup vorgenommene Sicherheits-Konzept verhindert im globalen Kontext den Zugriff auf das komplette Filesystem (von root an alles). .. code-block:: apache Require all denied Order Deny,Allow Deny from all AllowOverride None Options -ExecCGI -FollowSymLinks -Includes -Indexes DirectoryIndex index.htm index.html Mit ``Deny from all`` im Kontext des root-Ordners (````) wird der Zugriff auf *jede* Resource (jeden Pfad) verweigert. Die Direktive ``Require all denied`` in dem gleichen Kontext verweigert zusätzlich den Zugriff für authentifizierte Benutzer. Das erscheint hier etwas *doppelt gemoppelt*, macht aber Sinn, wenn man an die Vererbung (s.o.) denkt. Mit der `Apache Options Direktive`_ gilt für alle unter root stehenden Ordner: * Es werden keine CGI Programme ausgeführt * Es werden keine symbolischen Links verfolgt. * Die Server Side Includes (SSI) sind deaktiviert * Der *Autoindex* ist abgeschaltet (:ref:`xref_autoindex_directories`) Die oben gezeigten Direktieven *vererben* sich auf jede Resource unterhalb des root-Ordners (also faktisch auf alle Resourcen). Die WEB-Anwendungen (Sites) müssen ihre Resourcen expliziet freigeben, dazu gehört auch das Setzen der Optionen, soweit sie diese benötigen. Weiter unten wird dies beim Einrichten der Sites dann deutlich. .. _xref_security_limits_timeouts: Request & Timeout ----------------- Vorschläge für Requests und Timeouts: .. code-block:: apache LimitRequestBody 13107200 Timeout 300 KeepAlive On MaxKeepAliveRequests 100 KeepAliveTimeout 5 .. hint:: Diese Einstellungen stehen ggf. in Konkurenz mit ModSecurity. Beispielsweise hat die Direktive ``LimitRequestBody`` das Pendant ``SecRequestBodyLimit`` im :ref:`xref_mod_security2` (siehe :ref:`xref_mod_security2_conf`). .. _xref_global_http_headers: HTTP-Headers ------------ In der ``security.conf`` werden auch die im globalen Kontext gültigen HTTP-Header Felder definiert, die dem WEB-Browser übergeben werden. Das *Header* Setup wurde an den Empfehlungen des OwnCloud Projekts angelehnt (*lesenswert* `OwnCloud: Serve security related Headers by the web server`_). Zum Setzen der HTTP-Header ist das `Apache mod_headers`_ Modul erforderlich die Registrierung von Header Feldern erfolgt über die IANA (siehe `Permanent Message Header Field Names (iana)`_). .. code-block:: apache Header always set Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" Header always set X-Frame-Options "SAMEORIGIN" # Header always set X-Robots-Tag "none" Header set X-Content-Type-Options "nosniff" Header set X-XSS-Protection "1; mode=block" Mit dem Feld ``X-Frame-Options: SAMEORIGIN`` wird der Browser angewiesen, die WEB-Seite nicht in einen *fremden* Frame einzubetten. Mit dem Feld ``X-Robots-Tag: none`` können Suchmaschinen angewiesen werden, die *Seiten* nicht zu indizieren. Will man, dass google & Co. den Content indizieren, so sollte man den dieses Feld nicht serverweit, sondern im jeweiligen Kontext setzen. Die :ref:`xref_static_content_chrome` ist ein Beispiel für einen Content, der i.d.R nicht von einem *Robot* indiziert werden soll. .. code-block:: apache ... Header always set X-Robots-Tag "none" ... .. hint:: Die Auswertung der Header-Felder wird von den Browsern implementiert. Nicht alle WEB-Browser haben die gleichen Implementierungen oder finden zur gleichen Bewertung eines Felds. Es steht den Browesern frei ob und wie sie ein Header Feld bewerten. SSL und Rewrite (``http://`` nach ``https://``) =============================================== In der Datei ``/etc/apache2/sites-available/000-default.conf`` wird der ```` eingerichtet. Sofern ``mod_ssl`` installiert ist, werden noch die Redirects nach ``https://`` konfiguriert (siehe `Apache mod_rewrite`_). .. code-block:: apache RewriteEngine on RewriteRule ^/(.*)$ https://%{SERVER_NAME}/$1 [L,R] ... In der Datei ``/etc/apache2/sites-available/default-ssl.conf`` wird der Security Layer (SSL) auf port 443 aktiviert und der Log-Level eingestellt: .. code-block:: apache LogLevel info ssl:warn CustomLog ${APACHE_LOG_DIR}/access.log combined ... SSLEngine on ... SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key ... In diesem Setup werden die selbst-signierten (*snakeoil*) Zertifikate verwendet (siehe auch :ref:`xref_ssl_ca_remarks`). .. _xref_mod_authnz_external: /etc/apache2/conf-available/authnz_external.conf ================================================ Mit dem :deb:`libapache2-mod-authnz-external` Paket wurde das `Apache mod_authnz_external`_ Modul installiert. Mit diesem Modul kann die Benutzerauthentifizierung an ein externes Tool wie `pwauth (github)`_ durchgereicht werden. In der Standard Installation des :deb:`libapache2-mod-authnz-external` Pakets ist dass Kommando :man:`pwauth` vorgesehen, das auch in diesem Setup verwendet wird. In der ``authnz_external.conf`` werden die folgenden Direktiven gesetzt. .. code-block:: apache AddExternalAuth pwauth /usr/sbin/pwauth SetExternalAuthMethod pwauth pipe Das Tool `pwauth (github)`_ verwendet zur Autorisierung die Benutzer Logins und Passwörter des Systems (PAM). Zu dem pwauth gehört noch ein PAM Setup ``/etc/pam.d/pwauth``:: auth requisite pam_nologin.so # Standard Un*x authentication. @include common-auth # Standard Un*x account @include common-account Will eine *Site* dieses Verfahren zur Authentifizierung nutzen, so kann sie dies durch das Setzen der folgenden Direktiven. .. code-block:: apache AuthType Basic AuthBasicProvider external AuthName "myAuthDomain Top Secret" AuthExternal pwauth Mit der `Apache AuthName Direktive`_ wird die Resource einem Bereich zugeordnet. Der Bezeichner des Bereichs (*realm*) wird an den WEB-Client gegeben und dort im Anmeldedialog angezeigt, damit der Benutzer, das für diesen Bereich richtige Passwort eingeben kann. .. todo:: Die Authentifizierung über `pwauth (github)`_ und ``authnz_external`` ist zwar ganz praktisch, aber damit ist nur eine *Basic* `HTTP-Authentifizierung (wiki)`_ möglich. Es sollte nochmal ein alternative Konzept vorgestellt werden (Schlagworte LDAP, mod_authn_file or mod_authn_dbm). .. _xref_start_your_engines: Gentleman, start your engines! ============================== Nachdem Änderungen an der Konfiguration vorgenommen wurden, müssen diese in den Apache-Server geladen werden. Bei so substantiellen Änderungen wie sie hier vorgenommen wurden, sollte man satt nur den *Reload* zu machen besser einen *Restart* vornehmen (s.a. :man:`apachectl`). .. code-block:: bash sudo -H a2ensite 000-default.conf default-ssl.conf sudo -H a2enconf security authnz_external sudo -H service apache2 restart # bei kleineren Änderungen reicht ein Reload sudo -H service apache2 reload Zum Testen des Redirects kann auf der Komandozeile das :man:`curl` Kommando genutzt werden. Das ``curl`` Kommando eignet sich eigentlich zum Download von Dateien von einem Server. Wenn man es auf *verbose* schaltet, dann kann man sehr schön sehen, was Client (in dem Fall ``curl``) und Server (in dem Fall der Apache-Prozess) so an HTTP Informationen austauschen und wie die ganze Kommunikation aufgebaut wird. Folgende Optionen des ``curl`` werden verwendent: * ``--verbose`` *gesprächige* Ausgabe * ``--location`` folge Redirects * ``--head`` tausche nur die HTTP-Header aus, der Content wird ignoriert * ``--insecure`` keine Validierung von Zertifikaten Der unten stehende Auszug zeigt, wie ``curl`` erst mal via ``http://`` auf Port 80 anfragt (Anfragen habe ein ``>`` als Präfix), dann aber ein ``HTTP 302`` Response vom Server erhält (Einkommendes hat das Präfix ``<``). Der ``302`` Response verweist auf die ``https://`` *Location*. .. code-block:: none $ curl --location --verbose --head --insecure http://localhost 2>&1 * Rebuilt URL to: http://ubuntu1504/ * Trying fd00::a00:27ff:fed5:7c85... * Connected to ubuntu1504 (fd00::a00:27ff:fed5:7c85) port 80 (#0) > HEAD / HTTP/1.1 > Host: ubuntu1504 > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 302 Found < Date: Thu, 11 Feb 2016 14:08:50 GMT < Server: Apache < Strict-Transport-Security: max-age=15768000; includeSubDomains; preload < X-Frame-Options: SAMEORIGIN < Location: https://ubuntu1504/ < Content-Type: text/html; charset=iso-8859-1 ... Der obige Auszug zeigt auch, dass eine Verbindung über IPv6 hergestellt wurde. Der Hostname ``ubuntu1504`` wurde vom DNS (hier nicht zu sehen, dass passiert eine Ebene tiefer in der IP Schicht) in die IPv6 *Unique Local* Adresse ``fd00::a00:27ff:fed5:7c85`` aufgelößt. Diese IPv6 Adresse wird später bei der Maskierung von Netzwerkadressen relevant werden, wenn Sites auf Basis der Host IP autorisieren (s.a. :ref:`xref_excursion_IPv4_6`). Weiter unten in der Ausgabe von ``curl`` ist dann auch zu sehen, wie ``curl`` auf die ``https://`` *Location* wechselt und seine Anfrage (Request) auf Port 443 wiederholt (``Issue another request ...``). .. code-block:: none ... * Connection #0 to host ubuntu1504 left intact * Issue another request to this URL: 'https://ubuntu1504/' * Found bundle for host ubuntu1504: 0x55c61d8a92a0 * Trying fd00::a00:27ff:fed5:7c85... * Connected to ubuntu1504 (fd00::a00:27ff:fed5:7c85) port 443 (#1) ... **CHECK: Redirect --> OK!** Im weiteren Auszug (unten) ist auch zu sehen, dass TLS1.2 für die Verschlüsselung gewählt wird. Man sieht auch, dass das selbstsignierte Zertifikat, das der Server dem Client gegeben hat und das oben über die Direktive: .. code-block:: apache SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem gesetzt wurde, nicht verifiziert wurde, Option ``--insecure``. Bei dieser Option *SKIPPED* das ``curl`` die Verfikation über einen CA (s.a. Abschnitt :ref:`xref_ssl_ca_remarks`). Desweiteren folgen dann noch Angaben zu dem Zertifikat, z.B. das der *CommonName* lediglich aus dem Hostnamen besteht, dass das Zertifikat noch gültig ist und das es einen öffentlichen RSA Schlüssel besitzt. .. code-block:: none ... * found 187 certificates in /etc/ssl/certs/ca-certificates.crt * found 755 certificates in /etc/ssl/certs * ALPN, offering http/1.1 * SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256 * server certificate verification SKIPPED * server certificate status verification SKIPPED * common name: ubuntu1504 (matched) * server certificate expiration date OK * server certificate activation date OK * certificate public key: RSA * certificate version: #3 * subject: CN=ubuntu1504 * start date: Thu, 11 Feb 2016 14:04:03 GMT * expire date: Sun, 08 Feb 2026 14:04:03 GMT * issuer: CN=ubuntu1504 * compression: NULL * ALPN, server did not agree to a protocol ... **CHECK: DSSL Setup --> OK!** Nach den Angaben zur Verschlüsselung und dem Zertifikat ist dann im Weiteren zu sehen, wie der HTTP-Request aussieht, den ``curl`` nun abschickt (wieder an dem ``>`` zu erkennen). .. code-block:: none ... > HEAD / HTTP/1.1 > Host: ubuntu1504 > User-Agent: curl/7.43.0 > Accept: */*scurl ... Am Ende sieht man dann auch die Antwort (den Response) vom Server. .. code-block:: none ... < HTTP/1.1 403 Forbidden < Date: Thu, 11 Feb 2016 14:08:50 GMT < Server: Apache < Strict-Transport-Security: max-age=15768000; includeSubDomains; preload < X-Frame-Options: SAMEORIGIN < Content-Type: text/html; charset=iso-8859-1 ... Der Server meldet dem Client, dass der Zugriff auf die URL ``https://ubuntu1504/`` nicht gestattet ist. Das entspricht dem :ref:`xref_deny_from_root` Konzept von oben. Erst wenn eine Site eingerichtet wird und diese dann Resource frei gibt, kann ein Client auf diese zugreifen. **CHECK: deny from root ... OK!** An der Antwort des Servers (``<``) ist auch zu sehen, das die HTTP-Header-Felder ``Strict-Transport-Security`` und ``X-Frame-Options`` aus dem globalen Kontext (vergleiche :ref:`xref_global_http_headers`) gesetzt wurden. **CHECK: HTTP Header ... OK!** Wie das Beispiel zeigt, ist es mit einfachen Werkzeug wie ``curl`` bereits möglich einiges zu testen und über die Komunikation zw. Client und Server zu erfahren. Zumindest so viel, dass es ausreicht alle in diesem Abschnitt vorgenommen Einstellungen grob zu überprüfen. Oder anders formuliert, es sind nicht immer die ganz großen Werkzeuge erforderlich, das Nötigste liegt den meisten System schon anbei.