I-BPF yabancane, ingxenye enguziro: i-BPF yakudala

I-Berkeley Packet Filters (BPF) ubuchwepheshe be-Linux kernel obusemakhasini aphambili wokushicilelwa kobuchwepheshe bolimi lwesiNgisi iminyaka eminingana manje. Izinkomfa zigcwele imibiko ngokusetshenziswa nokuthuthukiswa kwe-BPF. UDavid Miller, umgcini we-subsystem ye-Linux, ubiza inkulumo yakhe ku-Linux Plumbers 2018 β€œLe nkulumo ayimayelana ne-XDP” (I-XDP iyindlela eyodwa yokusetshenziswa kwe-BPF). UBrendan Gregg unikeza izinkulumo ezinesihloko I-Linux BPF Superpowers. Toke HΓΈiland-JΓΈrgensen uyahlekaukuthi i-kernel manje isiyi-microkernel. UThomas Graf ukhuthaza umbono wokuthi I-BPF i-javascript ye-kernel.

Akukabikho incazelo ehlelekile ye-BPF ku-HabrΓ©, ngakho-ke ochungechungeni lwezihloko ngizozama ukukhuluma ngomlando wobuchwepheshe, ngichaze amathuluzi ezakhiwo nokuthuthukiswa, futhi ngichaze izindawo zokusebenzisa nokusebenza kokusebenzisa i-BPF. Lesi sihloko, i-zero, ochungechungeni, sitshela umlando kanye nezakhiwo ze-BPF yakudala, futhi yembula nezimfihlo zezimiso zayo zokusebenza. tcpdump, seccomp, strace, nokunye okuningi.

Ukuthuthukiswa kwe-BPF kulawulwa umphakathi wokuxhumana we-Linux, izinhlelo zokusebenza ezikhona ze-BPF zihlobene namanethiwekhi ngakho-ke, ngemvume. @eucariot, Ngabiza uchungechunge "i-BPF yabancane", ngokuhlonipha uchungechunge olukhulu "Amanethiwekhi abancane".

Isifundo esifushane emlandweni we-BPF(c)

Ubuchwepheshe besimanje be-BPF inguqulo ethuthukisiwe nenwetshiwe yobuchwepheshe obudala obunegama elifanayo, manje elibizwa nge-BPF yakudala ukuze kugwenywe ukudideka. Isisetshenziswa esaziwayo sadalwa ngokusekelwe ku-BPF yakudala tcpdump, indlela seccomp, kanye namamojula awaziwa kancane xt_bpf ngoba iptables kanye nomdidiyeli cls_bpf. Ku-Linux yesimanje, izinhlelo ze-BPF zakudala zihunyushwa ngokuzenzakalelayo efomini elisha, nokho, ngokombono wabasebenzisi, i-API isekhona futhi ukusetshenziswa okusha kwe-BPF yakudala, njengoba sizobona kulesi sihloko, kusatholakala. Ngenxa yalesi sizathu, futhi futhi ngenxa yokuthi ngokulandela umlando wokuthuthukiswa kwe-BPF yakudala eLinux, kuzocaca ukuthi yavela kanjani futhi kungani yavela ngendlela yayo yesimanje, nginqume ukuqala ngendatshana emayelana ne-BPF yakudala.

Ekupheleni kweminyaka engamashumi ayisishiyagalombili yekhulu leminyaka elidlule, onjiniyela abavela eLaboratory edumile yaseLawrence Berkeley baba nesithakazelo embuzweni wokuthi ungahlunga kanjani kahle amaphakethe enethiwekhi ku-hardware eyayiyisimanje ngasekupheleni kweminyaka engamashumi ayisishiyagalombili ekhulwini leminyaka elidlule. Umqondo oyisisekelo wokuhlunga, owaqala ukusetshenziswa kubuchwepheshe be-CSPF (CMU/Stanford Packet Filter), kwakuwukuhlunga amaphakethe angadingekile ngokushesha ngangokunokwenzeka, i.e. esikhaleni se-kernel, njengoba lokhu kugwema ukukopisha idatha engadingekile endaweni yomsebenzisi. Ukuze kuhlinzekwe ukuphepha kwesikhathi sokusebenza sokuqalisa ikhodi yomsebenzisi esikhaleni se-kernel, kusetshenziswe umshini we-sandboxed virtual.

Kodwa-ke, imishini ebonakalayo yezihlungi ezikhona yayiklanyelwe ukusebenza emishinini esekelwe kusitaki futhi ayizange isebenze kahle emishinini emisha ye-RISC. Ngenxa yalokho, ngemizamo yonjiniyela abavela eBerkeley Labs, kwasungulwa ubuchwepheshe obusha be-BPF (Berkeley Packet Filters), umshini wokwakhiwa kwemishini ebonakalayo owaklanywa ngokusekelwe kuphrosesa ye-Motorola 6502 - ihhashi lemikhiqizo eyaziwa kakhulu njenge. I-Apple II noma I-NES. Umshini omusha obonakalayo ukhuphule ukusebenza kwesihlungi izikhathi ezingamashumi uma kuqhathaniswa nezixazululo ezikhona.

Ukwakhiwa komshini we-BPF

Sizojwayelana nezakhiwo ngendlela esebenzayo, sihlaziya izibonelo. Kodwa-ke, okokuqala, ake sithi umshini ubunamarejista amabili angama-32-bit afinyeleleka kumsebenzisi, i-accumulator. A kanye nerejista yenkomba X, 64 bytes of memory (amagama angu-16), atholakalayo ukuze abhalwe nokufunda okulandelayo, kanye nesistimu encane yemiyalo yokusebenza ngalezi zinto. Imiyalo ye-Jump yokusebenzisa izinkulumo ezinemibandela nayo yayitholakala ezinhlelweni, kodwa ukuze kuqinisekiswe ukuphothulwa ngesikhathi kohlelo, ukweqa kungenziwa phambili kuphela, okungukuthi, ikakhulukazi, kwakungavunyelwe ukudala izihibe.

Uhlelo olujwayelekile lokuqalisa umshini lumi kanje. Umsebenzisi udala uhlelo lwezakhiwo ze-BPF futhi, esebenzisa abanye i-kernel mechanism (njengocingo lwesistimu), ilayisha futhi ixhuma uhlelo kuyo kwabanye kujeneretha yomcimbi ku-kernel (isibonelo, umcimbi ukufika kwephakethe elilandelayo ekhadini lenethiwekhi). Uma kwenzeka umcimbi, i-kernel iqhuba uhlelo (isibonelo, kumhumushi), futhi inkumbulo yomshini ihambisana kwabanye isifunda senkumbulo ye-kernel (isibonelo, idatha yephakethe elingenayo).

Okungenhla kuzokwanela ukuthi siqale ukubuka izibonelo: sizojwayelana nesistimu nefomethi yomyalo njengoba kudingeka. Uma ufuna ukufunda ngokushesha uhlelo lomyalo lomshini obonakalayo futhi ufunde ngawo wonke amakhono awo, khona-ke ungafunda isihloko sokuqala. Isihlungi sephakethe le-BSD kanye/noma ingxenye yokuqala yefayela Documentation/networking/filter.txt kusuka kumadokhumenti e-kernel. Ngaphezu kwalokho, ungakwazi ukufunda isethulo libpcap: Indlela Yokwakha Neyokuthuthukisa Yokuthwebula Iphakethe, lapho uMcCanne, omunye wababhali be-BPF, ekhuluma ngomlando wendalo libpcap.

