Debian 9 : Apache mit mod_qos und fail2ban absichern

Es kommt immer wieder vor das die Webserver unter Volllast geraten da jemand unsere API exzessiv anfragt. Da hier alle anderen Anfragen auch mit betroffen sind ist hier ein möglicher Weg einen Apache dagegen abzusichern. In meinem Fall handelt es sich um ein Debian 9 bei anderen Linux Derivaten sollte es ähnlich funktionieren.
Distributor ID:	Debian
Description:	Debian GNU/Linux 9.5 (stretch)
Release:	9.5
Codename:	stretch
Natürlich kann man die Werte aus diesem Beispiel nicht einfach übernehmen, diese müssen der jeweiligen Anwendung angepasst werden, sie dienen lediglich als Beispiel

Erstmal installieren wir die benötigten Packete
apt install libapache2-mod-qos fail2ban
Dann machen wir die Konfiguration für mod_qos
vi /etc/apache2/conf-available/mod_qos.conf
dort tragen wir erstmal eine Grundkonfiguration ein
## QoS Settings
<IfModule mod_qos.c>
    # Gleichzeitige Verbindungen von 100000 IP Adressen zulassen 
    QS_ClientEntries 100000
    # maximal 20 Verbindungen pro IP Adresse
    QS_SrvMaxConnPerIP 20
    # maximale Anzahl der aktiven TCP Verbindungen hier 256
    MaxClients              256
    # QS_SrvMaxConnClose <Nummer> [%] definiert die maximale Anzahl der gleichzeitigen TCP-Verbindungen,
    # bis der Server Keep-Alive für diesen Server deaktiviert (die Verbindung wird nach jeder Anforderung geschlossen. 
    # Sie können die Anzahl der Verbindungen als Prozentsatz von MaxClients angeben, wenn Sie das Suffix hinzufügen '%' auf den angegebenen Wert.
    QS_SrvMaxConnClose      70%
    # minimum request/response speed (https://de.wikipedia.org/wiki/Slowloris Schutz):
    QS_SrvMinDataRate       150 1200
    # QS_SrvMinDataRate <bytes pro seconds> [<max bytes pro second> [<connections>]], definiert den minimalen Upload / Download-Durchsatz
    # QS_SrvMaxConnExcludeIP <addr>
    # QS_SrvMaxConnExcludeIP 192.168.x.xxx
    #
    # Quelle : https://www.mankier.com/1/mod_qos
</IfModule>
Jetzt geben wir noch die Statusseite für qos frei damit wir auch sehen was hier so passiert.
<Location /qos>
   SetHandler qos-viewer
   Require ip [Eigene IP Adresse oder IP Range (CIDR)]
   # z.B. Require ip 127.0.0.1
