Category Archives: Maximaldurchsatz

Neuausrichtung der Beiträge

Nach der Pause ist vor der Pause. Nicht ganz, denn einige Veränderungen, die mir seit längerer Zeit unter den Nägeln brennen, werde ich nach der Blog-Pause umsetzen. Die erste Änderung dürfte schon aus meinem ersten Satz herauszulesen sein: Hier blogge ich, Falk.

Bisher habe ich mein möglichstes gegeben, meine persönliche Meinung zu Technologien aus dem Blog herauszuhalten. Das wird sich Schritt für Schritt ändern. Für euch bedeutet das eine direktere Ansprache sowie an passender Stelle kleine Einschübe mit meiner Meinung zu einer Software oder Dienstleistung. Ich glaube, dass Meinungen nur dann für den Leser einen Mehrwert bieten, wenn sie klar vom Inhalt abgegrenzt sind.

Als zweite Änderung werde ich mehr Artikelserien und Tests veröffentlichen. Man muss nicht immer das Rad neu erfinden, um ein gutes Ergebnis zu erhalten. Die dritte und vorerst letzte Änderung wird die Kenntnisunabhängige Ansprache sein. Einige Artikel meines Blogs sind für Anfänger geschrieben. Da ich meinem Blog leider weniger Zeit widmen kann, werde ich meine Artikel hauptsächlich an technisch versierte Leser richten. Ich hoffe inständig, dass es niemanden betrifft, aber falls doch: Kommentar mit Fragen hinterlassen.

Bildschirmfoto - 17.11.2014 - 22:05:42

Der Neustart wird mit einem ausführlichen Test des VPN-Anbieters hide.me beginnen, die mir zu diesem Zweck einen Zugang zur Verfügung gestellt haben.

Der Testplan liegt dem Anbieter zur Zeit zur Ansicht vor..

Ausnahmen für OpenVPN Verbindung mit iptables, ipset und Policy-based Routing

Wer auf eine permanent bestehende VPN-Verbindung angewiesen ist, oder einfach etwas paranoid, möchte einige Ziel-IPs oder Hostnamen im Internet trotzdem gern direkt ansprechen. Dazu zählt zum Beispiel der Speedtest des eigenen Internetanbieters oder Distributions-Spiegelserver. Ohne den Umweg über die VPN-Verbindung wird der Maximaldurchsatz der eigenen Internetanbindung erreicht, was bei vielen Diensten von Vorteil ist. Darüber hinaus lässt sich so zum Beispiel eine Trennung zwischen anonymisiert besuchten Webseiten und nicht anonymisiert besuchten Webseiten herstellen. Wie das geht? Mit iproute2, ipset und einer iptables-Regel.

Zwei Routing-Wege zu unterschiedlichen Zielen

Zwei Routing-Wege zu unterschiedlichen Zielen

Um das Ziel zu erreichen, wird eine zweite Routing-Tabelle angelegt, die den zur Vorgabe (default route) unterschiedlichen Router enthält. Basierend auf der Ziel-IP oder dem Ziel-Hostnamen der Ausnahme-Ziele wird der Kernel die Routing-Entscheidung abweichend treffen. Dafür wird jedes Paket zu oder von den Ausnahme-Zielen mit einer Markierung versehen.

1. Neue Routing-Tabelle in /etc/iproute2/rt_tables

Zuerst wird durch folgenden Eintrag die neue Routing-Tabelle definiert.

1       novpn

2. Regeln zu /etc/network/interfaces hinzufügen

Folgend werden zwei Regeln für die neue Routing-Tabelle novpn angelegt. Dies muss nicht in der Datei interfaces geschehen, sondern könnte auch auf die Datei /etc/rc.local angewendet werden. Die interfaces Datei bietet sich aber aufgrund des Sachzusammenhangs an. Die beiden Regeln lauten wie folgt.

ip rule add fwmark 1 table novpn
ip route add default via 192.168.178.1 dev eth0 table novpn

Die erste Regel führt dazu, dass die Routing-Entscheidung für durch die Firewall mit dem Marker 1 markierte Pakete von der Vorgabe abweicht. Es wird statt der voreingestellten Routing-Tabelle die Tabelle novpn für die Routing-Entscheidung herangezogen. Die zweite Regel fügt der Tabelle novpn ein default gateway hinzu, dass von der Vorgabe abweicht.

Werden die Regeln in der Datei interfaces ergänzt (für das externe Interface der Firewall), könnte das Ergebnis wie folgt aussehen.

