Tag Archives: server

vsftpd mit virtuellen Benutzern, FXP und Verschlüsselung in 5 Minuten

Manchmal möchte man Benutzern einen FTP-Zugang zur Verfügung stellen, aber nicht gleich einen Systemzugang anlegen. Das geht mit vsftpd besonders einfach. Vorraussetzung ist eine funktionierende Installation von vsftpd und einige kleine Anpassungen. Natürlich darf auch die Sicherheit und nützliche Zusatzfunktionen wie FXP nicht zu kurz kommen.

Zuerst werden alle nötigen Programme installiert.

apt-get install vsftpd apache2-utils ssl-cert libpam-pwdfile

Es muss die Datei /etc/vsftpd.conf wie folgt angepasst werden.

listen=YES
local_enable=YES
write_enable=YES
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
chroot_local_user=YES
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/private/vsftpd.pem

# Virtuelle Benutzer verwenden
nopriv_user=shared
virtual_use_local_privs=YES
guest_enable=YES
user_sub_token=$USER
local_root=/home/shared/pub
chroot_local_user=YES
hide_ids=YES

# FXP erlauben
pasv_promiscuous=YES
pasv_enable=YES
pasv_min_port=49152
pasv_max_port=50000
port_promiscuous=YES

# SSL fuer Daten- und Kontrollverbindung erzwingen
ssl_enable=YES
force_local_data_ssl=YES
force_local_logins_ssl=YES

# Kleiner Scherz ;) (http://www.exploit-db.com/exploits/15449/)
ftpd_banner=ProFTPD 1.3.3a

Diese Konfigurationsdatei erlaubt es allen angelegten Benutzern das Verzeichnis /home/shared zu sehen. Soll jeder Benutzer nur ein eigenes Verzeichnis sehen können, muss die Option local_root auf den Wert /home/shared/pub/$USERgesetzt werden.

Dann wird das selbst-signierte SSL-Zertifikat für vsftpd angelegt.

make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /etc/ssl/private/vsftpd.pem

Nun muss die PAM-Authentifizierung von vsftpd angepasst werden, sodass vsftpd die Daten aus einer Datei liest. Dafür wird der Inhalt der Datei /etc/pam.d/vsftpd gelöscht und durch folgenden Inhalt ersetzt.

auth required pam_pwdfile.so pwdfile /etc/ftpd.passwd
account required pam_permit.so

Die genannte Datei /etc/ftpd.passwd kann durch das Werkzeug htpasswd mit Benutzern und Passwörtern befüllt werden.

# Für den ersten Benutzer
htpasswd -c /etc/ftpd.passwd user1
# Für alle folgenden Benutzer
htpasswd /etc/ftpd.passwd userN

Nach einem Neustart von vsftpd mittels dem Befehl /etc/init.d/vsftpd restart ist der neue FTP-Server einsatzbereit.

DNS-Query Limits mit iptables und Burstrate

Seit etwas über zwei Monaten betreibe ich einen OpenNIC Nameserver, über den jeder Mensch auf der Welt Hostnamen in IP-Adressen auflösen kann (mehr zum Nameserver gibt es hier). Jeder Mensch, aber leider auch jeder durch Viren befallene Zombie-Computer. Die massiven Anfragen nach Mailservern führten bereits zweimal dazu, dass mein Router die Anzahl von Anfragen nicht mehr bearbeiten konnte und der Internetzugang sich verabschiedete.

Query Flood! Was tun?

Im Blog von Benny Baumann werden Tips vorgestellt, die sehr spezifisch bestimmte Anfragen mit einfachen iptables Regeln verwerfen. Da ich leider nicht Nachfragen nach den Rootservern ablehnen kann (öffentliche Nameserver müssen hier antworten) und auch leider nicht nach einer einzigen Domain gefragt wird, kam nur eine Limitierung in Frage. Dabei wird die Anzahl der maximal in einem Zeitintervall (zum Beispiel eine Sekunde) verarbeiteten Pakete begrenzt.

Durch Nachfragen bei anderen OpenNIC Serveradmins und Analyse anonymisierter Logfiles konnte ich 5 Anfragen pro Sekunde als Durchschnitt pro IP feststellen. Diese Einstellung brachte zwar Besserung, führte aber dazu, dass bei einem Rechnerstart einige Programmer länger brauchten. Klar, die Anfragen pro Sekunde sind zu stark begrenzt. Die Lösung des Problems möchte ich gern mit euch teilen.

Es wird die Anzahl der Pakete pro Sekunde einer Quell-IP nicht über den Zeitraum einer Sekunde gemessen, sondern über einen längeren Zeitraum. Das würde zu einer Reduzierung der Anfragen führen (fünf pro Sekunde ist trivialierweise mehr als 5 pro zehn Sekunden), also wird die Anzahl der Anfragen mit den Sekunden multipliziert. Jetzt ist es natürlich möglich, alle erlaubten Anfragen in der ersten Sekunde zu senden, was wieder zu einer Überlastung der Anbindung führen würde. Dem wird ein Riegel vorgeschoben, indem die Anzahl der Anfragen pro Sekunde auch limitiert wird, aber eben auf einen höheren als den angestrebten Wert.

