MySQL Server Absichern

Oft gewünscht – bei MySQL vorhanden: Das mach mich sicher Skript! Um einen MySQL server im ersten Schritt abzusichern gibt man als root folgenden Befehl ein:

mysql_secure_installation

Danach folgen eine Handvoll Fragen die natürlich mit dem MySQL-root-Benutzer anfangen:

image

image

image

image

image

Hat man die Fragen alle richtig beantwortet, so sind die Testdaten und Zugänge aus dem System entfernt, der root Benutzer abgesichert und die entsprechenden Privilegien richtig gesetzt. Zusätzlich empfehle ich den Datenbankport nicht auf der Firewall freizuschalten damit ganz sicher keiner von außen auf das System kommt. Wie man das mit Hilfe von iptables macht erkläre ich hier.

facebooktwittergoogle_pluslinkedinmail

Debian Webserver – Einstellungen für die Mailzustellung (MTA)

Ein Webserver soll in aller Regel auch die Fähigkeit besitzen eMails zu senden. Ich bin ein großer Freund davon diese Systeme zu trennen und auf den Webservern den MTA (in unserem Fall exim4) so einzustellen, dass er ausgehende Mails an einen dedizierten Webserver (Smarthost) zum Versand weiter gibt. Auf diesem Weg umgeht man zum einen die Komplexität der umfänglichen Konfiguration eines Mailserver und zum anderen muss man sich nicht mit Problemen wie SPAM-listen etc. herumschlagen. Auf unserem System starten wir die Konfiguration wie folgt (vorausgesetzt exim4 ist schon installiert – sonst muss man dies mit apt-get install exim4 noch erledigen):

# dpkg-reconfigure exim4-config

SNAGHTMLa8d3bfdimage image image image image image image

Nach der Grundkonfiguration von exim müssen wir noch die Zugangsdaten für unseren Smarthost hinterlegen (heute sollte es keinen offenen Mailserver mehr geben – und wenn steht er mit Sicherheit auf allen SPAM listen und sollte nicht verwendet werden). Hierzu fügen wir in der Konfigurationsdatei /etc/exim4/passwd.client unsere Zugangsdaten ein:

# vi /etc/exim4/passwd.client
target.mail.server.example:login:password

Da mein Mailserverprovider noch immer auf SSL (Port 465) setzt und noch kein STARTSSL (Port 587) anbietet, muss ich EXIM noch beibringen sich auch entsprechend mit dem Server zu verbinden. Dies erledigt man in der Konfigurationsdatei /etc/exim4/exim4-conf-template. Dort sucht man nach dem String (der Doppelpunkt am Ende ist wichtig):

remote_smtp_smarthost:

und fügt danach folgendes ein:

protocol=smtps

SNAGHTMLac113d7

Mails an den Root Benutzer weiterleiten

Es gibt diverse Services (z. B. cron) welche Nachrichten an den root-Benutzer des Systems schicken. Um diese Nachrichten in angemessener Zeit verarbeiten zu können ist es ratsam diese an eine Mailadresse weiterzuleiten

# vi /etc/aliases

in diese Datei fügt man die Zeile:

root:whatever@fragmichnicht.de

ein und lässt danach die Aliase neu erstellen

# newaliases

Nun sollten die Maileinstellungen des Server vollständig funktionsfähig sein und ausgehende Mails (z. B. von einem Blog-System oder cron) an die dafür vorgesehenen Adressen versendet werden.

facebooktwittergoogle_pluslinkedinmail

Kernel für einen Webserver härten

Die Standards der meisten Debian Vorlagen von Hostern enthalten oft schon einige Verbesserungen der Sicherheitseinstellungen. Es schadet aber nicht diese zu prüfen und ggf. zu justieren. Der einfachste Weg besteht dabei darin eine Kopie der Konfigurationsdatei sysctl.conf zu erstellen und dort die eigenen Einstellungen zu hinterlegen (so behält man immer die Standards und bekommt keine Probleme bei Systemupdates):

# cp /etc/sysctl.conf /etc/sysctl.d/local.conf