# The external (DMZ) network interface
allow-hotplug eth0
iface eth0 inet static
        address 192.168.178.254
        netmask 255.255.255.0
        network 192.168.178.0
        gateway 192.168.178.1
        dns-nameservers 192.168.178.1
        # check with ip route show table novpn && ip rule
        post-up ip rule add fwmark 1 table novpn
        post-up ip route add default via 192.168.178.1 dev eth0 table novpn

iptables und ipset

Es bleibt die Erstellung einer adequaten iptables Regel. Diese lautet wie folgt.

# Setup ipset
if [ -x /etc/rc.firewall.ipset ]; then
       /etc/rc.firewall.ipset || echo "problem loading ipsets"
fi
iptables -A PREROUTING -i $LAN -t mangle -m set --match-set Direct_Hosts dst  -j MARK --set-mark 1

Die Regel muss an den PREROUTING-Chain angehängt werden, um die Routing-Entscheidung beeinflussen zu können (siehe hier). Umgangssprachlich ausgedrückt wird der Marker jedes Pakets, dessen Ziel in der Tabelle Direct_Hosts vorkommt, auf 1 gesetzt. Dieser Marker führt dazu, dass die so gekennzeichneten Pakete die alternative Routing-Tabelle verwenden.

Bleibt die Einrichtung des ipsets Direct_Hosts. Fehlt das Programm ipset, kann es mit dem Befehl apt-get install ipset installiert werden. Um einzelne Ziele in einem ipset zu verwalten, bietet sich die Datenstruktur hash:ip an, die das geforderte leistet. Abkürzend folgt das fertige Beispiel.

#!/bin/bash
#
# Direct_Hosts - Hosts to connect directly to (no VPN)
#
ipset destroy Direct_Hosts
ipset create Direct_Hosts hash:ip hashsize 4096
# Hosts 
ipset add Direct_Hosts -! '[speedtest-1.unitymedia.de]'
ipset add Direct_Hosts -! '[speedtest-2.unitymedia.de]'
ipset add Direct_Hosts -! web.de
ipset add Direct_Hosts -! 8.8.8.8

Zu beachten ist bei ipset-Einträge, dass Hostnamen bei der Erstellung des Sets aufgelöst werden und nur die IP-Adresse gespeichert werden. Hostnamen, die Bindestriche enthalten, müssen in eckige Klammern gesetzt werden. Um die Auswertung der eckigen Klammern in der Laufzeitumgebung (bash) zu verhindern, werden einfache Anführungszeichen verwendet.

Abfall der Geschwindigkeit von Festplatten von Außen nach Innen

In der Fachliteratur wird oft ein Abfall der Geschwindigkeit bei Festplatten von den äußeren zu den inneren Bereichen beschrieben. Natürlich klingt dieser Effekt sehr plausibel, aber beobachten kann man ihn im Betrieb meist nicht.

Darum hier ein Beispiel einer Western Digital RED 3TB NAS-Festplatte während eines badblocks Tests. Dabei wird die Festplatte einmal komplett gelesen.

sdo-pinpoint=1376161314,1376191959

Deutlich ersichtlich der Abfall von über 150 MB/sec auf 80 MB/sec.

Synology DS213J User-Review und Quelldateien

f-DS213j-front

Im Forum des Online-Magazins Hardwareluxx ist mein Test des NAS-Systems DS213J erschienen, der sich kritisch mit der Sicherheit und Geschwindigkeit des Einsteiger-NAS auseinandersetzt. Einzusehen hier:

[Lesertest] Synology DS213j – Sicherheit und Maximaldurchsatz

Die Quelldatei für den Benchmark mit Ergebnissen aus allen einzelnen Testläufen ist hier zu finden:

Benchmark Tabelle (ODS)

Das Shellskript für den Benchmark lokal einbindbarer Dateisysteme (NFS und CIFS) lautet wie folgt:

#!/bin/bash -x
HOSTNAME="123"
LOGIN="123"
PASS="123"
SHARE="benchmark"

echo `date` >> bench.log
echo "Iteration,10GB Upload, 1GB Upload, 10GB Download, 1GB Download" >> bench.log
for i in {1..10}
do
	# Cleanup
	rm -f ./mount/testfile10G
	rm -f ./mount/testfile1G

	START10=`date +%s`
	cp ./testfile10G ./mount/
	END10=`date +%s`
	TIME10=`echo  "10240 / ( $END10 - $START10 )" | bc`

	START1=`date +%s`
        cp ./testfile1G ./mount/
	END1=`date +%s`
	TIME1=`echo "1024 / ( $END1 - $START1 )" | bc`

	START10D=`date +%s`
	cp ./mount/testfile10G /dev/null
	END10D=`date +%s`
	TIME10D=`echo "10240 / ( $END10D - $START10D )" | bc`

	START1D=`date +%s`
	cp ./mount/testfile1G /dev/null
	END1D=`date +%s`
	TIME1D=`echo "1024 / ( $END1D - $START1D )" | bc`
	echo $i,$TIME10,$TIME1,$TIME10D,$TIME1D >> bench.log
