auf die Schnelle: eine WLAN-Bake
Bei einer Autofahrt mit einem Parteifreund kam uns die Idee, man könnte
mittels WLAN-Baken - also Geräten, die ein WLAN aufspannen z.B. mit einem
klingenden Namen - auch Wahlkampf oder sonstige Werbung machen.
Und das Konzept wurde dann immer ausgefeilter, wie das so ist, wenn zwei
diplomierte Ingenieure so ins Brainstorming kommen.
Bei weiteren Recherchen viel dann auf, dass so ein Projekt durchaus eine
Anwendung finden könnte.
Und dass es ggf. als Blaupause und Anleitung dienen könnte für andere Leute.
Daher haben wir uns entschlossen, dass ich eine Anleitung zum Bau so eines
Gerätes erstellen.
Also machen wir das jetzt hier.
Schritt für Schritt
Die Grundidee dieser Seite ist, dass hier ein einfaches Kochrezept
dargestellt wird, das man einfach Schritt für Schritt nachvollziehen
kann und so zum fertigen Gerät kommt.
Wenn ich aus dem erhaltenen feedback Interesse verspüre, dann mache ich
zu den Einzelschritten noch separate Seiten, die den jeweiligen Schritt
genauer darstellen.
Bin gespannt, wie das klappt.
Kommentare und Anregungen unter mailto://hase@hase.net sind also durchaus erwünscht.
Übersicht
Was brauchen wir?
Zunächst mal einen RaspberryPi in der Version 3, was zum Zeitpunkt dieses
Projektes die aktuelle Fassung darstellt.
Der 3er-Raspi enthält bereits ein WLAN Funkmodul, das bei älteren Modellen
erst nachgerüstet werden müsste, z.B. als USB-Stick.
Mit der Kombo aus einem Raspbi-V2 und USB-Wlan-Stick müste die Anleitung
auch funktionieren, aber probiert habe ich es nur mit der V3 und dem
dort integrierten WLAN.
Dann eine Speicherkarte Typ Micro-SD mit mindestens 8 GB.
Ich empfehle eine 16- oder 32-GB Karte, Markenhersteller aus zuverlässiger Quelle.
Schnelle Karten machen mehr Freude als langsame, aber die Markengeräte sind
heutzutage alle sehr gut, weil für den Einsatz in Handies vorgesehen, die
schnelle Karten besonders mögen.
Dann eine Stromversorgung.
Für stationären Betrieb wäre das ein Netzteil - und da ist der Raspi etwas
anspruchsvoll.
Spannender erscheint mir aber der mobile Betrieb über eine PowerBank.
Hier würde ich ein Modell empfehlen, das bei angeschlossenem Ladekabel immer noch
Strom auf den Ausgangsbuchsen liefert.
Selbstverständlich ist das nicht, bei mehreren von mir gekauften Geräten
werden die USB-Ausgänge deaktiviert während die PowerBank lädt.
Grosse Akkusysteme, die für den Betrieb von Laptops oder gar als
Starthilfebox für Kraftfahrzeuge vorgesehen sind, liefern nach meiner
Erfahrung permanent die 5V am USB-Ausgang.
Mit so einer PowerBank lässt sich dann sehr bequem zwischen Mobil- und
Stationärbetrieb wechseln.
Verbunden wird die USB-Stromquelle über ein Micro-USB-Kabel mit dem Pi.
Ein möglichst kurzes Kabel hoher Qualität (grosser Leitungsquerschnitt für
minimale Verluste; gute Ladekabel bieten das) macht hier mehr Freude als Billigware.
Zum Einrichten benötigen wir einen Internetzugang für den neuen Raspbi,
der über (verkabeltes) Ethernet bereitgestellt wird:
da das Wlan ja als AccessPoint konfiguriert wird, kann es nicht gleichzeitig
die Netzwerk-Anbindung des Raspi herstellen.
Zum Einrichten benötigen wir weiterhin eine Tastatur mit USB-Anschluss sowie
einen Monitor mit HDMI-Eingang und das passende Verbindungskabel.
DVI-Monitore sollten mit dem passenden Adapterkabel ebenfalls funktionieren.
Und wir benötigen letztlich einen Computer mit dem wir eine Mikro-SD-Karte
beschreiben können.
Ich verwende einen Linux-Computer, erfahrene Windows-Anwender sollten
alle Schritte jedoch analog nachvollziehen können.
Dieses Zubehör sollte sich in vielen Haushalten finden.
Schritt 1: Raspbian herunterladen.
Auf der Seite der RaspberryPi Foundation finden wir unter downloads
das gewünschte Image.
Für die Anleitung verwende ich die Variante
Raspbian Stretch Lite
Schritt 2: Auf die SD-Karte schreiben
Unter Linux ist das besonders einfach:
image entpacken (unzip)
auf die SD-Karte schreiben (dd)
Die offizielle Installationsanleitung der Foundation empfiehlt für
windows-Anwender das Programm Etcher. Dieser Empfehlung
schliesse ich mich an.
Schritt 3: erster Boot
Das frisch installierte Image wird hier das erste Mal gestartet.
Dazu schliessen wir die Tastatur an einen beliebigen USB-Port an, verbinden den HDMI-Ausgang
mit dem Monitor und schliessen zuletzt die Stromversorgung an.
Der Monitor sollte zuvor eingeschaltet sein, damit man den Bootvorgang
komplett sehe kann.
Zunächst wird ein Farbmuster dargestellt, dann erscheint die Textkonsole des Pi
mit 4 Himbeeren in der linken oberen Ecke des Bildschirms (ältere Modelle
zeigen hier eine oder zwei Himbeeren; das stellt die Anzahl der CPU-Kerne dar).
Achtet dabei - und während der ganzen Instalaltion - bitte genau auf die
rechte obere Ecke des Monitorbildes.
Erscheint hier ein gelber Blitz, dann hat der Raspi eine Unterspannung der
Stromversorgung festgestellt.
Von einem Betrieb mit so einer Stromversorgung rate ich dringend ab.
Es scheint zwar zunächst alles gut zu funktionieren, aber die SD-Karte wird
dann sehr schnell ausfallen; viele Gerüchte um die "Unzuverlässigkeit" von
"Bastellösungen" mit Raspis gehen auf diesen Umstand zurück.
Die Foundation empfiehlt daher Netzteile, deren Spannung sich am oberen Ende der
USB-Spezifikation bewegen (5,2V oder 5,25V), viele Powerpanks liefern ähnliche Spannungen.
Übrigens: die Versorgung mit 5V über eine USB-Buchse für ein Gerät, das selber
USB-Buchsen hat, halte ich für die grösste Schwäche des RaspberryPi-Konzeptes überhaupt.
Das Gerät sollte jetzt booten.
Schritt 4: Grundkonfiguration des Pi
Auf der Konsole loggen wir uns ein mit dem benutzer pi und dem Passwort raspberry.
Achtung Anfängerfalle: auf einer deutschen Tastatur ist das als raspberrz einzutippen...
Jetzt gilt es, die Grundkonfiguration herzustellen mittels sudo raspi-config.
Als erstes wählen wir unter Advanced Options den Punkt Expand Filesystem.
Damit wird das Dateisystem auf der SD-Karte so modifiziert, dass wir nach
einem Neustart die gesamte Kapazität nutzen können.
Danach verlassen wir raspbi-config mit finish und starten den Pi nue mit
sudo shutdown -r now.
Dann wieder einloggen (wie oben) und mit sudo raspbi-config in die Konfiguration
einsteigen.
Jetzt den Punk Update wählen, um raspbi-config auf die aktuelle Version
zu bringen.
Danach bitte unbedingt den Punkt Change User Password ausführen.
Dies ändert das Passwort für den Benutzer pi (der bei Raspbian der Standard-Benutzer ist).
Passwort merken, sonst von vorn :-)
Nun die anderen Grundeinstellungen, hier im Schnelldurchlauf:
Network Options
- Hostname: ich vergebe immer einen Hostnamen nach der Funktion des Geräts. Z.B. Bake
- Wi-Fi: unverändert lassen
- Network Interface Names: "yes" für "predictables names" anwählen
Boot Options
- Desktop/Cli: Console (Textkonsole, ohne grafischen desktop denn: wir bauen einen Server)
localization options
- Change Locale: nach Wunsch, ich bleib immer bei UK-English
- Change Timezone: auf deutsche Zeitzone (Büsingen oder so) einstellen
- Change Keyboard: auf das verwendete Keyboard einstellen; bei mir "german"
- Change Wi-fi Country: auf DE einstellen.
Grad das Setting für Wi-fi Country ist wichtig: damit stellt man das Funkmodul so
ein, dass nur mit zulässigen Sendeleistungen in den hierzulande zulässigen
Bändern gefunkt wird.
Soll das Gerät ausserhalb Deutschlands eingesetzt werden, dann muss hier das
Land eingestellt werden, wo der betrieb vorgesehen ist.
Interfacing Options
SSH: einschalten, alles andere aus. (Wer mag aktiviert eine serielle Konsole,
aber wenn Du damit was anfangen kannst, warum liest Du das hier überhaupt? :-)
Overclocking:
geht bei V3-Pi eh nicht, ist auch sonst selten ratsam, weil Überhitzung droht.
Advanced Options
- Overscan hilft mit manchen Monitoren, ausprobieren.
- Memory Split: auf 16 stellen (nur 16MB für die GPU - mehr für die CPU, denn wir bauen einen Server)
- Resolution: ggf. anpassen an den eigenen Monitor
- Pixel Doubling: ggf. ebenfalls anpassen für ein lesbareres Bild
- GL driver: aus
Zum Abschluss dann neu starten ("yes" bei "reboot now" oder auf der Kommandozeile
sudo shutdown -r now)
Schritt 5: Raspbian updaten, benötigte Software installieren
Zunächst müssen wir uns hier wieder einloggen, ich würde sagen per ssh.
Dazu gilt es zunächst, die IP-Adresse des neuen Pi herauszufinden.
Bei einem OpenWRT-Router zeigt der Statusbildschirm die zur Zeit vergebenen Adressen;
Im Screenshot sehen wir, dass der Router für manche Geräte einen Hostnamen kenn, für andere Geräte nicht; der Pi gehört
offenbar zu denen, die keinen Namen im DHCP-Request senden - was schade ist.
Dennoch finden wir über den DHCP-Status des Routers die gesuchte IP-Adresse,
hier die 192.168.42.170:

