Webserver mit Apache: Difference between revisions
No edit summary |
|||
(59 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
Einer der häufigsten genutzten Webserver ist [https://httpd.apache.org Apache]. Abgesehen davon, dass man bereits mit der Standardkonfiguration relativ schnell zu einer einfachen Website kommt, bringt er den Vorteil, dass viele Module bereits eingebunden oder schnell nachzuinstallieren sind (z.B. libapache2.php). Zudem werden regelmäßig Updates gegen mögliche Exploits auf diesen weit verbreiteten Webdienst geliefert, also Versionsstand aktuell halten! |
|||
Zum Entstehungszeitpunkt dieses Dokuments war die aktuellste Version der apache2. Wir verlassen uns aber nicht auf diese Aussage, sondern prüfen den Versionsstand selbst nach mit |
Zum Entstehungszeitpunkt dieses Dokuments war die aktuellste Version der apache2. Wir verlassen uns aber nicht auf diese Aussage, sondern prüfen den Versionsstand selbst nach mit |
||
# |
# apt search apache |
||
Danach installieren wir die aktuellste Version: |
Danach installieren wir die aktuellste Version: |
||
# |
# apt install apache2 |
||
Nach der Installation läuft der Dienst auch schon. Überprüfung mit |
Nach der Installation läuft der Dienst auch schon. Überprüfung mit |
||
# service apache2 status |
|||
# ps auxw | grep apache |
|||
==Konfigurationsdateien== |
==Konfigurationsdateien== |
||
Diese befinden sich im Verzeichnis /etc/apache2. Die wichtigste Datei ist die apache2.conf. Diese verweist auf weitere Dateien und Unterverzeichnisse. |
Diese befinden sich im Verzeichnis /etc/apache2. Die wichtigste Datei ist die apache2.conf. Diese verweist auf weitere Dateien und Unterverzeichnisse. <br> |
||
In einem Standard /etc/apache2-Verzeichnis wird man folgende Dateien und Ordner vorfinden: |
|||
<i> |
|||
apache2.conf <br> |
|||
conf-enabled <br> |
|||
magic <br> |
|||
mods-enabled <br> |
|||
sites-available <br> |
|||
conf-available <br> |
|||
envvars <br> |
|||
mods-available <br> |
|||
ports.conf <br> |
|||
sites-enabled |
|||
</i> |
|||
Dies ist die Verzeichnisstruktur für Debian. Andere Distributionen können sich anders verhalten, z.B. werden unter CentOS keine sites-available/sites-enabled verwendet. |
|||
Wie gesagt, handelt es sich bei der ''apache2.conf'' um die Hauptkonfigurationsdatei. Diese nur mit Vorsicht anfassen, weil Gefahr besteht, dass die Änderungen mit dem nächsten Update überschrieben werden. |
|||
Die eigentliche Konfigurationsdateien befinden sich in ''sites-available'' bzw. ''conf-available''. Meistens wird ''sites-available'' für Virtualhosts (s.u.) benützt und ''conf-available'' für Konfig, die für bestimmte Services gelten soll. Hier speichern i.d.R. auch webservice-related Software-Pakete ihre Konfig (z.B. Nagios oder Mediawiki). |
|||
Die Dateien, die hier abgelegt werden, sind aber noch nicht aktiv. Dies passiert per Symlink in den Verzeichnissen ''conf-enabled'' und ''sites-enabled''. '''Darauf achten, dass die Symlinks immer mit .conf enden !''' |
|||
== Module == |
|||
Module sind kleine Codestücke oder Konfigschnipsel, die die Funktionalität des Webservers erweitern. Es gibt z.B. welche für andere Scriptsprachen (php, cgi), für Verschlüsselung, Authentifizierung u.v.m. |
|||
Im Verzeichnis ''mods-available'' sind bereits einige Standardmodule abgelegt. Diese lassen sich durch einen Symlink im ''mods-enabled'' Verzeichnis aktivieren oder durch das a2enmod Kommando, z.B. |
|||
# a2enmod ssl |
|||
==Wohin mit den Webseiten== |
==Wohin mit den Webseiten== |
||
Der Standardordner für Webseiten ist das Verzeichnis /var/www/. Wer weitere/andere Verzeichnisse festlegen will, kann das in der Datei sites-available/ |
Der Standardordner für Webseiten ist das Verzeichnis /var/www/. Wer weitere/andere Verzeichnisse festlegen will, kann das in der Datei sites-available/<filename> im Abschnitt '''DocumentRoot''' tun. |
||
Wir wollen in unserem Fall die Standardwebseite im Verzeichnis /var/www haben. Zu diesem Zweck ändern wir in der Datei sites-available/default den Eintrag |
|||
Falls der Index nicht automatisch geladen werden sollte, lässt sich das mittels Option "DirectoryIndex" bewirken, z.B. |
|||
RedirectMatch ^/$ /apache2-default/ |
|||
DirectoryIndex index.php |
|||
in |
|||
oder |
|||
RedirectMatch ^/$ /index.html |
|||
DirectoryIndex index.html |
|||
(setzt natürlich voraus, dass mit einer Datei index.html begonnen wird) |
|||
Neustart des Apache nach Konfigurationsänderungen erfolgt mittels |
Neustart des Apache nach Konfigurationsänderungen erfolgt mittels |
||
# |
# systemctl reload apache2 |
||
==Virtual Hosting== |
==Virtual Hosting== |
||
Mal angenommen, ihr entschließt euch, mehrere Domains auf einem Webserver zu hosten. Dafür gibt es die Virtual-Host-Einträge in der Datei sites-available/ |
Mal angenommen, ihr entschließt euch, mehrere Domains auf einem Webserver zu hosten. Dafür gibt es die Virtual-Host-Einträge in der Datei sites-available/<domain>.conf (Im Grunde kann die Datei heißen wie sie will, aber der Übersicht halber wird man domainnamen vergeben). In unserem Fall wollen wir 2 Domains hosten, example.de unter /var/www/example und nomorebluescreen.com unter /var/www/nmbs. Zu diesem Zweck werden unter /etc/apache2/sites-available 2 Dateien angelegt, z.B. example.conf und nmbs.conf. |
||
1. Datei: |
|||
NameVirtualHost * |
|||
<VirtualHost *> |
|||
<VirtualHost *:80> |
|||
ServerName www.example.de |
ServerName www.example.de |
||
ServerAlias ... |
|||
Dann wird der ganze Abschnitt kopiert und der ServerName-Eintrag für die 2. Domain angepasst: |
|||
ServerAdmin webmaster@example.de |
|||
NameVirtualHost * |
|||
(...) |
|||
<VirtualHost *> |
|||
</VirtualHost> |
|||
2. Datei: |
|||
<VirtualHost *:80> |
|||
ServerName www.nomorebluescreen.com |
ServerName www.nomorebluescreen.com |
||
(...) |
|||
</Virtual Host> |
</Virtual Host> |
||
Sollte es für eine Domain einen IP-Eintrag, aber noch keine config-Datei geben, wird beim Aufruf der Seite per default die Domain genommen, die im Alphabet als 1. kommt.<br> |
|||
Um die Änderung wirksam zu machen, müssen diese Seiten noch nach sites-enabled verlinkt sein. Hierbei darauf achten, dass die Dateiendung .conf ist, sonst wird die Datei ignoriert. |
|||
Die entsprechenden Namen müssen natürlich im DNS (oder zu Testzwecken auch in der /etc/hosts) hinterlegt sein! |
Die entsprechenden Namen müssen natürlich im DNS (oder zu Testzwecken auch in der /etc/hosts) hinterlegt sein! |
||
Line 46: | Line 81: | ||
==Logfiles== |
==Logfiles== |
||
Diese befinden sich im Verzeichnis /var/log/apache2 |
Diese befinden sich im Verzeichnis /var/log/apache2 |
||
Mit der Direktive |
|||
CustomLog |
|||
bzw. |
|||
ErrorLog |
|||
in der entsprechenden Konfigdatei kann (auch für VirtualHosts getrennt) der Pfad zur Logdatei angegeben werden. |
|||
Es gibt die Möglichkeit, die geloggten Parameter selbst zu definieren: https://httpd.apache.org/docs/2.4/logs.html#accesslog |
|||
Hier ein paar Beispiele, wie man in den Logfiles suchen kann: |
|||
<pre> |
|||
request per hour |
|||
cat access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":00"}' | sort -n | uniq -c |
|||
request per hour by date |
|||
grep "23/Jan" access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":00"}' | sort -n | uniq -c |
|||
request per hour by IP |
|||
grep "XX.XX.XX.XX" access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":00"}' | sort -n | uniq -c |
|||
requests per minute: |
|||
cat access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":"$3}' | sort -nk1 -nk2 | uniq -c |
|||
requests per minute for date: |
|||
grep "02/Nov/2017" access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":"$3}' | sort -nk1 -nk2 | uniq -c |
|||
requests per minute for url: |
|||
grep "[url]" access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":"$3}' | sort -nk1 -nk2 | uniq -c |
|||
per IP per minute |
|||
grep "XX.XX.XX.XX" access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":"$3}' | sort -nk1 -nk2 | uniq -c |
|||
</pre> |
|||
s.a. http://www.inmotionhosting.com/support/website/server-usage/view-level-of-traffic-with-apache-access-log |
|||
==php einbinden== |
==php einbinden== |
||
Dies ist zumindest unter Debian sehr trivial, weil nur das Paket php installiert werden muss. |
Dies ist zumindest unter Debian sehr trivial, weil nur das Paket php und das entsprechende Modul installiert werden muss. |
||
Mit |
Mit |
||
# aptitude search php |
# aptitude search php |
||
informieren wir uns über die aktuelle Version. |
informieren wir uns über die aktuelle Version. Mit "aptitude install php<version>" wird diese installiert. |
||
Um den apache php-fähig zu bekommen, muss außerdem das php-Modul installiert werden (wird u.U. schon bei der apache-Installation mitgeliefert): |
|||
# aptitude install libapache2-mod-php |
|||
Kontrollieren, ob das Modul bereits geladen ist: |
|||
# ls /etc/apache2/mods-enabled/|grep php |
|||
Hier sollte (je nach Version) zu sehen sein: |
|||
php7.0.conf |
|||
php7.0.load |
|||
Wenn nicht, gibt es den Befehl '''a2enmod''', um Module zu installieren: |
|||
# a2enmod php7 |
|||
Der Neustart des apache wird während der php-Installation übernommen. |
|||
Eine bessere Alternative ist das modernere '''php-fpm'''. Auch dieses kann als Paket installiert werden. |
|||
Achtung: php-fpm muss für jede Version extra aktiviert werden, e.g.: |
|||
# a2enconf php8.2-fpm |
|||
Danach muss der Webserver neu gestratet werden. |
|||
Hier ein Beispiel für ein schlichtes Testscript: |
Hier ein Beispiel für ein schlichtes Testscript: |
||
<?php |
<?php |
||
Line 59: | Line 152: | ||
Bei Ausführung desselben ist im Browser folgende Auflistung zu sehen |
Bei Ausführung desselben ist im Browser folgende Auflistung zu sehen |
||
[[ |
[[File:Phpinfo2.jpeg|500px|center|phpinfo]] |
||
== Directory Listing erlauben == |
== Directory Listing erlauben == |
||
Line 92: | Line 185: | ||
htpasswd -c <dateiname> <username> |
htpasswd -c <dateiname> <username> |
||
Dann erfolgt eine Eingabeaufforderung für das Passwort. Vorhandene User in einer htpasswd ändert man durch Weglassen der Option -c |
Dann erfolgt eine Eingabeaufforderung für das Passwort. Vorhandene User in einer htpasswd ändert man durch Weglassen der Option -c |
||
Weitere nützliche Optionen: |
|||
<pre> |
|||
$ htpasswd -n <username> |
|||
</pre> |
|||
(erzeugt nur eine Ausgabe, die man irgendwohin pasten kann) |
|||
<pre> |
|||
$ htpasswd -B .htpasswd <username> |
|||
</pre> |
|||
Use bcrypt instead of md5. Sicherer Algorithmus. |
|||
Die .htaccess schützt automatisch auch alle Unterverzeichnisse durch ein Passwort. Wenn man das nicht will, muss man in seiner Config für jedes der Verzeichnisse eine Ausnahme generieren, z.B. |
Die .htaccess schützt automatisch auch alle Unterverzeichnisse durch ein Passwort. Wenn man das nicht will, muss man in seiner Config für jedes der Verzeichnisse eine Ausnahme generieren, z.B. |
||
Line 98: | Line 201: | ||
Satisfy any |
Satisfy any |
||
</DirectoryMatch> |
</DirectoryMatch> |
||
=== DOS Attacken === |
|||
Zum Abwehren von (D)DOS-Attacken gibt es das Modul '''mod-evasive'''. |
|||
Das zugehörige Paket heißt '''libapache2-mod-evasive'''.<br> |
|||
Protipp: Die Parameter ''DOSPageCount'' und ''DOSSiteCount'' nicht zu niedrig wählen, sonst blockt man möglicherweise auch normale Webrequests. |
|||
Configbeispiel:<br> |
|||
https://github.com/kdx99/apache-role/blob/main/vars/main.yaml<br> |
|||
(Abschnitt # mod_evasive) |
|||
Weiteres hier: <br> |
|||
* https://phoenixnap.com/kb/apache-mod-evasive |
|||
* https://www.howtogeek.com/devops/how-to-configure-mod_evasive-for-apache-ddos-protection/ |
|||
=== Fail2ban === |
=== Fail2ban === |
||
Zum Ausbremsen von Brute-Force-Angriffen hilft fail2ban, ein Tool, das zu häufige Fehlversuche beim Anmelden mit einer IP-Tables-Regel auf die zugehörige Source IP quittiert. |
Zum Ausbremsen von Brute-Force-Angriffen hilft fail2ban, ein Tool, das zu häufige Fehlversuche beim Anmelden mit einer IP-Tables-Regel auf die zugehörige Source IP quittiert. |
||
==== Beispiel ==== |
|||
Erstmal das Paket „fail2ban" installieren, dann ins Verzeichnis /etc/fail2ban wechseln. |
Erstmal das Paket „fail2ban" installieren, dann ins Verzeichnis /etc/fail2ban wechseln. |
||
Line 110: | Line 227: | ||
loglevel = 4 # default=3 |
loglevel = 4 # default=3 |
||
Achtung: nach dem Debuggen wieder auf default (=3) setzen. Die Logfiles werden sonst sehr schnell sehr groß!<br> |
Achtung: nach dem Debuggen wieder auf default (=3) setzen. Die Logfiles werden sonst sehr schnell sehr groß!<br> |
||
Nun kann man in der ''jail.conf'' die unterschiedlichen jails für die |
Nun kann man in der ''jail.conf'' die unterschiedlichen jails für die einzelnen Dienste einrichten. Für mache gibt es auch Subsections, z.B. für apache: |
||
[apache] |
[apache-auth] |
||
enabled = true |
enabled = true |
||
port = http,https |
port = http,https |
||
filter = apache-auth |
filter = apache-auth |
||
logpath = |
logpath = %(apache_error_log)s |
||
maxretry = 10 |
maxretry = 10 |
||
bantime = |
bantime = 5m |
||
Bei den allgemeinen Optionen kann man Excludes für einzelne IPs oder Netze angeben |
Bei den allgemeinen Optionen kann man Excludes für einzelne IPs oder Netze angeben |
||
ignoreip = 127.0.0.1/8 192.168.99.0/24 |
ignoreip = 127.0.0.1/8 192.168.99.0/24 |
||
Achtung: Als Trenner ein Space benutzen. Kommas o.ä. werden zwar akzeptiert, danach funktioniert aber die Banaction nicht. |
Achtung: Als Trenner ein Space benutzen. Kommas o.ä. werden zwar akzeptiert, danach funktioniert aber die Banaction nicht. |
||
Bei „banaction“ sollte im allgemeinen Teil „iptables-multiport" eingestellt sein. Dienst neu starten, fertig. |
Bei „banaction“ sollte im allgemeinen Teil „iptables-multiport" oder "nftables-multiport" eingestellt sein. Dienst neu starten, fertig. |
||
<u>Erfolgskontrolle</u><br> |
<u>Erfolgskontrolle</u><br> |
||
n- mal falsch anmelden und „iptables -L -n -v“ ausführen (zum testen evtl. eine etwas kürzere bantime wählen) |
n- mal falsch anmelden und „iptables -L -n -v“ ausführen (zum testen evtl. eine etwas kürzere bantime wählen) |
||
Anmerkung: Seit bullseye ist per Default nicht mehr iptables, sondern nftables am Start. fail2ban schert sich da wenig drum, versucht iptables-Regeln zu generieren und wirft einen Fehler.<br> |
|||
<u>Debugging</u><br> |
|||
Abhilfe: In der jail.conf alles, was mit ''iptables-'' zu tun hat, durch ''nftables-'' ersetzen, e.g. nftables-multiport, nftables-allports, nftables-multiport-log |
|||
Nach n Fehlversuchen, folgendes Kommando absetzen: |
|||
<pre> |
|||
# nft list table inet f2b-table |
|||
</pre> |
|||
==== Debugging ==== |
|||
Bei Problemen kann man den Dienst auch im Vordergrund starten: |
Bei Problemen kann man den Dienst auch im Vordergrund starten: |
||
# fail2ban-server -f |
# fail2ban-server -f |
||
Line 137: | Line 262: | ||
===Verschlüsselte Webseiten=== |
===Verschlüsselte Webseiten=== |
||
Feind hört mit (Gerüchten zufolge zuweilen auch Freund). Also am besten nichts im Klartext übers Netz schicken. Verschlüsselt wird bei apache üblicherweise mit TLS, die Echtheit (Authentizität) der Webseite wird durch ein Zertifikat überprüft. |
Feind hört mit (Gerüchten zufolge zuweilen auch Freund). Also am besten nichts im Klartext übers Netz schicken. Verschlüsselt wird bei apache üblicherweise mit TLS, die Echtheit (Authentizität) der Webseite wird durch ein Zertifikat überprüft. |
||
Wer geschäftlich eine Seite (Webshop o.ä.) betreibt, wird sein Zertifikat höchstwahrscheinlich durch eine offizielle Zertifizierungsstelle (Certificate Authority) signieren lassen |
Wer geschäftlich eine Seite (Webshop o.ä.) betreibt, wird sein Zertifikat höchstwahrscheinlich durch eine offizielle Zertifizierungsstelle (Certificate Authority) signieren lassen. Privatanwender signieren u.U. selbst (nicht empfohlen). |
||
==== Alternative Zertifikat selbst erzeugen ==== |
|||
Von dieser Möglichkeit wird abgeraten, da es hier keine offizielle CA für das Zertifikat gibt, d.h. die Clients wissen nicht, ob die Website vertrauenswürdig ist. Hässliche Warnings sind die Folge bzw. im worst case wird die Seite gar nicht ausgeliefert. Besser eine offizielle CA verwenden (2 Alternativen gibt es weiter unten). |
|||
Schritte von der Zertifikatserstellung zur verschlüsselten Webseite: |
Schritte von der Zertifikatserstellung zur verschlüsselten Webseite: |
||
Line 157: | Line 285: | ||
4. Überprüfen des Zertifikats: |
4. Überprüfen des Zertifikats: |
||
openssl x509 -in www.example.de.crt -text -noout |
openssl x509 -in www.example.de.crt -text -noout |
||
5. Apache konfigurieren<br> |
|||
Alternativ bietet sich das im Paket openssl enthaltene Tool '''CA.pl''' an (hier nicht weiter ausgeführt, da ungetestet). |
|||
5.1. mod_ssl aktivieren |
|||
==== Konfguration des Webservers ==== |
|||
Die folgende Schritte sind wieder identisch, unabhängig davon, wie das Zertifikat erzeugt wurde. |
|||
1. mod_ssl aktivieren |
|||
cd /etc/apache2/sites-enabled/ |
cd /etc/apache2/sites-enabled/ |
||
ln -s ../mods-available/ssl.conf |
ln -s ../mods-available/ssl.conf |
||
ln -s ../mods-available/ssl.load |
ln -s ../mods-available/ssl.load |
||
5.2. Virtual-Host auf Port 443 einrichten<br> |
|||
2. Virtual-Host auf Port 443 einrichten<br> |
|||
<VirtualHost *:443> |
<VirtualHost *:443> |
||
ServerAdmin webmaster@example.de |
ServerAdmin webmaster@example.de |
||
Line 170: | Line 304: | ||
SSLCertificateFile /etc/apache2/ssl/www.example.de.crt |
SSLCertificateFile /etc/apache2/ssl/www.example.de.crt |
||
SSLCertificateKeyFile /etc/apache2/ssl/www.example.de.key |
SSLCertificateKeyFile /etc/apache2/ssl/www.example.de.key |
||
SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 |
|||
SSLCipherSuite \ EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH |
|||
</VirtualHost> |
</VirtualHost> |
||
5.3. Redirects<br> |
|||
Letztere Parameter lassen nur sichere Protokolle (TLS>=2) und Cipher-Suites mit starker Verschlüsselung zu.<br> |
|||
Ein Beispiel für geeignete Cipher-Suites gibt es auf https://cipherlist.eu/. |
|||
3. Redirects<br> |
|||
Wer es nicht dem Zufall überlassen will, ob der Benutzer im Browser http:// oder https:// eingibt, kann eine automatische Weiterleitung zur verschlüsselten Seite einrichten: |
Wer es nicht dem Zufall überlassen will, ob der Benutzer im Browser http:// oder https:// eingibt, kann eine automatische Weiterleitung zur verschlüsselten Seite einrichten: |
||
a2enmod rewrite |
a2enmod rewrite |
||
Line 181: | Line 321: | ||
RewriteRule ^/?download(.*) https://%{SERVER_NAME}/download/$1 [R,L] |
RewriteRule ^/?download(.*) https://%{SERVER_NAME}/download/$1 [R,L] |
||
==== |
=====Error===== |
||
Wer eine gratis-CA nutzen, will, um zu einem öffentlich signierten Zertifikat zu kommen, kann sich über http://startssl.com registrieren. Hier sind keine openssl-Commands nötig, man klickt sich seine Zertifikate zusammen, pastet sie in Textdateien und fügt sie wie gehabt in seine apache-Config ein. |
|||
Sollten beim Erneuern Fehlermeldungen auftauchen aka |
|||
Achtung: Damit das Ganze funktioniert, muss man sich hier ein Zwischenzertifikat (intermediate certificate) herunterladen und seine apache-Config durch folgende Anweisung erweitern: |
|||
<console> |
|||
SSLCertificateChainFile /etc/apache2/ssl/sub.class1.server.ca.pem |
|||
An unexpected error occurred: |
|||
OpenSSL.SSL.Error: [('x509 certificate routines', 'X509_load_cert_crl_file', 'no certificate or crl found')] |
|||
Please see the logfiles in /var/log/letsencrypt for more details. |
|||
</console> |
|||
gibt es ein Problem mit den default ca-certificates. In dem Fall hilft ein: |
|||
<console> |
|||
># update-ca-certificates |
|||
</console> |
|||
====Alternative [https://letsencrypt.com/ letsencrypt]==== |
|||
Hier sind keine openssl-Commands nötig. Man verwendet als Root CA letsencrypt. Geholt werden die Zertifikate über einen sogenannten „certbot“, der einmalig eingerichtet wird und dann als Cron weiterläuft. |
|||
# apt install python3-certbot-apache |
|||
Eine Art Manpage erhält man mit dem Command |
|||
# certbot (--help) |
|||
===== Initial Zertifikate erzeugen ===== |
|||
<console> |
|||
# certbot --apache certonly |
|||
</console> |
|||
(interaktive Abfragen z.B. fqdn, evtl. config file) |
|||
Anschließend hat man im Verzeichnis /etc/letsencrypt haufenweise neue Dateien. Die eigentlichen Zertifikate findet man im Verzeichnis „live“. |
|||
* archive: Alte Zertifikate |
|||
* options-ssl-apache.conf: Configschnipsel |
|||
* accounts: private Key fürs Erzeugen der nonce (don't lose!) |
|||
Die Zertifikate, die automatisch erzeugt werden, landen im '''renewal''' Verzeichnis. |
|||
Die entstandenen Zertifikate können entweder ins entsprechende Verzeichnis (/etc/ssl/...) kopiert werden (dann muss man aber dafür sorgen, dass das ggf. automatisch passiert) oder man verwendet den direkten Pfad in der Konfig, z.B.: |
|||
SSLCertificateFile /etc/letsencrypt/live/mail.example.de/fullchain.pem |
|||
SSLCertificateKeyFile /etc/letsencrypt/live/mail.example.de/privkey.pem |
|||
Wobei fullchain.pem sowohl das Zwischenzertifikat als auch das eigentliche Zertifikat enthält.<br> |
|||
Natürlich lässt sich der Certbot auf alle Virtual Hosts anwenden. |
|||
In der Datei /etc/cron.d/certbot sollte sich der Cronjob befinden, der alle 12h prüft, ob ein Zertifikat < 30 Tage gültig ist und ggf. erneuert. |
|||
=====Manuell erneuern===== |
|||
<console> |
|||
# cerbot renew |
|||
</console> |
|||
==== Dehydrated ==== |
|||
Eine Alternative zum certbot ist dehydrated. Hierfür braucht es einen offenen Port 80, den es bei einem Webserver i.a. gibt. Einfach das Paket '''dehydrated-apache2''' installieren. Danach den benötigten Hostname in die Datei domains.txt einfügen. |
|||
<pre> |
|||
# echo $HOSTNAME >> /etc/dehydrated/domains.txt |
|||
</pre> |
|||
Dort können auch mehrere Hostnames stehen. |
|||
Zertifikat generieren: |
|||
<pre> |
|||
# dehydrated --register --accept-terms |
|||
</pre> |
|||
<pre> |
|||
# dehydrated -c |
|||
</pre> |
|||
Die Zertifikate liegen dann im Verzeichnis /var/lib/dehydrated/ |
|||
Auch hierfür wird per Default ein Cronjob angelegt. |
|||
=== Immer verschlüsseln === |
|||
Wer immer von http auf https umleiten will, kann in seine Config folgendes eintragen: |
|||
RewriteCond %{HTTPS} !=on |
|||
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L] |
|||
Alternativ geht auch folgendes: |
|||
(sub.class1.server.ca.pem natürlich durch den aktuellen Namen des Zwischenzertifikats ersetzen) |
|||
<IfModule mod_ssl.c> |
|||
<IfModule mod_rewrite.c> |
|||
RewriteEngine On |
|||
RewriteRule (.*) https://%{HTTP_HOST}$1 [R,L] |
|||
</IfModule> |
|||
</IfModule> |
|||
Das waren die ersten Schritte mit Apache. Viel Spaß beim Konfigurieren und Probieren! |
|||
s.a. http://www.startssl.com/?app=25#31 |
Latest revision as of 21:09, 29 October 2024
Einer der häufigsten genutzten Webserver ist Apache. Abgesehen davon, dass man bereits mit der Standardkonfiguration relativ schnell zu einer einfachen Website kommt, bringt er den Vorteil, dass viele Module bereits eingebunden oder schnell nachzuinstallieren sind (z.B. libapache2.php). Zudem werden regelmäßig Updates gegen mögliche Exploits auf diesen weit verbreiteten Webdienst geliefert, also Versionsstand aktuell halten! Zum Entstehungszeitpunkt dieses Dokuments war die aktuellste Version der apache2. Wir verlassen uns aber nicht auf diese Aussage, sondern prüfen den Versionsstand selbst nach mit
# apt search apache
Danach installieren wir die aktuellste Version:
# apt install apache2
Nach der Installation läuft der Dienst auch schon. Überprüfung mit
# service apache2 status
Konfigurationsdateien
Diese befinden sich im Verzeichnis /etc/apache2. Die wichtigste Datei ist die apache2.conf. Diese verweist auf weitere Dateien und Unterverzeichnisse.
In einem Standard /etc/apache2-Verzeichnis wird man folgende Dateien und Ordner vorfinden:
apache2.conf
conf-enabled
magic
mods-enabled
sites-available
conf-available
envvars
mods-available
ports.conf
sites-enabled
Dies ist die Verzeichnisstruktur für Debian. Andere Distributionen können sich anders verhalten, z.B. werden unter CentOS keine sites-available/sites-enabled verwendet. Wie gesagt, handelt es sich bei der apache2.conf um die Hauptkonfigurationsdatei. Diese nur mit Vorsicht anfassen, weil Gefahr besteht, dass die Änderungen mit dem nächsten Update überschrieben werden.
Die eigentliche Konfigurationsdateien befinden sich in sites-available bzw. conf-available. Meistens wird sites-available für Virtualhosts (s.u.) benützt und conf-available für Konfig, die für bestimmte Services gelten soll. Hier speichern i.d.R. auch webservice-related Software-Pakete ihre Konfig (z.B. Nagios oder Mediawiki). Die Dateien, die hier abgelegt werden, sind aber noch nicht aktiv. Dies passiert per Symlink in den Verzeichnissen conf-enabled und sites-enabled. Darauf achten, dass die Symlinks immer mit .conf enden !
Module
Module sind kleine Codestücke oder Konfigschnipsel, die die Funktionalität des Webservers erweitern. Es gibt z.B. welche für andere Scriptsprachen (php, cgi), für Verschlüsselung, Authentifizierung u.v.m. Im Verzeichnis mods-available sind bereits einige Standardmodule abgelegt. Diese lassen sich durch einen Symlink im mods-enabled Verzeichnis aktivieren oder durch das a2enmod Kommando, z.B.
# a2enmod ssl
Wohin mit den Webseiten
Der Standardordner für Webseiten ist das Verzeichnis /var/www/. Wer weitere/andere Verzeichnisse festlegen will, kann das in der Datei sites-available/<filename> im Abschnitt DocumentRoot tun.
Falls der Index nicht automatisch geladen werden sollte, lässt sich das mittels Option "DirectoryIndex" bewirken, z.B.
DirectoryIndex index.php
oder
DirectoryIndex index.html
Neustart des Apache nach Konfigurationsänderungen erfolgt mittels
# systemctl reload apache2
Virtual Hosting
Mal angenommen, ihr entschließt euch, mehrere Domains auf einem Webserver zu hosten. Dafür gibt es die Virtual-Host-Einträge in der Datei sites-available/<domain>.conf (Im Grunde kann die Datei heißen wie sie will, aber der Übersicht halber wird man domainnamen vergeben). In unserem Fall wollen wir 2 Domains hosten, example.de unter /var/www/example und nomorebluescreen.com unter /var/www/nmbs. Zu diesem Zweck werden unter /etc/apache2/sites-available 2 Dateien angelegt, z.B. example.conf und nmbs.conf.
1. Datei:
<VirtualHost *:80> ServerName www.example.de ServerAlias ... ServerAdmin webmaster@example.de (...) </VirtualHost>
2. Datei:
<VirtualHost *:80> ServerName www.nomorebluescreen.com (...) </Virtual Host>
Sollte es für eine Domain einen IP-Eintrag, aber noch keine config-Datei geben, wird beim Aufruf der Seite per default die Domain genommen, die im Alphabet als 1. kommt.
Um die Änderung wirksam zu machen, müssen diese Seiten noch nach sites-enabled verlinkt sein. Hierbei darauf achten, dass die Dateiendung .conf ist, sonst wird die Datei ignoriert.
Die entsprechenden Namen müssen natürlich im DNS (oder zu Testzwecken auch in der /etc/hosts) hinterlegt sein!
Test
Standardeinstellungen: Ein Connect mit dem Browser auf die IP des Webservers sollte die eingestellte Indexseite oder den Apache-Default „It works!“ zeigen. Virtual Hosting: Nach Eingabe der unterschiedlichen Servernamen sollten die entsprechenden Webseiten zu sehen sein.
Ein einfacher Configcheck geht mit
apache2ctl -t
Hier sollte "Syntax OK" zurückkommen.
Logfiles
Diese befinden sich im Verzeichnis /var/log/apache2
Mit der Direktive
CustomLog
bzw.
ErrorLog
in der entsprechenden Konfigdatei kann (auch für VirtualHosts getrennt) der Pfad zur Logdatei angegeben werden.
Es gibt die Möglichkeit, die geloggten Parameter selbst zu definieren: https://httpd.apache.org/docs/2.4/logs.html#accesslog
Hier ein paar Beispiele, wie man in den Logfiles suchen kann:
request per hour cat access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":00"}' | sort -n | uniq -c request per hour by date grep "23/Jan" access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":00"}' | sort -n | uniq -c request per hour by IP grep "XX.XX.XX.XX" access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":00"}' | sort -n | uniq -c requests per minute: cat access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":"$3}' | sort -nk1 -nk2 | uniq -c requests per minute for date: grep "02/Nov/2017" access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":"$3}' | sort -nk1 -nk2 | uniq -c requests per minute for url: grep "[url]" access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":"$3}' | sort -nk1 -nk2 | uniq -c per IP per minute grep "XX.XX.XX.XX" access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print $2":"$3}' | sort -nk1 -nk2 | uniq -c
php einbinden
Dies ist zumindest unter Debian sehr trivial, weil nur das Paket php und das entsprechende Modul installiert werden muss.
Mit
# aptitude search php
informieren wir uns über die aktuelle Version. Mit "aptitude install php<version>" wird diese installiert.
Um den apache php-fähig zu bekommen, muss außerdem das php-Modul installiert werden (wird u.U. schon bei der apache-Installation mitgeliefert):
# aptitude install libapache2-mod-php
Kontrollieren, ob das Modul bereits geladen ist:
# ls /etc/apache2/mods-enabled/|grep php
Hier sollte (je nach Version) zu sehen sein:
php7.0.conf php7.0.load
Wenn nicht, gibt es den Befehl a2enmod, um Module zu installieren:
# a2enmod php7
Der Neustart des apache wird während der php-Installation übernommen.
Eine bessere Alternative ist das modernere php-fpm. Auch dieses kann als Paket installiert werden. Achtung: php-fpm muss für jede Version extra aktiviert werden, e.g.:
# a2enconf php8.2-fpm
Danach muss der Webserver neu gestratet werden.
Hier ein Beispiel für ein schlichtes Testscript:
<?php phpinfo(); ?>
Bei Ausführung desselben ist im Browser folgende Auflistung zu sehen
Directory Listing erlauben
Wenn in einem Unterverzeichnis von DocumentRoot eine Index-Datei (index.html, index.php, ... ) fehlt, bekommt der Benutzer normalerweise eine Fehlermeldung
Forbidden You don't have permission to access /images/ on this server. Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
Wenn man stattdessen möchte, dass der Benutzer alle Dateien aufgelistet bekommt, muss man folgendes einrichten
<Directory /var/www/images> Option +Indexes </Directory>
Falls die Option auf alle Verzeichnisse zutreffen soll, die den String „images“ enthalten, macht man besser einen DirectoryMatch
<DirectoryMatch images> Option +Indexes </DirectoryMatch>
Security
.htaccess und .htpasswd
Zum Passwortschutz einzelner Ordner bieten sich o.g. Dateien an. Die .htaccess beinhaltet, wer sich überhaupt wie anmelden darf, die .htpasswd beinhaltet die Passwörter
Beispiel für eine .htaccess:
AuthType basic AuthName "Access limited" AuthUserFile /var/www/download/.htpasswd Require valid-user
Die .htpasswd wird mit folgendem Command erzeugt
htpasswd -c <dateiname> <username>
Dann erfolgt eine Eingabeaufforderung für das Passwort. Vorhandene User in einer htpasswd ändert man durch Weglassen der Option -c
Weitere nützliche Optionen:
$ htpasswd -n <username>
(erzeugt nur eine Ausgabe, die man irgendwohin pasten kann)
$ htpasswd -B .htpasswd <username>
Use bcrypt instead of md5. Sicherer Algorithmus.
Die .htaccess schützt automatisch auch alle Unterverzeichnisse durch ein Passwort. Wenn man das nicht will, muss man in seiner Config für jedes der Verzeichnisse eine Ausnahme generieren, z.B.
<DirectoryMatch "/fotos/fotoclub/example/images/"> Satisfy any </DirectoryMatch>
DOS Attacken
Zum Abwehren von (D)DOS-Attacken gibt es das Modul mod-evasive.
Das zugehörige Paket heißt libapache2-mod-evasive.
Protipp: Die Parameter DOSPageCount und DOSSiteCount nicht zu niedrig wählen, sonst blockt man möglicherweise auch normale Webrequests.
Configbeispiel:
https://github.com/kdx99/apache-role/blob/main/vars/main.yaml
(Abschnitt # mod_evasive)
Weiteres hier:
- https://phoenixnap.com/kb/apache-mod-evasive
- https://www.howtogeek.com/devops/how-to-configure-mod_evasive-for-apache-ddos-protection/
Fail2ban
Zum Ausbremsen von Brute-Force-Angriffen hilft fail2ban, ein Tool, das zu häufige Fehlversuche beim Anmelden mit einer IP-Tables-Regel auf die zugehörige Source IP quittiert.
Beispiel
Erstmal das Paket „fail2ban" installieren, dann ins Verzeichnis /etc/fail2ban wechseln.
Die Optionen in der fail2ban.conf sind normal bereits auf sinnvolle Werte gesetzt. Gegebenenfalls lässt sich bei Problemen noch das Loglevel raufsetzen
loglevel = 4 # default=3
Achtung: nach dem Debuggen wieder auf default (=3) setzen. Die Logfiles werden sonst sehr schnell sehr groß!
Nun kann man in der jail.conf die unterschiedlichen jails für die einzelnen Dienste einrichten. Für mache gibt es auch Subsections, z.B. für apache:
[apache-auth] enabled = true port = http,https filter = apache-auth logpath = %(apache_error_log)s maxretry = 10 bantime = 5m
Bei den allgemeinen Optionen kann man Excludes für einzelne IPs oder Netze angeben
ignoreip = 127.0.0.1/8 192.168.99.0/24
Achtung: Als Trenner ein Space benutzen. Kommas o.ä. werden zwar akzeptiert, danach funktioniert aber die Banaction nicht. Bei „banaction“ sollte im allgemeinen Teil „iptables-multiport" oder "nftables-multiport" eingestellt sein. Dienst neu starten, fertig.
Erfolgskontrolle
n- mal falsch anmelden und „iptables -L -n -v“ ausführen (zum testen evtl. eine etwas kürzere bantime wählen)
Anmerkung: Seit bullseye ist per Default nicht mehr iptables, sondern nftables am Start. fail2ban schert sich da wenig drum, versucht iptables-Regeln zu generieren und wirft einen Fehler.
Abhilfe: In der jail.conf alles, was mit iptables- zu tun hat, durch nftables- ersetzen, e.g. nftables-multiport, nftables-allports, nftables-multiport-log
Nach n Fehlversuchen, folgendes Kommando absetzen:
# nft list table inet f2b-table
Debugging
Bei Problemen kann man den Dienst auch im Vordergrund starten:
# fail2ban-server -f
und in einer anderen Shell
# fail2ban-client reload
Verschlüsselte Webseiten
Feind hört mit (Gerüchten zufolge zuweilen auch Freund). Also am besten nichts im Klartext übers Netz schicken. Verschlüsselt wird bei apache üblicherweise mit TLS, die Echtheit (Authentizität) der Webseite wird durch ein Zertifikat überprüft. Wer geschäftlich eine Seite (Webshop o.ä.) betreibt, wird sein Zertifikat höchstwahrscheinlich durch eine offizielle Zertifizierungsstelle (Certificate Authority) signieren lassen. Privatanwender signieren u.U. selbst (nicht empfohlen).
Alternative Zertifikat selbst erzeugen
Von dieser Möglichkeit wird abgeraten, da es hier keine offizielle CA für das Zertifikat gibt, d.h. die Clients wissen nicht, ob die Website vertrauenswürdig ist. Hässliche Warnings sind die Folge bzw. im worst case wird die Seite gar nicht ausgeliefert. Besser eine offizielle CA verwenden (2 Alternativen gibt es weiter unten).
Schritte von der Zertifikatserstellung zur verschlüsselten Webseite:
1. Verzeichnis für Zertifikate anlegen
mkdir /etc/apache2/ssl/
2. Request, Key und gleichzeitig Zertifikat erstellen
openssl req -x509 -nodes -days 720 -newkey rsa:4096 -keyout /etc/apache2/ssl/www.example.de.key -out /etc/apache/ssl/www.example.de.crt
Darauf achten, dass bei FQDN unbedingt der Servername eingetragen wird, unter dem der Webserver erreichbar ist (i.d.R. identisch mit dem Wert für ServerName im apache)
Alternative Cert Request für offizielle CA erstellen
1. Key erstellen
openssl genrsa -out www.example.de.key 4096
2. Zertifikats-Request erstellen
openssl req -new -key www.example.de.key -out www.example.de.csr
3. Das .csr file an die Zertifizierungsstelle schicken
in der Regel kommt z.B. ein File namens www.example.de.crt zurück
4. Überprüfen des Zertifikats:
openssl x509 -in www.example.de.crt -text -noout
Alternativ bietet sich das im Paket openssl enthaltene Tool CA.pl an (hier nicht weiter ausgeführt, da ungetestet).
Konfguration des Webservers
Die folgende Schritte sind wieder identisch, unabhängig davon, wie das Zertifikat erzeugt wurde.
1. mod_ssl aktivieren
cd /etc/apache2/sites-enabled/ ln -s ../mods-available/ssl.conf ln -s ../mods-available/ssl.load
2. Virtual-Host auf Port 443 einrichten
<VirtualHost *:443> ServerAdmin webmaster@example.de ServerName www.example.de:443 ServerAlias mail.example.de:443 SSLEngine on SSLCertificateFile /etc/apache2/ssl/www.example.de.crt SSLCertificateKeyFile /etc/apache2/ssl/www.example.de.key SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 SSLCipherSuite \ EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH </VirtualHost>
Letztere Parameter lassen nur sichere Protokolle (TLS>=2) und Cipher-Suites mit starker Verschlüsselung zu.
Ein Beispiel für geeignete Cipher-Suites gibt es auf https://cipherlist.eu/.
3. Redirects
Wer es nicht dem Zufall überlassen will, ob der Benutzer im Browser http:// oder https:// eingibt, kann eine automatische Weiterleitung zur verschlüsselten Seite einrichten:
a2enmod rewrite
Dann im VirtualHost:80-Abschnitt folgendes eintragen (z.B. wenn „download“ im URL-Name dann auf https umleiten)
RewriteEngine On RewriteCond %{HTTPS} !=on RewriteRule ^/?download(.*) https://%{SERVER_NAME}/download/$1 [R,L]
Error
Sollten beim Erneuern Fehlermeldungen auftauchen aka
An unexpected error occurred: OpenSSL.SSL.Error: [('x509 certificate routines', 'X509_load_cert_crl_file', 'no certificate or crl found')] Please see the logfiles in /var/log/letsencrypt for more details.
gibt es ein Problem mit den default ca-certificates. In dem Fall hilft ein:
># update-ca-certificates
Alternative letsencrypt
Hier sind keine openssl-Commands nötig. Man verwendet als Root CA letsencrypt. Geholt werden die Zertifikate über einen sogenannten „certbot“, der einmalig eingerichtet wird und dann als Cron weiterläuft.
# apt install python3-certbot-apache
Eine Art Manpage erhält man mit dem Command
# certbot (--help)
Initial Zertifikate erzeugen
# certbot --apache certonly
(interaktive Abfragen z.B. fqdn, evtl. config file)
Anschließend hat man im Verzeichnis /etc/letsencrypt haufenweise neue Dateien. Die eigentlichen Zertifikate findet man im Verzeichnis „live“.
- archive: Alte Zertifikate
- options-ssl-apache.conf: Configschnipsel
- accounts: private Key fürs Erzeugen der nonce (don't lose!)
Die Zertifikate, die automatisch erzeugt werden, landen im renewal Verzeichnis.
Die entstandenen Zertifikate können entweder ins entsprechende Verzeichnis (/etc/ssl/...) kopiert werden (dann muss man aber dafür sorgen, dass das ggf. automatisch passiert) oder man verwendet den direkten Pfad in der Konfig, z.B.:
SSLCertificateFile /etc/letsencrypt/live/mail.example.de/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/mail.example.de/privkey.pem
Wobei fullchain.pem sowohl das Zwischenzertifikat als auch das eigentliche Zertifikat enthält.
Natürlich lässt sich der Certbot auf alle Virtual Hosts anwenden.
In der Datei /etc/cron.d/certbot sollte sich der Cronjob befinden, der alle 12h prüft, ob ein Zertifikat < 30 Tage gültig ist und ggf. erneuert.
Manuell erneuern
# cerbot renew
Dehydrated
Eine Alternative zum certbot ist dehydrated. Hierfür braucht es einen offenen Port 80, den es bei einem Webserver i.a. gibt. Einfach das Paket dehydrated-apache2 installieren. Danach den benötigten Hostname in die Datei domains.txt einfügen.
# echo $HOSTNAME >> /etc/dehydrated/domains.txt
Dort können auch mehrere Hostnames stehen.
Zertifikat generieren:
# dehydrated --register --accept-terms
# dehydrated -c
Die Zertifikate liegen dann im Verzeichnis /var/lib/dehydrated/
Auch hierfür wird per Default ein Cronjob angelegt.
Immer verschlüsseln
Wer immer von http auf https umleiten will, kann in seine Config folgendes eintragen:
RewriteCond %{HTTPS} !=on RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L]
Alternativ geht auch folgendes:
<IfModule mod_ssl.c> <IfModule mod_rewrite.c> RewriteEngine On RewriteRule (.*) https://%{HTTP_HOST}$1 [R,L] </IfModule> </IfModule>
Das waren die ersten Schritte mit Apache. Viel Spaß beim Konfigurieren und Probieren!