done

Das nahezu identische Skript für den Test mittels FTP ( benchFTP.bash ) steht auch zur Verfügung.

Bidirektionale IP-Benchmarks mit iperf durch NAT-Gateways

Um die Geschwindigkeit der Anbindung zwischen zwei Punkten im Internet zu messen wird der Benchmark iperf eingesetzt. Leider beinhaltet dieser in der Standardversion keine Möglichkeit als Client auch Daten zu empfangen und so nicht nur den Upload vom Client zum Server, sondern auch den Download vom Server zum Client zu messen. Matt Tierney stellt in seinem GitHub-Repository eine mit dem Patch von Prof. Lucas Nussbaum (iperf reverse mode) versehene iperf Version zur Verfügung, die dieses Problem löst.

Diese gepatchtet Version ist sehr empfehlenswert. Zusammengefasst kann damit in beide Richtungen der Maximaldurchsatz gemessen werden, ohne im Router zuhause Ports öffnen zu müssen. Das neue --reverse Flag macht es möglich.

 

Große Datenbestände mit lftp synchronisieren

Im letzten Artikel zum File Transfer Protocol wurde die moderne Einrichtung eines FTP-Servers vorgestellt. Jetzt soll ein Verzeichnis des FTP-Servers mit einem lokalen Server synchronisiert werden.

Besonders der Maximaldurchsatz soll dabei errreicht werden. Dazu bieten viele Windows FTP-Clients zwei Modi an.

  • Segmentiert
    bedeutet, dass eine Datei in logische Abschnitte geteilt und mit mehreren Verbindungen heruntergeladen und auf dem Zielcomputer zusammengesetzt wird.
  • Threaded
    bedeutet mehrere Dateien gleichzeitig über mehrere Datenverbindungen herunterzuladen.

Sowohl Threaded wie auch Segmented Übertragungen sollen gegebenfalls vorhandene Durchsatzprobleme bei Verwendung einer einzigen Verbindung umgehen. Das geht doch auch mit Linux?

Im folgenden wird ein Skript vorgestellt, dass lftp so in einer screen Sitzung startet, dass die Vorteile der Segmented und Threaded Verfahren zusammen mit den Vorteilen einer Hintergrundsitzung bietet. Dabei kommt der FTP-Client lftp zum Einsatz, der sich zur Automatisierung besonders gut eignet, weil er umfangreiche Konfigurationsmöglichkeiten bietet.

lftp Konfigurieren

Zuerst muss die notwendige Software installiert werden.

apt-get install lftp screen

Bevor das Skript eingesetzt werden kann, muss lftp konfiguriert werden, indem im Verzeichnis ~/.lftp/ des ausführenden Benutzers eine Datei rc mit folgendem Inhalt angelegt wird.

# GENERAL
set color:use-color true

# FTP
set ftp:list-options -a
set ftp:passive-mode true
# Send multiple commands async.
set ftp:sync-mode false

# SEGMENTED
set pget:default-n 4
set pget:save-status 30

# DIRECTORES
set mirror:order "*.txt [rR]eadme"
set mirror:use-pget-n 4
set mirror:parallel-transfer-count 2
set mirror:parallel-directories true

# Always SSL!
set ftp:ssl-force true

# Foreground cmds first!
set net:connection-takeover true
# Disconnect after 30mins idle!
set net:idle 1800
# Max 32 connections to everywhere!
set net:connection-limit 32

Synchronisations-Skript

Das folgende Skript synchronisiert das Verzeichnis REMOTE_DIR mit dem Verzeichnis LOCAL_DIR. Dafür wird eine screen Sitzung mit dem Namen lftp-sync im Hintergrund gestartet, in der lftp gestartet wird. An diese Sitzung sendet das Skript den mirror Befehl und beendet sich nach dem sichergestellt ist, dass eine solche Sitzung auch existiert.

#!/bin/bash

# Information about the source
HOST="123.123.123.123"
PORT=21
USER="sync"
PASS="foobar"

# download target
LOCAL_DIR="/mnt/123.123.123.123/forschungsdaten"

# source dir
REMOTE_DIR="/forschungsdaten"

function lftpcmd()
{
screen -S lftp-sync -p 0 -X stuff "$1"`echo -ne '\015'` 2>&1 >> /dev/null
}
function lftpkill()
{
screen -ls lftp-sync | grep lftp-sync | cut -d "." -f 1 | sed -e 's/^[ \t]*//' | xargs kill -9 $1
screen -wipe
}