Siqhubekela phambili ngokucabangela zonke izibonelo ezibalulekile zokusebenzisa i-BPF yakudala ku-Linux: tcpdump (libpcap), isikhashana, xt_bpf, cls_bpf.

tcpdump

Ukuthuthukiswa kwe-BPF kwenziwa ngokuhambisana nokuthuthukiswa kwe-frontend yokuhlunga iphakethe - insiza eyaziwayo. tcpdump. Futhi, njengoba lesi kuyisibonelo esidala nesidume kakhulu sokusebenzisa i-BPF yakudala, etholakala ezinhlelweni eziningi zokusebenza, sizoqala ngayo isifundo sethu sobuchwepheshe.

(Ngisebenzise zonke izibonelo kulesi sihloko ku-Linux 5.6.0-rc6. Okukhiphayo kweminye imiyalo kuhlelwe ukuze kufundeke kangcono.)

Isibonelo: ukubheka amaphakethe e-IPv6

Ake sicabange ukuthi sifuna ukubuka wonke amaphakethe e-IPv6 kusixhumi esibonakalayo eth0. Ukwenza lokhu singasebenzisa uhlelo tcpdump ngesihlungi esilula ip6:

$ sudo tcpdump -i eth0 ip6

Ngakho tcpdump ihlanganisa isihlungi ip6 ku-bytecode yezakhiwo ze-BPF bese uyithumela ku-kernel (bona imininingwane esigabeni I-Tcpdump: iyalayisha). Isihlungi esilayishiwe sizosetshenziswa kuwo wonke amaphakethe adlula kusixhumi esibonakalayo eth0. Uma isihlungi sibuyisela inani elingelona uziro n, bese kufika n amabhayithi ephakethe azokopishelwa esikhaleni somsebenzisi futhi sizokubona kokuphumayo tcpdump.

I-BPF yabancane, ingxenye enguziro: i-BPF yakudala

Kuvela ukuthi singathola kalula ukuthi iyiphi i-bytecode ethunyelwe ku-kernel tcpdump ngosizo lwe tcpdump, uma siyisebenzisa ngenketho -d:

$ sudo tcpdump -i eth0 -d ip6
(000) ldh      [12]
(001) jeq      #0x86dd          jt 2    jf 3
(002) ret      #262144
(003) ret      #0

Emgqeni we-zero sisebenzisa umyalo ldh [12], okusho ukuthi β€œlayisha ungene kwirejista A isigamu segama (amabhithi ayi-16) atholakala ekhelini 12” futhi umbuzo kuphela ukuthi hlobo luni lwenkumbulo esikhuluma ngalo? Impendulo ithi at x kuyaqala (x+1)Ibhayithi yephakethe lenethiwekhi elihlaziyiwe. Sifunda amaphakethe avela kusixhumi esibonakalayo se-Ethernet eth0, futhi lokhu kushoukuthi iphakethe libukeka kanje (ukuze kube lula, sicabanga ukuthi abekho omaka be-VLAN ephaketheni):

       6              6          2
|Destination MAC|Source MAC|Ether Type|...|

Ngakho ngemva kokwenza umyalo ldh [12] kurejista A kuyoba khona insimu Ether Type β€” uhlobo lwephakethe elithunyelwa kulolu hlaka lwe-Ethernet. Emgqeni 1 siqhathanisa okuqukethwe kwirejista A (uhlobo lwephakheji) c 0x86dd, futhi lokhu futhi kukhona Uhlobo esiluthakaselayo yi-IPv6. Emgqeni 1, ngaphezu komyalo wokuqhathanisa, kunamakholomu amabili ngaphezulu - jt 2 ΠΈ jf 3 - amamaki okufanele uye kuwo uma isiqhathaniso siphumelele (A == 0x86dd) futhi akuphumelelanga. Ngakho-ke, esimweni esiyimpumelelo (IPv6) siya emgqeni wesi-2, futhi esimweni esingaphumeleli - ukuya kulayini 3. Emgqeni wesi-3 uhlelo luphela ngekhodi 0 (ungakopishi iphakethe), kulayini 2 uhlelo luphela ngekhodi. 262144 (ngikopishe inani eliphakeme lama-kilobytes angama-256).

Isibonelo esiyinkimbinkimbi kakhulu: sibheka amaphakethe e-TCP ngembobo yendawo

Ake sibone ukuthi isihlungi sibukeka kanjani esikopisha wonke amaphakethe e-TCP anembobo yendawo engu-666. Sizocabangela ikesi le-IPv4, njengoba ikesi le-IPv6 lilula. Ngemva kokufunda lesi sibonelo, ungakwazi ukuhlola isihlungi se-IPv6 ngokwakho njengomsebenzi (ip6 and tcp dst port 666) kanye nesihlungi secala elijwayelekile (tcp dst port 666). Ngakho, isihlungi esinentshisekelo kuso sibukeka kanje:

$ sudo tcpdump -i eth0 -d ip and tcp dst port 666
(000) ldh      [12]
(001) jeq      #0x800           jt 2    jf 10
(002) ldb      [23]
(003) jeq      #0x6             jt 4    jf 10
(004) ldh      [20]
(005) jset     #0x1fff          jt 10   jf 6
(006) ldxb     4*([14]&0xf)
(007) ldh      [x + 16]
(008) jeq      #0x29a           jt 9    jf 10
(009) ret      #262144
(010) ret      #0

Sesiyazi kakade ukuthi ulayini 0 no-1 benzani. Emgqeni wesi-2 sesivele sihlolile ukuthi leli yiphakethe le-IPv4 (Uhlobo lwe-Ether = 0x800) bese uyilayisha kurejista A 24th byte yephakethe. Iphakheji yethu ibukeka kanje

       14            8      1     1
|ethernet header|ip fields|ttl|protocol|...|

okusho ukuthi silayisha kurejista A inkambu Yephrothokholi yesihloko se-IP, okunengqondo, ngoba sifuna ukukopisha amaphakethe we-TCP kuphela. Siqhathanisa iProtocol ne 0x6 (IPPROTO_TCP) kulayini 3.

Emgqeni wesi-4 nowesi-5 silayisha amagama amancane atholakala ekhelini lama-20 futhi sisebenzisa umyalo jset hlola ukuthi eyodwa kokuthathu isethiwe amafulege - ukugqoka imaski ekhishwe jset izingcezu ezintathu ezibaluleke kakhulu zisusiwe. Amabhithi amabili kwamathathu asitshela ukuthi ingabe iphakethe liyingxenye yephakethe le-IP elihlukanisiwe, futhi uma kunjalo, noma ngabe liwucezu lokugcina. Ibhithi lesithathu ligodliwe futhi kufanele libe nguziro. Asifuni ukuhlola amaphakethe angaphelele noma aphukile, ngakho sibheka womathathu amabhithi.

