ProHoster > blog > Gweinyddiaeth > Rydym yn ysgrifennu amddiffyniad yn erbyn ymosodiadau DDoS ar XDP. Rhan niwclear
Rydym yn ysgrifennu amddiffyniad yn erbyn ymosodiadau DDoS ar XDP. Rhan niwclear
Mae technoleg eXpress Data Path (XDP) yn caniatáu prosesu traffig yn fympwyol ar ryngwynebau Linux cyn i becynnau fynd i mewn i'r pentwr rhwydwaith cnewyllyn. Cymhwyso XDP - amddiffyniad yn erbyn ymosodiadau DDoS (CloudFlare), hidlwyr cymhleth, casglu ystadegau (Netflix). Mae rhaglenni XDP yn cael eu gweithredu gan beiriant rhithwir eBPF, ac felly mae ganddynt gyfyngiadau ar eu cod a'r swyddogaethau cnewyllyn sydd ar gael, yn dibynnu ar y math o hidlydd.
Bwriad yr erthygl yw gwneud iawn am ddiffygion nifer o ddeunyddiau ar XDP. Yn gyntaf, maent yn darparu cod parod sy'n osgoi nodweddion XDP ar unwaith: wedi'i baratoi ar gyfer dilysu neu'n rhy syml i achosi problemau. Pan geisiwch ysgrifennu eich cod eich hun o'r dechrau yn ddiweddarach, nid oes unrhyw ddealltwriaeth o beth i'w wneud â gwallau nodweddiadol. Yn ail, nid yw'n ymdrin â ffyrdd o brofi XDP yn lleol heb VM a chaledwedd, er gwaethaf y ffaith bod ganddynt eu peryglon eu hunain. Mae'r testun wedi'i fwriadu ar gyfer rhaglenwyr sy'n gyfarwydd â rhwydweithiau a Linux sydd â diddordeb mewn XDP ac eBPF.
Yn y rhan hon, byddwn yn deall yn fanwl sut mae'r hidlydd XDP yn cael ei ymgynnull a sut i'w brofi, yna byddwn yn ysgrifennu fersiwn syml o'r mecanwaith cwcis SYN adnabyddus ar lefel prosesu pecynnau. Hyd nes i ni ffurfio "rhestr wen"
cleientiaid wedi'u dilysu, cadw cownteri a rheoli'r hidlydd - digon o foncyffion.
Byddwn yn ysgrifennu yn C - nid yw hyn yn ffasiynol, ond yn ymarferol. Mae'r holl god ar gael ar GitHub yn y ddolen ar y diwedd ac mae wedi'i rannu'n ymrwymiadau yn ôl y camau a ddisgrifir yn yr erthygl.
Ymwadiad. Yn ystod yr erthygl, bydd datrysiad bach ar gyfer gwrthyrru ymosodiadau DDoS yn cael ei ddatblygu, oherwydd mae hon yn dasg realistig i XDP a fy ardal i. Fodd bynnag, y prif nod yw deall y dechnoleg, nid yw hwn yn ganllaw i greu amddiffyniad parod. Nid yw'r cod tiwtorial wedi'i optimeiddio ac mae'n hepgor rhai arlliwiau.
Trosolwg Cryno o'r XDP
Nodaf y pwyntiau allweddol yn unig er mwyn peidio â dyblygu'r ddogfennaeth a'r erthyglau presennol.
Felly, mae'r cod hidlo yn cael ei lwytho i mewn i'r cnewyllyn. Mae'r hidlydd yn cael ei basio pecynnau sy'n dod i mewn. O ganlyniad, rhaid i'r hidlydd wneud penderfyniad: i drosglwyddo'r pecyn i'r cnewyllyn (XDP_PASS), pecyn gollwng (XDP_DROP) neu ei anfon yn ôl (XDP_TX). Gall yr hidlydd newid y pecyn, mae hyn yn arbennig o wir am XDP_TX. Gallwch hefyd chwalu'r rhaglen (XDP_ABORTED) a gollwng y pecyn, ond mae hwn yn gyfatebol assert(0) - ar gyfer dadfygio.
Mae'r peiriant rhithwir eBPF (Hidlo Pecyn Berkley estynedig) yn cael ei wneud yn syml yn fwriadol fel bod y cnewyllyn yn gallu gwirio nad yw'r cod yn dolennu ac nad yw'n niweidio cof pobl eraill. Cyfyngiadau a gwiriadau cronnol:
Gwaherddir dolenni (neidiau yn ôl).
Mae pentwr ar gyfer data, ond dim swyddogaethau (rhaid i holl swyddogaethau C fod wedi'u mewnlinio).
Gwaherddir mynediad i'r cof y tu allan i'r pentwr a byffer pecyn.
Mae maint y cod yn gyfyngedig, ond yn ymarferol nid yw hyn yn arwyddocaol iawn.
Dim ond swyddogaethau cnewyllyn arbennig (cynorthwywyr eBPF) a ganiateir.
Mae datblygu a gosod hidlydd yn edrych fel hyn:
cod ffynhonnell (ee. kernel.c) yn llunio i wrthwynebu (kernel.o) ar gyfer pensaernïaeth peiriannau rhithwir eBPF. O fis Hydref 2019 ymlaen, mae llunio i eBPF yn cael ei gefnogi gan Clang a'i addo yn GCC 10.1.
Os oes galwadau i strwythurau cnewyllyn yn y cod gwrthrych hwn (er enghraifft, i dablau a chownteri), yn lle eu IDau mae sero, hynny yw, ni ellir gweithredu cod o'r fath. Cyn eu llwytho i mewn i'r cnewyllyn, rhaid disodli'r seroau hyn â rhifau adnabod gwrthrychau penodol a grëwyd trwy alwadau cnewyllyn (cyswllt y cod). Gallwch wneud hyn gyda chyfleustodau allanol, neu gallwch ysgrifennu rhaglen a fydd yn cysylltu a llwytho hidlydd penodol.
Mae'r cnewyllyn yn gwirio'r rhaglen sy'n cael ei llwytho. Mae'n gwirio am absenoldeb cylchoedd a pheidio â gadael y pecyn a ffiniau stac. Os na all y dilysydd brofi bod y cod yn gywir, caiff y rhaglen ei gwrthod - rhaid i un allu ei blesio.
Ar ôl dilysu llwyddiannus, mae'r cnewyllyn yn llunio cod gwrthrych pensaernïaeth eBPF yn god peiriant pensaernïaeth system (mewn union bryd).
Mae'r rhaglen ynghlwm wrth y rhyngwyneb ac yn dechrau prosesu pecynnau.
Gan fod XDP yn rhedeg yn y cnewyllyn, mae dadfygio yn cael ei wneud gan logiau olrhain ac, mewn gwirionedd, gan becynnau y mae'r rhaglen yn eu hidlo neu'n eu cynhyrchu. Fodd bynnag, mae eBPF yn cadw'r cod wedi'i lawrlwytho yn ddiogel ar gyfer y system, felly gallwch chi arbrofi gyda XDP yn union ar eich Linux lleol.
Paratoi'r Amgylchedd
Cynulliad
Ni all Clang gyhoeddi cod gwrthrych yn uniongyrchol ar gyfer pensaernïaeth eBPF, felly mae'r broses yn cynnwys dau gam:
Llunio cod C i god byte LLVM (clang -emit-llvm).
Trosi beitcode i god gwrthrych eBPF (llc -march=bpf -filetype=obj).
Wrth ysgrifennu hidlydd, bydd cwpl o ffeiliau gyda swyddogaethau ategol a macros yn dod yn ddefnyddiol o brofion cnewyllyn. Mae'n bwysig eu bod yn cyfateb i'r fersiwn cnewyllyn (KVER). Lawrlwythwch nhw i helpers/:
KDIR yn cynnwys y llwybr i benawdau'r cnewyllyn, ARCH - pensaernïaeth system. Gall llwybrau ac offer amrywio ychydig rhwng dosbarthiadau.
Enghraifft o wahaniaeth ar gyfer Debian 10 (cnewyllyn 4.19.67)
# другая команда
CLANG ?= clang
LLC ?= llc-7
# другой каталог
KDIR ?= /usr/src/linux-headers-$(shell uname -r)
ARCH ?= $(subst x86_64,x86,$(shell uname -m))
# два дополнительных каталога -I
CFLAGS =
-Ihelpers
-I/usr/src/linux-headers-4.19.0-6-common/include
-I/usr/src/linux-headers-4.19.0-6-common/arch/$(ARCH)/include
# далее без изменений
CFLAGS cynnwys cyfeiriadur gyda phenawdau ategol a sawl cyfeiriadur gyda phenawdau cnewyllyn. Symbol __KERNEL__ yn golygu bod penawdau UAPI (userspace API) wedi'u diffinio ar gyfer cod cnewyllyn, gan fod yr hidlydd yn cael ei weithredu yn y cnewyllyn.
Gellir analluogi amddiffyniad stac (-fno-stack-protector) oherwydd bod dilysydd cod yr eBPF yn gwirio ffiniau nad ydynt allan o stac beth bynnag. Dylech alluogi optimeiddiadau ar unwaith, oherwydd mae maint y cod byte eBPF yn gyfyngedig.
Gadewch i ni ddechrau gyda hidlydd sy'n pasio pob pecyn ac yn gwneud dim byd:
Tîm make yn casglu xdp_filter.o. Ble gallwch chi ei brofi nawr?
stondin prawf
Dylai'r stondin gynnwys dau ryngwyneb: y bydd hidlydd arno ac y bydd pecynnau'n cael eu hanfon ohono. Rhaid i'r rhain fod yn ddyfeisiau Linux llawn gyda'u IPs eu hunain er mwyn gwirio sut mae cymwysiadau rheolaidd yn gweithio gyda'n hidlydd.
Mae dyfeisiau fel veth (Veth Ethernet) yn addas i ni: maen nhw'n bâr o ryngwynebau rhwydwaith rhithwir “wedi'u cysylltu” yn uniongyrchol â'i gilydd. Gallwch chi eu creu fel hyn (yn yr adran hon, pob gorchymyn ip perfformio o root):
ip link add xdp-remote type veth peer name xdp-local
Yma xdp-remote и xdp-local - enwau dyfeisiau. Ar xdp-local (192.0.2.1/24) bydd hidlydd yn cael ei atodi, gyda xdp-remote (192.0.2.2/24) bydd traffig sy'n dod i mewn yn cael ei anfon. Fodd bynnag, mae yna broblem: mae'r rhyngwynebau ar yr un peiriant, ac ni fydd Linux yn anfon traffig i un ohonynt trwy'r llall. Gallwch chi ei ddatrys gyda rheolau anodd iptables, ond bydd yn rhaid iddynt newid pecynnau, sy'n anghyfleus wrth ddadfygio. Mae'n well defnyddio gofodau enwau rhwydwaith (gofodau enwau rhwydwaith, rhwydi pellach).
Mae gofod enwau'r rhwydwaith yn cynnwys set o ryngwynebau, tablau llwybro, a rheolau NetFilter sydd wedi'u hynysu oddi wrth wrthrychau tebyg mewn rhwydi eraill. Mae pob proses yn rhedeg mewn rhyw ofod enw, a dim ond gwrthrychau'r rhwydi hwn sydd ar gael iddi. Yn ddiofyn, mae gan y system un gofod enw rhwydwaith ar gyfer pob gwrthrych, felly gallwch chi weithio ar Linux a pheidio â gwybod am netns.
Gadewch i ni greu gofod enw newydd xdp-test a symud yno xdp-remote.
ip netns add xdp-test
ip link set dev xdp-remote netns xdp-test
Yna y broses yn rhedeg i mewn xdp-test, ni fydd yn "gweld" xdp-local (bydd yn aros mewn netns yn ddiofyn) ac wrth anfon pecyn i 192.0.2.1 yn ei basio drwodd xdp-remote, oherwydd dyna'r unig ryngwyneb yn 192.0.2.0/24 sydd ar gael i'r broses hon. Mae hyn hefyd yn gweithio i'r gwrthwyneb.
Wrth symud rhwng netns, mae'r rhyngwyneb yn mynd i lawr ac yn colli'r cyfeiriad. I sefydlu rhyngwyneb mewn netns, mae angen i chi redeg ip ... yn y gofod enw gorchymyn hwn ip netns exec:
ip netns exec xdp-test
ip address add 192.0.2.2/24 dev xdp-remote
ip netns exec xdp-test
ip link set xdp-remote up
Fel y gallwch weld, nid yw hyn yn wahanol i'r gosodiad xdp-local yn y gofod enw diofyn:
ip address add 192.0.2.1/24 dev xdp-local
ip link set xdp-local up
Os rhedeg tcpdump -tnevi xdp-local, gallwch weld bod pecynnau a anfonwyd o xdp-test, yn cael eu danfon i'r rhyngwyneb hwn:
ip netns exec xdp-test ping 192.0.2.1
Mae'n gyfleus rhedeg cragen i mewn xdp-test. Mae gan y storfa sgript sy'n awtomeiddio gwaith gyda'r stondin, er enghraifft, gallwch chi osod y stondin gyda'r gorchymyn sudo ./stand up a gwared ef sudo ./stand down.
olrhain
Mae'r hidlydd ynghlwm wrth y ddyfais fel hyn:
ip -force link set dev xdp-local xdp object xdp_filter.o verbose
Allwedd -force angen cysylltu rhaglen newydd os oes un arall eisoes yn gysylltiedig. Nid yw "Dim newyddion yn newyddion da" yn ymwneud â'r gorchymyn hwn, mae'r allbwn yn swmpus beth bynnag. nodi verbose dewisol, ond gydag ef mae adroddiad am waith y dilysydd cod gyda'r rhestr cydosodwr yn ymddangos:
Verifier analysis:
0: (b7) r0 = 2
1: (95) exit
Datgysylltwch y rhaglen o'r rhyngwyneb:
ip link set dev xdp-local xdp off
Yn y sgript, dyma'r gorchmynion sudo ./stand attach и sudo ./stand detach.
Trwy rwymo'r hidlydd, gallwch chi wneud yn siŵr hynny ping yn parhau i weithio, ond a yw'r rhaglen yn gweithio? Gadewch i ni ychwanegu logos. Swyddogaeth bpf_trace_printk() yn debyg i printf(), ond dim ond yn cefnogi hyd at dair dadl ar wahân i'r patrwm, a rhestr gyfyngedig o fanylebwyr. Macro bpf_printk() yn symleiddio'r alwad.
Am y rheswm hwn, mae allbwn dadfygio yn chwyddo'r cod canlyniadol yn fawr.
Anfon Pecynnau XDP
Gadewch i ni newid yr hidlydd: gadewch iddo anfon yr holl becynnau sy'n dod i mewn yn ôl. Mae hyn yn anghywir o safbwynt rhwydwaith, gan y byddai angen newid y cyfeiriadau yn y penawdau, ond nawr mae'r gwaith mewn egwyddor yn bwysig.
Lansio tcpdump ar xdp-remote. Dylai ddangos Cais Echo ICMP sy'n mynd allan ac yn dod i mewn a stopio dangos ICMP Echo Reply. Ond nid yw'n dangos. Yn troi allan i weithio XDP_TX yn y rhaglen ar gyfer xdp-localangenrheidioli baru rhyngwyneb xdp-remote neilltuwyd rhaglen hefyd, hyd yn oed os oedd yn wag, a chodwyd hi.
Sut oeddwn i'n gwybod?
Olrhain llwybr pecyn yn y cnewyllyn mae'r mecanwaith digwyddiadau perf yn caniatáu, gyda llaw, ddefnyddio'r un peiriant rhithwir, hynny yw, defnyddir eBPF ar gyfer dadosod ag eBPF.
Rhaid i ti wneud daioni allan o ddrwg, oherwydd nid oes dim arall i'w wneud ohono.
Os mai dim ond ARP a ddangosir yn lle hynny, mae angen i chi gael gwared ar yr hidlwyr (mae hyn yn gwneud sudo ./stand detach), gadewch ping, yna gosodwch hidlwyr a cheisiwch eto. Y broblem yw bod yr hidlydd XDP_TX dilys ar ARP ac os yw'r pentwr
gofodau enwau xdp-test llwyddo i "anghofio" y cyfeiriad MAC 192.0.2.1, ni fydd yn gallu datrys yr IP hwn.
Datganiad o'r broblem
Gadewch i ni symud ymlaen at y dasg a nodir: ysgrifennu mecanwaith cwci SYN ar XDP.
Hyd yn hyn, mae llifogydd SYN yn parhau i fod yn ymosodiad DDoS poblogaidd, a'i hanfod fel a ganlyn. Pan sefydlir cysylltiad (ysgwyd llaw TCP), mae'r gweinydd yn derbyn SYN, yn dyrannu adnoddau ar gyfer cysylltiad yn y dyfodol, yn ymateb gyda phecyn SYNACK, ac yn aros am ACK. Mae'r ymosodwr yn syml yn anfon pecynnau SYN o gyfeiriadau ffug yn y swm o filoedd yr eiliad o bob gwesteiwr mewn botnet aml-fil. Mae'r gweinydd yn cael ei orfodi i ddyrannu adnoddau yn syth ar ôl i'r pecyn gyrraedd, ond yn ei ryddhau ar ôl cyfnod hir, o ganlyniad, mae cof neu derfynau wedi dod i ben, ni dderbynnir cysylltiadau newydd, nid yw'r gwasanaeth ar gael.
Os nad ydych yn dyrannu adnoddau ar y pecyn SYN, ond dim ond yn ymateb gyda phecyn SYNACK, yna sut gall y gweinydd ddeall bod y pecyn ACK a ddaeth yn ddiweddarach yn perthyn i'r pecyn SYN na chafodd ei gadw? Wedi'r cyfan, gall ymosodwr hefyd gynhyrchu ACKs ffug. Hanfod cwci SYN yw amgodio i mewn seqnum paramedrau cysylltiad fel hash o gyfeiriadau, porthladdoedd a newid halen. Os llwyddodd yr ACK i gyrraedd cyn y newid halen, gallwch gyfrifo'r hash eto a'i gymharu â acknum. ffug acknum ni all yr ymosodwr, gan fod yr halen yn cynnwys y gyfrinach, ac ni fydd ganddo amser i ddidoli trwyddo oherwydd y sianel gyfyngedig.
Mae cwcis SYN wedi cael eu gweithredu yn y cnewyllyn Linux ers amser maith a gellir eu galluogi hyd yn oed yn awtomatig os yw SYNs yn cyrraedd yn rhy gyflym ac mewn swmp.
Rhaglen addysgol ar ysgwyd llaw TCP
Mae TCP yn darparu trosglwyddiad data fel llif o beit, er enghraifft, trosglwyddir ceisiadau HTTP dros TCP. Mae'r ffrwd yn cael ei throsglwyddo fesul darn mewn pecynnau. Mae gan bob pecyn TCP fflagiau rhesymegol a rhifau dilyniant 32-did:
Mae'r cyfuniad o fflagiau yn diffinio rôl pecyn penodol. Mae baner SYN yn golygu mai hwn yw pecyn cyntaf yr anfonwr ar y cysylltiad. Mae baner ACK yn golygu bod yr anfonwr wedi derbyn yr holl ddata cysylltiad hyd at beit. acknum. Gall fod gan becyn sawl baner ac fe'i enwir ar ôl eu cyfuniad, er enghraifft, pecyn SYNACK.
Mae rhif dilyniant (sequnum) yn pennu'r gwrthbwyso yn y ffrwd data ar gyfer y beit cyntaf a anfonir yn y pecyn hwn. Er enghraifft, os mai N oedd y rhif hwn yn y pecyn cyntaf gyda X beit o ddata, yn y pecyn nesaf gyda data newydd bydd yn N+X. Ar ddechrau'r alwad, mae pob ochr yn dewis y rhif hwn ar hap.
Rhif cydnabod (acnum) - yr un gwrthbwyso â seqnum, ond nid yw'n pennu nifer y beit a drosglwyddir, ond nifer y beit cyntaf gan y derbynnydd, na welodd yr anfonwr.
Ar ddechrau'r cysylltiad, rhaid i'r partïon gytuno seqnum и acknum. Mae'r cleient yn anfon pecyn SYN gyda'i seqnum = X. Mae'r gweinydd yn ymateb gyda phecyn SYNACK, lle mae'n ysgrifennu ei becyn ei hun seqnum = Y ac yn amlygu acknum = X + 1. Mae'r cleient yn ymateb i SYNACK gyda phecyn ACK, lle seqnum = X + 1, acknum = Y + 1. Ar ôl hynny, mae'r trosglwyddiad data gwirioneddol yn dechrau.
Os na fydd y cydgysylltydd yn cydnabod derbyn y pecyn, mae TCP yn ei ail-anfon erbyn terfyn amser.
Pam na ddefnyddir cwcis SYN bob amser?
Yn gyntaf, os collir SYNACK neu ACK, bydd yn rhaid i chi aros am ail-anfon - mae'r sefydliad cysylltu yn arafu. Yn ail, yn y pecyn SYN - a dim ond ynddo! - trosglwyddir nifer o opsiynau sy'n effeithio ar weithrediad pellach y cysylltiad. Heb gofio pecynnau SYN sy'n dod i mewn, mae'r gweinydd felly yn anwybyddu'r opsiynau hyn, yn y pecynnau canlynol ni fydd y cleient yn eu hanfon mwyach. Gall TCP weithio yn yr achos hwn, ond o leiaf yn y cam cychwynnol, bydd ansawdd y cysylltiad yn gostwng.
O ran pecynnau, dylai rhaglen XDP wneud y canlynol:
ymateb i SYN gyda SYNACK gyda cwci;
ateb ACK gyda RST (torri'r cysylltiad);
gollwng pecynnau eraill.
Ffuggod yr algorithm ynghyd â dosrannu pecynnau:
Если это не Ethernet,
пропустить пакет.
Если это не IPv4,
пропустить пакет.
Если адрес в таблице проверенных, (*)
уменьшить счетчик оставшихся проверок,
пропустить пакет.
Если это не TCP,
сбросить пакет. (**)
Если это SYN,
ответить SYN-ACK с cookie.
Если это ACK,
если в acknum лежит не cookie,
сбросить пакет.
Занести в таблицу адрес с N оставшихся проверок. (*)
Ответить RST. (**)
В остальных случаях сбросить пакет.
Un (*) mae'r pwyntiau lle mae angen i chi reoli cyflwr y system wedi'u nodi - yn y cam cyntaf, gallwch wneud hebddynt trwy weithredu ysgwyd llaw TCP gyda chynhyrchu cwci SYN fel seqnum.
Ar safle (**), er nad oes gennym fwrdd, byddwn yn hepgor y pecyn.
Gweithredu ysgwyd llaw TCP
Dosrannu pecyn a dilysu cod
Mae angen strwythurau pennawd rhwydwaith arnom: Ethernet (uapi/linux/if_ether.h), IPv4 (uapi/linux/ip.h) a TCP (uapi/linux/tcp.h). Yr un olaf ni allwn gysylltu oherwydd gwallau yn ymwneud â atomic64_t, roedd yn rhaid i mi gopïo'r diffiniadau angenrheidiol i'r cod.
Rhaid i'r holl swyddogaethau sy'n cael eu gwahaniaethu yn C ar gyfer darllenadwyedd gael eu halinio yn y safle galwadau, gan fod y dilysydd eBPF yn y cnewyllyn yn gwahardd neidiau cefn, hynny yw, mewn gwirionedd, dolenni a galwadau ffwythiant.
Macro LOG() yn analluogi argraffu mewn adeilad rhyddhau.
Mae'r rhaglen yn biblinell o swyddogaethau. Mae pob un yn derbyn pecyn lle mae pennawd o'r lefel gyfatebol yn cael ei amlygu, er enghraifft, process_ether() yn aros i gael ei lenwi ether. Yn seiliedig ar ganlyniadau dadansoddiad maes, gall y swyddogaeth drosglwyddo'r pecyn i lefel uwch. Canlyniad y swyddogaeth yw gweithred XDP. Tra bod y trinwyr SYN ac ACK yn gadael pob pecyn drwodd.
Llinyn allweddol invalid access to packet, off=13 size=1, R7(id=0,off=0,r=0): mae yna lwybrau gweithredu pan fydd y trydydd beit ar ddeg o ddechrau'r byffer y tu allan i'r pecyn. Mae'n anodd dweud o'r rhestr pa linell rydyn ni'n siarad amdani, ond mae yna rif cyfarwyddyd (12) a dadosodwr sy'n dangos llinellau'r cod ffynhonnell:
sy'n ei gwneud yn glir bod y broblem ether. Byddai felly bob amser.
Ymateb i SYN
Y nod ar hyn o bryd yw cynhyrchu pecyn SYNACK cywir gyda phecyn sefydlog seqnum, a fydd yn cael ei ddisodli gan gwci SYN yn y dyfodol. Mae pob newid yn digwydd yn process_tcp_syn() a'r amgylchoedd.
Gwirio'r pecyn
Yn rhyfedd ddigon, dyma’r llinell fwyaf rhyfeddol, neu yn hytrach, sylw iddi:
Wrth ysgrifennu'r fersiwn gyntaf o'r cod, defnyddiwyd y cnewyllyn 5.1, ac ar gyfer y dilysydd roedd gwahaniaeth rhwng data_end и (const void*)ctx->data_end. Ar adeg ysgrifennu, nid oedd gan y cnewyllyn 5.3.1 y broblem hon. Efallai bod y casglwr yn cyrchu newidyn lleol yn wahanol i faes. Moesol - ar nythu mawr, gall symleiddio'r cod helpu.
Gwiriadau rheolaidd pellach o hydoedd er gogoniant y gwiriwr; O MAX_CSUM_BYTES isod.
Cyfnewid porthladdoedd TCP, cyfeiriadau IP a MAC. Nid yw'r llyfrgell safonol ar gael o'r rhaglen XDP, felly memcpy() — macro sy'n cuddio'r cynhenid Clang.
Mae gwiriadau IPv4 a TCP yn gofyn am ychwanegu'r holl eiriau 16-bit yn y penawdau, ac mae maint y penawdau wedi'i ysgrifennu ynddynt, hynny yw, nid yw'n hysbys ar adeg eu llunio. Mae hyn yn broblem oherwydd ni fydd y dilysydd yn hepgor y ddolen arferol tan y newidyn terfyn. Ond mae maint y penawdau yn gyfyngedig: hyd at 64 beit yr un. Gallwch wneud dolen gyda nifer sefydlog o iteriadau, a all ddod i ben yn gynnar.
Sylwaf fod yna RFC 1624 sut i ailgyfrifo'r siec yn rhannol os mai dim ond geiriau sefydlog y pecynnau sy'n cael eu newid. Fodd bynnag, nid yw'r dull yn gyffredinol, a byddai'n anoddach cynnal y gweithrediad.
Swyddogaeth cyfrifo siec:
#define MAX_CSUM_WORDS 32
#define MAX_CSUM_BYTES (MAX_CSUM_WORDS * 2)
INTERNAL u32
sum16(const void* data, u32 size, const void* data_end) {
u32 s = 0;
#pragma unroll
for (u32 i = 0; i < MAX_CSUM_WORDS; i++) {
if (2*i >= size) {
return s; /* normal exit */
}
if (data + 2*i + 1 + 1 > data_end) {
return 0; /* should be unreachable */
}
s += ((const u16*)data)[i];
}
return s;
}
Er size wedi'i wirio gan y cod galw, mae angen yr ail gyflwr ymadael fel y gall y dilysydd brofi diwedd y ddolen.
Ar gyfer geiriau 32-bit, gweithredir fersiwn symlach:
INTERNAL u32
sum16_32(u32 v) {
return (v >> 16) + (v & 0xffff);
}
Mewn gwirionedd ailgyfrifo'r sieciau ac anfon y pecyn yn ôl:
Swyddogaeth carry() yn gwneud siec allan o swm 32-did o eiriau 16-did, yn ôl RFC 791.
Gwiriad ysgwyd llaw TCP
Mae'r hidlydd yn sefydlu cysylltiad â netcat, gan sgipio'r ACK terfynol, yr ymatebodd Linux iddo gyda phecyn RST, gan nad oedd y pentwr rhwydwaith yn derbyn SYN - cafodd ei drawsnewid i SYNACK a'i anfon yn ôl - ac o safbwynt yr OS, cyrhaeddodd pecyn nad oedd yn yn ymwneud â chysylltiadau agored.
$ sudo ip netns exec xdp-test nc -nv 192.0.2.1 6666
192.0.2.1 6666: Connection reset by peer
Mae'n bwysig gwirio gyda cheisiadau llawn ac arsylwi tcpdump ar xdp-remote oherwydd, er enghraifft, hping3 ddim yn ymateb i wiriadau anghywir.
Cwci SYN
O safbwynt XDP, mae'r siec ei hun yn ddibwys. Mae'r algorithm cyfrifo yn gyntefig ac yn debygol o fod yn agored i ymosodwr soffistigedig. Mae'r cnewyllyn Linux, er enghraifft, yn defnyddio'r cryptograffig SipHash, ond mae ei weithrediad ar gyfer XDP yn amlwg y tu hwnt i gwmpas yr erthygl hon.
Ymddangos ar gyfer TODOs newydd yn ymwneud â rhyngweithio allanol:
Ni all rhaglen XDP storio cookie_seed (rhan gyfrinachol yr halen) mewn newidyn byd-eang, mae angen storfa gnewyllyn arnoch y bydd ei werth yn cael ei ddiweddaru o bryd i'w gilydd o gynhyrchydd dibynadwy.
Os yw'r cwci SYN yn y pecyn ACK yn cyfateb, nid oes angen i chi argraffu neges, ond cofiwch IP y cleient sydd wedi'i ddilysu er mwyn hepgor pecynnau ymhellach ohono.
Cyn belled nad oes rhestr o IPs wedi'u dilysu, ni fydd unrhyw amddiffyniad rhag llifogydd SYN ei hun, ond dyma'r ymateb i'r llifogydd ACK a lansiwyd gan y gorchymyn hwn:
sudo ip netns exec xdp-test hping3 --flood -A -s 1111 -p 2222 192.0.2.1
Weithiau mae eBPF yn gyffredinol a XDP yn arbennig yn cael eu cyflwyno fel mwy o arf gweinyddwr uwch na llwyfan datblygu. Yn wir, mae XDP yn offeryn ar gyfer ymyrryd â phrosesu pecynnau cnewyllyn, ac nid yn ddewis arall i'r pentwr cnewyllyn, fel DPDK ac opsiynau ffordd osgoi cnewyllyn eraill. Ar y llaw arall, mae XDP yn caniatáu ichi weithredu rhesymeg eithaf cymhleth, sydd, ar ben hynny, yn hawdd ei diweddaru heb oedi wrth brosesu traffig. Nid yw'r dilysydd yn creu problemau mawr, yn bersonol ni fyddwn yn gwrthod o'r fath ar gyfer rhannau o'r cod userspace.
Yn yr ail ran, os yw'r pwnc yn ddiddorol, byddwn yn cwblhau'r tabl o gleientiaid wedi'u dilysu ac yn torri cysylltiadau, yn gweithredu cownteri ac yn ysgrifennu cyfleustodau gofod defnyddiwr i reoli'r hidlydd.