[Raspberry Pi ] Funksteckdosen mit dem Raspberry Pi verwalten

Funksteckdosen mit dem Raspberry Pi verwalten

17.01.2015 | 10:10 Uhr | Thomas Springer

Artikel empfehlen:

 

 

 

 

 

 >Übersicht

<![if !supportLists]>·         <![endif]>Preisvergleich

<![if !supportLists]>·         <![endif]>ebay Angebote

<![if !supportLists]>·         <![endif]>Alle Artikel

Funksteckdosen: Schalten & walten

VergrößernFunksteckdosen: Schalten & walten

© Thomas Springer

Ein Funkmodul für wenige Euro macht den Raspberry Pi zur heimischen Steuerzentrale, die über das Haus verteilte Funksteckdosen schaltet – bei Bedarf auch über das Netzwerk und mit dem Smartphone.

https://bilder.pcwelt.de/1411620DXEvXZ_03100x07680.jpg

Funksteckdosen sind im Dreier- oder Sechserpack samt Fernbedienung in fast jedem Baumarkt erhältlich, oft schon für wenige Euro. Für sich alleine sind die Steckdosen begrenzt interessant: Die mitgelieferte Fernbedienung ist nie zur Hand, wenn man sie braucht, und ist so klein, dass sie gerne zwischen den Sofaritzen verschwindet. Mit einem günstigen Sender und ein wenig Software machen Sie den Raspberry zur Schaltzentrale, die Steckdosen per Browser, Makro oder Handy von überall her steuert. Was Sie dafür benötigen, ist ein Funkmodul mit 433 MHz. Ein Set mit Sender und Empfänger kostet bei Ebay oder Amazon zwischen einem Euro (aus China) und rund vier Euro (aus Deutschland) und ist über eine Suche nach „RF Link Arduino“ schnell zu finden. Die Sets werden in erster Linie für den Arduino-Mikro-Controller verkauft, funktionieren aber mit einer entsprechenden Software-Bibliothek auch am Raspberry Pi.

Drei Kabel sollt ihr sein: Für die Ansteuerung des Senders zur Übertragung der Befehle an die Funksteckdosen genügt eine einzige Datenleitung des Raspberry Pi plus Spannungsversorgung.

VergrößernDrei Kabel sollt ihr sein: Für die Ansteuerung des Senders zur Übertragung der Befehle an die Funksteckdosen genügt eine einzige Datenleitung des Raspberry Pi plus Spannungsversorgung.

© Thomas Springer

Auswahl: Nicht jede Funksteckdose ist geeignet

Funksteckdosen gibt es inzwischen nicht nur optisch, sondern auch technisch in großer Vielfalt. Fast alle Arten lassen sich auch mit dem Raspberry steuern. Am einfachsten und zuverlässigsten funktionieren Steckdosen, die sich über zehn Dipschalter einstellen lassen, die hinter einer kleinen Klappe mit kleiner Kreuzschlitzschraube verborgen sind. Steckdosen ohne Dipschalter, insbesondere die aktuell oft als Billigware verkauften selbstlernenden Dosen, lassen sich über den Raspberry oft nur nach längeren Versuchen ansteuern und erfordern je nach Hersteller Software-Anpassungen auf dem Raspberry Pi.