Umugqa wesi-6 yiwo othakasela kakhulu kulolu hlu. Inkulumo ldxb 4*([14]&0xf) kusho ukuthi silayisha kurejista X amabhithi amane abalulekile ebhayithi yeshumi nanhlanu yephakethe iphindwe ngo-4. Amabhithi amane abalulekile webhayithi yeshumi nanhlanu yinkambu Ubude Beheda Ye-inthanethi IPv4 unhlokweni, ogcina ubude besihloko emagameni, ngakho-ke udinga ukuphindaphinda ngo-4. Kuyathakazelisa ukuthi isisho 4*([14]&0xf) iwuphawu lohlelo lwamakheli olukhethekile olungasetshenziswa kuphela kuleli fomu futhi kurejista kuphela X, i.e. nathi ngeke sisho ldb 4*([14]&0xf) noma ldxb 5*([14]&0xf) (singacacisa kuphela i-offset ehlukile, isibonelo, ldxb 4*([16]&0xf)). Kuyacaca ukuthi lolu hlelo lwamakheli lwengezwe ku-BPF ngokuqondile ukuze lwamukelwe X (irejista yenkomba) ubude besihloko se-IPv4.

Ngakho emgqeni wesi-7 sizama ukulayisha uhhafu wegama kuwo (X+16). Ukukhumbula ukuthi amabhayithi ayi-14 athathwe unhlokweni we-Ethernet, futhi X iqukethe ubude besihloko se-IPv4, siyaqonda ukuthi ku A Imbobo yendawo ye-TCP ilayishiwe:

       14           X           2             2
|ethernet header|ip header|source port|destination port|

Okokugcina, kulayini wesi-8 siqhathanisa imbobo okuyiwa kuyo nenani elifiswayo futhi emigqeni 9 noma 10 sibuyisela umphumela - noma ukukopisha iphakethe noma cha.

I-Tcpdump: iyalayisha

Ezibonelweni ezedlule, asizange sihlale ngokuningiliziwe ukuthi siyilayisha kanjani i-BPF bytecode ku-kernel ukuze sihlunge iphakethe. Sengisho nje, tcpdump ifakwe kumasistimu amaningi nokusebenza ngezihlungi tcpdump isebenzisa umtapo wolwazi libpcap. Kafushane, ukubeka isihlungi kusixhumi esibonakalayo usebenzisa libpcap, udinga ukwenza okulandelayo:

Ukuze ubone ukuthi umsebenzi pcap_setfilter kusetshenziswa ku-Linux, sisebenzisa strace (eminye imigqa isusiwe):

$ sudo strace -f -e trace=%network tcpdump -p -i eth0 ip
socket(AF_PACKET, SOCK_RAW, 768)        = 3
bind(3, {sa_family=AF_PACKET, sll_protocol=htons(ETH_P_ALL), sll_ifindex=if_nametoindex("eth0"), sll_hatype=ARPHRD_NETROM, sll_pkttype=PACKET_HOST, sll_halen=0}, 20) = 0
setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, {len=4, filter=0xb00bb00bb00b}, 16) = 0
...

Emigqeni emibili yokuqala yokuphuma siyakha isokhethi eluhlaza ukufunda zonke izinhlaka ze-Ethernet futhi uyibophe kusixhumi esibonakalayo eth0. Kusuka isibonelo sethu sokuqala siyazi ukuthi isihlungi ip izoqukatha imiyalelo emine ye-BPF, futhi emugqeni wesithathu sibona indlela yokusebenzisa inketho SO_ATTACH_FILTER ikholi yesistimu setsockopt silayisha futhi sixhuma isihlungi sobude 4. Lesi isihlungi sethu.

Kuyaphawuleka ukuthi ku-BPF yakudala, ukulayisha nokuxhuma isihlungi kuhlala kwenzeka njengokusebenza kwe-athomu, futhi enguqulweni entsha ye-BPF, ukulayisha uhlelo nokulubophezela ku-generator umcimbi kuhlukaniswa ngesikhathi.

Iqiniso Elifihliwe

Inguqulo egcwele kancane yokuphumayo ibonakala kanje:

$ sudo strace -f -e trace=%network tcpdump -p -i eth0 ip
socket(AF_PACKET, SOCK_RAW, 768)        = 3
bind(3, {sa_family=AF_PACKET, sll_protocol=htons(ETH_P_ALL), sll_ifindex=if_nametoindex("eth0"), sll_hatype=ARPHRD_NETROM, sll_pkttype=PACKET_HOST, sll_halen=0}, 20) = 0
setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, {len=1, filter=0xbeefbeefbeef}, 16) = 0
recvfrom(3, 0x7ffcad394257, 1, MSG_TRUNC, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, {len=4, filter=0xb00bb00bb00b}, 16) = 0
...

Njengoba kushiwo ngenhla, silayisha futhi sixhuma isihlungi sethu esokhethi kumugqa wesi-5, kodwa kwenzekani emigqeni 3 no-4? Kuvele ukuthi lokhu libpcap uyasinakekela - ukuze okuphumayo kwesihlungi sethu kungafaki amaphakethe anganelisi, umtapo wolwazi ixhuma isihlungi se-dummy ret #0 (yehlisa wonke amaphakethe), ishintshela isokhethi kumodi yokungavimbi futhi izame ukukhipha wonke amaphakethe angasala kuzihlungi zangaphambilini.

Sekukonke, ukuhlunga amaphakheji ku-Linux usebenzisa i-BPF yakudala, udinga ukuba nesihlungi ngendlela yesakhiwo esifana naso struct sock_fprog kanye nesokhethi evulekile, ngemva kwalokho isihlungi singaxhunywa kusokhethi kusetshenziswa ucingo lwesistimu setsockopt.

Kuyathakazelisa ukuthi isihlungi singaxhunywa kunoma iyiphi isokhethi, hhayi nje eluhlaza. Lapha isibonelo uhlelo olunqamula wonke ngaphandle kwamabhayithi amabili okuqala kuwo wonke amadathagramu e-UDP angenayo. (Ngingeze amazwana kukhodi ukuze ngingahlanganisi isihloko.)

Imininingwane eyengeziwe mayelana nokusetshenziswa setsockopt ukuze uthole izihlungi zokuxhuma, bheka isokhethi(7), kodwa mayelana nokubhala izihlungi zakho njenge struct sock_fprog ngaphandle kosizo tcpdump sizokhuluma esigabeni Ukuhlela i-BPF ngezandla zethu.

I-BPF yakudala kanye nekhulu lama-XNUMX

I-BPF yafakwa ku-Linux ngo-1997 futhi isilokhu iyihhashi emsebenzini isikhathi eside libpcap ngaphandle kwezinguquko ezikhethekile (izinguquko eziqondene ne-Linux, kunjalo, babe, kodwa abazange bashintshe isithombe somhlaba wonke). Izimpawu zokuqala ezibucayi zokuthi i-BPF izovela ngo-2011, lapho u-Eric Dumazet ehlongoza i-patch, okwengeza i-Just In Time Compiler ku-kernel - umhumushi wokuguqula i-BPF bytecode ibe yendabuko x86_64 ikhodi.

