Tech & GadgetsAI-generated

Hoe Starlink internet via satellieten levert

Internet via een satelliet had lang een slechte naam. Een videocall voelde als een walkietalkiegesprek. Starlink levert ook internet via satellieten, maar met een latency van enkele tientallen milliseconden in plaats van een halve seconde. Het verschil zit vooral in de hoogte waarop de satellieten vliegen.

In dit artikel reken ik uit waarom een geostationaire satelliet nooit snel kan zijn, tel ik hoeveel Starlink-satellieten er op dit moment boven Nederland staan en volg ik een pakketje van een schotel in Twente naar het internet. Met echte metingen van een Starlink-aansluiting naast een vaste lijn.

Waarom geostationaire satellieten traag zijn

Een geostationaire satelliet draait precies even snel rond als de aarde zelf, waardoor hij vanaf de grond stil lijkt te staan. Met de wetten van Kepler kun je uitrekenen waar zo'n baan ligt: een omloop van één sterrendag (23 uur, 56 minuten en 4 seconden) hoort bij een hoogte van 35.786 km boven de evenaar.

Vanaf Nederland, op 52 graden noorderbreedte, staat zo'n satelliet nog verder weg: ruim 38.500 km. Licht doet daar 128,7 ms over. Een vraag aan een webserver gaat van je schotel naar de satelliet en dan naar een grondstation. Het antwoord maakt dezelfde reis terug. Dat zijn vier trajecten, samen minstens 514 ms, nog zonder één milliseconde verwerking of wachtrij.

Hoe Starlink het oplost: een baan onder de 500 km

Starlink kiest het andere uiterste. Ik heb de actuele baangegevens van alle Starlink-objecten gedownload bij CelesTrak en voor elk de gemiddelde hoogte uitgerekend. Het zijn er 10.633, inclusief een kleine 640 die gemarkeerd zijn als direct-to-cell, voor verbindingen rechtstreeks met telefoons. Ruim acht op de tien vliegen tussen 450 en 500 km hoog. De mediaan is 465 km.

Op die hoogte doet een satelliet 94 minuten over een rondje aarde, met ongeveer 7,6 km per seconde. De satellieten liggen in schillen met verschillende hellingshoeken ten opzichte van de evenaar:

HellingshoekAantal
53°4963
43°3609
97°1346
70°708

Een satelliet met een helling van 53 graden komt nooit verder naar het noorden dan 53 graden breedte. Nederland ligt daar net onder, en dat is gunstig: bij die keerlijn zijn de satellieten van zo'n schil het dichtst opeengepakt. De schillen van 70 en 97 graden zijn er voor gebieden dichter bij de polen, zoals Alaska.

Elke paar minuten een andere satelliet

De keerzijde van een lage baan is dat een satelliet snel voorbij is. Volgens een meetstudie van Mohan e.a. (WWW 2024) verbindt de schotel alleen met satellieten die hoger dan 25 graden boven de horizon staan. Het is een phased-array-antenne, die zijn bundel elektronisch richt.

Ik heb met de baangegevens een uur lang, elke tien seconden, uitgerekend welke satellieten boven Utrecht hoger dan 25 graden stonden. Dat waren er steeds tussen de 44 en 66. Geen enkele satelliet bleef langer dan 290 seconden in dat stuk hemel, de mediaan was 230 seconden.

Dezelfde studie laat zien dat Starlink zijn netwerk elke 15 seconden opnieuw indeelt, wereldwijd tegelijk. Op die grenzen springt de latency en zakt de doorvoer even in. Dat gebeurde ook als er maar één satelliet in beeld was, dus een overstap tussen satellieten is niet de oorzaak. De onderzoekers denken aan een planningsronde van het netwerk.

Van schotel naar internet: de bent pipe

Een Starlink-satelliet is in de basis een doorgeefluik: de schotel praat met de satelliet in de Ku-band, de satelliet stuurt het verkeer in de Ka-band door naar een grondstation, en dat stuurt het via het vaste net naar een point of presence (PoP), waar het verkeer het internet op gaat. Dat heet een bent pipe, een gebogen pijp.

In een traceroute zie je de satelliet zelf niet. Ik heb de traceroute opgehaald van een openbaar RIPE Atlas-meetpunt dat op een Starlink-aansluiting bij de Universiteit Twente hangt, naar de rootserver k.root-servers.net:

1  10.13.37.254     0,2 ms
2  100.64.0.1      21-30 ms
3  172.16.253.124  23-34 ms
...
10 193.0.14.129    37-43 ms

De eerste hop is de lokale router. Bij de tweede hop zit het hele ruimtedeel er al in: schotel, satelliet en grondstation. Het adres 100.64.0.1 komt uit de reeks die RFC 6598 reserveerde voor carrier-grade NAT, een sterke aanwijzing dat deze aansluiting geen eigen publiek IPv4-adres heeft. Wat dat betekent, lees je in het artikel over NAT.

Laserlinks tussen satellieten

Is er geen grondstation in de buurt, bijvoorbeeld op een eiland, dan stuurt de satelliet het verkeer met een laser door naar een volgende satelliet, tot er een is die wel een grondstation ziet. Volgens de studie hebben de meeste Starlink-satellieten sinds versie 1.5 uit 2021 zulke laserverbindingen.

Het mooiste voorbeeld van de onderzoekers is Réunion. Een meetpunt daar gaat via Starlink naar een PoP in Frankfurt, zo'n 9000 km verderop, en is dan ongeveer 60 ms sneller dan via de glasvezel van het eiland. Die loopt volgens de studie via twee zeekabels naar Azië of Zuid-Amerika, zo'n 10.000 km ver. Een laser heeft nog een voordeel: in glas gaat licht ongeveer 32 procent langzamer dan in vacuüm, zoals ik uitlegde in waarom Sydney altijd ver weg is. In Duitsland, met grondstations en vaste lijnen dichtbij, won de glasvezel het in dezelfde metingen wel.

