Et hjemmelab bak en prosumer-gateway begynte å feile på store nedlastinger. HTTPS-overføringer døde midt i, etter 12 til 15 MB, med SSL record-feil. HTTP kom gjennom i riktig størrelse, men med feil innhold: ulik hash for hvert forsøk. Små filer og strupede overføringer gikk fint. LAN-trafikk var helt upåvirket.
Alle verter bak gatewayen var rammet, så feilen satt i den delte veien ut mot internett. Her er hvordan den ble sporet ned til én offload-funksjon i nettverksdriveren, og hvordan den fikses med ett kall.
Symptomet
HTTPS-testen mot et raskt endepunkt døde konsekvent. curl avsluttet med exit 56 og en OpenSSL-feil:
$ curl -4sL -o /dev/null https://speed.example/100mb
curl: (56) OpenSSL SSL_read: error:0A000119:SSL routines::decryption failed or bad record mac
Samme endepunkt strupet til 1 MB/s: 30 av 30 MB komplett, hver gang. Feilen var altså hastighetsavhengig. HTTP viste et annet ansikt av samme problem, riktig antall bytes men ulik hash:
$ for i in 1 2; do curl -4s http://mirror/20mb.bin | md5sum; done
9017c3... -
2bef4a... - # samme fil, samme storrelse, ulik hash
Diagnosen
En strupet nedlasting fungerte som ren referanse. En byte-for-byte-sammenligning mot de raske kopiene viste et systematisk mønster, ikke tilfeldig støy:
- Enkeltbyte-feil, 1 til 3 bytes per 20 MB.
- Alltid samme bit som nulles: bit 2, altså 0x04. 0x16 blir 0x12, 0x3d blir 0x39, 0x77 blir 0x73, 0x8e blir 0x8a.
- Tre av fire treff på samme intra-segment-offset. En systematisk defekt bit-bane, ikke sviktende minne.
Det avgjørende funnet: den korrupte HTTP-payloaden ankom klienten med gyldig TCP-sjekksum. Sjekksummen ble altså regnet om etter at byten var flippet. Det peker på en komponent som rører pakkene og reberegner sjekksummer underveis, ikke på linja utenfor. HTTPS overlever ikke dette: TLS-record-MAC-en fanger endringen og forbindelsen dør. HTTP har ingen slik kontroll og slipper feilen rett gjennom til fila.

Isolering: er det gatewayen eller linja?
Reboot av både gateway og fibersentral endret ingenting. En reboot-resistent, deterministisk feil er enten defekt maskinvare eller en software-bug. For å frikjenne linja ble en liten enkeltkort-maskin koblet rett inn i fibersentralens bridge-port, utenom gatewayen, med et autonomt testscript:
- Utenom gatewayen, samme fiber og samme offentlige IP: HTTP 0 av 12 korrupte, HTTPS 2 av 2 store nedlastinger komplette.
- Samme maskin, samme kveld, men gjennom gatewayen: HTTP korrupt igjen, HTTPS kuttet.
Fiber og fibersentral var dermed frikjent. Feilen satt i gatewayen.
Rotårsaken: GRO
Bit-2-signaturen og hastighetsavhengigheten ledet til Generic Receive Offload (GRO). GRO slår sammen flere innkommende TCP-segmenter til én stor buffer før de går videre opp i stacken. Det sparer CPU ved høy pakkerate, men gjør koalescering og sjekksum-reberegning i en driver-bane som i denne firmware-grenen hadde en bug. Ved høy pakkerate ble en byte i ny og ne flippet i sammenslåingen, og sjekksummen regnet pent om over den korrupte payloaden. Ved lav rate skjer ingen aggressiv koalescering, og derfor var strupede overføringer alltid rene.
Fiksen er å skru av GRO på WAN-grensesnittet:
ethtool -K eth8 gro off
Resultatet var umiddelbart og entydig: 6 av 6 store HTTPS-nedlastinger komplette, 0 av 30 HTTP-overføringer korrupte, mot 1 av 3 og 2 av 10 rett før. Hastigheten var uendret. To firmware-oppgraderinger hadde ikke rørt feilen, men ett ethtool-kall fjernet den.
Gjor fiksen varig
ethtool-innstillingen overlever ikke reboot alene. En liten systemd-unit setter den etter at nettet er oppe:
[Unit]
Description=Disable GRO on WAN (driver bit-flip workaround)
After=network.target
[Service]
Type=oneshot
ExecStart=/sbin/ethtool -K eth8 gro off
[Install]
WantedBy=multi-user.target
Firmware-oppgraderinger på slike bokser overskriver gjerne slike enheter. En vaktbikkje-cron på en annen maskin sjekker innstillingen jevnlig over SSH, legger den inn igjen om den er borte, og varsler hvis den måtte gripe inn:
*/30 * * * * /opt/udmp_gro_watchdog.sh # sjekk 'ethtool -k eth8 | grep generic-receive-offload'
Lærdom
- Gyldig TCP-sjekksum utelukker ikke korrupt payload. En offload-motor som reberegner sjekksummen kan maskere sin egen feil.
- HTTPS som dør og HTTP som blir korrupt kan være samme rotårsak. TLS gjør en stille datafeil til en høylytt tilkoblingsfeil.
- En strupet overføring er en gratis ren referanse når du jakter på hastighetsavhengig korrupsjon.
- Test alltid utenom mistenkt utstyr før du kjøper nytt. Feilen så ut som defekt maskinvare, men var en driver-bug som forsvant med én flagg-endring.