I-JIT compiler yaba ngowokuqala ochungechungeni lwezinguquko: ngo-2012 kwavela ikhono lokubhalela izihlungi secomp, usebenzisa i-BPF, ngoJanuwari 2013 kwakukhona kungezwe module xt_bpf, okuvumela ukuthi ubhale imithetho ye iptables ngosizo lwe-BPF, futhi ngo-Okthoba 2013 kwaba kungezwe futhi module cls_bpf, okukuvumela ukuthi ubhale izihlukanisi zethrafikhi usebenzisa i-BPF.

Sizobheka zonke lezi zibonelo ngokuningiliziwe maduze, kodwa okokuqala kuzoba usizo kithi ukuthi sifunde ukubhala nokuhlanganisa izinhlelo ezingafanele ze-BPF, njengoba amakhono anikezwe umtapo wezincwadi. libpcap okulinganiselwe (isibonelo esilula: isihlungi senziwe libpcap ingabuyisela amanani amabili kuphela - 0 noma 0x40000) noma ngokuvamile, njengasendabeni ye-seccomp, awasebenzi.

Ukuhlela i-BPF ngezandla zethu

Ake sijwayelane nefomethi kanambambili yemiyalelo ye-BPF, ilula kakhulu:

   16    8    8     32
| code | jt | jf |  k  |

Umyalelo ngamunye uthatha amabhithi angu-64, lapho amabhithi okuqala angu-16 eyikhodi yomyalelo, bese kuba nama-indenti amabili ayisishiyagalombili, jt ΠΈ jf, kanye namabhithi angu-32 engxabano K, inhloso yayo ehluka ngokuyala. Ngokwesibonelo, umyalo ret, enqamula uhlelo inekhodi 6, futhi inani lokubuyisela lithathwa kokungaguquki K. Ku-C, umyalelo owodwa we-BPF umelwe njengesakhiwo

struct sock_filter {
        __u16   code;
        __u8    jt;
        __u8    jf;
        __u32   k;
}

futhi lonke uhlelo lusesimweni sesakhiwo

struct sock_fprog {
        unsigned short len;
        struct sock_filter *filter;
}

Ngakho-ke, sesingakwazi kakade ukubhala izinhlelo (isibonelo, siyawazi amakhodi emiyalo evela [1]). Yile ndlela isihlungi esizobukeka ngayo ip6 kusuka ku isibonelo sethu sokuqala:

struct sock_filter code[] = {
        { 0x28, 0, 0, 0x0000000c },
        { 0x15, 0, 1, 0x000086dd },
        { 0x06, 0, 0, 0x00040000 },
        { 0x06, 0, 0, 0x00000000 },
};
struct sock_fprog prog = {
        .len = ARRAY_SIZE(code),
        .filter = code,
};

uhlelo prog singasebenzisa ngokusemthethweni ocingweni

setsockopt(sk, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog))

Ukubhala izinhlelo ngendlela yamakhodi omshini akulula kakhulu, kodwa ngezinye izikhathi kuyadingeka (isibonelo, ukulungisa iphutha, ukudala ukuhlolwa kweyunithi, ukubhala izihloko ku-HabrΓ©, njll.). Ukuze kube lula, kufayela <linux/filter.h> amamakhro omsizi achazwa - isibonelo esifanayo nangenhla singabhalwa kabusha ngokuthi

struct sock_filter code[] = {
        BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 12),
        BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ETH_P_IPV6, 0, 1),
        BPF_STMT(BPF_RET|BPF_K, 0x00040000),
        BPF_STMT(BPF_RET|BPF_K, 0),
}

Nokho, le nketho ayilula kakhulu. Lokhu yilokho abahleli bezinhlelo ze-Linux kernel abacabangisise ngakho, ngakho-ke kunkomba tools/bpf ama-kernels ungathola isihlanganisi nesilungisa iphutha sokusebenza nge-BPF yakudala.

Ulimi lokuhlanganisa lufana kakhulu nokukhipha iphutha tcpdump, kodwa ngaphezu kwalokho singacacisa amalebula angokomfanekiso. Isibonelo, nalu uhlelo oluwisa wonke amaphakethe ngaphandle kwe-TCP/IPv4:

$ cat /tmp/tcp-over-ipv4.bpf
ldh [12]
jne #0x800, drop
ldb [23]
jneq #6, drop
ret #-1
drop: ret #0

Ngokuzenzakalelayo, isihlanganisi sikhiqiza ikhodi ngefomethi <количСство инструкций>,<code1> <jt1> <jf1> <k1>,..., isibonelo sethu nge-TCP kuzoba

$ tools/bpf/bpf_asm /tmp/tcp-over-ipv4.bpf
6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 6,6 0 0 4294967295,6 0 0 0,

Ukuze kube lula kubahleli bezinhlelo ze-C, ifomethi ehlukile yokuphumayo ingasetshenziswa:

$ tools/bpf/bpf_asm -c /tmp/tcp-over-ipv4.bpf
{ 0x28,  0,  0, 0x0000000c },
{ 0x15,  0,  3, 0x00000800 },
{ 0x30,  0,  0, 0x00000017 },
{ 0x15,  0,  1, 0x00000006 },
{ 0x06,  0,  0, 0xffffffff },
{ 0x06,  0,  0, 0000000000 },

Lo mbhalo ungakopishelwa encazelweni yesakhiwo sohlobo struct sock_filter, njengoba senzile ekuqaleni kwalesi sigaba.

I-Linux kanye ne-netsniff-ng izandiso

Ngaphezu kwe-BPF ejwayelekile, i-Linux kanye tools/bpf/bpf_asm ukwesekwa kanye isethi engajwayelekile. Ngokuyisisekelo, imiyalelo isetshenziselwa ukufinyelela izinkambu zesakhiwo struct sk_buff, echaza iphakethe lenethiwekhi ku-kernel. Nokho, kukhona nezinye izinhlobo zemiyalelo yomsizi, isibonelo ldw cpu izolayisha kurejista A umphumela wokusebenzisa umsebenzi we-kernel raw_smp_processor_id(). (Enguqulweni entsha ye-BPF, lezi zandiso ezingajwayelekile zinwetshiwe ukuze kuhlinzekwe izinhlelo ngesethi yabasizi be-kernel ukuze bafinyelele inkumbulo, izakhiwo, kanye nemicimbi ekhiqizayo.) Nasi isibonelo esithakazelisayo sesihlungi lapho sikopisha khona kuphela hlanganisa izihloko endaweni yomsebenzisi usebenzisa isandiso poff, i-payload offset:

ld poff
ret a

Izandiso ze-BPF azikwazi ukusetshenziswa ku tcpdump, kodwa lesi yisizathu esihle sokujwayelana nephakheji yokusetshenziswa netsniff-ng, okuyinto, phakathi kwezinye izinto, equkethe uhlelo oluthuthukisiwe netsniff-ng, okuthi, ngaphezu kokuhlunga usebenzisa i-BPF, futhi iqukethe ijeneretha yethrafikhi ephumelelayo, futhi ethuthuke kakhulu kune tools/bpf/bpf_asm, kwabizwa umdidiyeli we-BPF bpfc. Iphakheji iqukethe imibhalo enemininingwane eminingi, bheka futhi izixhumanisi ekugcineni kwe-athikili.