In der kopierten Datei sollten folgende Werte (fett) angepasst bzw. auskommentiert werden. Die Beschreibungen über den Werten selbst sind recht aussagekräftig. Ich verzichte jetzt mal dies alles zu wiederholen:

#
# /etc/sysctl.conf - Configuration file for setting system variables
# See /etc/sysctl.d/ for additional system variables.
# See sysctl.conf (5) for information.
#
#kernel.domainname = example.com
# Uncomment the following to stop low-level messages on console
#kernel.printk = 3 4 1 3
##############################################################3
# Functions previously found in netbase
#
# Uncomment the next two lines to enable Spoof protection (reverse-path filter)
# Turn on Source Address Verification in all interfaces to
# prevent some spoofing attacks
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1 
# Uncomment the next line to enable TCP/IP SYN cookies
# See http://lwn.net/Articles/277146/
# Note: This may impact IPv6 TCP sessions too
net.ipv4.tcp_syncookies=1
# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1
# Uncomment the next line to enable packet forwarding for IPv6
#  Enabling this option disables Stateless Address Autoconfiguration
#  based on Router Advertisements for this host
#net.ipv6.conf.all.forwarding=1
###################################################################
# Additional settings - these settings can improve the network
# security of the host and prevent against some network attacks
# including spoofing attacks and man in the middle attacks through
# redirection. Some network environments, however, require that these
# settings are disabled so review and enable them as needed.
#
# Do not accept ICMP redirects (prevent MITM attacks)
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
# _or_
# Accept ICMP redirects only for gateways listed in our default
# gateway list (enabled by default)
# net.ipv4.conf.all.secure_redirects = 1
#
# Do not send ICMP redirects (we are not a router)
net.ipv4.conf.all.send_redirects = 0
#
# Do not accept IP source route packets (we are not a router)
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
#
# Log Martian Packets
#net.ipv4.conf.all.log_martians = 1
#
facebooktwittergoogle_pluslinkedinmail

SSH-Zugang Absichern und Härten

Normalen (nicht root) Benutzer anlegen

Bevor wir uns um das Absichern/Härten des SSH Zugangs kümmer können ist es wichtig einen regulären Benutzer auf dem System anzulegen. Dies erledigt man auf der Kommandozeile mit folgendem Befehl:  

adduser fragmichnicht

Adding user `fragmichnicht' ...

Adding new group `fragmichnicht' (1002) ...

Adding new user `fragmichnicht' (1002) with group `fragmichnicht' ...

Creating home directory `/home/fragmichnicht' ...

Copying files from `/etc/skel' ...

Enter new UNIX password:

Retype new UNIX password:

passwd: password updated successfully

Changing the user information for fragmichnicht

Enter the new value, or press ENTER for the default

Full Name []:

Room Number []:

Work Phone []:

Home Phone []:

Other []:

Is the information correct? [Y/n] y

SSH Schlüssel erzeugen und einbinden

Als nächsten Schritt legen wir uns einen private und einen public-key an um diesen für die Anmeldung via ssh verwenden zu können. Passwörter sind schon lange nicht mehr wirklich sicher und die Verwendung von solchen keys ist zudem deutlich praktischer als die Verwendung von vermeintlich sicheren Passwörtern. Die Schlüssel erstellen Sie entweder über die Linux Kommandozeile oder über das Windows tool Putty Key Generator.

Den Private-Key schützt man auf seinem lokalen System am besten weiterhin mit einem Passwort und speichert ihn an einem sicheren Ort. Der Schlüssel sollte nach Möglichkeit wirklich privat sein und nicht aus den Händen gegeben werden. Den Public-key zu veröffentlichen ist dagegen kein wirkliches Problem (wie der Name schon impliziert).

cd /home/fragmichnicht/  

mkdir .ssh

chmod 700 .ssh

chown fragmichnicht:fragmichnicht .ssh

cd .ssh

vi authorized_keys

Hier fügen wir nun den public key zu dem Schlüsselpaar welches wir gerade erstellt haben ein.