Ich habe die Anfragen pro Sekunde auf 5 limitiert, was dazu führt, dass in 7 Sekunden 35 Anfragen erlaubt sind.
Um das Erste-Sekunde Problem zu lösen, sind in jeder der sieben Sekunden nur maximal 15 Anfragen erlaubt.

Skript schreiben statt manuell blockieren!

Hier das Skript für Interessierte:

#!/bin/bash
# This script limits the queries per second to 5/s
# with a burst rate of 15/s and does not require
# buffer space changes

# Requests per second
RQS="15"

# Requests per 7 seconds
RQH="35"

iptables --flush
iptables -A INPUT -p udp --dport 53 -m state --state NEW -m recent --set --name DNSQF --rsource
iptables -A INPUT -p udp --dport 53 -m state --state NEW -m recent --update --seconds 1 --hitcount ${RQS} --name DNSQF --rsource -j DROP
iptables -A INPUT -p udp --dport 53 -m state --state NEW -m recent --set --name DNSHF --rsource
iptables -A INPUT -p udp --dport 53 -m state --state NEW -m recent --update --seconds 7 --hitcount ${RQH} --name DNSHF --rsource -j DROP

rsync,ssh,tar und socat – Große Datenbestände kopieren

Manchmal muss es etwas schneller sein als sonst. Gerade wenn man mit einem zehn Jahre alten Datenbestand von einem Computer auf einen anderen umziehen möchte.

Wie ist dabei der Maximaldurchsatz zu erreichen?

Am Transfer großer Datenbestände sind in erster Linie zwei Komponenten zwangsweise beteiligt. Das Festplatten-Subsystem und das Netzwerk-Subsystem der zu synchronisierenden Computer.

Standardlösung

Da das Problem nicht neu ist und sich selbst in Lehrbüchern wiederfindet gibt es eine Standardlösung: rsync.