secomp

Ngakho-ke, sesivele sazi ukuthi singabhala kanjani izinhlelo ze-BPF zobunzima obungenangqondo futhi silungele ukubheka izibonelo ezintsha, eyokuqala okuyi-seccomp technology, evumela, kusetshenziswa izihlungi ze-BPF, ukuphatha isethi kanye nesethi yezingxabano zocingo zesistimu ezitholakalayo inqubo enikeziwe kanye nenzalo yayo.

Inguqulo yokuqala ye-seccomp yengezwe ku-kernel ngo-2005 futhi yayingadumile kakhulu, ngoba inikeze inketho eyodwa kuphela - ukukhawulela isethi yezingcingo zesistimu ezitholakalayo kwinqubo kulokhu okulandelayo: read, write, exit ΠΈ sigreturn, futhi inqubo eyephula imithetho yabulawa kusetshenziswa SIGKILL. Kodwa-ke, ngo-2012, i-seccomp yengeze amandla okusebenzisa izihlungi ze-BPF, okukuvumela ukuthi uchaze isethi yezingcingo ezivunyelwe zesistimu futhi wenze nokuhlola izingxabano zabo. (Kuyathakazelisa ukuthi i-Chrome ibingomunye wabasebenzisi bokuqala balokhu kusebenza, futhi abantu be-Chrome njengamanje bakha indlela ye-KRSI esekelwe enguqulweni entsha ye-BPF futhi ivumela ukwenziwa ngendlela oyifisayo kwamamojula okuvikela e-Linux.) Izixhumanisi zemibhalo eyengeziwe zingatholakala ekugcineni yesihloko.

Qaphela ukuthi sekuvele kunezindatshana kuhabhu mayelana nokusebenzisa i-seccomp, mhlawumbe othile uzofuna ukuzifunda ngaphambi (noma esikhundleni sokufunda) izigatshana ezilandelayo. Esihlokweni Iziqukathi nokuvikeleka: seccomp inikeza izibonelo zokusebenzisa i-seccomp, kokubili inguqulo ka-2007 kanye nenguqulo esebenzisa i-BPF (izihlungi zenziwa kusetshenziswa i-libseccomp), ikhuluma ngokuxhunywa kwe-seccomp ne-Docker, futhi inikeza izixhumanisi eziningi eziwusizo. Esihlokweni Ukuhlukanisa ama-daemon nge-systemd noma "awudingi i-Docker kulokhu!" Ihlanganisa, ikakhulukazi, indlela yokwengeza uhlu lwabavinjiwe noma uhlu olumhlophe lwezingcingo zesistimu zamademoni asebenzisa i-systemd.

Okulandelayo sizobona indlela yokubhala nokulayisha izihlungi seccomp ku-C ongenalutho nokusebenzisa umtapo wolwazi libseccomp futhi yiziphi izinzuzo nezingozi zenketho ngayinye, futhi ekugcineni, ake sibone ukuthi i-seccomp isetshenziswa kanjani uhlelo strace.

Ukubhala nokulayisha izihlungi ze-seccomp

Sesivele sazi ukuthi zibhalwa kanjani izinhlelo ze-BPF, ngakho-ke ake siqale sibheke i-seccomp programming interface. Ungasetha isihlungi kuleveli yenqubo, futhi zonke izinqubo zengane zizozuza imikhawulo njengefa. Lokhu kwenziwa kusetshenziswa ikholi yesistimu seccomp(2):

seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)

kuphi &filter - lesi yisikhombi esakhiweni esesijwayelekile kithi struct sock_fprog, i.e. Uhlelo lwe-BPF.

Zihluke kanjani izinhlelo ze-seccomp ezinhlelweni zamasokhethi? Ingqikithi edlulisiwe. Endabeni yamasokhethi, sanikezwa indawo yenkumbulo equkethe iphakethe, futhi esimweni se-seccomp sanikezwa isakhiwo esifana

struct seccomp_data {
    int   nr;
    __u32 arch;
    __u64 instruction_pointer;
    __u64 args[6];
};

kuyinto nr inombolo yocingo lwesistimu okumele lwethulwe, arch - izakhiwo zamanje (ngaphezulu kulokhu ngezansi), args - kufika ku-izimpikiswano zekholi zesistimu eziyisithupha, futhi instruction_pointer iyisikhombi kumyalelo wesikhala somsebenzisi owenze ikholi yesistimu. Ngakho, isibonelo, ukulayisha inombolo yocingo yesistimu kurejista A kufanele sisho

ldw [0]

Kukhona ezinye izici zezinhlelo ze-seccomp, isibonelo, umongo ungafinyelelwa kuphela ngokuqondisa kwe-32-bit futhi awukwazi ukulayisha uhhafu wegama noma ibhayithi - uma uzama ukulayisha isihlungi. ldh [0] ikholi yesistimu seccomp izobuya EINVAL. Umsebenzi uhlola izihlungi ezilayishiwe seccomp_check_filter() izinhlamvu. (Into ehlekisayo ukuthi, ekuzinikeleni kwasekuqaleni okwengeze ukusebenza kwe-seccomp, bakhohlwe ukungeza imvume yokusebenzisa umyalo kulo msebenzi. mod (ingxenye esele) futhi manje ayitholakali ezinhlelweni ze-seccomp ze-BPF, kusukela yengezwe izophuka ABI.)

Ngokuyisisekelo, sesivele sazi konke ukubhala nokufunda izinhlelo ze-seccomp. Ngokuvamile i-logic yohlelo ihlelwa njengohlu olumhlophe noma olumnyama lwezingcingo zesistimu, isibonelo uhlelo

ld [0]
jeq #304, bad
jeq #176, bad
jeq #239, bad
jeq #279, bad
good: ret #0x7fff0000 /* SECCOMP_RET_ALLOW */
bad: ret #0

ihlola uhlu oluvinjelwe lwezingcingo ezine zesistimu ezinenombolo 304, 176, 239, 279. Ziyini lezi zingcingo zesistimu? Ngeke sasho ngokuqinisekile, njengoba asazi ukuthi lolu hlelo lwabhalelwa luphi uhlobo lwezakhiwo. Ngakho-ke, ababhali be-seccomp ukunikela qala zonke izinhlelo ngokuhlolwa kwezakhiwo (isakhiwo samanje sikhonjiswe kumongo njengenkambu arch izakhiwo struct seccomp_data). Uma i-architecture ihloliwe, isiqalo sesibonelo singabukeka kanje:

ld [4]
jne #0xc000003e, bad_arch ; SCMP_ARCH_X86_64

bese izinombolo zekholi zesistimu yethu zizothola amanani athile.

Sibhala futhi silayishe izihlungi zokusebenzisa i-seccomp libseccomp