</Location>
Jetzt aktivieren wir noch das Modul und die Konfiguration
a2enmod qos
a2enconf mod_qos
dann der obligatorische Neustart des Apaches
systemctl restart apache2
nun kann man den ersten Test durchführen, von einem anderen Rechner die IP Adresse des Servers über das Apache Benchmark Tool einfach mal anfragen mit diesen Werten
ab -n 1500 -c 100 http://[IP des Webservers]/index.html
im Errorlog des Apaches sollten jetzt solche Meldungen erscheinen
[xxx] [:error] [xxx] mod_qos(034): access denied, QS_SrvMinDataRate rule (in): min=354, this connection=26, c=192.168.x.xxx
[xxx] [:error] [xxx] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=192.168.x.xxx
Dann machen wir mit fail2ban weiter
vi /etc/fail2ban/jail.d/http-requests.conf
dort fügen wir diesen Inhalt ein
[http-requests]
enabled = true
port = http,https
filter = http-requests
logpath = /var/log/apache2/access.log
# maxretry bedeutet wieviele GET / POST wir im Log finden bevor wir die IP sperren
maxretry = 30
# findtime ist die Zeitperiode in der wir GET/POST zählen (10 Sekunden)
findtime = 10
# Wielange wird die IP gebannt in Sekunden (600 Sekunden = 10 Minuten)
bantime = 600
action = iptables[name=HTTP, port=http, protocol=tcp]
den Filter dazu erstellen
vi /etc/fail2ban/filter.d/http-requests.conf
und dort diesen Inhalt rein
# Fail2Ban configuration file
# http-requests.conf
#
[Definition]
# failregex = es wird gegen GET/POST im Logfile gematched
failregex = ^<HOST> -.*"(GET|POST).*
# ignoreregex = 
ignoreregex =
ein neustart von fail2ban aktiviert die Config
systemctl restart fail2ban
Jetzt kann wieder mit dem Apache Benchmark Tool getestet werden, bevor wir allerdings das Benchmark Tool von einem anderen Rechner aus starten öffnen wir lokal das Logfile von fail2ban damit wir sehen was passiert.
tail -f /var/log/fail2ban.log
jetzt den Benchmark starten wie oben angegeben. Im Log sollten jetzt solche Meldungen erscheinen
2018-07-20 00:25:27,998 fail2ban.filter         [6203]: INFO    [http-requests] Found 192.168.x.xxx
2018-07-20 00:25:27,998 fail2ban.filter         [6203]: INFO    [http-requests] Found 192.168.x.xxx
2018-07-20 00:25:28,096 fail2ban.actions        [6203]: NOTICE  [http-requests] 192.168.x.xxx already banned
2018-07-20 00:25:29,098 fail2ban.actions        [6203]: NOTICE  [http-requests] 192.168.x.xxx already banned
In fail2ban kann man sich jetzt den Status anzeigen lassen
root@ddev-01: fail2ban-client status http-requests
Status for the jail: http-requests
|- Filter
|  |- Currently failed:	1
|  |- Total failed:	1629
|  `- File list:	/var/log/apache2/access.log
`- Actions
   |- Currently banned:	1
   |- Total banned:	2
   `- Banned IP list:	192.168.x.xxx
möchte man die IP wieder entsperren genügt ein
fail2ban-client set http-requests unbanip 192.168.x.xxx
wenn eine bestimmte IP oder eine IP Range freigegeben werden muss ist das in der jail.conf zu erledigen
vi /etc/fail2ban/jail.conf
dort nach ignoreip = suchen und die eigene IP hinzufügen

Quellen :
http://mod-qos.sourceforge.net/#variables
https://de.wikipedia.org/wiki/Slowloris
https://www.fail2ban.org/wiki/index.php/Main_Page
https://sourceforge.net/p/mod-qos/discussion/
http://mod-qos.sourceforge.net/#statusviewer
http://mod-qos.sourceforge.net/glossary.html
http://mod-qos.sourceforge.net/dos.html

VIM Sonderzeichen ersetzen (hexadezimal)

Problem : In manchen Fällen bekommt man Dateien von Kunden geschickt die irgendein unbekanntes encoding enthalten. mit recode und iconv kam in meinem Fall auch nur Mist raus.

Lösung :
Die Datei mit vim öffnen und das encoding auf utf8 festnageln.
set fenc=utf8
dann können die unbekannten Zeichen ersetzt werden. Hier ein paar Beispiele.
:%s#\%x86#Ü#g
:%s#\%x9f#ü#g
:%s#\%x8a#ä#g
:%s#\%x9a#ö#g
:%s#§#ß#g

mosquitto absichern & Standardbefehle

erstmal für alle die mosquitto nicht kennen das ist es : mosquitto.org

erstmal installieren wir alles was wir benötigen
sudo apt install mosquitto mosquitto-clients
nach der Installation aus den Debian Paketen liegt ein funktionierendes mosquitto auf der Platte nur ist es nicht sicher konfiguriert. Um es noch ein bisschen mehr abzusichern sollte man an den Configfiles etwas schrauben.

Hier ist meine mosquitto.conf diese liegt unter /etc/mosquitto/
pid_file /var/run/mosquitto.pid
persistence true
persistence_location /var/lib/mosquitto/
persistent_client_expiration 7d
connection_messages true
log_dest syslog
log_timestamp false
log_type error
log_type warning
log_type notice
log_type information
port 1883
max_connections -1
allow_anonymous false
use_identity_as_username false
password_file /etc/mosquitto/users
acl_file /etc/mosquitto/roles
include_dir /etc/mosquitto/conf.d

Als erstes legen wir einen Benutzer für mosquitto an.
touch /etc/mosquitto/users ; mosquitto_passwd /etc/mosquitto/users BENUTZERNAME

Jetzt brauchen wir die Rechte der User
touch /etc/mosquitto/roles ; vi /etc/mosquitto/roles

Hier ein Vorschlag für die roles, der Benutzer monitor hat alle rechte während der Benutzer clmon nur schreiben darf.
user monitor
topic write /mqtt/#
topic read /mqtt/#

user clmon
topic write /mqtt/#


Zum testen der konfig bieten sich die beiden tools mosquitto_sub und mosquitto_pub an.

Subscribe
mosquitto_sub -u USERNAME -P PASSWORD -t "/mqtt/#"
Publish
mosquitto_pub -h localhost -u USERNAME -P PASSWORD -t "/mqtt/test/" -m "TESTNACHRICHT"


Quelle : Mosquitto Dokumentation

InfluxDB absichern & Standardbefehle

erstmal was ist Influx db eigentlich : Influxdb

Um eine InfluxDB absichern zu können muss als erstes ein Benutzer mit Admin Rechten angelegt werden, BEVOR man Auth aktiviert.

Anlegen eines Admin Users :
CREATE USER admin WITH PASSWORD 'SECUREPASSWORD' WITH ALL PRIVILEGES
Überprüfen / Anzeigen der User geht mit dem Befehl :
SHOW USERS
bzw für die Rechte
SHOW GRANTS FOR admin

Jetzt muss die Authentifizierung aktiviert werden. Dazu muss die Konfiguration unter /etc/influx/influx.conf angepasst werden.
Hier mal der entscheidende Block (Ohne Kommentare)
[http]
   enabled = true
   bind-address = ":8086"
   auth-enabled = true
   access-log-path = "/var/log/influxdb/access.log"
   write-tracing = false
   pprof-enabled = false
   https-enabled = false
   https-certificate = "/etc/ssl/influxdb.pem"

Ab jetzt könnt ihr euch mit dem folgenden Befehl verbinden
influx -username admin -password SECUREPASSWORD -database DATABASENAME
was auch funktioniert ist mit dem Befehl
influx
die cli starten und dann mit dem Befehl
auth
die Authentifizierung einleiten.


Weitere Standardbefehle

InfluxDB Datenbanken anzeigen :
SHOW DATABASES
InfluxDB Datenbank anlegen :
CREATE DATABASE "DATABASENAME"
InfluxDB User anlegen :
CREATE USER dev WITH PASSWORD 'SECUREPASSWORD'
InfluxDB Rechte vergeben auf Datenbank :
GRANT (READ,WRITE,ALL) ON DATABASENAME TO dev

Quelle : InfluxDB 1.5 documentation


Amazon Linux AMI : Fehler beim Versuch "yum update"

Problem : beim Versuch ein Amazon Linux AMI erscheint diese Meldung
There was a problem importing one of the Python modules
required to run yum. The error leading to this problem was:

   /usr/lib64/python2.7/dist-packages/pycurl.so: undefined symbol: CRYPTO_num_locks

Please install a package which provides this module, or
verify that the module is installed correctly.

It's possible that the above module doesn't match the
current version of Python, which is:
2.7.12 (default, Nov  2 2017, 19:20:38) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]

If you cannot solve this problem yourself, please go to 
the yum faq at:
  http://yum.baseurl.org/wiki/Faq

Lösung : Überprüfen auf welche libs curl verweist
ldconfig -p -N -X | grep curl
Output :
	libcurl.so.4 (libc6,x86-64) => /usr/lib64/libcurl.so.4
dann prüfen wir das selbe beim python modul
ldd /usr/lib64/python2.7/dist-packages/pycurl.so
	linux-vdso.so.1 =>  (0x00007ffe65d10000)
	libcurl.so.4 => /libs/test/libcurl.so.4 (0x00007f5edd1e7000) <----- GRUND !!
	libpython2.7.so.1.0 => /usr/lib64/libpython2.7.so.1.0 (0x00007f5edce0b000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f5edcbef000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f5edc82b000)
	libssl.so.1.1 => /libs/test/libssl.so.1.1 (0x00007f5edc5bd000)
	libcrypto.so.1.1 => /libs/test/libcrypto.so.1.1 (0x00007f5edc153000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f5edbf4f000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f5edbd39000)
	librt.so.1 => /lib64/librt.so.1 (0x00007f5edbb31000)
	libutil.so.1 => /lib64/libutil.so.1 (0x00007f5edb92e000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f5edb62c000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f5edd65e000)
Die Pfade sind hier unterschiedlich, ich habe hier einfach die lib von dem Entwickler umbenannt und die andere rein gelinkt.
mv /libs/test/libcurl.so.4 /libs/test/libcurl.so.4.dev ; ln -s /usr/lib64/libcurl.so.4 /libs/test/libcurl.so.4
Dann ging YUM wieder durch.

Quelle : https://access.redhat.com/solutions/641093
“Sicher ist, dass nichts sicher ist. Selbst das nicht.”
Joachim Ringelnatz