Danach fügen wir den neu angelegten Benutzer der Gruppe sudo hinzu damit dieser sich jederzeit via sudo root Rechte besorgen kann.

usermod -a -G sudo fragmichnicht

Sollte sudo noch nicht installiert sein so erledigt dies ein:

apt-get install sudo

Wenn ihr für die Benutzer der Gruppe sudo nicht wollt, dass diese ein Passwort eingeben müssen um sich root Rechte zu besorgen, dann erreicht man dies über folgende Zeile in der /etc/sudoers (Änderungen an dem file über visudo!)

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL) NOPASSWD: ALL

Härten der SSH-config

An sich sollte sich ein root-Benutzer nie direkt remote an einem System anmelden können und auf einem Server benötigt man auch keine grafische Oberfläche (X11). Ich poste nachfolgend meine sshd-config mit allen Werten (die geänderten fett gedruckt). Je nach System und Version müssen ggf. mehr Werte angepasst werden um zu dieser Konfiguration zu kommen. Die Änderungen an der Konfiguration müssen mit root-Rechten und folgendem Befehl durchgeführt werden:

vi /etc/ssh/sshd-config

# What ports, IPs and protocols we listen for
Port 22
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes
# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 1024
# Logging
SyslogFacility AUTH
LogLevel INFO
# Authentication:
LoginGraceTime 120
PermitRootLogin no
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
#AuthorizedKeysFile     %h/.ssh/authorized_keys
# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes
# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no
# Change to no to disable tunnelled clear text passwords
PasswordAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

X11Forwarding no
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#MaxStartups 10:30:60
#Banner /etc/issue.net
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes

Damit die Einstellungen wirksam werden muss der SSH Dienst neu gestartet werden. Dies erreicht man mit dem Befehl:

/etc/init.d/ssh restart

Damit sind die Grundlagen für einen sicheren SSH-Zugang zu dem eigenen Server gelegt.

facebooktwittergoogle_pluslinkedinmail

iptables – Debian Firewall Regeln für einen Webserver

In diesem Artikel werde ich erklären wie man die Firewall iptables auf einem Debian Linux einrichten um nur Zugriffe auf die erwarteten Dienste (HTTP, HTTPS und SSH) zu erlauben.

Firewall Grundlagen

Iptables bestimmt wie die meisten Firewalls ob ein Packet durch darf oder nicht indem es das eingerichtete Regelwerk von oben noch unten durchgeht. Sobald die erste Regel gefunden wird, die auf das Packet passt, wird diese Angewendet. Wenn unser Regelwerk also wie folgt aussehen würde, dann würden nur SSH Verbindungen zustande kommen und keine HTTP Verbindungen:

  1. Erlaube alle SSH Verbindungen
  2. Verbiete alle Verbindungen
  3. Erlaube HTTP Verbindungen

Es ist also wichtig auf die Reihenfolge der Regeln zu achten und am Schluss sollte immer eine Regel stehen “Verbiete alle Verbindungen” (Deny All).

 IPv4 vs IPv6

Die meisten Webserver sind heute sowohl über eine IPv4 wie auch eine neue IPv6 Adresse erreichbar. Die neue Protokollversion wird jedoch oft sträflich vernachlässigt obwohl diese auf den Systemen aktiv ist. Dies ist bei Firewalls im besonderen ein Problem. Wenn wir bei dem Beispiel oben bleiben und in der Standardkonfiguration von IPtables nun via IPv6 eine HTTP Verbindung öffnen würden, so würden wir bis zu dem Webserver kommen. Da IPv6 die Zukunft ist empfehle ich daher explizit nicht einfach alle solchen Verbindungen zu verbieten sondern die Regeln auch für dieses Protokoll einzurichten. Bei iptables ist dies besonders einfach, da die meisten Befehle in beiden Versionen funktionieren und das einzige was man ändern muss ist der Programmname (von iptables zu ip6tables). In meinem Beispielen führe ich daher jeweils beide Befehlssätze (IPv4 & IPv6) auf.

System Vorbereiten