Ukubhala izihlungi ngekhodi yomdabu noma ekuhlanganiseni kwe-BPF kukuvumela ukuthi ukwazi ukulawula ngokugcwele umphumela, kodwa ngesikhathi esifanayo, ngezinye izikhathi kuyathandeka ukuba nekhodi ephathekayo kanye/noma efundekayo. Umtapo wolwazi uzosisiza ngalokhu libsecomp, okunikeza isixhumi esibonakalayo esijwayelekile sokubhala izihlungi ezimnyama noma ezimhlophe.

Ake, isibonelo, sibhale uhlelo olusebenzisa ifayela kanambambili elikhethwa ngumsebenzisi, esifake ngaphambilini uhlu olumnyama lwezingcingo zesistimu ezivela isihloko esingenhla (uhlelo lwenziwe lula ukuze lufundeke kakhudlwana, inguqulo egcwele ingatholakala lapha):

#include <seccomp.h>
#include <unistd.h>
#include <err.h>

static int sys_numbers[] = {
        __NR_mount,
        __NR_umount2,
       // ... Π΅Ρ‰Π΅ 40 систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² ...
        __NR_vmsplice,
        __NR_perf_event_open,
};

int main(int argc, char **argv)
{
        scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);

        for (size_t i = 0; i < sizeof(sys_numbers)/sizeof(sys_numbers[0]); i++)
                seccomp_rule_add(ctx, SCMP_ACT_TRAP, sys_numbers[i], 0);

        seccomp_load(ctx);

        execvp(argv[1], &argv[1]);
        err(1, "execlp: %s", argv[1]);
}

Okokuqala sichaza uhlu sys_numbers yezinombolo zekholi zesistimu ezingu-40+ ukuze uvimbele. Bese, qala umongo ctx futhi sitshele umtapo wolwazi ukuthi yini esifuna ukuyivumela (SCMP_ACT_ALLOW) zonke izingcingo zesistimu ngokuzenzakalela (kulula ukwakha izinhlu ezivinjelwe). Bese, ngamunye ngamunye, sengeza zonke izingcingo zesistimu ezivela ohlwini oluvinjelwe. Ekuphenduleni ucingo lwesistimu oluvela ohlwini, siyacela SCMP_ACT_TRAP, kulokhu i-seccomp izothumela isignali kunqubo SIGSYS ngencazelo yokuthi yiluphi ucingo lwesistimu oluphule imithetho. Ekugcineni, silayisha uhlelo ku-kernel sisebenzisa seccomp_load, ezohlanganisa uhlelo futhi inamathisele kunqubo isebenzisa ikholi yesistimu seccomp(2).

Ukuze luhlanganiswe ngempumelelo, uhlelo kufanele luxhunywe nomtapo wolwazi libseccompisibonelo:

cc -std=c17 -Wall -Wextra -c -o seccomp_lib.o seccomp_lib.c
cc -o seccomp_lib seccomp_lib.o -lseccomp

Isibonelo sokuqaliswa ngempumelelo:

$ ./seccomp_lib echo ok
ok

Isibonelo sekholi yesistimu evinjiwe:

$ sudo ./seccomp_lib mount -t bpf bpf /tmp
Bad system call

Sisebenzisa stracengemininingwane:

$ sudo strace -e seccomp ./seccomp_lib mount -t bpf bpf /tmp
seccomp(SECCOMP_SET_MODE_FILTER, 0, {len=50, filter=0x55d8e78428e0}) = 0
--- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0xboobdeadbeef, si_syscall=__NR_mount, si_arch=AUDIT_ARCH_X86_64} ---
+++ killed by SIGSYS (core dumped) +++
Bad system call

singakwazi kanjani ukuthi uhlelo lunqanyuliwe ngenxa yokusetshenziswa kocingo lwesistimu olungekho emthethweni mount(2).

Ngakho, sibhale isihlungi sisebenzisa umtapo wolwazi libseccomp, ukufaka ikhodi engasho lutho emigqeni emine. Esibonelweni esingenhla, uma kunenombolo enkulu yezingcingo zesistimu, isikhathi sokwenza singancishiswa ngokuphawulekayo, njengoba isheke liwuhlu nje lokuqhathanisa. Ukuze kuthuthukiswe, i-libseccomp isanda kwenziwa isichibi sifakiwe, okwengeza usekelo lwesibaluli sesihlungi SCMP_FLTATR_CTL_OPTIMIZE. Ukusetha lesi sici sibe ngu-2 kuzoguqula isihlungi sibe uhlelo lokusesha olunambambili.

Uma ufuna ukubona ukuthi izihlungi zosesho kanambambili zisebenza kanjani, bheka umbhalo olula, ekhiqiza izinhlelo ezinjalo ku-BPF assembler ngokudayela izinombolo zekholi zesistimu, isibonelo:

$ echo 1 3 6 8 13 | ./generate_bin_search_bpf.py
ld [0]
jeq #6, bad
jgt #6, check8
jeq #1, bad
jeq #3, bad
ret #0x7fff0000
check8:
jeq #8, bad
jeq #13, bad
ret #0x7fff0000
bad: ret #0

Ngeke ukwazi ukubhala noma yini ngokushesha okukhulu, njengoba izinhlelo ze-BPF zingakwazi ukwenza ukugxuma kokuhlehlisa (ngokwesibonelo, asikwazi ukukwenza, jmp A noma jmp [label+X]) ngakho-ke zonke izinguquko zimile.

i-seccomp kanye ne-strace

Wonke umuntu uyazi insiza strace iyithuluzi elibalulekile lokufunda ukuziphatha kwezinqubo ku-Linux. Nokho, abaningi baye bezwa ngakho nezindaba zokusebenza uma usebenzisa lolu hlelo lokusebenza. Iqiniso liwukuthi strace isetshenziswa ngokusebenzisa ptrace(2), futhi kule nqubo asikwazi ukucacisa ukuthi iyiphi isethi yezingcingo zesistimu esizidingayo ukuze simise inqubo, okungukuthi, isibonelo, imiyalo.

$ time strace du /usr/share/ >/dev/null 2>&1

real    0m3.081s
user    0m0.531s
sys     0m2.073s

ΠΈ

$ time strace -e open du /usr/share/ >/dev/null 2>&1

real    0m2.404s
user    0m0.193s
sys     0m1.800s

zicutshungulwa cishe ngesikhathi esifanayo, nakuba esimweni sesibili sifuna ukulandelela ucingo lwesistimu olulodwa kuphela.

Inketho entsha --seccomp-bpf, kwengezwe ku strace inguqulo 5.3, ikuvumela ukuthi usheshise inqubo izikhathi eziningi futhi isikhathi sokuqalisa ngaphansi komkhondo wocingo olulodwa lwesistimu sesivele siqhathaniswa nesikhathi sokuqalisa okuvamile:

$ time strace --seccomp-bpf -e open du /usr/share/ >/dev/null 2>&1

real    0m0.148s
user    0m0.017s
sys     0m0.131s

$ time du /usr/share/ >/dev/null 2>&1

real    0m0.140s
user    0m0.024s
sys     0m0.116s