Ein weiterer Nachteil der Billigware ist, dass viele Modelle nach einem Stromausfall oder auch nur einem Wechsel der Steckdose ihre Codierung vergessen und dann neu eingelernt werden müssen. Wir raten deshalb zu Steckdosenmodellen, das sich mit zehn Dipschaltern programmieren lassen. Je nach Hersteller sind die Dipschalter mit 1 bis 10 oder mit 1 bis 5 und A bis D beschriftet – beide Versionen sind gleichermaßen nutzbar. Aktuell kostet ein Dreierset etwa bei Online- Versandhäusern rund zehn Euro (Beispiel:http://www.pollin.de , Artikelnummer 550666). Zunächst sollten Sie Fernbedienung und Steckdosen aufeinander abstimmen. Dazu wird an den fünf Dipschaltern der Fernbedienung und den linken fünf Dipschaltern der Steckdosen der Systemcode eingestellt, über den die Dosen erreichbar sind. Vorsicht: Die Verwendung von 00000 oder 11111 als Systemcode bietet gute Chancen, dass einer Ihrer Nachbarn denselben Code verwendet und damit unter Umständen Ihre Steckdosen schaltet. Funktioniert die Steckdose mit der Fernbedienung, kann die Einrichtung des Raspberry Pi als Schaltzentrale beginnen.

Raspberry 2 Model B

 

 

Die besten verwendungsmöglichkeiten für den Raspberry Pi

Belegung der GPIO-Pins: Diese hat sich zwischen den Raspberry-Pi-Revisionen und Versionen geringfügig geändert. Der hier vorgestellte Aufbau funktioniert aber mit allen Versionen des Raspberry Pi.

VergrößernBelegung der GPIO-Pins: Diese hat sich zwischen den Raspberry-Pi-Revisionen und Versionen geringfügig geändert. Der hier vorgestellte Aufbau funktioniert aber mit allen Versionen des Raspberry Pi.

Prototyp: Schaltung am Breadboard entwerfen

Zunächst muss der Sender mit dem Raspberry verbunden werden. Am einfachsten geht das über ein kleines Breadboard (Steckbrett) und einige Steckkabel. In den meisten Elektronik-Bastelsets sind nur beidseitig männliche Steckkabel dabei. Je nachdem, ob Sie ein Steckbrett verwenden oder den Empfänger direkt anschließen, brauchen Sie aber weiblich/männlich oder weiblich/weiblich.

Tipp : Die meisten Steckkabel lassen sich durch Abknipsen des metallenen Aderendes in ein weibliches Ende improvisieren, das sich vorsichtig auf einen Pin-Anschluss aufstecken lässt. Den Sender stecken Sie mit seinen drei oder vier Pins am besten direkt quer auf das Steckbrett. Verbinden Sie die dann VCC (rot) mit Pin 2 (5 Volt) und Pin 6 (Erdung) des Raspberry Pi. Die Datenleitung zum RF-Sender erwarten fast alle Programme zur Steckdosensteuerung an Pin 11 (GPIO 17) des Raspberry. Die Antenne wird bei einigen Sendern über einen Pin geführt, bei anderen ist ein Anschluss auf dem Board. Die passende Länge errechnet sich über die Faustformel (Lichtgeschwindigkeit/Frequenz)/4. Eine optimale Länge für 433,92 MHz wären 17,2 Zentimeter – in der Praxis tut es aber ein beliebiges Drahtstück mit einer Länge um die 17 Zentimeter, das mit dem Antennen-Pin verbunden oder mit auf der Platine eingehakt oder verlötet wird.

Wiring Pi: vom Mikro-Controller Arduino inspiriert

Um den Raspberry Pi mit einem RF-Sender zu verbinden, gibt es inzwischen eine Vielzahl von Programmen. So gut wie alle bauen auf der GPIO-Bibliothek von Gordon Henderson auf, der die Funktionalität der Arduino-Bibliothek „Wiring“ auf den Raspberry portiert hat. Die Bibliothek wird am einfachsten direkt über Git installiert (drei Zeilen):

sudo apt-get install build-essential git-core
cd ~ && git clone git://git.drogon.net/wiringPi
cd wiringPi && ./build

Damit ist die Grundlage zur Nutzung der GPIO-Ports geschaffen. Ein einfaches, aber leistungsfähiges Projekt zur Ansteuerung von Funksteckdosen ist unter dem Namen „Raspberry Remote“ veröffentlicht. Auch hier können wir die Quelltextverwaltung Git zum Herunterladen des Programms verwenden (zwei Zeilen):

cd ~ && git clone git://github.com/xkonni/raspberry-remote.git
cd raspberry-remote

Raspberry Remote besteht aus einem Kommandozeilenprogramm zum Schalten der Steckdosen sowie einem Server-Teil, der auf einem frei wählbaren Port im Netz zuhört und Steckdosen auf Zuruf schaltet. Das Kommandozeilenprogramm wird mit

sudo make send

kompiliert. Mit „send“ lassen sich beliebige Steckdosen aus- und anschalten. Um eine Steckdose zu schalten, rufen Sie das Programm mit folgenden Parametern auf:

sudo ./send <Systemcode> <Steckdosennummer> <Zustand>

Die Codes ergeben sich aus der Stellung der Dipschalter. Der fünfstellige Systemcode entspricht der Stellung der ersten Dipschalters an der Steckdose: 0 für aus, 1 für an. Stehen diese Schalter alle auf ein, wäre der Systemcode die 11111. Stehen nur der erste und der letzte Schalter auf 1, wäre der Systemcode 10001.

Die Steckdosennummer ergibt sich aus den rechten fünf Dipschaltern, von denen nur einer auf 1 stehen darf. Die möglichen Gerätecodes sind 1,2,3,4 und 5, je nachdem, welcher der fünf rechten Dipschalter auf „on“ steht. Es darf nur einer der Schalter auf „on“ stehen. Der dritte Parameter gibt an, ob die Funksteckdose an („1“) oder ausgeschaltet werden soll („0“). Ein Beispielaufruf zum Einschalten der Dose sieht dann so aus:

sudo ./send 10001 1 1

Damit sollte, sofern die Dipschalter entsprechend gesetzt sind, die Steckdose angehen. Der sendende Raspberry hat übrigens keine Möglichkeit zu erkennen, ob und wenn ja was wirklich passiert ist: Es gibt keinen Rückkanal, über den die Funksteckdose Vollzug oder eventuelle Fehler melden könnte.

Die maximale Zahl schaltbarer Steckdosen ist 160. Sie ergibt sich aus den möglichen Dipschalterstellungen nach der Formel: (2*2*2*2*2)*5 oder einfacher 2 hoch 5*5.

Displays am Raspberry Pi anbringen

Schalten übers Netz: automatisch per Script

Die Steckdosen über eine SSH-Konsole schalten zu können ist ein nettes Spielzeug, für eine echte Anwendung aber etwas unpraktisch – weder kann man übers Netz schalten noch kann man externe Geräte einbinden. Interessanter wird es, wenn man den in Rasberry Remote enthaltenen Server startet. Dazu müssen Sie den Quellcode etwas anpassen. Verwenden Sie den Befehl nano ~/raspberry-remote/daemon.cpp und ändern die Zeile „nPlugs=10“ zu „nPlugs=1110“.

Standardmäßig ist der Server über Port 11337 erreichbar. Wem Sie dies ändern wollen, tragen Sie eine andere Nummer hinter „Port“ im Quellcode von „daemon.h“ ein. Mit

sudo make daemon

wird der Hintergrundprozess (Daemon) dann kompiliert. Mit

sudo ./daemon >/dev/null &

starten Sie den Server als Hintergrundprozess. Bedient wird der Dämon über eine simple TCP-Netzwerkverbindung, zum Beispiel über Netcat oder ähnliche Programme. Um beispielsweise eine Steckdose anzuschalten, geben Sie auf der Kommandozeile an:

echo -en "Codierung"|nc -w 1 <ip> <port>

Als IP geben Sie die IP-Nummer ihres Raspberry Pi an und als Port den TCP-Port, auf den der Server lauscht. „Codierung“ besteht aus dem Systemcode wie bei „send“, gefolgt von „0“ und der Dosennummer. In unserem Fall wäre das etwa

echo -en "1000101"|nc -w 1 192.168.178.25 11337

wobei der Parameter „-w“ dafür sorgt, dass Netcat die Verbindung zum Dämon nach einer Sekunde selbsttätig wieder trennt. Damit ist die Funksteckdose also schon mal am Netz und kann von beliebigen Applikationen ein- und ausgeschaltet werden, sofern diese TCP-Socket-Verbindungen aufbauen können. Sinnvoll ist diese Art der Ansteuerung in erster Linie für Script-Sprachen wie Python oder Perl, die man auf diese Weise zum Steuern von Funksteckdosen über das lokale Netzwerk oder das Internet verwendet. Es besteht jedoch ein gewisses Risiko, wenn man den Port des Dämons für das gesamte Internet freigibt. Ein Missbrauch könnte unter Umständen das Raspberry-Pi-System samt dem dahinterliegenden Netzwerk für einen Angreifer offenlegen. Wenn Sie das System also in einem fremden Netz oder dem Internet über TCP-Sockets erreichbar machen, sollten Sie unbedingt den Zugriff über IP-Tables oder ein VPN auf autorisierte Kommunikationspartner beschränken.

Universelles Schalten: ein und aus per Browser

Die Socket-Verbindung des Dämons bringt die Funksteckdosen ans Netz, die Bedienung erfordert aber immer noch ein wenig Programmierung oder den Aufruf hässlicher Befehlszeilen auf der Konsole. Raspberry Remote hat auch hier Abhilfe: Im Verzeichnis „./webinterface“ finden Sie eine Weboberfläche, mit der man die Funksteckdosen in den Browser bringt. Die Weboberfläche benötigt einen Webserver wie Apache und PHP. Dies lässt sich mit dem Kommando

sudo apt-get install apache2 php5

installieren, falls noch nicht vorhanden. Bringen Sie dann das Script-Verzeichnis in das Wurzelverzeichnis des Webservers:

mv ~/raspberry-remote/webinterface/* /var/www/funk

und passen Sie dort die Konfigurationsdatei an:

nano /var/www/funk/config.php

Wenn der Dämon auf dem selben Raspberry Pi läuft wie der Webserver, setzen Sie folgende Variable:

$target=$_SERVER['SERVER_ADDR']

Schaltung im Browser: Die Weboberfläche zum Ein- und Ausschalten von Funksteckdosen ist auf dem Raspi schnell installiert.

VergrößernSchaltung im Browser: Die Weboberfläche zum Ein- und Ausschalten von Funksteckdosen ist auf dem Raspi schnell installiert.

Laufen Webserver und Dämon auf verschiedenen Rechnern, geben Sie hier die IP-Nummer des Dämons an, den der Webserver ansprechen soll. Die Variable „$port“ setzen Sie auf die Portnummer, unter welcher der Dämon erreichbar ist. Unter „$config“ können Sie in einem Array beliebig viele Schaltaktoren definieren. Sie geben wie gehabt als Parameter den Systemcode, die Dosennummer und eine frei wählbare Textbeschreibung für diese Dose an. Nun können Sie über den Browser unter<ip>/funk das Kommando-Interface zum Schalten aufrufen.

Mit der Weboberfläche ergibt sich die Option, auf anderen, tastaturlosen Geräten wie etwa Smartphones oder Tablets zu schalten. Sie können dafür einfach ein Lesezeichen auf dem Desktop des Gerätes hinterlegen. Für kleinere Displays können Größe und Layout der Schalterquadrate im Quellcode leicht verändert werden, so dass bei Bedarf auch mehr Geräte auf das Handydisplay passen. Auch über das Webinterface kann nicht nur per Fingerzeig oder Mausklick, sondern auch ganz direkt geschaltet werden. Geben Sie dafür einfach beim Aufruf die Parameter in der URL an. Ein Beispiel:

 http://<ip>/funk/index.php?group=10001&switch=01&action=1

Die Parameter sind dieselben wie oben, „action=1“ heißt, dass die Steckdose eingeschaltet wird. Dafür gibt es dafür viele nützliche Anwendungen: So können Sie etwa den Strom an Peripheriegeräten wie Scanner, Drucker oder externer Festplatte einschalten, indem Sie die URL in einer Verknüpfung ablegen.

Tipp: Eine alternative Methode mit einer Android-App und Sprachsteuerung ist hierbeschrieben.

Pilight Zusätzliche Funktionen für Funksteckdosen

Neben dem hier vorgestellten Raspberry Remote gibt es eine Reihe von Paketen, die teils eine Vielzahl verschiedener Steckdosentypen schalten, Unterstützung für Dimmer bieten oder eine komplexere Weboberfläche bieten. Wer einen Steckertyp ohne Dipschalter verwenden will, hat mit „ Pilight “ eine komplexe und vielseitige Umgebung, die breite Hardware-Unterstützung und in Verbindung mit einem Empfängermodul sogar einen Lernmodus bietet.

Dieser Artikel stammt aus der LinuxWelt 5/2014

Die neue Linux-Welt 5/2014 finden Sie jetzt am Kiosk und im PC-WELT Shop.

Zehn Top-Systeme für den USB-Stick – der Linux-Multiboot-Stick für jeden Einsatzzweck, die besten Power-Tricks für Mint 17 – das und mehr finden Sie in der neuen LinuxWelt 5/2014 . 

 

[bash] Given the IP and netmask, how can I calculate the network address using bash?

Given the IP and netmask, how can I calculate the network address using bash?

 

 

In a bash script I have an IP address like 192.168.1.15 and a netmask like 255.255.0.0. I now want to calculate the start address of this network, that means using the &-operator on both addresses. In the example, the result would be 192.168.0.0. Does someone have something like this ready? I’m looking for an elegant way to deal with ip addresses from bash

 

up vote28down voteaccepted

Use bitwise & (AND) operator:

$ IFS=. read -r i1 i2 i3 i4 <<< "192.168.1.15"
$ IFS=. read -r m1 m2 m3 m4 <<< "255.255.0.0"
$ printf "%d.%d.%d.%dn" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
192.168.0.0

Example with another IP and mask:

$ IFS=. read -r i1 i2 i3 i4 <<< "10.0.14.97"
$ IFS=. read -r m1 m2 m3 m4 <<< "255.255.255.248"
$ printf "%d.%d.%d.%dn" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
10.0.14.96

shareimprove this answer

edited Aug 26 ’14 at 6:36

answered Mar 15 ’13 at 10:18

 

https://www.gravatar.com/avatar/21f80e8ae8c0da98241d8a0e07f94e7b?s=32&d=identicon&r=PG

 

kamituel

19.6k24267

 

1

 

Thank you so much! Exactly what I was looking for, beautiful! – Christian Mar 15 ’13 at 16:18

  

 

This is brilliant. Thank you for taking the time to develop it. – jacksonecac Feb 28 at 20:32

add a comment

 

DSL-Modem im Bridging-Modus betreiben

;widows: 2;-webkit-text-stroke-width: 0px;word-spacing:0px“> Von wogri

Wir hören es fast jeden Tag in den Medien: Großflächige DDoS-Angriffe auf strategisch interessante Ziele im Internet. Bei DDoS-Angriffen haben Angreifer in der Regel private Geräte unter ihrer Kontrolle, ohne dass die Besitzer davon wissen.

Ein mögliches Angriffsziel ist hier der alte DSL-Router, dessen Hersteller schon Jahre kein Softwarupdate mehr ausliefert, und der vor Exploits nur so strotzt. Ein Angriff auf dieses Gerät bleibt unbemerkt, da es weiterhin seinen Dienst verrichtet und der Besitzer kein Fehlverhalten feststellen kann. Während einer DDoS-Attacke sendet das Gerät eine Sequenz von IP-Paketen, die dem privaten User wahrscheinlich nicht auffallen.

Dieser Artikel ist der erste Teil einer Serie aus vorerst zwei Artikeln[1]. Der vorliegende größere Teil beschreibt die Änderung der Router-Einstellungen und die Einrichtung eines Linux-Rechners mit Firewall. Der zweite Teil behandelt die Konfiguration von IPv6 mit DHCP und Firewall.

Wie kann ich mein DSL-Modem schützen?

Abgesehen von regelmäßigen Software-Updates gibt es noch eine mögliche Alternative: Das DSL-Modem vom Internet aus nicht ansprechbar zu machen. Das bedeutet, dass man dem Modem keine öffentliche IP-Adresse zuweist. Ohne öffentliche IP-Adresse ist jedoch keine Teilnahme am Internet möglich. Der Trick ist, das Modem in einen Bridging-Modus zu versetzen und die öffentliche IP-Adresse an einen Linux Software-Router zu vergeben.

Ein weiterer Vorteil dieses Modus ist, dass man frei aus den Netzwerkfähigkeiten von Linux schöpfen kann. VLANs, IPv6 Tunnel, Dynamisches DNS, IPSec, Split Horizon DNS – alles wird möglich. Es muss natürlich erwähnt werden, dass man damit eine Linux-Installation als Angriffsziel im Internet exponiert. Im Unterschied zu proprietären DSL-Boxen hat man hier jedoch selbst die Möglichkeit, das Gerät auf dem aktuellen Softwarestand zu halten, wie auch das Gerät mit Firewall-Regeln komplett von außen unzugänglich zu machen.

Bridging-Modus im DSL-Modem

Nicht jedes DSL-Modem unterstützt den Bridging-Modus. Um herauszufinden, ob ein DSL-Modem dazu fähig ist, muss man in der Konfigurationsoberfläche (oder im Manual) nachsehen. Bei meinem Zyxel-Modem war es glücklicherweise sehr einfach. Man kann ganz unkompliziert zwischen Routing und Bridging Mode umschalten.

Router-Konfiguration

WOLFGANG HENNERBICHLER

Router-Konfiguration

Wie man die jeweiligen DSL-Modems in den Bridging-Modus versetzt, ist im Handbuch der jeweiligen Hersteller nachzulesen. Nicht jedes Modem wird diesen Modus unterstützen.

Achtung: Sobald sich das Modem im Bridging-Modus befindet, ist es vorbei mit der Internet-Verbindung. Man möchte daher diesen Schritt daher gut vorbereiten und auf jeden Fall die Zugangsdaten zum DSL-Provider zur Hand haben, falls man doch wieder auf Routing umkonfigurieren möchte.

Was bedeutet Bridging-Modus?

Falls man bisher mit gebridgten Netzwerken nicht so viel zu tun hatte, ist der Bridging-Modus etwas schwer zu begreifen. Was hier passiert ist, dass das Modem etwaige PPPoE-Pakete direkt an die physische DSL-Schnittstelle weiterleitet. Das kann man mit einem WLAN Access Point vergleichen, der LAN-Pakete ins WLAN weiterleitet. Das Modem braucht nicht mal mehr eine IP-Adresse, um als DSL-Bridge zu fungieren. Ich empfehle dennoch, unbedingt eine lokale IP-Adresse auf dem LAN-Interface zu konfigurieren, damit das DSL-Modem nach wie vor über eine Administrations-Schnittstelle konfiguriert werden kann. Diese lokale IP-Adresse wird von der Linux Firewall geschützt und ist von außen nicht zugänglich, außer man befiehlt der Linux-Firewall explizit, Pakete an dieses Interface weiterzuleiten.

An welche IP-Adresse müssen PPPoE-Pakete geschickt werden?

Die genaue Erklärung findet man auf Wikipedia[2], die kurze Antwort hier: Man muss es nicht konfigurieren. PPPoE hat zwei Phasen. Zuerst die Discovery Phase (auch PADI genannt, steht für PPPoE Active Discovery Initiation) in der ein spezieller Ethernet Broadcast (an FF:FF:FF:FF:FF:FF) geschickt wird. Als Antwort erhält der Absender die MAC-Adresse des DSL-Modems. Ab diesem Zeitpunkt weiß der PPPoE-Client, an welche Ziel-MAC er die PPPoE-Pakete schicken soll.

Das Modem im Bridging-Modus nimmt die PPPoE-Pakete in Empfang und leitet sie an das DSL-Interface weiter. Aus diesem Grund braucht das DSL-Modem keine IP-Adresse im LAN, sobald es als Bridge funktioniert. Wie oben erwähnt empfehle ich dennoch, eine Management-IP auf das LAN-Interface des Modems zu konfigurieren.

Linux wird zum DSL-Router

Unterstützt das Modem den Bridging-Modus, braucht man noch einen Computer für die DSL-Einwahl. Ein Rasperry Pi mit Linux ist wahrscheinlich ausreichend dafür. Da der Pi seine Ethernet-Schnittstelle mit dem restlichen USB-Bus teilt, bevorzuge ich in meinem Beispiel eine virtuelle Maschine mit Debian Jessie, um die Netzwerk-Latenz für berufliche Videokonferenzen gering zu halten.

In diesem Tutorial probiere ich nicht nur, das Ding zum Laufen zu bringen, ich probiere auch, moderne Software dafür zu verwenden. Das war endlich ein Grund, mich zumindest etwas näher mit systemd zu beschäftigen und nftables zu verstehen.

systemd

Wie vorher erwähnt, verwende ich als PPPoE-Dialer und Firewall eine dezidierte virtuelle Maschine mit Debian. Um meine Skripte und Konfigurationsdateien etwas leserlicher zu gestalten, habe ich mir vorgenommen, die physischen Schnittstellen gleich vorneweg richtig zu benennen. Systemd hilft hier sehr, und es ist einfacher als jemals zuvor (ich denke hier an udev), physische Schnittstellen richtig zu benennen. Leider hat Debian Jessie noch nicht alle Features, die wir für unser Setup benötigen. Daher holen wir uns Systemd aus den Backports:

echo deb ftp.debian.org/debian jessie-backports main >> /etc/apt/sources.list
apt-get update
apt-get -t jessie-backports install "systemd"

Zuerst ist es notwendig, systemd-networkd zu aktivieren, um von den vielen Vorteilen der Netzwerkkonfiguration mit systemd zu profitieren: systemct enable systemd-networkd.service aktiviert den networkd. Um ein Interface namens lan als solches zu benennen, geht man nach /etc/systemd/network und erzeugt eine Datei namens 01-lan.link. Der Dateiname muss auf .link enden, und das 01 gibt die Reihenfolge in der Bootsequenz bekannt. Die Datei schaut bei mir folgendermaßen aus:

[Match]
MACAddress=52:54:00:c1:f8:1a
[Link]
Name=lan

Die IP-Adressen des Systems habe ich nicht altmodisch in /etc/network/interfaces konfiguriert, sondern auch mit systemd in der Datei /etc/systemd/network/lan.network:

[Match]
Name=lan
 
[Network]
Address=192.168.1.1/24
IPForward=yes

Dann selbiges auch noch mit dem Loopback-Interface in der Datei lo.network:

[Match]
Name=lo
 
[Network]
Address=127.0.0.1/8

PPPoE

PPPoE setzt ein paar Pakete voraus, die eventuell im System noch nicht vorinstalliert sind:

apt-get install pppd pppoeconf

Mit pppoeconf kann man die angesprochene Discovery anstoßen. Bevor wir die Discovery anstoßen, sollten wir aber die PPP-Parameter noch setzen. Zuerst tragen wir die Zugangsdaten zu unserem Provider in /etc/ppp/chap-secrets ein:

wogri@myprovider.com * my-secret-password *

Danach konfigurieren wir den pppd in /etc/ppp/peers/provider. Die Datei namens provider stellt den Default-Provider für pppd dar. Da die meisten User nur einen DSL-Provider haben, ist es praktisch diese Datei zu verwenden, da sonsten immer der Provider in den anschließenden Befehlen separat angegeben werden muss. Hier also die Konfiguration:

# Use Roaring Penguin's PPPoE implementation.
plugin rp-pppoe.so lan
 
# Login settigns.
user "wogri@myprovider.com&quot;
noauth
hide-password
 
# Connection settings.
persist
maxfail 0
holdoff 5
 
# LCP settings.
lcp-echo-interval 10
lcp-echo-failure 3
 
# PPPoE compliant settings.
noaccomp
default-asyncmap
mtu 1492
 
# IP settings.
noipdefault
defaultroute

Man beachte hier die MTU von 1492. Bei Ethernet ist der Default 1500. Das wird im weiteren Verlauf der Konfiguration noch wichtig (Stichwort MSS Clamping).

Mit pon sollte man nun eine Verbindung zum ISP aufbauen können. ip address show ppp0 sollte die verhandelte IPv4-Konfiguration zeigen.

PPP-Verbindung beim Booten aufbauen

Natürlich müssen wir sicherstellen, dass bei einem Neustart die PPP-Verbindung wieder zuverlässig aufgebaut wird. Dafür müssen wir systemd mitteilen, dass wir eine neuen Service haben:

cat <<EOF >/etc/systemd/system/pppoe.service
[Unit]
Description=PPPoE connection
After=network-online.target
 
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/pon
ExecStop=/usr/bin/poff -a
 
[Install]
WantedBy=default.target
EOF
systemctl daemon-reload
systemctl enable pppoe.service
systemctl start pppoe.service

Routing

Das IPForward=yes in der systemd-networkd-Konfiguration erledigt das Setzen der bekannten ip_forwarding-Parameter, somit sollte ein manuelles Bearbeiten von sysctl.conf nicht notwendig sein.

Die Maschine sollte von nun an mit dem Internet verbunden sein. Was hier aber noch fehlt, ist das Masquerading. Da das interne Netzwerk mit privaten IP-Adressen betrieben wird, ist es notwendig, die private Quell-IP-Adresse der nach außen gerichteten Pakete zu verändern. Unter Linux wird diese Technik Masquerading genannt. Da dieses Tutorial neue Technologien verwendet, werde ich zuerst auf die Masquerading-Konfiguration von nftables eingehen, danach auch kurz iptables aufzeigen.

Firewall

Ziel dieses Tutorials ist es, die Angriffsfläche aufs Heimnetzwerk zu verkleinern. Daher konfigurieren wir eine Firewall, die per Default von außen keine Verbindungen erlaubt. Ich empfehle StrongSwan + IKEv2, sollte jemand das Bedürfnis haben, von außen auf sein Heimnetzwerk zugreifen zu wollen.

nftables

NFTables[3] ist die geplante Ablöse von IPTables. NFTables befindet sich bereits im Linux-Kernel seit Version 3.13. Ein schönes Tutorial über nftables[4] hat Martin Loschwitz im Linux-Magazin geschrieben. Mein Fazit zu nftables ist, dass es bereits ganz gut verwendbar ist, jedoch noch ein paar Features fehlen, bzw. teilweise die Syntax für mich nicht ganz verständlich ist. Fehlende Features für meine Anwendungsfälle sind:

  • mangelnde IPSec-Integration
  • teilweise inkonsistente Syntax der nft-Befehlszeile.
  • Spezial-Features wie MSS Clamping (mehr dazu später) sind noch nicht verfügbar.

Ich gehe davon aus, dass diese Probleme mit der Zeit gelöst werden.

Nun zur Installation: Das Userspace-Tool ist in Debian Jessie nur aus den Backports zu beziehen:

apt-get -t jessie-backports install "nftables"

Nftables kann man wie iptables mit einzelnen Befehlen betreiben oder aber über eine Datei, die atomar in den Kernel geladen (oder geändert) wird. Ich bevorzuge, eine Datei zu pflegen, die atomar in den Kernel geladen wird, ähnlich zum pf-System unter BSD. Eine weitere Eigenheit von nftables NAT ist, dass iptables NAT nicht geladen sein darf. Daher ist es erforderlich, das iptabes NAT-Modul zu entladen:

rmmod iptables_nat

Hier sieht man ein einfaches Beispiel, das nur ein Masquerading mit nftables macht und sinnvolle Chains für die weitere Verwendung angelegt hat:

#!/usr/sbin/nft -f
 
flush ruleset
 
table inet filter {
  chain input {
    type filter hook input priority 0;
    iifname lo accept
    iifname lan accept
    iifname ppp0 jump input_ppp0
    drop
  }
  chain input_ppp0 { # rules applicable to public interface
    ct state {established,related} counter accept
    ct state invalid counter drop
    log
    drop
  }
  chain ouput {
    type filter hook output priority 0;
    accept
  }
  chain forward {
    type filter hook forward priority 0;
    iifname ppp0 counter jump from_internet
    accept
  }
  chain from_internet {
    ct state {established,related} counter accept
    ct state invalid counter drop
    drop
  }
}
 
table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
  }
  chain postrouting {
    type nat hook postrouting priority 0;
    oifname ppp0 counter masquerade
  }
}

Mit diesem Regelwerk sollte die einfachste Variante von nft, nämlich ein simples NAT, erledigt sein. Wer ein Beispiel mit mehr Komplexität in seinen Regeln braucht, hier meine Konfiguration, inkl. IPv6:

#!/usr/sbin/nft -f
 
define server_net = 1.2.3.0/28
define my_phone = 192.168.1.100
 
# ipv6
define dovecot_ip6 = 2001:dead:beef:2::143
define server_net_ip6 = 2001:dead:beef::/64
 
flush ruleset
 
table inet filter {
  chain input {
    type filter hook input priority 0;
    iifname lo accept
    iifname lan accept
    iifname servlan accept
    iifname ipsec0 accept
    iifname ppp0 jump input_ppp0
    drop
  }
  chain input_ppp0 { # rules applicable to public interface
    ct state {established,related} counter accept
    ct state invalid counter drop
    ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 10/second counter accept
    ip6 nexthdr icmpv6 icmpv6 type {
      destination-unreachable, packet-too-big, time-exceeded, 
      parameter-problem, nd-router-advert, nd-neighbor-solicit, 
      nd-neighbor-advert } counter accept
    ip protocol icmp icmp type echo-request limit rate 10/second counter accept
    ip6 daddr fe80::/64 udp dport dhcpv6-client counter accept
    ip6 saddr $server_net_ip6 tcp dport {22} counter accept
    # letsencrypt
    ip saddr 0.0.0.0/0 tcp dport {80,443} counter accept
    ip6 saddr ::/0 tcp dport {80,443} counter accept
    # ipsec
    ip protocol esp accept
    ip saddr 0.0.0.0/0 udp dport {500,4500} counter accept
    log
    drop
  }
  chain ouput {
    type filter hook output priority 0;
    accept
  }
  chain forward {
    type filter hook forward priority 0;
    iifname ppp0 counter jump from_internet
  }
  chain from_internet {
    ct state {established,related} counter accept
    ct state invalid counter drop
    ip6 daddr $dovecot_ip6 jump to_dovecot
    log
    drop
  }
  chain to_dovecot {
    ip6 saddr $server_net_ip6 tcp dport {22} counter accept
  }
}
 
table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
    iifname ppp0 counter jump dnat_from_internet 
  }
  chain dnat_from_internet {
    udp dport { sip, 16384-16400 } counter dnat $my_phone
  }
  chain postrouting {
    type nat hook postrouting priority 0;
    oifname ppp0 counter masquerade
  }
}

iptables

Wer sich nftables nicht antun möchte, kann das simple NAT mit IPv4 mit iptables folgendermaßen einrichten:

#!/bin/bash                                                                         
                                                                                    
iptables --flush                                                                    
iptables -t nat --flush                                                             
iptables -X                                                                         
                                                                                    
set -x                                                                              
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE                                
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu 
iptables -A FORWARD -i ppp0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i ppp0 -m state --state RELATED,ESTABLISHED -j ACCEPT            
iptables -A INPUT -i ppp0 -j LOG                                                    
iptables -A INPUT -i ppp0 -j DROP                                                   
set +x                                                                              

Firewall-Skript automatisch laden

Egal ob man iptables oder nftables verwendet, man muss sicherstellen, dass die Regeln geladen werden, wenn das PPP-Interface hochkommt. Das erledigt man am einfachsten, indem man eine ausführbare Datei nach /etc/ppp/ip-up.d legt. Bei mir sieht der Inhalt folgendermaßen aus:

#!/bin/bash
nft -f /etc/nftables.conf
iptables --flush
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Ich habe an dieser Stelle nicht überprüft, wann dieses Skript ausgeführt wird – theoretisch könnte es einen kurzen Zeitpunkt geben, wo das PPP-Interface bereits von außen erreichbar, aber die Firewall noch nicht geladen worden ist (oder aufgrund eines Syntax-Fehlers in der Datei die Firewall gar nicht aktiviert wird). Da auf meiner Firewall außer SSH keine Internet-Dienste laufen, mache ich mir darüber keine weiteren Sorgen.

MSS Clamping

Eingangs habe ich erwähnt, dass das PPPoE-Protokoll zum Einsatz kommt. Aus diesem Grund muss man bei der gesetzten MTU besonders aufpassen. PPP setzt die MTU mit dem ISP auf 1492. Ethernet hat eine MTU von 1500. Da vor das PPP-Paket mit 1492 Bytes noch ein 8 Byte Header kommt, kommuniziert der pppd mit dem ISP mit 1500 Bytes.

Wird ein TCP Paket jedoch im Ethernet (das annimmt, 1500 Byte als MTU im gesamten Pfad bis ins Internet zu haben) mit einer Paketgröße von 1500 Bytes versendet, muss unser PPP-Router das Paket fragmentieren.

Hier kommt eine Technik namens Maximum Segment Size Clamping zum Einsatz. Kurzum, mit dem Befehl

iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

wird der Header in TCP-Paketen derart verändert, dass kein TCP-Paket größer als 1492 von innen oder außen gesendet wird. Das kann für einige Provider erforderlich sein. Manche ISPs erlauben jedoch MTUs, die größer als 1500 Bytes sind, dann wird das MSS Clamping nicht benötigt. Für IPv6 ist kein MSS Clamping notwendig, da IPv6 die MTU im gesamten Routing-Pfad ermittelt.

Über den Autor

Wolfgang Hennebichler (Webseite[5]) ist Site Reliability Engineer bei Google.

Linkverweise:


[1] www.pro-linux.de/artikel/1/73/dsl-modem-im-bridging-modus-betreiben.html 
[2] de.wikipedia.org/wiki/PPP_over_Ethernet 
[3] www.pro-linux.de/news/1/21853/netfilter-projekt-veröffentlicht-nftables-04.html 
[4] www.linux-magazin.de/Ausgaben/2014/01/NFtables 
[5] www.wogri.at/

http://www.pro-linux.de/images/NB3/base/print/nb3_logo.png

Mediadaten RSS/Feeds Datenschutz Impressum

© 2017 Pro-Linux

 

Erst du, dann du, dann du, dann du

;widows: 2;-webkit-text-stroke-width: 0px;word-spacing:0px“> Von Mathias Weidner

Vor einiger Zeit kam ein Kollege auf mich zu und fragte, wie er am besten mehrere Backup-Jobs gleichzeitig starten könne. Außerdem sollten ein paar andere Jobs später laufen, wenn die ersten fertig sind. Das Ganze wollte er möglichst schnell und ohne zusätzliche Programme erledigen – also in der Shell.

Mehrere Jobs in der Shell

MATHIAS WEIDNER

Mehrere Jobs in der Shell

Die Abbildung veranschaulicht das Problem: Zum Zeitpunkt t0 starten die ersten Jobs. Sie sind zum Zeitpunkt t1 fertig. Die nächsten Jobs sollen zum Zeitpunkt t2 starten. Eine dritte Staffel sollte frühestens zum Zeitpunkt t3 starten, wenn alle Jobs der zweiten Staffel fertig sind. Außerdem sollen t1 und t2 nicht allzu weit auseinander liegen – es ging ja um Backup-Jobs, die über Nacht laufen und am Morgen fertig sein sollen.

Die erste Idee, die Jobs mit & in den Hintergrund zu schicken, bringt einige Probleme mit sich:

  • Bei Hintergrund-Jobs bekommt ein Shell-Skript nicht mit, wann sie fertig sind. Man muss t1 und t3 daher schätzen und verschenkt Zeit, weil zuviel Reserve bleibt oder die nächste Staffel zu früh startet, während die vorherige noch läuft.
  • Die Ausgaben der einzelnen Jobs vermischen sich. Man kann nicht vorhersagen, wessen Ausgabe an welcher Stelle erscheint.
  • Man bekommt keine Rückgabewerte der Jobs und kann somit im Skript nicht darauf reagieren.

Für diese Probleme gibt es Abhilfen, auch mit den Mitteln der Shell selbst. Doch die meisten benötigen Interprozesskommunikation und temporäre Dateien. Außerdem blähen sie das Skript auf, bis am Ende die eigentlichen Jobs kaum noch zu finden sind. Das möchte man nicht an einen Kollegen weitergeben.

Synchronisation mit Pipes

Es gibt allerdings eine einfache Möglichkeit, Jobs in der Shell gleichzeitig zu starten, bei der die Shell automatisch wartet, bis der letzte der Jobs geendet hat: Prozesse, die über Pipes miteinander verbunden sind, startet die Shell gleichzeitig.

Die Standardausgabe jeder dieser Jobs ist mit der Standardeingabe des nächsten verbunden, und die Standardeingabe mit der Standardausgabe des vorigen Jobs. Auf diese Art reichen die Ausgaben aber nur zum jeweils nächsten Job, und die Shell sieht nur die Ausgabe des jeweils letzten. Die Jobs davor würden zudem blockieren, wenn ihre Ausgabe nicht gelesen wird.

Nun ließe sich die Ausgabe der Jobs mit cat in eine Datei leiten und diese so entsperren:

( cat >> $logfile &; jobx )

Damit würden zwar alle Jobs problemlos laufen. Aber die Ausgabe würde wieder durcheinander in die Logdatei geschrieben. Besser ist es, wenn jeder Job die Ausgabe des vorigen Jobs an den nächsten weiterleiten würde. Das heißt, jeder Job, mit Ausnahme des ersten, müsste etwa so aussehen:

( jobx; cat )

Die runden Klammern schicken die Jobs in eine Subshell, sodass das Semikolon nicht die Pipe auseinanderreißt. Auf diese Weise erscheinen die Ausgaben allerdings in umgekehrter Reihenfolge:

$ echo 1|(echo 2; cat)|(echo 3; cat)
3
2
1

Außerdem kann Job Nummer 2 seine Ausgabe erst vollständig schreiben, wenn Job 3 beendet ist und cat die Ausgabe weiterleitet. Dito für Job 1: Zwar starten alle Jobs zur gleichen Zeit, aber die ersten blockieren, bis die letzten fertig sind. Das lässt sich zwar lösen, wenn die Reihenfolge des cat-Befehls und des Jobs getauscht ist:

$ echo 1|(cat; echo 2)|(cat; echo 3)
1
2
3

Nun stimmt zwar die Reihenfolge. Aber Job 2 startet erst, wenn Job 1 seine Ausgabe schließt. Und Job 3 startet erst, wenn Job 2 seine Standardausgabe schließt.

Hier hilft der Trick, die Ausgabe jedes Jobs in Variablen zwischenzuspeichern und sie erst am Ende auszugeben. Abgesehen davon, dass alle Jobs unabhängig voneinander laufen können, lässt sich die Ausgabe nun auch in die richtige Reihenfolge bringen. Damit es übersichtlicher wird, kapselt eine Shell-Funktion den Aufruf von cat und den Job, der ich den Job als Argument übergebe:

01 in_pipe() {
02   CMD="$*"
03   BEFORE=$(date)
04   LOG=$($CMD)
05   RESULT=$?
06   AFTER=$(date)
07   
08   cat
09   echo $BEFORE
10   echo "$CMD"
11   echo "-----"
12   echo "$LOG"
13   echo "-----"
14   echo "RESULT=$RESULT"
15   echo $AFTER
16   echo "====="
17   return $RESULT
18 }

Diese Funktion zieht alle Register. Zeile 02 speichert alle übergebenen Argumente in einer Variablen, die als Befehl für den Job dient. Die Zeilen 03 und 06 notieren die Zeit vor und nach dem Aufruf des Jobs in zwei weiteren Variablen. Zeile 04 speichert die Ausgaben des Jobs in einer Shell-Variablen, während er läuft, und Zeile 05 hebt den Rückgabewert für später auf. Zeile 08 enthält den Aufruf von cat, der die Ausgabe des vorherigen Jobs durchleitet: Dadurch entspricht die Reihenfolge der Ausgaben der Reihenfolge der Jobs in der Pipe. Ab Zeile 09 kommt die Ausgabe aller gesammelten Werte des aktuellen Jobs, gefolgt von einer Trennzeile. In Zeile 17 schließlich gibt die Funktion den Rückgabewert des Jobs an die aufrufende Shell zurück.

Diese Funktion findet nun wie folgt Einsatz:

01 echo "=====" 
     | in_pipe sleep 3 
     | in_pipe echo Hallo 
     | in_pipe sleep 2
02 date

Die Ausgabe sieht folgendermaßen aus:

=====
Mi 21. Jan 10:01:58 CET 2015
sleep 3
-----
-----
RESULT=0
Mi 21. Jan 10:02:01 CET 2015
=====
Mi 21. Jan 10:01:58 CET 2015
echo Hallo
-----
Hallo
-----
RESULT=0
Mi 21. Jan 10:01:58 CET 2015
=====
Mi 21. Jan 10:01:58 CET 2015
sleep 2
-----
-----
RESULT=0
Mi 21. Jan 10:02:00 CET 2015
=====
Mi 21. Jan 10:02:01 CET 2015

Alle Jobs starten also zur gleichen Zeit, werden aber zu unterschiedlichen Zeiten fertig. Das Skript fährt fort, nachdem der langsamste Job endete.

Probleme und Einschränkungen

Ein Problem gibt es noch, das mit folgendem Aufruf deutlich wird:

01 echo "=====" 
    | in_pipe false 
    | in_pipe sleep 1
02 echo $?

Das Problem wird in der letzten Zeile der Ausgabe offenbar:

=====
Mi 21. Jan 10:09:08 CET 2015
false
-----
-----
RESULT=1
Mi 21. Jan 10:09:08 CET 2015
=====
Mi 21. Jan 10:09:08 CET 2015
sleep 1
-----
-----
RESULT=0
Mi 21. Jan 10:09:09 CET 2015
=====
0

Die Ausgabe zeigt: Obwohl ein Job einen Fehlerwert gemeldet hat, registriert die Shell diesen nicht, weil der letzte Job in der Pipe ohne Fehler endete.

Bei der POSIX– oder Bourne-Shell muss man mit diesem Umstand leben – oder die Ausgabe der Pipe weiter untersuchen. Verwendet man jedoch bash, ksh oder zsh, erscheint folgende Lösungsanweisung im Skript vor der Pipe:

set -o pipefail

Allerdings hat auch diese Lösung Einschränkungen.

  • Pro Job lässt sich nur ein Befehl aufrufen. Immerhin kann man Argumente mitgeben.
  • Da die Ausgabe der Jobs in Variablen zwischenlagert, sollte die Ausgabe sich auf den maximalen Wert für Shell-Variablen beschränken. Wer mehr braucht, muss mit temporären Dateien arbeiten.
  • Keine Ausgabeumleitungen lassen sich an die Funktion durchreichen. Das könnte man allerdings in die Funktion selbst einbauen, wodurch sie für alle Jobs gelten würde.

Wer das im Hinterkopf behält, kann verschiedene Jobs gleichzeitig aufrufen, ohne dass sich aufeinanderfolgende Staffeln von Jobs überlappen oder zwischendurch Zeit zu verschenken.

Autoreninformation

Mathias Weidner studierte Ende der 1980-er Jahre Automatisierungstechnik in Leipzig. Nach verschiedenen Stellen in der Software-Entwicklung arbeitet er als Administrator für Unix/Linux, Netzwerke und Sicherheitsthemen. Seit einiger Zeit schreibt er hin und wieder Bücher dazu, die unter buecher.mamawe.net[1] zu finden sind.

Dieser Artikel ist zuerst erschienen in UpTimes[2], Mitgliederzeitschrift des GUUG e.V., Ausgabe 2016-2. Veröffentlichung mit freundlicher Genehmigung.

Linkverweise:


[1] buecher.mamawe.net 
[2] www.guug.de/uptimes/

http://www.pro-linux.de/images/NB3/base/print/nb3_logo.png

Mediadaten RSS/Feeds Datenschutz Impressum

© 2017 Pro-Linux

 

Smartphone-Recycling: Alte Geräte sinnvoll einsetzen

Smartphone-Recycling: Alte Geräte sinnvoll einsetzen

19.03.2017 | 16:09 Uhr | Hermann Apfelböck

 

Nicht wegwerfen! Alte Smartphones können noch sinnvoll genutzt werden.

VergrößernNicht wegwerfen! Alte Smartphones können noch sinnvoll genutzt werden.

© Maksym Yemelyanov – Fotolia

Smartphones sind bekanntlich ein kompletter Mini-PC, Hardware-technisch mit leistungsstarken Platinen-PCs zu vergleichen, dabei kompletter ausgestattet. Ausrangierte Smartphones sind daher dankbare Kandidaten fürs Re-und Upcycling.

Das Display hat einen Sprung, der Akku ist hinüber, oder der Arbeitgeber hat ein neues Modell spendiert: Selbst bei Pragmatikern, die nicht an der hochansteckenden Volkskrankheit Neophilie leiden, landen Smartphones irgendwann in der Schublade „Elektroschrott“. Dabei ist kaum eine andere Geräteklasse so gut geeignet, neue Aufgaben zu übernehmen. Bastler, die gerade überlegen, sich einen Platinenrechner, ein Mobilradio, eine IP-Kamera (und, und, und …) anzuschaffen, sollten erst das alte Handy aus der Schublade holen. CPU-Leistung, RAM und vor allem die Peripherie-Ausstattung sind exzellent, lediglich an Anschlussports mangelt es.

Siehe auch: Das iPhone als Wandgadget einsetzen 

Andere Geräte ins Netz bringen

Shopping Cart Icon Samsung Galaxy S5 bei Amazon ansehen

Auch ältere Android-Smartphones bieten standardmäßig Netzwerkfunktionen, die sie zumindest zur Behelfsbrücke ins Internet befähigen. Hat ein PC oder ein Notebook im Heimnetz keinen funktionierenden WLAN-Adapter und keine Kabelverbindung, hilft das Smartphone aus: Das Smartphone muss selbst mit dem WLAN verbunden sein und über sein USB-Kabel mit dem Rechner. Sobald unter „Verbindungen -> Weitere

Einstellungen -> Tethering […] -> USB-Tethering“ aktiviert ist, erhält der Rechner eine „Kabelnetzverbindung“ und kann ins Internet.

Eine etwas aufwendigere Lösung macht das ausgediente Handy zum mobilen WLAN-Hotspot für Notebooks oder Tablets, die kein Mobilfunknetz besitzen. Dazu muss das Handy über „Mobile Daten“ im Netz sein und dieses über „Verbindungen -> Weitere Einstellungen -> Tethering […] -> Mobiler WLAN-Hotspot“ als WLAN anbieten. Damit können sich dann andere Geräte wie gewohnt verbinden. Eine solche Lösung lässt sich etwa dauerhaft im Auto realisieren, wenn Sie das Handy mit einem Ladeadapter mit Strom versorgen (ab circa zehn Euro). Aufwendiger ist dieses Szenario aber auch deshalb, weil das recycelte Smartphone eine aktive SIM-Karte benötigt.

Apps und Server-Apps für einzelne Funktionen

Mit Kamera, Mikrofon, Audio Line Out, GPS, Bewegungssensoren, WLAN, Bluetooth und Mobilfunknetzen, USB-Zugriff (OTG), Hotspot-Funktion sowie DLNA-Medien-Streaming („Geräte in der Nähe“) haben auch ältere Android-Smartphones viel Potenzial an Bord. Manche Apps nutzen lediglich diese Gerätefunktionen mehr oder weniger kreativ, andere fügen einen kleinen Server hinzu, um die gewünschte Komponente über den Browser oder eine andere Netz-Software auf anderen Rechnern anzubieten. Hier nur wenige typische Beispiele:

<![if !supportLists]>·         <![endif]>Apps wie Radio FM oder Tune In ersetzen ein Radio. Sie brauchen nur WLAN und – sehr zu empfehlen – ein direkt am Klinkenstecker angeschlossenes oder per Bluetooth empfangendes Lautsprechersystem (je nach Anspruch ab zehn und bis 300 Euro).

<![if !supportLists]>·         <![endif]>Die App Cerberus nutzt den GPS-Chip des Smartphones und dient eigentlich dazu, ein verlorenes oder gestohlenes Smartphone zu orten. Auf einem ausgedienten Android-Handy, das Sie im Auto deponieren und dort per Ladeadapter mit Strom versorgen, dient es zum Auffinden des Fahrzeugs.

<![if !supportLists]>·         <![endif]>Die App Mobile Alarmanlage macht aus dem Smartphone eine simple Alarmanlage. Die kostenlose Version schaltet fast alle interessantesten Optionen ab, daher sind bei Interesse die 0,99 Cent unvermeidlich. Die App schaltet auf Wunsch einzelne oder sämtliche Komponenten scharf (Mikro, Kamera, Bewegungssensor, Ladekabel) und verschickt bei einem Ereignis SMS oder Mail. Die laute Alarmfunktion eignet sich eher für Scherzaktionen.

<![if !supportLists]>·         <![endif]>Die Android-App Baby Monitor nutzt das Smartphone-Mikrofon zur Überwachung des Kinderzimmers. Ein einstellbarer „Sensity Level“ definiert, ab welcher Lautstärke Ihre Telefonnummer angerufen werden soll.

<![if !supportLists]>·         <![endif]>Eine simple, aber nützliche Monofunktionalisierung alter Handys ist der Einsatz als Fernsteuerung für Smart-TVs oder Mediencenter. In beiden Fällen ist es wichtig, dass das zu steuernde Gerät über den Router stets eine feste IP-Adresse erhält. Steuerungs-Apps für Fernseher bietet Google Play zuhauf, am besten grenzen Sie die Suche gleich auf den TV-Hersteller ein (etwa „Samsung“ oder „LG“). Für das Mediencenter XBMC/Kodi sind die Apps Kore , Yatse und XBMC remote zu empfehlen.

Zwei Szenarien in der Praxis

Android-Apps für Internetradio gibt es zuhauf. Zusätzlich brauchen Sie nur noch ein kleines Lautsprechersystem für zehn Euro aufwärts.

VergrößernAndroid-Apps für Internetradio gibt es zuhauf. Zusätzlich brauchen Sie nur noch ein kleines Lautsprechersystem für zehn Euro aufwärts.

Das Handy als Kamera: Ein altes Smartphone bringt alles mit, um als IP-Webcam oder Überwachungskamera zu arbeiten. Das einzige technische Problem ist die Fixierung des Handys an der gewünschten Position; die sollte für einen längeren Einsatz zudem in der Nähe einer Steckdose liegen. Der Rest ist einfach: Die Android-App IP Webcam ist schnell installiert. In den App-Einstellungen aktivieren Sie „Local broadcasting“ und den untersten Punkt „Starte Server“. Schon geht’s los. Wenn Sie die IP-Adresse des Handys nicht kennen, hilft die App mit dem Punkt „Wie verbinde ich mich?“. Jeder Browser im gleichen Netz zeigt den „Android Webcam Server“ nach Eingabe der IP in die Adresszeile. Der Live-Stream erscheint, sobald Sie hier einen „Video Renderer“ anklicken. Über „Aufnahme Kontrolle“ lässt sich der Stream aufzeichnen, der dann am Handy unter „/ipwebcam_videos“ abgelegt wird. Einzelfotos speichern Sie am einfachsten gleich am PC mit „Foto Ausnahme“ und dann „Bild speichern unter“ im Browser. Die App bietet überdies zahlreiche Qualitäts-und Feineinstellungen.

Tipp: Funktionen von Android 6 nachrüsten 

Das Handy als Daten-und Medienserver: Um Audio-und Videodateien vom Handy zu streamen, brauchen Sie noch nicht mal eine spezielle App (wie BubbleUPnP). Nicht allzu alte Android-Smartphones zeigen unter „Verbindungen“ die Option „Geräte in der Nähe“. Es genügt diese zu aktivieren, und schon erscheint die Medienbibliothek auf den Rechnern und TV-Geräten im Netz – als UPnP-Medienbibliothek (PC) oder als „All Share“-Quelle (TV).

Wer das Smartphone zu einem echten NAS-Server ausbauen will, muss Kompromisse eingehen und einige technische Probleme lösen. Da der Verkehr über das Funknetz laufen muss, sollte das WLAN wenigstens stabil und schnell sein. Wir konnten einen Durchsatz von 40 bis 50 MBit/s erzielen, was sicher nicht schnell ist, aber für Streaming und Büro-Backups allemal ausreicht.

Damit wird das Handy zu einem kleinen PC und kann auch als Daten-Server genutzt werden.

VergrößernDamit wird das Handy zu einem kleinen PC und kann auch als Daten-Server genutzt werden.

Nächster Punkt ist der Speicherplatz: Ohne externe USB-Festplatte hätte der Smartphone-Server seinen Namen nicht verdient. Nun ist es zwar kein Problem, mit einem USB-OTG-Kabel (circa fünf Euro) eine USB-Festplatte anzuschließen. Wenn diese keine eigene Stromversorgung hat, müssen Sie jedoch ein USB-OTG-Y-Kabel (ab acht Euro) wählen.

Das Hauptproblem: Hängt eine Festplatte am Micro-USB-Adapter des Handys, kann das Smartphone nicht gleichzeitig laden. Damit wäre das Server-Projekt eigentlich begraben – es sei denn, Sie entschließen sich zu einem Upcycling mit geeigneter Investition:Multimedia-Docking-Stations insbesondere für Samsung-Smartphones (Produktbezeichnungen EDD-S20E und ähnlich) bieten USB-Anschlüsse, HDMI, Audioausgang plus Ladefunktion. Sie kosten 20 Euro aufwärts, Markenprodukte 45 bis 70 Euro. Achten Sie auf die angegebenen kompatiblen Smartphone-Modelle und darauf, dass Ladefunktion und USB-Anschluss gewährleistet sind.

Passende Apps gibt es in Menge: Servers Ultimate mit Servers Ultimate Pack B (für Samba), ferner Samba Droid bringen die Smartphone-Daten zu Linux-und Windows-Rechnern, fordern aber zu diesem Zweck ein gerootetes Android. Wem eine Weboberfläche für Up-und Downloads reicht, kommt ohne Rooten mit Droid over Wifi über die Runden.

 

DSL-Modem im Bridging-Modus betreiben

> Von wogri

Wir hören es fast jeden Tag in den Medien: Großflächige DDoS-Angriffe auf strategisch interessante Ziele im Internet. Bei DDoS-Angriffen haben Angreifer in der Regel private Geräte unter ihrer Kontrolle, ohne dass die Besitzer davon wissen.

Ein mögliches Angriffsziel ist hier der alte DSL-Router, dessen Hersteller schon Jahre kein Softwarupdate mehr ausliefert, und der vor Exploits nur so strotzt. Ein Angriff auf dieses Gerät bleibt unbemerkt, da es weiterhin seinen Dienst verrichtet und der Besitzer kein Fehlverhalten feststellen kann. Während einer DDoS-Attacke sendet das Gerät eine Sequenz von IP-Paketen, die dem privaten User wahrscheinlich nicht auffallen.

Dieser Artikel ist der erste Teil einer Serie aus vorerst zwei Artikeln[1]. Der vorliegende größere Teil beschreibt die Änderung der Router-Einstellungen und die Einrichtung eines Linux-Rechners mit Firewall. Der zweite Teil behandelt die Konfiguration von IPv6 mit DHCP und Firewall.

Wie kann ich mein DSL-Modem schützen?

Abgesehen von regelmäßigen Software-Updates gibt es noch eine mögliche Alternative: Das DSL-Modem vom Internet aus nicht ansprechbar zu machen. Das bedeutet, dass man dem Modem keine öffentliche IP-Adresse zuweist. Ohne öffentliche IP-Adresse ist jedoch keine Teilnahme am Internet möglich. Der Trick ist, das Modem in einen Bridging-Modus zu versetzen und die öffentliche IP-Adresse an einen Linux Software-Router zu vergeben.

Ein weiterer Vorteil dieses Modus ist, dass man frei aus den Netzwerkfähigkeiten von Linux schöpfen kann. VLANs, IPv6 Tunnel, Dynamisches DNS, IPSec, Split Horizon DNS – alles wird möglich. Es muss natürlich erwähnt werden, dass man damit eine Linux-Installation als Angriffsziel im Internet exponiert. Im Unterschied zu proprietären DSL-Boxen hat man hier jedoch selbst die Möglichkeit, das Gerät auf dem aktuellen Softwarestand zu halten, wie auch das Gerät mit Firewall-Regeln komplett von außen unzugänglich zu machen.

Bridging-Modus im DSL-Modem

Nicht jedes DSL-Modem unterstützt den Bridging-Modus. Um herauszufinden, ob ein DSL-Modem dazu fähig ist, muss man in der Konfigurationsoberfläche (oder im Manual) nachsehen. Bei meinem Zyxel-Modem war es glücklicherweise sehr einfach. Man kann ganz unkompliziert zwischen Routing und Bridging Mode umschalten.

Router-Konfiguration

WOLFGANG HENNERBICHLER

Router-Konfiguration

Wie man die jeweiligen DSL-Modems in den Bridging-Modus versetzt, ist im Handbuch der jeweiligen Hersteller nachzulesen. Nicht jedes Modem wird diesen Modus unterstützen.

Achtung: Sobald sich das Modem im Bridging-Modus befindet, ist es vorbei mit der Internet-Verbindung. Man möchte daher diesen Schritt daher gut vorbereiten und auf jeden Fall die Zugangsdaten zum DSL-Provider zur Hand haben, falls man doch wieder auf Routing umkonfigurieren möchte.

Was bedeutet Bridging-Modus?

Falls man bisher mit gebridgten Netzwerken nicht so viel zu tun hatte, ist der Bridging-Modus etwas schwer zu begreifen. Was hier passiert ist, dass das Modem etwaige PPPoE-Pakete direkt an die physische DSL-Schnittstelle weiterleitet. Das kann man mit einem WLAN Access Point vergleichen, der LAN-Pakete ins WLAN weiterleitet. Das Modem braucht nicht mal mehr eine IP-Adresse, um als DSL-Bridge zu fungieren. Ich empfehle dennoch, unbedingt eine lokale IP-Adresse auf dem LAN-Interface zu konfigurieren, damit das DSL-Modem nach wie vor über eine Administrations-Schnittstelle konfiguriert werden kann. Diese lokale IP-Adresse wird von der Linux Firewall geschützt und ist von außen nicht zugänglich, außer man befiehlt der Linux-Firewall explizit, Pakete an dieses Interface weiterzuleiten.

An welche IP-Adresse müssen PPPoE-Pakete geschickt werden?

Die genaue Erklärung findet man auf Wikipedia[2], die kurze Antwort hier: Man muss es nicht konfigurieren. PPPoE hat zwei Phasen. Zuerst die Discovery Phase (auch PADI genannt, steht für PPPoE Active Discovery Initiation) in der ein spezieller Ethernet Broadcast (an FF:FF:FF:FF:FF:FF) geschickt wird. Als Antwort erhält der Absender die MAC-Adresse des DSL-Modems. Ab diesem Zeitpunkt weiß der PPPoE-Client, an welche Ziel-MAC er die PPPoE-Pakete schicken soll.

Das Modem im Bridging-Modus nimmt die PPPoE-Pakete in Empfang und leitet sie an das DSL-Interface weiter. Aus diesem Grund braucht das DSL-Modem keine IP-Adresse im LAN, sobald es als Bridge funktioniert. Wie oben erwähnt empfehle ich dennoch, eine Management-IP auf das LAN-Interface des Modems zu konfigurieren.

Linux wird zum DSL-Router

Unterstützt das Modem den Bridging-Modus, braucht man noch einen Computer für die DSL-Einwahl. Ein Rasperry Pi mit Linux ist wahrscheinlich ausreichend dafür. Da der Pi seine Ethernet-Schnittstelle mit dem restlichen USB-Bus teilt, bevorzuge ich in meinem Beispiel eine virtuelle Maschine mit Debian Jessie, um die Netzwerk-Latenz für berufliche Videokonferenzen gering zu halten.

In diesem Tutorial probiere ich nicht nur, das Ding zum Laufen zu bringen, ich probiere auch, moderne Software dafür zu verwenden. Das war endlich ein Grund, mich zumindest etwas näher mit systemd zu beschäftigen und nftables zu verstehen.

systemd

Wie vorher erwähnt, verwende ich als PPPoE-Dialer und Firewall eine dezidierte virtuelle Maschine mit Debian. Um meine Skripte und Konfigurationsdateien etwas leserlicher zu gestalten, habe ich mir vorgenommen, die physischen Schnittstellen gleich vorneweg richtig zu benennen. Systemd hilft hier sehr, und es ist einfacher als jemals zuvor (ich denke hier an udev), physische Schnittstellen richtig zu benennen. Leider hat Debian Jessie noch nicht alle Features, die wir für unser Setup benötigen. Daher holen wir uns Systemd aus den Backports:

echo deb ftp.debian.org/debian jessie-backports main >> /etc/apt/sources.list
apt-get update
apt-get -t jessie-backports install "systemd"

Zuerst ist es notwendig, systemd-networkd zu aktivieren, um von den vielen Vorteilen der Netzwerkkonfiguration mit systemd zu profitieren: systemct enable systemd-networkd.service aktiviert den networkd. Um ein Interface namens lan als solches zu benennen, geht man nach /etc/systemd/network und erzeugt eine Datei namens 01-lan.link. Der Dateiname muss auf .link enden, und das 01 gibt die Reihenfolge in der Bootsequenz bekannt. Die Datei schaut bei mir folgendermaßen aus:

[Match]
MACAddress=52:54:00:c1:f8:1a
[Link]
Name=lan

Die IP-Adressen des Systems habe ich nicht altmodisch in /etc/network/interfaces konfiguriert, sondern auch mit systemd in der Datei /etc/systemd/network/lan.network:

[Match]
Name=lan
 
[Network]
Address=192.168.1.1/24
IPForward=yes

Dann selbiges auch noch mit dem Loopback-Interface in der Datei lo.network:

[Match]
Name=lo
 
[Network]
Address=127.0.0.1/8

PPPoE

PPPoE setzt ein paar Pakete voraus, die eventuell im System noch nicht vorinstalliert sind:

apt-get install pppd pppoeconf

Mit pppoeconf kann man die angesprochene Discovery anstoßen. Bevor wir die Discovery anstoßen, sollten wir aber die PPP-Parameter noch setzen. Zuerst tragen wir die Zugangsdaten zu unserem Provider in /etc/ppp/chap-secrets ein:

wogri@myprovider.com * my-secret-password *

Danach konfigurieren wir den pppd in /etc/ppp/peers/provider. Die Datei namens provider stellt den Default-Provider für pppd dar. Da die meisten User nur einen DSL-Provider haben, ist es praktisch diese Datei zu verwenden, da sonsten immer der Provider in den anschließenden Befehlen separat angegeben werden muss. Hier also die Konfiguration:

# Use Roaring Penguin's PPPoE implementation.
plugin rp-pppoe.so lan
 
# Login settigns.
user "wogri@myprovider.com&quot;
noauth
hide-password
 
# Connection settings.
persist
maxfail 0
holdoff 5
 
# LCP settings.
lcp-echo-interval 10
lcp-echo-failure 3
 
# PPPoE compliant settings.
noaccomp
default-asyncmap
mtu 1492
 
# IP settings.
noipdefault
defaultroute

Man beachte hier die MTU von 1492. Bei Ethernet ist der Default 1500. Das wird im weiteren Verlauf der Konfiguration noch wichtig (Stichwort MSS Clamping).

Mit pon sollte man nun eine Verbindung zum ISP aufbauen können. ip address show ppp0 sollte die verhandelte IPv4-Konfiguration zeigen.

PPP-Verbindung beim Booten aufbauen

Natürlich müssen wir sicherstellen, dass bei einem Neustart die PPP-Verbindung wieder zuverlässig aufgebaut wird. Dafür müssen wir systemd mitteilen, dass wir eine neuen Service haben:

cat <<EOF >/etc/systemd/system/pppoe.service
[Unit]
Description=PPPoE connection
After=network-online.target
 
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/pon
ExecStop=/usr/bin/poff -a
 
[Install]
WantedBy=default.target
EOF
systemctl daemon-reload
systemctl enable pppoe.service
systemctl start pppoe.service

Routing

Das IPForward=yes in der systemd-networkd-Konfiguration erledigt das Setzen der bekannten ip_forwarding-Parameter, somit sollte ein manuelles Bearbeiten von sysctl.conf nicht notwendig sein.

Die Maschine sollte von nun an mit dem Internet verbunden sein. Was hier aber noch fehlt, ist das Masquerading. Da das interne Netzwerk mit privaten IP-Adressen betrieben wird, ist es notwendig, die private Quell-IP-Adresse der nach außen gerichteten Pakete zu verändern. Unter Linux wird diese Technik Masquerading genannt. Da dieses Tutorial neue Technologien verwendet, werde ich zuerst auf die Masquerading-Konfiguration von nftables eingehen, danach auch kurz iptables aufzeigen.

Firewall

Ziel dieses Tutorials ist es, die Angriffsfläche aufs Heimnetzwerk zu verkleinern. Daher konfigurieren wir eine Firewall, die per Default von außen keine Verbindungen erlaubt. Ich empfehle StrongSwan + IKEv2, sollte jemand das Bedürfnis haben, von außen auf sein Heimnetzwerk zugreifen zu wollen.

nftables

NFTables[3] ist die geplante Ablöse von IPTables. NFTables befindet sich bereits im Linux-Kernel seit Version 3.13. Ein schönes Tutorial über nftables[4] hat Martin Loschwitz im Linux-Magazin geschrieben. Mein Fazit zu nftables ist, dass es bereits ganz gut verwendbar ist, jedoch noch ein paar Features fehlen, bzw. teilweise die Syntax für mich nicht ganz verständlich ist. Fehlende Features für meine Anwendungsfälle sind:

  • mangelnde IPSec-Integration
  • teilweise inkonsistente Syntax der nft-Befehlszeile.
  • Spezial-Features wie MSS Clamping (mehr dazu später) sind noch nicht verfügbar.

Ich gehe davon aus, dass diese Probleme mit der Zeit gelöst werden.

Nun zur Installation: Das Userspace-Tool ist in Debian Jessie nur aus den Backports zu beziehen:

apt-get -t jessie-backports install "nftables"

Nftables kann man wie iptables mit einzelnen Befehlen betreiben oder aber über eine Datei, die atomar in den Kernel geladen (oder geändert) wird. Ich bevorzuge, eine Datei zu pflegen, die atomar in den Kernel geladen wird, ähnlich zum pf-System unter BSD. Eine weitere Eigenheit von nftables NAT ist, dass iptables NAT nicht geladen sein darf. Daher ist es erforderlich, das iptabes NAT-Modul zu entladen:

rmmod iptables_nat

Hier sieht man ein einfaches Beispiel, das nur ein Masquerading mit nftables macht und sinnvolle Chains für die weitere Verwendung angelegt hat:

#!/usr/sbin/nft -f
 
flush ruleset
 
table inet filter {
  chain input {
    type filter hook input priority 0;
    iifname lo accept
    iifname lan accept
    iifname ppp0 jump input_ppp0
    drop
  }
  chain input_ppp0 { # rules applicable to public interface
    ct state {established,related} counter accept
    ct state invalid counter drop
    log
    drop
  }
  chain ouput {
    type filter hook output priority 0;
    accept
  }
  chain forward {
    type filter hook forward priority 0;
    iifname ppp0 counter jump from_internet
    accept
  }
  chain from_internet {
    ct state {established,related} counter accept
    ct state invalid counter drop
    drop
  }
}
 
table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
  }
  chain postrouting {
    type nat hook postrouting priority 0;
    oifname ppp0 counter masquerade
  }
}

Mit diesem Regelwerk sollte die einfachste Variante von nft, nämlich ein simples NAT, erledigt sein. Wer ein Beispiel mit mehr Komplexität in seinen Regeln braucht, hier meine Konfiguration, inkl. IPv6:

#!/usr/sbin/nft -f
 
define server_net = 1.2.3.0/28
define my_phone = 192.168.1.100
 
# ipv6
define dovecot_ip6 = 2001:dead:beef:2::143
define server_net_ip6 = 2001:dead:beef::/64
 
flush ruleset
 
table inet filter {
  chain input {
    type filter hook input priority 0;
    iifname lo accept
    iifname lan accept
    iifname servlan accept
    iifname ipsec0 accept
    iifname ppp0 jump input_ppp0
    drop
  }
  chain input_ppp0 { # rules applicable to public interface
    ct state {established,related} counter accept
    ct state invalid counter drop
    ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 10/second counter accept
    ip6 nexthdr icmpv6 icmpv6 type {
      destination-unreachable, packet-too-big, time-exceeded, 
      parameter-problem, nd-router-advert, nd-neighbor-solicit, 
      nd-neighbor-advert } counter accept
    ip protocol icmp icmp type echo-request limit rate 10/second counter accept
    ip6 daddr fe80::/64 udp dport dhcpv6-client counter accept
    ip6 saddr $server_net_ip6 tcp dport {22} counter accept
    # letsencrypt
    ip saddr 0.0.0.0/0 tcp dport {80,443} counter accept
    ip6 saddr ::/0 tcp dport {80,443} counter accept
    # ipsec
    ip protocol esp accept
    ip saddr 0.0.0.0/0 udp dport {500,4500} counter accept
    log
    drop
  }
  chain ouput {
    type filter hook output priority 0;
    accept
  }
  chain forward {
    type filter hook forward priority 0;
    iifname ppp0 counter jump from_internet
  }
  chain from_internet {
    ct state {established,related} counter accept
    ct state invalid counter drop
    ip6 daddr $dovecot_ip6 jump to_dovecot
    log
    drop
  }
  chain to_dovecot {
    ip6 saddr $server_net_ip6 tcp dport {22} counter accept
  }
}
 
table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
    iifname ppp0 counter jump dnat_from_internet 
  }
  chain dnat_from_internet {
    udp dport { sip, 16384-16400 } counter dnat $my_phone
  }
  chain postrouting {
    type nat hook postrouting priority 0;
    oifname ppp0 counter masquerade
  }
}

iptables

Wer sich nftables nicht antun möchte, kann das simple NAT mit IPv4 mit iptables folgendermaßen einrichten:

#!/bin/bash                                                                         
                                                                                    
iptables --flush                                                                    
iptables -t nat --flush                                                             
iptables -X                                                                         
                                                                                    
set -x                                                                              
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE                                
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu 
iptables -A FORWARD -i ppp0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i ppp0 -m state --state RELATED,ESTABLISHED -j ACCEPT            
iptables -A INPUT -i ppp0 -j LOG                                                    
iptables -A INPUT -i ppp0 -j DROP                                                   
set +x                                                                              

Firewall-Skript automatisch laden

Egal ob man iptables oder nftables verwendet, man muss sicherstellen, dass die Regeln geladen werden, wenn das PPP-Interface hochkommt. Das erledigt man am einfachsten, indem man eine ausführbare Datei nach /etc/ppp/ip-up.d legt. Bei mir sieht der Inhalt folgendermaßen aus:

#!/bin/bash
nft -f /etc/nftables.conf
iptables --flush
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Ich habe an dieser Stelle nicht überprüft, wann dieses Skript ausgeführt wird – theoretisch könnte es einen kurzen Zeitpunkt geben, wo das PPP-Interface bereits von außen erreichbar, aber die Firewall noch nicht geladen worden ist (oder aufgrund eines Syntax-Fehlers in der Datei die Firewall gar nicht aktiviert wird). Da auf meiner Firewall außer SSH keine Internet-Dienste laufen, mache ich mir darüber keine weiteren Sorgen.

MSS Clamping

Eingangs habe ich erwähnt, dass das PPPoE-Protokoll zum Einsatz kommt. Aus diesem Grund muss man bei der gesetzten MTU besonders aufpassen. PPP setzt die MTU mit dem ISP auf 1492. Ethernet hat eine MTU von 1500. Da vor das PPP-Paket mit 1492 Bytes noch ein 8 Byte Header kommt, kommuniziert der pppd mit dem ISP mit 1500 Bytes.

Wird ein TCP Paket jedoch im Ethernet (das annimmt, 1500 Byte als MTU im gesamten Pfad bis ins Internet zu haben) mit einer Paketgröße von 1500 Bytes versendet, muss unser PPP-Router das Paket fragmentieren.

Hier kommt eine Technik namens Maximum Segment Size Clamping zum Einsatz. Kurzum, mit dem Befehl

iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

wird der Header in TCP-Paketen derart verändert, dass kein TCP-Paket größer als 1492 von innen oder außen gesendet wird. Das kann für einige Provider erforderlich sein. Manche ISPs erlauben jedoch MTUs, die größer als 1500 Bytes sind, dann wird das MSS Clamping nicht benötigt. Für IPv6 ist kein MSS Clamping notwendig, da IPv6 die MTU im gesamten Routing-Pfad ermittelt.

Über den Autor

Wolfgang Hennebichler (Webseite[5]) ist Site Reliability Engineer bei Google.

Linkverweise:


[1] www.pro-linux.de/artikel/1/73/dsl-modem-im-bridging-modus-betreiben.html 
[2] de.wikipedia.org/wiki/PPP_over_Ethernet 
[3] www.pro-linux.de/news/1/21853/netfilter-projekt-veröffentlicht-nftables-04.html 
[4] www.linux-magazin.de/Ausgaben/2014/01/NFtables 
[5] www.wogri.at/

http://www.pro-linux.de/images/NB3/base/print/nb3_logo.png

Mediadaten RSS/Feeds Datenschutz Impressum

© 2017 Pro-Linux