rsync -ar --stats --progress /home/meinBenutzer/*Ü meinBenutzer@neuerComputer:~/

Soll es mit rsync, dass auf SSH für den Transfer setzt, schneller gehen, passt man die Chiffre an. Das funktioniert durch die Option -e "ssh -c arcfour", die den RC4 Stromchiffre verwendet. Der Durchsatz steigt, aber erreicht aufgrund des Overheads der Verschlüsselung und der Integritätsprüfungen, die rsync bietet nicht Netzwerk- oder Festplatten-Maximaldurchsatz.

Mehr Power!

Der Maximaldurchsatz der Festplatte lässt sich erreichen, indem die lesenden und schreibenden Operationen sequentiell durchgeführt werden. Ein Programm, dass die Daten sequentiell liest ist tar. Indem man tar anweist, das erzeugte Archiv auf die Standardausgabe zu senden, kann es über das LAN transportiert werden. Um hierbei den Prozessor nicht einzuspannen, erfolgt die Übertragung unverschlüsselt und unkomprimiert mit socat.

Das geht wie folgt:

Auf dem Server (Empfänger)

socat tcp-listen:31337,rcvbuf=67108864,dontroute stdout | tar xvf - -C ./

Auf dem Client (Sender)

tar cvf - ./* | socat stdin tcp:192.168.my.ip:31337,sndbuf=67108864,dontroute

Erwähnenswert ist besonders die Option dontroute, durch die sichergestellt wird, dass der Datenverkehr der sensiblen privaten Daten nicht das lokale Netz verlässt. Mit den Optionen rcbuf und sndbuf werden die TCP-Puffer auf beiden Seiten vergrößert und das Auto-Tuning des Kernels umgangen.

Fazit

Durch die Vermeidung von Verschlüsselung, Komprimierung und der manuellen Vergrößerung der Sende- und Empfangspuffer sollte theoretisch jetzt der Maximaldurchsatz erreicht werden können. Bei einem sehr unwissenschaftlichen Test bestätigte sich die Vermutung, dass socat mit tar schneller ist.

Beim Kopieren von 560 Gigabyte von einem mit 170 MB/sec lokal gemessenen Software-RAID1 zu einem 411 MB/sec lokal gemessenen Software-RAID1 erreichte rsync einen Maximaldurchsatz von 340 MBit/sec, tar mit socat reizte die vollen 988 MBit/sec aus.

Alternativer DNS Server

EDIT: Aktuelle Informationen zum DNS-Server und dessen IP gibt es in diesem Beitrag.

Seit spätestens 2003 betreibe ich meinen DNS Server selbst zuhause. Das bringt mir gerade beim surfen im Internet einen kleinen Geschwindigkeitsvorteil, weil oft aufgerufene Webseiten im Cache bleiben. Durch einen glücklichen Zufall kann ich den Dienst jetzt allgemein zugänglich zur Verfügung stellen.

Die IP-Adresse des DNS Servers lautet:

EDIT: Siehe hier.

DNS ist das Telefonbuch des Internets. Um diesen Blog zu erreichen wurde zum Namen falkhusemann.de die zugehörige (IP-)Nummer bestimmt. Die zuständigen voreingestellten DNS-Server werden meist durch den jeweiligen Internetanbieter betrieben.

Personenbezogene Daten speichert mein DNS Server nicht. Einzig aggregierte Statistiken werden erzeugt und sind für jeden hier einsehbar. Eine Funktionsgarantie für den Dienst kann ich natürlich nicht geben, eine Auswertung der Verfügbarkeit seit Inbetriebnahme aber schon.

Zusätzlich zum Auflösen der ICANN Domains wie .de oder .com ist der Server in das OpenNIC Projekt eingebunden und kann damit eine Menge alternativer TLDs wie .geek oder .null auflösen. OpenNIC ist ein nicht-kommerzielles Projekt, dass alternative DNS Server zur Verfügung stellt.

Eine interaktive Anleitung, wie OpenNIC eingebunden werden kann, ist hier aufrufbar. Der CCC bietet eine allgemein Anleitung für viele Betriebssysteme.

Mailscanner running with -T switch und Lock.pm

Wird das Debian Squeeze MailScanner Paket mit postfix eingesetzt, tut sich erstmal nichts.

Problem

root@outpost:~# MailScanner --debug
# [...] Gekürzt [...]
Insecure dependency in open while running with -T switch at /usr/share/MailScanner//MailScanner/Lock.pm line 358.

Das Ergebnis ist, dass MailScanner nicht startet. Schaut man sich die an Zeile 347 beginnende Funktion openlock() an, wird schnell klar, worum es geht: File Locking. Und der Fehler ist eigentlich keiner, sondern ein Feature. Leider ein Feature von perl, dass in MailScanner nicht vollständig umgesetzt wird. Einige Module von MailScanner werden im Perl Taint Mode ausgeführt, bei dem keiner Eingabe vertraut wird.

Dabei muss jede Eingabe vom Programmierer als zulässig bestätigt werden, was für die Postfix Anbindung anscheinend noch nicht geschehen ist. Der Thread auf der MailScanner Mailinglist zu diesem Thema (einer von vielen) bestätigt das.

Workaround

Man verändert das Hauptskript unter /usr/sbin/MailScanner und ergänzt am Ende des Shebang ein großes -U. Damit wird Eingaben wieder vertraut.

#!/usr/bin/perl -I/usr/share/MailScanner/ -U

Transmission auto-delete Quota Skript

Möchte man immer die aktuellsten frei zugänglichen Linux-Distributions Torrents herunterladen, um andere Nutzer durch die eigene Bandbreite zu unterstützen, wird irgendwann die Festplatte voll. Dieses Skript schafft Abhilfe.

#!/bin/bash
# transmission-quota.bash
#
# FIFO quota for transmission-daemon.
# This script forces a maximum size upon
# your transmission download directory
# by deleting the oldest torrent, until
# the quota is met again.
#
# Run regularily from cron:
# */5 * * * *     /home/torrent/transmission-quota.bash
#

# Where is your transmission download directory?
TR_DIR="/path/to/your/transmission/downloads"

# How big in bytes may the download directory grow?
TR_MAXBYTES=1879048192000

# Wheres your transmission-remote binary?
CLIPATH="/usr/bin/transmission-remote"

# Login:Password, if applicable
TR_UPASS="myUsername:myPassword"

# URL to Transmission RPC Interface (usually http://X:9091/transmission/rpc)
TR_URL="http://localhost:9091/transmission/rpc"

# # # No Configuration needed below here # # #

while [ "`du -sb ${TR_DIR} | awk '{print $1}'`" -gt "${TR_MAXBYTES}" ]; do
        CURRENT_SEEDING=`${CLIPATH} ${TR_URL} -n ${TR_UPASS} -l | awk '{ if ($2 == "100%") print $1 }' | sed 's/*$//'`
        OLDEST_TIMESTAMP=`date +%s`

        for torrent in ${CURRENT_SEEDING}
        do
                DATE_ADDED=`${CLIPATH} ${TR_URL} -n ${TR_UPASS} -t ${torrent} -i |grep "Date added:" | sed 's/Date added://g'`
                TIMESTAMP_ADDED=`date --date "${DATE_ADDED}" +%s`
                if [ "${TIMESTAMP_ADDED}" -lt "${OLDEST_TIMESTAMP}" ]; then
                        OLDEST_TIMESTAMP=${TIMESTAMP_ADDED}
                        OLDEST_ID=${torrent}
                fi
        done
        ${CLIPATH} ${TR_URL} -n ${TR_UPASS} -t ${OLDEST_ID} --remove-and-delete &> /dev/null
        DAYS_AGO=`echo $(( ( $(date +%s) - $OLDEST_TIMESTAMP ) / 3600 / 24 ))`
        echo deleted torrent id ${OLDEST_ID} from ${DAYS_AGO} days ago | logger -t transmission-quota
done