Waar de milliseconden van Starlink heen gaan

De afstand tot de satelliet is niet de grootste post. Op 465 km recht boven je zit een satelliet op 1,6 ms. Op 25 graden boven de horizon is hij 967 km ver weg, 3,2 ms. SpaceX noemt in een eigen document uit 2024 1,8 tot 3,6 ms per traject en meestal minder dan 10 ms voor de hele rondgang. Die getallen passen bij een baan van ongeveer 550 km.

De rest komt volgens hetzelfde document uit drie andere hoeken. Er is de afstand over de grond van grondstation naar PoP. Er is de planning van de radioverbinding, omdat één bundel van een satelliet gedeeld wordt door meerdere gebruikers. En er zijn overbodige buffers en verwerking. SpaceX zette onder meer fq_codel op de eigen wifi-router, zodat een grote download de ping van een spelletje op hetzelfde netwerk niet opblaast. Met dit soort aanpassingen daalde de mediane latency in de VS in de spits (18 tot 21 uur lokale tijd) van 48,5 naar 33 ms. Het doel is een stabiele mediaan van 20 ms.

In Nederland heb ik het Starlink-meetpunt vergeleken met een meetpunt op de vaste verbinding van dezelfde universiteit. Beide pingen elke vier minuten drie keer naar k.root-servers.net. Over 24 uur, 1080 pings per meetpunt:

AansluitingMinimumMediaan90e percentielMaximum
Starlink29,3 ms36,5 ms48,2 ms112,2 ms
Vaste lijn4,2 ms5,0 ms5,1 ms6,8 ms

Genoeg voor een videocall, maar met veel meer spreiding dan een kabel.

Zelf proberen

Baangegevens zijn openbaar. CelesTrak ververst ze eens per twee uur; vraag je vaker, dan krijg je een melding in plaats van data. Je hebt ook de Python-module sgp4 nodig:

curl -s -o starlink.txt "https://celestrak.org/NORAD/elements/gp.php?GROUP=starlink&FORMAT=tle"
pip install sgp4

Dit script berekent per satelliet de hoek boven de horizon vanaf Utrecht:

import math, datetime
from sgp4.api import Satrec, jday

lat, lon = math.radians(52.09), math.radians(5.12)   # Utrecht
t = datetime.datetime.now(datetime.timezone.utc)
jd, fr = jday(t.year, t.month, t.day, t.hour, t.minute, t.second)
draai = math.radians((280.46061837 + 360.98564736629 * (jd + fr - 2451545)) % 360)
R = 6371.0
ik = [R * math.cos(lat) * math.cos(lon), R * math.cos(lat) * math.sin(lon), R * math.sin(lat)]
omhoog = [c / R for c in ik]

regels = open("starlink.txt").read().splitlines()
boven = []
for i in range(0, len(regels) - 2, 3):
    fout, r, _ = Satrec.twoline2rv(regels[i + 1], regels[i + 2]).sgp4(jd, fr)
    if fout:
        continue
    x = r[0] * math.cos(draai) + r[1] * math.sin(draai)    # draai mee met de aarde
    y = -r[0] * math.sin(draai) + r[1] * math.cos(draai)
    d = [x - ik[0], y - ik[1], r[2] - ik[2]]
    afstand = math.dist(d, [0, 0, 0])
    hoek = math.degrees(math.asin(sum(a * b for a, b in zip(d, omhoog)) / afstand))
    if hoek > 25:
        boven.append((hoek, afstand, regels[i].strip()))

print(t.strftime("%H:%M UTC"), len(boven), "satellieten boven 25 graden")
for hoek, afstand, naam in sorted(boven, reverse=True)[:3]:
    print(f"{naam:15} {hoek:4.1f} graden  {afstand:4.0f} km  {afstand / 299792.458 * 1000:.2f} ms")

Mijn uitvoer:

04:38 UTC 50 satellieten boven 25 graden
STARLINK-37228  85.5 graden   464 km  1.55 ms
STARLINK-36033  71.9 graden   484 km  1.62 ms
STARLINK-35900  70.4 graden   488 km  1.63 ms

Draai het een minuut later nog eens en je ziet een andere top drie.

De pings van het Starlink-meetpunt van het afgelopen uur haal je op bij RIPE Atlas:

curl -s "https://atlas.ripe.net/api/v2/measurements/1001/results/?probe_ids=1004353&start=$(($(date +%s)-3600))" \
  | python3 -c "import json,sys; print(sorted(r['rtt'] for x in json.load(sys.stdin) for r in x['result'] if 'rtt' in r))"
[30.561259, 30.756045, 30.82339, ..., 51.138541, 62.775719, 86.758377, 90.818772]

Vervang 1004353 door 53514 voor de vaste lijn ter vergelijking.

Tot slot

Ik had verwacht dat de afstand tot de satelliet de latency zou bepalen. Maar die kost samen hooguit een paar milliseconden, terwijl de teller bij hop 2 al op 21 ms staat. Het meeste zit in de planning: wie mag wanneer zenden, en via welke satelliet. Wat me ook verraste, is hoe kort je een satelliet hebt. Hooguit vijf minuten staat hij hoog genoeg, en ondertussen deelt het netwerk zich elke 15 seconden opnieuw in. Dat er dan nog een stabiele videocall overheen gaat, vind ik knapper dan de raketlanceringen.