# Start background lftp session if none or more than 1 is found running
if ! [ "`screen -ls lftp-sync | lftp-sync | wc -l`" -eq 1 ]; then
if [ "`screen -ls lftp-sync | grep lftp-sync | wc -l`" -gt 1 ]; then
lftpkill
fi
# Start a new session
screen -dmS lftp-sync lftp
# Set up the connection using commands sent to screen
lftpcmd "open ftp://$USER:$PASS@$HOST:$PORT/"
fi

# Add a new sync to the queue
lftpcmd "queue mirror -x ^\Incoming/$ -p \"${REMOTE_DIR}\" \"${LOCAL_DIR}\""

Transmission uTP and UDP buffer optimizations

Recently in debug mode on a box running Transmission to seed BackTrack Torrents:

[17:42:40.319] UDP Failed to set receive buffer: requested 4194304, got 262142 (tr-udp.c:75)
[17:42:40.319] UDP Please add the line "net.core.rmem_max = 4194304" to /etc/sysctl.conf (tr-udp.c:80)
[17:42:40.319] UDP Failed to set send buffer: requested 1048576, got 262142 (tr-udp.c:86)
[17:42:40.319] UDP Please add the line "net.core.wmem_max = 1048576" to /etc/sysctl.conf (tr-udp.c:91)

This message tries to tell us, that for some reason, Transmission would like to have 4 Megabytes of receive buffer and 1 Megabyte send buffer for it’s UDP socket. It turns out that the support for uTP, the uTorrent transport protocol, is implemented using a single socket.

By tuning the two variables, higher throughput can be achieved more easily using uTP.

Here is the relevant part from the changeset:

Since we’re using a single UDP socket to implement multiple uTP sockets,
and since we’re not always timely in servicing an incoming UDP packet,
it’s important to use a large receive buffer. The send buffer is probably
less critical, we increase it nonetheless.

Four Megabyte might seem huge for embedded clients, but running behind a fast dedicated connection, it might even be too small when Transmission has to handle hundreds of connections. I recommend to use 16 Megabyte for receive buffering and 4 for the send buffer. That is, because uTP implements a retransmission algorithm and by scaling up the buffers we achieve less retransmits because of dropped datagrams. Let’s set it up that way.

echo 'net.core.rmem_max = 16777216' >> /etc/sysctl.conf
echo 'net.core.wmem_max = 4194304' >> /etc/sysctl.conf
sysctl -p

WordPress mit CoralCDN beschleunigen

Meine potenzielle beste Ehefrau von Allen hat auch einen Blog, einen sehr bilderlastigen Blog. Nachdem sie selbst, dutzende kleiner bunter Boxen und Kästchen, lebendige Pflanzen, ein Kater sowie ein wunderschöner Gummibaum eingezogen sind, zieht heute auch ihr Blog nach. Beim Kopieren der über 200 Megabyte an Bildern befiel mich das kalte Grausen.

Das kostenlose Content Delivery Network CoralCDN hilft hier weiter. Indem eine beliebige URL um nyud.net ergänzt wird, kann Coral eingebunden werden. Das CoralCDN meldet sich wie folgt in der Apache access.log:

164.107.abc.def - - [04/Jul/2012:19:58:54 +0200] "GET /wp-content/uploads/2012/07/img_0870.jpg HTTP/1.0" 200 100628 "-" "CoralWebPrx/0.1.20 (See http://coralcdn.org/)"

Nach dem Ersten Aufruf, wie oben abgebildet, ist das Bild oder die Webseite im CDN gespeichert und kann von dort bei jedem nächsten Aufruf schneller ausgeliefert werden. Um nicht jede Adresse um nyud.net ergänzen zu müssen, wird im Verzeichnis wp-content/uploads/ eine .htaccess Datei angelegt, die alle Anfragen um .nyud .net ergänzt. Dabei ist zu beachten, dass Anfragen vom CoralCDN selbst nicht umgeschrieben werden.

RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} !^CoralWebPrx
RewriteCond %{QUERY_STRING} !(^|&)coral-no-serve$
RewriteRule ^(.*)$ http://%{HTTP_HOST}.nyud.net/wp-content/uploads/$1 [R,L]

Gegebenenfalls muss für die Funktion der htaccess noch mittels a2enmod rewrite der mod_rewrite aktiviert werden, oder die Aktivierung beim Provider erfragt werden. Da dieser Datenverkehr einspart, dürfte die Aktivierung problemlos sein.