Auf der Kommandozeile können wir uns nun mit ssh pi@<IP-Adresse> also ssh pi@192.168.42.170
auf dem Pi einloggen.
Das Passwort sollte im Moment noch das Standardpasswort für Raspbian sein (raspberry).
Als erstes ändern wir nun dieses Standardpasswort:
und dann altes und neues Passwort (zweimal) eingeben.
In einem zweiten Fenster mit Kommandozeile loggen wir uns nun ein zweites Mal ein mit
und können so testen, dass auch mit dem neuen Passwort der Login funktioniert.
Für extra Komfort erlaube ich dann noch meinen üblichen ssh-keys den Zugang zum
Pi ohne Passwort-Eingabe; auf der Linux-Kommandozeile:
ssh-copy-id pi@<IP-Adresse>
Das fragt dann nach dem aktuellen Passwort des Benutzers (pi) und kopiert dann den
öffentlichen ssh-Schlüssel aus .ssh/id_ecdsa.pub auf den pi.
Damit kann jeder Computer, auf dem der zugehörige private Schlüssel erfügbar ist,
eine ssh-Verbindung herstellen ohne dass ein Passwort abgefragt wird.
Nun die Software.
Ich bevorzuge aptitude gegenüber apt, weil man damit besser nach Paketen suchen kann, für diese Anleitung verwende ich aber apt.
Zunächst ein komplettes Update aller installierten Software auf die aktuellen Stände:
sudo bash -c 'for i in update {,dist-}upgrade auto{remove,clean}; do apt-get $i -y; done'
Das führt nacheinander einige apt-Kommandos aus:
- update: aktualisiert die Paketlisten vom Server
- upgrade -y: aktualisiert installierte Software (ohne Nachfragen durch das -y)
- dist-upgrade -y: aktualisiert Basissoftware (wieder ohne Nachfragen durch -y)
- autoremove -y: entfernt nicht mehr benötigte Pakete
- autoclean -y: entfernt alte Daten aus dem Paket-Cache
Danach starten wir zur Sicherheit neu, da vermutlich der Kernel und andere
wichtige Software aktualisiert wurden.
Wieder einloggen und nun die Installation der benötigten Software für unseren Server:
sudo apt-get install aptitude supervisor python python-pip vim hostapd dnsmasq apache2
Der Editor vim wird heutzutage nicht mehr automatisch in Debian/Raspbian installiert,
und viele bevorzugen heute den vorinstallierten nano - ich bleibe bei dem, was ich kenne :-).
Schritt 6: Konfiguration WLAN-AccessPoint (hostapd)
Grundsätzlich werden bei WiFi drei Betriebsmodi unterschieden:
Point-to-Point auch WiFi Direct genannt; erlaubt Kommunikation zwischen Geräte ohne weitere Infrastruktur; heute selten eingesetzt.
Station
* AccessPoint (AP)
Manche WLAN-Hardware lässt sich gar nicht als AP betreiben, heutzutage ist das allerdings
selten geworden; dennoch werden Wlan-Adapter meisst im Modus Station betrieben.
Eine Station registriert sich gegenüber einem AccessPoint und stellt so eine
Assoziation her. Das ist vergleichbar mit dem Einstecken eines Ethernet-Kabels am Gerät.
Die Interfaces von Routern werden idR. im Modus AccessPoint betrieben, stellen
also Stations gegenüber eine Funkzelle bereit.
Genau das wollen wir hier mit dem Pi bewirken.
Der Daemon hostapd ist die Standard-AP-mplementation für Linux und dient auf
Millionen "Wlan-Routern" für genau diesen Zweck.
Konfiguriert wird der Daemon über die Datei /etc/hostapd/hostapd.conf.
Die bei Raspbian gelieferte Beispiel-config ist recht lang, was auch daran liegt, dass der WiFi-Standard seit
zwei Jahrzehnten immer wieder erweitert wird.
Zunächst ist diese zu kopieren und zu dekomprimieren:
sudo cp /usr/share/doc/hostapd/examples/hostapd.conf.gz /etc/hostapd
sudo gunzip /etc/hostapd/hostapd.conf.gz
Danach ändern wir die Zeilen, die wir benötigen und lassen die anderen Werte auf
den Beispielwerten stehen - das passt schon sehr gut.
Editieren darf die config-Datei nur der Superuser (root), daher öffnen wir die Datei mit
sudo <lieblingseditor> /etc/hostapd/hostapd.conf.
In der Datei suchen wir jetzt die Zeilen, die zu ändern sind; ich gebe hier nur die zu ändernden
Zeilen an, die ganze config-Datei wäre zu lang.
Die Suchen-Funktion des verwendeten Editors hilft hier, in vim ist das einfach der Slash (/).
Protip: eine Suche nach ^string findet den gesuchten string nur am Zeilenanfang, wenn der Editor Suche mit regular expression beherrscht wie vim.
#ssid=test # Zeile entfernen oder mit # zum Kommentar machen
ssid2=P"Pirate\nOpenSpot"
country_code=DE
ieee80211d=1
ieee80211h=1
local_pwr_constraint=3
spectrum_mgmt_required=1
hw_mode=g
channel=12
beacon_int=50
dtim_period=2
no_probe_resp_if_max_sta=254
ap_max_inactivity=120
skip_inactivity_poll=1
disassoc_low_ack=1
ap_isolate=1
Besonderes Augenmerk verdienen hier
- ssid2: das ist der Name des WLAN der in den Auswahlmenüs der Clients angezeigt wird. Der hostapd erlaubt hier auch Return-Zeichen, was ungewöhnlich ist.
- country_code: muss unbedingt auf den korrekten Wert (DE für Deutschland) gesetzt werden.
- ap_isolate=1: damit können Stations an diesem AP nicht direkt miteinander kommunizieren. In einem Heimnetz würde man das auf 0 setzen.
- wir haben keine Verschlüsselung für das WLAN spezifiziert, betreiben es also offen; für ein Heimnetz ist das idR. nicht die "richtige" Einstellung.
Als nächstes teilen wir Rasbian mit, wo nach der hostapd.config zu suchen ist.
sudo <lieblingseditor> /etc/default/hostapd
#DAEMON_CONF=""
ändern in
DAEMON_CONF="/etc/hostapd/hostapd.conf"
Schritt 7: DHCP client konfigurieren
Wir wollen auf dem kabelgebundenen Ethernet weiterhin unsere IP-Adresse mittels
DHCP von unserem lokalen Router beziehen.
Auf dem Wlan-Interface dagegen benötigen wir eine statische IP-Adresse für unseren
Hotspot.
Die Konfiguration des DHCP-clients in Raspian erledigt beides;
normalerweise bezieht der dhcpcd auf allen verfügbaren interfaces eine IP-Adresse,
wir stellen das nur für das wlan0 interface um und schon entsteht das gewünschte Verhalten.
sudo <lieblingseditor> /etc/dhcpcd.conf
Am Ende der Datei einfügen:
interface wlan0
static ip_address=192.168.23.1/24
Danach ist leider offenbar ein reboot nötig?
Schadet nicht und geht fix :-)
und wieder einloggen.
Jetzt gilt es noch, den hostap-Dienst auch zu aktivieren und zu starten:
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl restart hostapd
Nun sollte das neue WLAN sichtbar sein unter der eingestellen SSID.
Nur funktioniert es (noch) nicht, weil wir noch keine IP-Adressen an assoziierte Stationen vergeben.
Schritt 8: Konfiguration DHCP-Server (dnsmasq)
Die Adressvergabe in Ethernet (und dem verwandten WiFi) geschieht idR. mit
dem Dynamic Host Configuration Protocol DHCP.
Für dieses gibt es eine Reihe Implemendationen, die häufiger im Einsatz sind.
Der freie dnsmasq ist auf Linux-basierten Routern besonders beliebt, da er
nicht nur DHCP bereitstellt sondern auch DNS-Caching und weitere Funktionen -
und das alles bei geringem Bedarf an Speicher und CPU, die auf (Heimnetz-)Routern
häufig knapp sind.
Konfiguriert wird der Dienst über /etc/dnsmasq.conf, die wieder mit sudo zu editieren ist.
Wir konfigurieren ihn wie folgt:
interface=wlan0 # Use the require wireless interface - usually wlan0
dhcp-range=192.168.23.2,192.168.23.253,255.255.255.0,1h
interface=wlan0 #listen on this interface only
except-interface=lo
bind-interfaces # needed for interface= option to work
listen-address=192.168.23.1
port=53
no-resolv # do not forward dns lookups to the servers in /etc/resolv.conf
server=127.0.0.1
Und aktivieren und starten den Dienst danach:
sudo systemctl enable dnsmasq
sudo systemctl restart dnsmasq
Nun sollte z.B. ein Smartphone beim Auswählen des neuen WLAN auch eine IP-Adresse erhalten.
Im Grunde funktioniert unser "Hotspot" jetzt schon.
Aber er stellt keinen Router dar, der Pakete aus dem WLAN über sein Ethernet
weiterleitet. Das war auch nicht das Ziel.
Die Weiterleitung von Paketen aus einem Netz (z.B. Wlan) in ein anderes Netz (z.B. Ethernet)
wird unter Linux von dem Kernel-Parameter net.ipv4.ip_forward gesteuert.
Dieser Parameter steht normalerweise auf 0, wie sich wie folgt überprüfen lässt:
sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
Dies verbietet dem Kernel, Pakete aus einem Netz in ein anderes weiterzuleiten, es
verbietet das, was man klassisch "Routing" nennt.
Nicht zu routen ist eine sinnvolle Grundeinstellung für alle Geräte, die nicht
explizit Router sein sollen, Raspbian macht das also richtig.
Über unseren Hotspot ist also nur Zugriff auf den Pi selbst (also auf Programme/Dienste/Daemonen die auf dem Pi laufen) möglich.
Gut so.
Allerdings wird der Pi ab dieser Stelle ein Problem mit dem Internetzugang haben:
Ab hier wird die DNS-Auflösung nicht mehr funktionieren, da wir keine externen
DNS server mehr abfragen (sondern nur den internen dnsmasq).
Das korrigieren wir temporär, indem wir die DNS-Konfiguration auf einen
externen DNS-Server umstellen:
sudo <lieblingseditor> /etc/resolv.conf
nameserver 127.0.0.1
ändern in
nameserver 8.8.8.8
Der Nameserver 8.8.8.8 wird von Google betrieben, wer Google nicht die DNS-
Abfragen seines Pi petzen möchte, kann hier einen anderen der öffentlichen
DNS einstellen oder die IP-Adresse des eigenen Routers: da ist normalerweise ein
dnsmasq drauf, der die Anfragen passend weiterleitet.
Schritt 9: Konfiguration DNS-Lügner
Im Grunde ist nach Schritt 7 der Zugriff auf Dienste auf dem Pi schon möglich.
Allerdings müsste man immer die IP-Adresse des wlan0 des Pi als "hostnamen" eintippen.
Geschickter wäre es, wenn wir den Pi über einen Namen adressieren könnten.
Noch pfiffiger scheint es mir allerdings, wenn wir den Pi über beliebige Namen
adressierten: egal, welcher Name angefragt wird, wir geben immer die IP-Adresse
des Pi-wlan0 zurück.
Dafür gibt es keine fertige Software.
Und das ist gut so: diese Software stellt im Grunde einen Eingriff in die Rechte Dritter dar.
Der Autor ist z.B. Inhaber der Domains "hase", sowohl in der TLD ".net" als auch in der TLD "rocks".
Letztlich heisst das, dass nur ich festlegen darf, welche Auskunft das DNS für Anfragen nach
<irgendwas>.hase.net oder <wasauchimmer>.hase.rocks geben darf.
Als Inhaber steht dieses Recht, diese Verfügungsgewalt über die DNS-Auskunft, nur mir zu.
Dieses Recht wurde zunächst in den 90ern mit dem aufkommenden DNS
festgelegt als das, was Juristen eine Standesregel nennen: der Berufsstand der
DNS-Admins stelle sicher, dass nur die Domain-Inhaber die Auskünfte aus diesem
Verzeichnisdienst bestimmten.
In dieses Recht wurde mehrfach schon eingegriffen.
Besonderes Aufsehen erregte z.B. Anfang der Nullerjahre ein Fall von DNS-Manipulationen, die
bei verschienen ISP aufgrund Verfügung durch die Bezirksregierung Düsseldorf
durchgeführt wurden.
Das im folgenden dargestellte Programm dns-liar.py macht im Grunde etwas
ähnliches: statt die im DNS vorgesehenen Antworten auf DNS-Queries gibt es einfach
immer dieselbe Antwort zurück.
Interessanterweise scheint das bis heute nicht gesetzwidrig zu sein, es ist halt noch immer eine Standesregel.
Und im privaten Umfeld und bei begrenzter Reichweite erscheint es dem Autor auch durchaus vertretbar,
speziell auf einem Hotspot-Gerät, das keine Verbindung zum Internet hat bzw. bereitstellt.
Stellen wir erstmal ein paar Grundlagen her.
Unser DNS-Lügner soll später als Daemon laufen, der muss irgendwie gestartet werden.
Für diese Anleitung verwende ich das Paket supervisor, das unabhängig von den
Linux-Systemeigenen Mechanismen daemonen kontrollieren kann.
Das bietet zum einen den Vorteil, dass es auf verschiedenne Distributionen
immer gleichartig läuft, egal welches Daemon-Management die Distribution intern
einsetzt. Und daher beisst es sich auch nicht mit Updates des Distributionsinternen Mechanismus.
Der supervisord wird über die Datei /etc/supervisor/supervisord.conf konfiguriert,
die wir aber im Zustand belassen können, den Raspbian ausliefert.
Die von supervisor kontrollierten Daemonen werden über einzelne Dateien in /etc/supervisor/conf.d
konfiguriert.
sudo <lieblingseditor> /etc/supervisor/conf.d/dns-liar.conf
[program:dns-liar]
logfile_maxbytes = 30MB
logfile_backups = 5
command=/usr/local/bin/dns-liar.py --address "127.0.0.1" --response ". 60 IN A 192.168.23.1"
Wichtig ist hier die IP-Adresse 192.168.23.1: diese gibt der DNS-Lügner als Antwort
auf jede Frage. Hier verwenden wir die IP-Adresse unseres wlan0-Interface.
Das entsprechende Programm brauchen wir jetzt noch.
sudo <lieblingseditor> /usr/local/bin/dns-liar.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
FixedResolver - example resolver which responds with fixed response
to all requests
"""
from __future__ import print_function
import copy
from dnslib import RR
from dnslib.server import DNSServer,DNSHandler,BaseResolver,DNSLogger
class FixedResolver(BaseResolver):
"""
Respond with fixed response to all requests
"""
def __init__(self,zone):
# Parse RRs
self.rrs = RR.fromZone(zone)
def resolve(self,request,handler):
reply = request.reply()
qname = request.q.qname
# Replace labels with request label
for rr in self.rrs:
a = copy.copy(rr)
a.rname = qname
reply.add_answer(a)
return reply
if __name__ == '__main__':
import argparse,sys,time
p = argparse.ArgumentParser(description="Fixed DNS Resolver")
p.add_argument("--response","-r",default=". 60 IN A 127.0.0.1", metavar="<response>", help="DNS response (zone format) (default: 127.0.0.1)")
p.add_argument("--zonefile","-f", metavar="<zonefile>", help="DNS response (zone file, '-' for stdin)")
p.add_argument("--port","-p",type=int,default=53, metavar="<port>", help="Server port (default:53)")
p.add_argument("--address","-a",default="", metavar="<address>", help="Listen address (default:all)")
p.add_argument("--udplen","-u",type=int,default=0, metavar="<udplen>", help="Max UDP packet length (default:0)")
p.add_argument("--tcp",action='store_true',default=False, help="TCP server (default: UDP only)")
p.add_argument("--log",default="request,reply,truncated,error", help="Log hooks to enable (default: +request,+reply,+truncated,+error,-recv,-send,-data)")
p.add_argument("--log-prefix",action='store_true',default=False, help="Log prefix (timestamp/handler/resolver) (default: False)")
args = p.parse_args()
if args.zonefile:
if args.zonefile == '-':
args.response = sys.stdin
else:
args.response = open(args.zonefile)
resolver = FixedResolver(args.response)
logger = DNSLogger(args.log,args.log_prefix)
print("Starting Fixed Resolver (%s:%d) [%s]" % (
args.address or "*",
args.port,
"UDP/TCP" if args.tcp else "UDP"))
for rr in resolver.rrs:
print(" | ",rr.toZone().strip(),sep="")
print()
if args.udplen:
DNSHandler.udplen = args.udplen
udp_server = DNSServer(resolver,
port=args.port,
address=args.address,
logger=logger)
udp_server.start_thread()
if args.tcp:
tcp_server = DNSServer(resolver,
port=args.port,
address=args.address,
tcp=True,
logger=logger)
tcp_server.start_thread()
while udp_server.isAlive():
time.sleep(1)
Das Programm muss ausführbar sein:
sudo chmod 777 /usr/local/bin/dns-liar.py
Und wir brauchen noch die entsprechenden Python-Module:
Wir können jetzt probieren, ob das so funktioniert wie gewünscht:
sudo /usr/local/bin/dns-liar.py --address "127.0.0.1" --response ". 60 IN A 192.168.23.1"
Wenn man jetzt ein Smartphone am Hotspot einbucht, sollten hier schon die ersten
Anfragen geloggt werden: Smartphone fragen ständig diverse Hosts an, auch um
zu testen, ob das WLAN auch Zugang zum Internet bereitstellt.
Mit Ctrl-C beenden wir das Programm und mit
sudo systemctl restart supervisor
sudo supervisorctl restart dns-liar
starten wir den Daemon im Hintergrund.
Die Ausgaben des Daemons finden wir dann in /var/log/supervisor.
Schritt 10: Content
Jetzt fehlt eigentlich nur noch ein Webserver auf dem Pi.
Da wir ja alle DNS-Anfragen mit der IP-Adresses des Pi beantworten landen alle
Browser-Connections auf diesem Webserver.
Das funktioniert übrigens nicht mit vielen modernen Websites, die schon
die aktuellen Sicherheitsstandards umsetzen.
In aller Kürze: idR. liefern grosse Sites heute nur noch über https aus
und teilen das den Browsern auch mit.
Die Browser merken sich das und verlangen für einmal besuchte https-only-Sites, dass
auch weiterhin nur https verwendet wird.
Bei Anfragen für solche Sites erscheint dann in unserem Hotspot-WLAN eine Fehlermeldung im Browser.
Das Paket apache2 stell in Raspbian den beliebten Webserver bereit.
Die Standardinstallation enthält eine simple config (/etc/apache2/sites-enabled/000-default.conf),
die für unsere Zwecke auch unmodifiziert einsetzbar ist.
Eine komplettere Anleitung zur Konfiguration von Webserver sprengte auch den
Rahmen dieses Kochrezeptes.
Nur gilt es nur noch, geeignete Inhalte im Verzeichnis /var/www/html abzulegen.
Auch die Anleitung zur Erstellung von Websites lasse ich an dieser Stelle weg.
Auf hase.net findet der eilige Leser ein
komplettes Projekt für pelican.
Enthalten ist nicht nur der "Quelltext" der Site sondern auch der fertige Output, der
direkt auf den Pi kopiert werden kann. Zum neu-Übersetzen bräuchte man dann pelican, entweder auf
dem Hotspot-Pi oder auf dem Linux-Desktop.
herunterladen der Datei:
wget https://www.hase.net/transfers/OpenSpot.tar.bz
auspacken:
Und nun noch die Dateien an die richtige Stelle kopieren:
cd OpenSpot/output
sudo cp -r * /var/www/html
sudo chown -R www-data:www-data /var/www/html/*
Und dann den Webserver zur Sicheheit heu starten (sollte an sich nicht erfoderlich sein?)
sudo systemctl restart apache2
Der Webserver auf dem Pi sollte jetzt unter http://<IP-Adresse> und auch unter jedem
beliebigen hostnamen z.B. http://huhu.blafasel.tld dieselbe Seite ausgeben.
Bei Fragen: fragen! mailto://hase@hase.net