Viel ist nicht nötig um mit der Konfiguration anfangen zu können. Wir müssen im wesentlichen nur ein Packet installieren (welches häufig schon vorhanden ist):

apt-get install iptables iptables-persistent

Filterregeln erstellen

Es gibt bei iptables im wesentlichen zwei Möglichkeiten Regeln zu erstellen. Man kann diese entweder in eine Datei schreiben und diese vom System automatisch laden lassen oder man schreibt die Regeln in den (flüchtigen) Speicher von iptables und lässt iptables am Ende das File schreiben. Ich bevorzuge und verwende hier letzteren Weg, da man hier bei einem Fehler das System nur neustarten muss um einen Weitere Versuch zu erhalten.

Derzeitiges Regelwerk anschauen

Um sich das aktuell vorhandene Regelwerk anzuschauen genügt ein einfacher Befehl. Im Auslieferungszustand sollte das Ergebnis wie folgt aussehen:

IPv4

# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

IPv6

# ip6tables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Regel für SSH Zugang und den Loopback Verkehr einrichten

Die erste Regel sollte immer für den Loopback Verkehr und dann für den Remotezugang verwendet werden. So wird verhindert, dass man sich zu einem späteren Zeitpunkt durch eine falsche Regel aussperrt bzw das System zu viel Zeit verbraucht um z. B. Verbindungen zum lokalen Datenbankserver aufzubauen.

IPv4

# iptables -I INPUT -p tcp --dport 22 -j ACCEPT
# iptables -I INPUT -i lo -j ACCEPT

IPv6

# ip6tables -I INPUT -p tcp --dport 22 -j ACCEPT
# ip6tables -I INPUT -i lo -j ACCEPT

Alle nicht explizit erlaubten Verbindungen ignorieren

Nachdem die SSH Regel gesetzt wurde können wir iptables scharf schalten und in der base policy einstellen, dass nur explizit erlaubte Verbindungen an unseren Server heran kommen dürfen.

IPv4

# iptables -P INPUT DROP

IPv6

# ip6tables -P INPUT DROP

Regeln für den Webserver anhängen

Für unseren Webserver erlauben wir nun noch HTTP und HTTPS Verbindungen auf den Ports 80 und 443:

IPv4

# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# iptables -A INPUT -p tcp --dport 443 -j ACCEPT

IPv6

# ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT
# ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT
# iptables -L -n
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:443
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED

Im Gegensatz zu dem Befehl den wir zum Anlegen der SSH Regel verwendet haben, haben wir hier den Parameter –I durch den Parameter –A ersetzt. Dies bewirkt, dass die Regel an das Regelwerk angehängt (append) wird.

Etablierte Verbindungen zulassen

Mit dem bestehenden Regelwerk würde der Webserver und der SSH Server wie erwartet funktionieren. Allerdings würdet Ihr vermutlich recht schnell über Fehlermeldungen z. B. von apt fallen, da hier verschiedene Verbindungen nicht durch gehen würden. Es ist daher ratsam noch folgende Regel hinzuzufügen:

IPv4

# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

IPv6

# ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Filterregeln permanent speichern

Alle Regeln die wir bis jetzt eingerichtet haben wären nach einer Reboot wieder weg. Um diese zu speichern ist ein kurzer Befehl notwendig:

# iptables-save > /etc/iptables/rules.v4
# ip6tables-save > /etc/iptables/rules.v6

Nach einem Reboot werden die Regeln nun automatisch wieder gelesen und geladen. Zur Sicherheit sollte man das System neustarten und prüfen ob dies auch der Fall ist.

Alles in einem Script für Schreibfaule

Um das setzen der Regeln zu vereinfachen habe ich alle Befehle in eine bash Datei geworfen. Ihr müsste diese also nur auf euer System herunter laden, die Datei ausführbar machen (chmod +x [name]) und danach ausführen. Den Schritt um die Regeln zu persistieren habe ich nicht mit aufgenommen um Fehlern vorzubeugen.

Datei herunterladen

facebooktwittergoogle_pluslinkedinmail