(Lapha, kunjalo, kukhona inkohliso encane yokuthi asilandeli ucingo lwesistimu oluyinhloko lwalo myalo. Uma besilandela, isibonelo, newfsstat, khona-ke strace lalizobhuleka liqine njengoba lingekho --seccomp-bpf.)

Isebenza kanjani le nketho? Ngaphandle kwakhe strace ixhuma kunqubo bese iqala ukuyisebenzisa PTRACE_SYSCALL. Uma inqubo ephethwe ikhipha (noma iyiphi) ikholi yesistimu, ukulawula kudluliselwa kokuthi strace, ebheka izimpikiswano zekholi yesistimu futhi iluqhube lusebenzisa PTRACE_SYSCALL. Ngemva kwesikhathi esithile, inqubo iqeda ikholi yesistimu futhi lapho iphuma, ukulawula kudluliselwa futhi strace, ebheka amanani okubuyisela futhi iqale inqubo isebenzisa PTRACE_SYSCALL, njalo njalo.

I-BPF yabancane, ingxenye enguziro: i-BPF yakudala

Nge-seccomp, nokho, le nqubo ingathuthukiswa ngendlela esingathanda ngayo. Okungukuthi, uma sifuna ukubheka kuphela ucingo lwesistimu X, khona-ke singabhala isihlungi se-BPF leso X ibuyisela inani SECCOMP_RET_TRACE, kanye nezingcingo ezingenasithakazelo kithi - SECCOMP_RET_ALLOW:

ld [0]
jneq #X, ignore
trace: ret #0x7ff00000
ignore: ret #0x7fff0000

Kulokhu strace ekuqaleni iqala inqubo njengoba PTRACE_CONT, isihlungi sethu sicutshungulwa kukholi yesistimu ngayinye, uma ucingo lwesistimu lungenziwanga X, khona-ke inqubo iyaqhubeka nokusebenza, kodwa uma lokhu X, bese i-seccomp izodlulisela ukulawula straceezobheka izimpikiswano bese iqala inqubo njenge PTRACE_SYSCALL (njengoba i-seccomp ingenawo amandla okusebenzisa uhlelo ekuphumeni ocingweni lwesistimu). Uma ikholi yesistimu ibuya, strace izoqala kabusha inqubo isebenzisa PTRACE_CONT futhi izolinda imilayezo emisha evela ku-seccomp.

I-BPF yabancane, ingxenye enguziro: i-BPF yakudala

Uma usebenzisa inketho --seccomp-bpf kunemikhawulo emibili. Okokuqala, ngeke kwenzeke ukujoyina inqubo esivele ikhona (inketho -p uhlelo strace), njengoba lokhu akusekelwe yi-seccomp. Okwesibili, akukho okwenzekayo hhayi bheka izinqubo zengane, njengoba izihlungi ze-seccomp zizuzwa yizo zonke izinqubo zengane ngaphandle kwekhono lokukhubaza lokhu.

Imininingwane eminingi yokuthi kanjani kahle strace isebenza ne- seccomp ingatholakala ku umbiko wakamuva. Kithina, iqiniso elithakazelisa kakhulu ukuthi i-BPF yakudala emelwe yi-seccomp isasetshenziswa nanamuhla.

xt_bpf

Manje ake sibuyele emhlabeni wamanethiwekhi.

Isendlalelo: kudala, ngo-2007, umnyombo wawukhona kungezwe module xt_u32 okwesihlungi. Yabhalwa ngesifaniso nesigaba sethrafikhi sakudala nakakhulu cls_u32 futhi ikuvumele ukuthi ubhale imithetho kanambambili engafanele yama-iptables usebenzisa le misebenzi elula elandelayo: layisha amabhithi angu-32 ukusuka kuphakheji futhi wenze isethi yemisebenzi yezibalo kuwo. Ngokwesibonelo,

sudo iptables -A INPUT -m u32 --u32 "6&0xFF=1" -j LOG --log-prefix "seen-by-xt_u32"

Ilayisha amabhithi angu-32 wesihloko se-IP, kusukela ku-padding 6, bese iwafaka imaski 0xFF (thatha ibhayithi ephansi). Le nkambu protocol Isihloko se-IP futhi siyiqhathanisa ne-1 (ICMP). Emthethweni owodwa ungahlanganisa amasheke amaningi, futhi ungasebenzisa futhi u-opharetha @ β€” hambisa amabhayithi angu-X kwesokudla. Ngokwesibonelo, umthetho

iptables -m u32 --u32 "6&0xFF=0x6 && 0>>22&0x3C@4=0x29"

ihlola ukuthi Inombolo Yokulandelana kwe-TCP ayilingani yini 0x29. Ngeke ngingene emininingwaneni eyengeziwe, ngoba sekuvele kucacile ukuthi ukubhala imithetho enjalo ngesandla akulula kakhulu. Esihlokweni I-BPF - i-bytecode ekhohliwe, kukhona izixhumanisi ezimbalwa ezinezibonelo zokusetshenziswa nokukhiqizwa kwemithetho xt_u32. Bheka futhi izixhumanisi ekupheleni kwalesi sihloko.

Kusukela 2013 module esikhundleni module xt_u32 ungasebenzisa imojuli esekelwe ku-BPF xt_bpf. Noma ubani ofunde kuze kube manje kufanele acace kakade mayelana nesimiso sokusebenza kwayo: sebenzisa i-BPF bytecode njengemithetho ye-iptables. Ungakha umthetho omusha, isibonelo, kanje:

iptables -A INPUT -m bpf --bytecode <Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄> -j LOG

lapha <Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄> - lena ikhodi ngefomethi yokuphuma kwe-assembler bpf_asm ngokuzenzakalelayo, isibonelo,

$ cat /tmp/test.bpf
ldb [9]
jneq #17, ignore
ret #1
ignore: ret #0

$ bpf_asm /tmp/test.bpf
4,48 0 0 9,21 0 1 17,6 0 0 1,6 0 0 0,

# iptables -A INPUT -m bpf --bytecode "$(bpf_asm /tmp/test.bpf)" -j LOG

Kulesi sibonelo sihlunga wonke amaphakethe e-UDP. Umongo wohlelo lwe-BPF kumojuli xt_bpf, vele, ikhomba kudatha yephakethe, esimweni sama-iptables, ekuqaleni kwesihloko se-IPv4. Buyisela inani elivela kuhlelo lwe-BPF booleankuphi false kusho ukuthi iphakethe alifani.

Kuyacaca ukuthi module xt_bpf isekela izihlungi eziyinkimbinkimbi kunesibonelo esingenhla. Ake sibheke izibonelo zangempela ezivela ku-Cloudfare. Kuze kube muva nje bebesebenzisa imojuli xt_bpf ukuvikela ekuhlaselweni kwe-DDoS. Esihlokweni Sethula Amathuluzi e-BPF bachaza ukuthi (futhi kungani) benza izihlungi ze-BPF futhi bashicilele izixhumanisi zesethi yezinsiza zokudala izihlungi ezinjalo. Isibonelo, ukusebenzisa uhlelo lokusebenza bpfgen ungakha uhlelo lwe-BPF olufana nombuzo we-DNS wegama habr.com:

$ ./bpfgen --assembly dns -- habr.com
ldx 4*([0]&0xf)
ld #20
add x
tax

lb_0:
    ld [x + 0]
    jneq #0x04686162, lb_1
    ld [x + 4]
    jneq #0x7203636f, lb_1
    ldh [x + 8]
    jneq #0x6d00, lb_1
    ret #65535

lb_1:
    ret #0

Ohlelweni siqale silayishe kurejista X ukuqala kwekheli lomugqa x04habrx03comx00 ngaphakathi kwedathagram ye-UDP bese uhlola isicelo: 0x04686162 <-> "x04hab" nokunye.

Kamuva, i-Cloudfare yashicilela i-p0f -> ikhodi ye-BPF compiler. Esihlokweni Sethula i-p0f BPF compiler bakhuluma ngokuthi iyini i-p0f nokuthi bangawaguqula kanjani amasiginesha e-p0f abe yi-BPF:

$ ./bpfgen p0f -- 4:64:0:0:*,0::ack+:0
39,0 0 0 0,48 0 0 8,37 35 0 64,37 0 34 29,48 0 0 0,
84 0 0 15,21 0 31 5,48 0 0 9,21 0 29 6,40 0 0 6,
...

Okwamanje ayisasebenzisi i-Cloudfare xt_bpf, njengoba bethuthela ku-XDP - enye yezinketho zokusebenzisa inguqulo entsha ye-BPF, bheka. I-L4Drop: I-XDP DDoS Mitigations.

cls_bpf

Isibonelo sokugcina sokusebenzisa i-BPF yakudala ku-kernel i-classifier cls_bpf ye-subsystem yokulawulwa kwethrafikhi e-Linux, engezwe ku-Linux ekupheleni kuka-2013 futhi ngokucatshangwayo ithatha indawo yasendulo. cls_u32.

Nokho, ngeke manje siwuchaze umsebenzi cls_bpf, kusukela ekubukeni kolwazi mayelana ne-BPF yakudala lokhu ngeke kusinike lutho - sesivele sajwayelana nakho konke ukusebenza. Ngaphezu kwalokho, ezihlokweni ezilandelayo ezikhuluma nge-BPF Enwetshiwe, sizohlangana nalesi sihlungi ngaphezu kwesisodwa.

Esinye isizathu sokungakhulumi ngokusebenzisa i-BPF yakudala c cls_bpf Inkinga ukuthi, uma kuqhathaniswa ne-BPF Enwetshiwe, ububanzi bokusebenza kuleli cala buncane kakhulu: izinhlelo zakudala azikwazi ukushintsha okuqukethwe kwamaphakheji futhi azikwazi ukulondoloza isimo phakathi kwezingcingo.

Ngakho-ke yisikhathi sokuvalelisa ku-BPF yakudala futhi ubheke ikusasa.

Valelisa ku-BPF yakudala

Sibheke ukuthi ubuchwepheshe be-BPF, obuthuthukiswe ekuqaleni kweminyaka engamashumi ayisishiyagalolunye, buphile kanjani ngempumelelo ingxenye yesine yekhulu futhi kuze kube sekupheleni bathola izinhlelo zokusebenza ezintsha. Kodwa-ke, kufana noshintsho olusuka emishinini yesitaki iye ku-RISC, esebenze njengomfutho wokuthuthukiswa kwe-BPF yakudala, ngeminyaka yawo-32 kwaba noshintsho olusuka kumishini engamabhithi angama-64 ukuya kwengama-XNUMX futhi i-BPF yakudala yaqala ukungasasebenzi. Ngaphezu kwalokho, amakhono e-BPF yakudala anqunyelwe kakhulu, futhi ngaphezu kwezakhiwo eziphelelwe yisikhathi - asinalo ikhono lokulondoloza isimo phakathi kwezingcingo ezinhlelweni ze-BPF, akukho okwenzekayo kokusebenzelana okuqondile komsebenzisi, akukho okungenzeka kokuxhumana. nge-kernel, ngaphandle kokufunda inombolo elinganiselwe yezinkambu zesakhiwo sk_buff futhi wethula imisebenzi yomsizi elula, awukwazi ukushintsha okuqukethwe kwamaphakethe bese uwaqondisa kabusha.

Eqinisweni, okwamanje konke okusele ku-BPF yakudala ku-Linux isixhumi esibonakalayo se-API, futhi ngaphakathi kwe-kernel zonke izinhlelo zakudala, kungaba izihlungi zesokhethi noma izihlungi ze-seccomp, zihunyushwa ngokuzenzakalela zibe ifomethi entsha, i-BPF Enwetshiwe. (Sizokhuluma ngokuthi lokhu kwenzeka kanjani esihlokweni esilandelayo.)

Ukushintshela ekwakhiweni okusha kwaqala ngo-2013, lapho u-Alexey Starovoitov ehlongoza uhlelo lokuvuselela i-BPF. Ngo-2014 amapheshana ahambisanayo waqala ukubonakala emnyombeni. Ngokwazi kwami, uhlelo lwangempela bekuwukuthuthukisa kuphela ukwakheka kanye ne-JIT compiler ukuthi isebenze kahle emishinini engama-64-bit, kodwa esikhundleni salokho lokhu kulungiselelwa kuphawule ukuqala kwesahluko esisha ekuthuthukisweni kweLinux.

Ezinye izindatshana zalolu chungechunge zizofaka ukwakhiwa kanye nokusetshenziswa kobuchwepheshe obusha, ekuqaleni obaziwa ngokuthi yi-BPF yangaphakathi, kwase kuba i-BPF enwetshiwe, futhi manje sekuyi-BPF nje.

izithenjwa

  1. USteven McCanne noVan Jacobson, "Isihlungi Sephakethe le-BSD: Isakhiwo Esisha Sokuthwebula Iphakethe lezinga lomsebenzisi", https://www.tcpdump.org/papers/bpf-usenix93.pdf
  2. USteven McCanne, "i-libpcap: I-Architecture kanye Nendlela Yokuthuthukisa Yokuthwebula Iphakethe", https://sharkfestus.wireshark.org/sharkfest.11/presentations/McCanne-Sharkfest'11_Keynote_Address.pdf
  3. tcpdump, libpcap: https://www.tcpdump.org/
  4. I-IPtable U32 Match Tutorial.
  5. I-BPF - i-bytecode ekhohliwe: https://blog.cloudflare.com/bpf-the-forgotten-bytecode/
  6. Sethula Ithuluzi le-BPF: https://blog.cloudflare.com/introducing-the-bpf-tools/
  7. bpf_cls: http://man7.org/linux/man-pages/man8/tc-bpf.8.html
  8. Ukubuka konke okuhlangene: https://lwn.net/Articles/656307/
  9. https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
  10. habr: Iziqukathi nokuphepha: seccomp
  11. habr: Ukuhlukanisa ama-daemon nge-systemd noma "awudingi i-Docker kulokhu!"
  12. Paul Chaignon, "strace --seccomp-bpf: look under the hood", https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
  13. netsniff-ng: http://netsniff-ng.org/

Source: www.habr.com

Engeza amazwana