3G/4G netwerksimulatie

Voor een project bij een klant zochten we een mogelijkheid om op eenvoudige manier een 3G/4G-netwerk te simuleren. Met een Raspberry-Pi-computer is dat eenvoudig te realiseren. Lees hieronder hoe je dat zelf doet.
De Raspberry Pi heeft sinds versie 3 een wifi-chip aan boord en je kunt er met een paar eenvoudige configuratiewijzigingen een wifi-basisstation mee bouwen. De handleiding daarvoor vind je hier. Op zichzelf is het maken van een accespoint niet zo bijzonder – het wordt pas leuk als je dat access point kunt inzetten voor netwerksimulatie. Dat is wat we hier zullen doen: we bouwen een raspberry pi om tot een langzaam en onbetrouwbaar netwerk: 4G, 3G of nog langzamer, met naar keuze extra latency en/of packet-loss.

Stap 1: een access point

In het voorbeeld hierna gebruiken we de Raspberry Pi 3 B+, maar de handleiding laat zich ook eenvoudig volgen op de gewone Raspberry Pi 3. Op oudere Pi’s moet je een aparte wifi-stick gebruiken. We volgen eenvoudigweg de handleiding van “Using the Raspberry Pi as an access point to share an internet connection (bridge)“, met een paar opmerkingen. Omdat deze handleiding op de site van de raspberry pi zelf heel goed is, volgt hieronder alleen nog een “lange-halen-snel-thuis”-script. Let dus op: hieronder overschrijven we instellingen. Eigenlijk is het script vooral goed bruikbaar met een nieuw geïnstalleerde RPi. Heb je een RPi met eigen netwerkconfiguratie, bijzondere instellingen of anderszins gegevens die je graag wilt behouden, voer dan onderstaande commando’s bij voorkeur niet uit. Of in elk geval niet blindelings. Sowieso is het oppassen geblazen: omdat we bijvoorbeeld /etc/network/interfaces.d/bridge nieuw aanmaken, betekent het dat eventuele instellingen in /etc/network/interfaces gewoon nog steeds geldig zijn – evenals eventuele andere bestanden in interfaces.d/. Kortom: weet wat je doet.

Installeer de juiste pakketten:

sudo apt-get install hostapd bridge-utils

zorg dat wlan0 en eth0 geen DHCP meer doen

sudo echo > /etc/dhcpcd.conf <<EOF
denyinterfaces wlan0
denyinterfaces eth0
EOF

Maak een netwerkbridge aan:

sudo echo > /etc/network/interfaces.d/bridge << EOF
auto br0
iface br0 inet manual
bridge_ports eth0 wlan0
EOF

Maak een zo eenvoudig mogelijke hostapd-configuratie aan. N.B. voor kanalen 36 en hoger (5GHz-band) kies je hw_mode=a in plaats van g.

sudo echo > /etc/hostapd/hostapd-minimal.conf << EOF
interface=wlan0
bridge=br0
ssid=Langzaam
country_code=NL
hw_mode=g
channel=1
wpa_passphrase=aapnootmies
EOF

Nu is er eerst nog een extra klusje te verrichten. In de eerste software-releases voor de RPi-3B+ zat een bug, die ervoor zorgde, dat de bridge bij het starten een kernel “oops” liet zien: https://github.com/raspberrypi/linux/issues/2437 – waarna je computer niet meer benaderbaar was. De bug is eruit, maar zorg er wel even voor dat je de ge-update versie ook aan boord hebt, anders kon het nog wel eens lastig worden om je RPi opnieuw te starten. Je moet dit commando uitvoeren met een netwerkverbinding (er wordt software gedownload).

sudo rpi-update

Als dat goed gegaan is, kun je herstarten. Na het starten van de Raspberry Pi heb je – als het allemaal goed gegaan is – een bridge-interface waar eth0 aan toegevoegd is. Start nu hostapd:

sudo hostapd /etc/hostapd/hostapd-minimal.conf

Dit levert je zoiets op als:

Configuration file: /etc/hostapd/hostapd-minimal.conf
Failed to create interface mon.wlan0: -95 (Operation not supported)
wlan0: interface state UNINITIALIZED->COUNTRY_UPDATE
wlan0: Could not connect to kernel driver
Using interface wlan0 with hwaddr b8:27:eb:52:d4:44 and ssid "Langzaam"
wlan0: interface state COUNTRY_UPDATE->ENABLED
wlan0: AP-ENABLED

Omdat we hostapd niet in de achtergrond draaien, blijft het programma op de voorgrond staan. Eventueel kun je de optie -B gebruiken om hostapd wel in de achtergrond te plaatsen. Test of de verbinding werkt. Goed? Dan nu stap 2: het langzaam en onbetrouwbaar maken.

Stap 2: een onbetrouwbare verbinding

Zoek je bijvoorbeeld op “open source network simulation”, dan vind je een aanzienlijk aantal uiterst veelzijdige, maar ook complexe, simulatie-systemen. Hier bijvoorbeeld een flinke lijst, met stuk voor stuk grafische tools om een heel kabel-  of 4G-netwerk te simuleren. Leuk als je Vodafone, Ziggo of KPN heet – minder handig als je gewoon een enkele mobiele kassa, een werkplek voor onderweg of een VOIP-set wilt testen.

