En kvote, der nulstilles, hver gang tunnelen genopkobles, er ikke en grænse, og det er præcis, hvad man får, når en byttæller boltes på en VPN-server uden et sted at gemme varig tilstand. Tælleren tilhører en session; kvoten tilhører en person eller en enhedskontrakt. Alt det svære ved funktionen kommer fra denne uoverensstemmelse, så kontrollerne nedenfor handler om, hvor tilstand bor, og hvilket lag der må træffe en beslutning.

Lås kvoten til en konto, ikke til en tunnel

Begynd med at navngive kvotens subjekt. Én person kan have tre enhedscertifikater, og ingen af dem bør få et uafhængigt månedligt budget, blot fordi de godkender sig separat. En stabil kontoidentifikator, der overlever genopkoblinger, nye tunneladresser og en flytning til en anden gateway, er det eneste anker, en kvote kan bruge. Et certifikats fællesnavn fungerer kun som den nøgle, når din udstedelsespolitik garanterer én konto pr. navn.

En tildelt tunneladresse er aldrig svaret. Adresser genbruges, puljer deles, og den samme konto kan optræde to gange på to gateways i samme minut. Hvis hovedbogen nøgler på en adresse, er det nok at afbryde og genopkoble for at fylde tanken igen.

Registrér nok pr. session til, at regnestykket kan revideres: kontoen, faktureringsperioden, gateway-instansen, sessionens identitet, de sidst observerede tællere og den fastlagte total. Medtag en daemon-startgeneration i sessionens identitet, fordi en genstartet server genbruger klient-id'er, og et naivt match ville arve den tidligere basislinje.

Fastlæg enhed, retning og nulstillingsgrænse

Fire definitioner skal fastlægges skriftligt, før nogen indsamling begynder. Tæller kvoten bytes, klienten sender, bytes den modtager, eller summen af begge? Er en gigabyte 10^9 bytes eller 2^30? På hvilken lokal time og i hvilken tidszone ruller perioden over? Og hvad måler tælleren egentlig, når tunnel-overhead og retransmissioner er inkluderet, mens applikationsfilens størrelse og en udbyders faktura ikke er?

Ingen af disse valg er forkerte, men implementeringen og det tal, kunden ser, skal stemme overens. To halvdele af samme system, der er uenige om GiB eller om et rollover, der sker ved midnat UTC i stedet for lokal tid, producerer præcis den slags billet, der underminerer tilliden til hele kvoten.

Omdan byte-totaler til ét opkrævet delta

Administrationsgrænsefladen rapporterer periodiske BYTECOUNT_CLI-linjer, der bærer et klient-id plus kumulative byte-totaler i hver retning, og kommandoen bytecount angiver, hvor ofte de ankommer. Fra serverens synspunkt tæller det modtagne tal de bytes, klienten har sendt, og det sendte tal tæller de bytes, der er leveret til den. Sæt intervallet til noget, hovedbogen kan absorbere; et meget kort interval køber en præcision, du ikke reelt får.

Én begrænsning former hele designet: administrationsstikket accepterer én enkelt kontrolforbindelse. En overvågningseksportør, en GUI og din controller kan ikke hver åbne deres egen. Beslut, hvilken proces der ejer kanalen, og lad de andre læse tilstand fra den, fordi denne grænseflade giver administrative handlinger og i øvrigt ikke bør eksponeres uden for værten.

rx_delta = sample.rx_now - session.prev_rx
tx_delta = sample.tx_now - session.prev_tx
charge  = rx_delta + tx_delta
# same transaction:
ledger.total += charge
session.prev_rx, session.prev_tx = sample.rx_now, sample.tx_now

Fastlå de nye basislinjer og forbrugsstigningen sammen, så afspilning af en prøve opkræver intet i stedet for at opkræve to gange. En tæller, der bevæger sig baglæns, er et signal, ikke en gæld: det betyder, at sessionen blev erstattet, eller at daemonen blev genstartet, og det korrekte svar er at afstemme sessionens identitet i stedet for at kreditere et negativt beløb.

Afbrydelsesstien kræver samme omhu. Hvis en endelig hændelse bærer totaler ved sessionens afslutning, opkræv kun forskellen fra den sidste fastlagte prøve. At lægge hele totalen til, efter at periodisk prøvetagning allerede er opkrævet, er den mest almindelige dobbelttælling i hjemmelavede kvotesystemer. Sessioner, der krydser en periodegrænse, har også brug for en regel, da en enkelt sluttotal ikke bærer information om, hvornår bytesene krydsede midnat.

Lad udtømning afvise adgang, ikke bare dræbe tunnelen

Når en konto når sin grænse, skal to ting ske: eksisterende sessioner slutter, og nye afvises. Administrationsprotokollen tilbyder client-kill pr. klient-id, hvilket klarer den første halvdel, så længe du opregner hver levende session for kontoen i stedet for at dræbe den ene adresse, du tilfældigvis lagde mærke til.

Den anden halvdel er, hvor kvotedesign fejler. Et drab alene er et kapløb med klientens genopkoblingsløkke, som gerne kommer tilbage sekunder senere. Adgang skal konsultere den delte hovedbog, og i en udrulning med flere gateways kan den kontrol ikke være en fil pr. maskine. Hver instans, der kan acceptere et login, skal se den samme udtømte tilstand.

Tokenbaserede genopkoblinger fortjener deres egen test. OpenVPN 2.6 kan validere et sessionstoken internt med auth-gen-token og springe det eksterne godkendelseskald over, som din controller brugte til at håndhæve loftet. Et token, der stadig er gyldigt, beviser derfor identitet, ikke resterende kvote, og hver ny klientinstans skal stadig konsultere hovedbogen. Hvis du i stedet aktiverer management-client-auth, bliver controlleren godkender og arver forpligtelsen til selv at parse sessionstilstand og afvise udløbne eller ugyldige tokens.

Accepter det overskrid, prøvetagningen skaber

Periodisk observation plus afbrydelse giver dig en prøvetaget kvote med en kendt tolerance. En klient kan overskride med omtrent ét rapporteringsinterval plus den tid, controlleren skal bruge for at handle, og samtidige sessioner på én konto multiplicerer det vindue. Sig det i grænsefladen i stedet for at annoncere et præcist snit ved sidste byte, som du ikke kan levere.

Et egentligt hårdt loft er et andet ingeniørproblem: håndhævelse inde i videresendelsesstien, knyttet til den samme konto på tværs af sessioner. At læse tællere hurtigere er ikke det samme, og det overlever ikke en klient, der bare åbner flere tunneler.

Før udrulning, kør de accepttilfælde, der bryder naive implementeringer: gentagne genopkoblinger, to enheder på én gang, genstart af controller og gateway, en mistet afbrydelseshændelse, et rollover midt i en session og et token-genopkoblingsforsøg lige efter udtømning. Beslut derefter fejltilstanden for afbrydelser i regnskabet. En varig hovedbog beskytter det forbrug, du registrerede; den kan ikke genoplive observationer, der aldrig ankom, og kunden fortjener at vide, hvilken af de to situationer de er i.

Relaterede artikler