Voor het eenvoudig langzaam maken gebruiken we een script met de naam “slow”, te vinden op Github: slow. De versie die gelinkt staat, heeft al vele verbeteringen ondergaan sinds de oorspronkelijke versie van gebruiker obscurerichard. Het script is nu goed bruikbaar, maar nog steeds met wat kanttekeningen.

wget https://gist.githubusercontent.com/svendroid/473c7d1bc90ce835ad1f81fbbe80508d/raw/ce38bcdefa403d1cfeba9ebef94a8fb1ededcac0/slow
chmod +x slow

Kanttekening 1. De laatste wijziging van slow bevat voor mobiele verbindingen eindelijk de juiste snelheid: EDGE 50 kilobit per seconde, 3G is grofweg 1000 kilobit/s en 4G zo’n 10000kbit/s (10 megabit). Maar de andere verbindingen bevatten nog steeds een typefout met forse consequenties: in plaats van “kbit” en “bit” staat er “kbps” en “bps“. Dat lijkt hetzelfde, maar dat is het niet: bps staat voor bytes per second: acht maal zoveel als de bedoeling is! Oftewel: bps moet overal vervangen worden door bit:

sed -i 's/bps$/bit/' slow

Kanttekening 2. De “traffic control” tool (“tc”) kan uitgaand verkeer wel afknijpen; inkomend verkeer wordt gewoon behandeld met de snelheid waarin het binnenkomt. Dat is wat lastig: een gesimuleerde 3G-verbinding die uitgaand 1 megabit is, maar inkomend 450megabit, is niet direct een bruikbare simulatieomgeving. Om dat op te lossen, zijn er twee mogelijkheden. De eerste is, om met een virtueel netwerkdevice te werken, het zogenaamde “Intermediate Functional Block“. Een soort van virtueel-doorstuur-device, waarbij dat doorsturen uiteraard in een door de gebruiker in te stellen tempo gebeurt.

In ons geval is dat niet nodig. De pakketten die we vanuit het wifi ontvangen, worden via de ethernet-poort weer uitgestuurd – in een vast tempo uiteraard – en de pakketten die we via ethernet ontvangen, worden juist doorgestuurd naar de wifi-interface. We hebben dus altijd uitgaande pakketten waar we traffic shaping op kunnen loslaten. Het betekent wel wat voor de implementatie van onze vertrager: die moet zowel op eth0 als op wlan0 geactiveerd worden. Om te voorkomen dat we daarmee dubbele latency (eigenlijk: round trip time, want dat meten we doorgaans) introduceren, moet die gehalveerd worden: de helft bij uitsturen via eth0, de andere helft bij het uitsturen naar wlan0.

Voorbeeld

Hoe gaan we nu simuleren? We simuleren hieronder een verbinding van 10 megabit per seconde, met een round trip time van 100 milliseconden. Dat doen we, door een snelheid van 10mbit met een latency van 50ms (de helft van de gewenste 100) op eth0 te zetten; en eveneens een snelheid van 10mbit met latency 50ms op wlan0:

sudo ./slow -b 10mbit -l 50ms -d eth0
sudo ./slow -b 10mbit -l 50ms -d wlan0

Wat hetzelfde is als:

sudo ./slow 4G -l 50ms -d eth0
sudo ./slow 4G -l 50ms -d wlan

Stel dus de gewenste snelheid op beide interfaces identiek in; de gewenste latency deel je eerst door twee.

1% packet loss op uitgaande pakketten kun je introduceren met:

sudo ./slow -b 10mbit -l 50ms -d eth0 -p 1

Let ook hier weer op, dat de packet loss opgeteld wordt: als je zowel op wlan0 als op eth0 een packetloss van 1% introduceert, wordt je totale packet loss ongeveer 2%. (Ongeveer. Het betreft hier een IP-kanaal waarover TCP of UDP verstuurd wordt. Voor een VOIP-verbinding (UDP) geldt grosso modo een opgetelde packet loss: 2% – waarbij je dan formeel de totale bandbreedte op 200% moet stellen. Maar voor TCP is een niet-bezorgde “ACK” niet hetzelfde als een niet-bezorgd datapakket. Omdat TCP een stream is, en verzonden pakketten bevestigd moeten worden, zijn de gevolgen niet zomaar in een enkel zinnetje samen te vatten).

En wil je de verbinding weer “normaal” maken, dan doe je:

sudo ./slow reset -d eth0
sudo ./slow reset -d wlan
Tenslotte

Is de simulatie perfect? Verre van. De “netem” Network Emulator module werkt nog altijd per pakket – en dat zijn wifi-pakketten, het is geen mobiele data. De typische verstoringen die je te zien krijgt als je een tunnel in rijdt of een zwakke verbinding hebt, krijg je niet zomaar te zien; terwijl je juist weer wel allerlei wifi-eigenaardigheden (background scans ten behoeve van roaming, verstoringen door andere wifi-stations) meeneemt in de vergelijking.

Maar voor zijn eenvoudige opzet is het een goed en eenvoudig bruikbaar hulpmiddel.