I-BPF yabantwana abancinci, inxalenye ye-zero: i-BPF yakudala

I-Berkeley Packet Filters (BPF) yitekhnoloji ye-Linux kernel ebikumaphepha angaphambili oshicilelo lobugcisa bolwimi lwesiNgesi iminyaka eliqela ngoku. Iinkomfa zizaliswe ngeengxelo zokusetyenziswa nophuhliso lwe-BPF. UDavid Miller, umgcini wenkqubo engaphantsi kwe-Linux, ubiza intetho yakhe kwi-Linux Plumbers 2018 β€œLe ntetho ayithethi ngeXDP” (I-XDP yinto enye yokusetyenziswa kwe-BPF). UBrendan Gregg unikela iintetho ezinomxholo othi Linux BPF Superpowers. Toke HΓΈiland-JΓΈrgensen uyahlekaukuba ikernel ngoku yimicrokernel. UThomas Graf ukhuthaza ingcamango yokuba I-BPF yijavascript yekernel.

Kusekho inkcazo ecwangcisiweyo ye-BPF kwi-HabrΓ©, kwaye ngoko ke kuluhlu lwamanqaku ndiya kuzama ukuthetha ngembali yethekhnoloji, ndichaze izixhobo zokwakha kunye nophuhliso, kwaye ndichaze imimandla yesicelo kunye nokusebenza kokusebenzisa i-BPF. Eli nqaku, zero, kuluhlu, lixelela imbali kunye noyilo lwe-BPF yakudala, kwaye ityhila iimfihlo zemigaqo yayo yokusebenza. tcpdump, seccomp, strace, nokunye okuninzi.

Uphuhliso lwe-BPF lulawulwa luluntu lwe-Linux networking, izicelo eziphambili ezikhoyo ze-BPF zihambelana nothungelwano kwaye ngoko ke, ngemvume. @eucariot, Ndabiza uchungechunge "i-BPF yabancinci", ngokuhlonipha uchungechunge olukhulu "Iinethiwekhi zabancinci".

Ikhosi emfutshane kwimbali ye-BPF(c)

Itekhnoloji ye-BPF yanamhlanje yinguqulelo ephuculweyo neyandisiweyo yetekhnoloji endala enegama elifanayo, ngoku ebizwa ngokuba yi-BPF yakudala ukunqanda ukubhideka. Isixhobo esaziwayo senziwe ngokusekelwe kwi-BPF yakudala tcpdump, indlela seccomp, kunye neemodyuli ezingaziwayo xt_bpf kuba iptables kunye nomdidi cls_bpf. KwiLinux yanamhlanje, iinkqubo zeBPF zakudala ziguqulelwa ngokuzenzekelayo kwifom entsha, nangona kunjalo, ukusuka kumbono womsebenzisi, i-API ihleli isendaweni kwaye ukusetyenziswa okutsha kweBPF yakudala, njengoko siza kubona kweli nqaku, kusafunyanwa. Ngesi sizathu, kwaye nangenxa yokuba ndilandela imbali yophuhliso lwe-BPF yakudala kwiLinux, iya kucaca ngakumbi ukuba yavela njani kwaye kwakutheni ukuze ibe kwimo yayo yangoku, ndigqibe ekubeni ndiqale ngenqaku malunga ne-BPF yakudala.

Ekupheleni kweminyaka yamashumi asibhozo kwinkulungwane edlulileyo, iinjineli ezivela kwiLabhoratri edumileyo yaseLawrence Berkeley baba nomdla kumbuzo wendlela yokucoca ngokufanelekileyo iipakethi zenethiwekhi kwi-hardware eyayiyila maxesha ngasekupheleni kweminyaka engamashumi asibhozo enkulungwane yokugqibela. Ingcamango esisiseko yokucoca, eyaphunyezwa ekuqaleni kwi-CSPF (CMU/Stanford Packet Filter) iteknoloji, yayikukuhluza iipakethi ezingeyomfuneko kwangoko kangangoko kunokwenzeka, o.k.t. kwindawo yekernel, kuba oku kuthintela ukukopa idatha engeyomfuneko kwindawo yomsebenzisi. Ukubonelela ngokhuseleko lwexesha lokusebenzisa ikhowudi yomsebenzisi kwindawo yekernel, umatshini wenyani wesanti wasetyenziswa.

Nangona kunjalo, oomatshini bokwenyani bezihluzo ezikhoyo babeyilelwe ukuba basebenze koomatshini abasekwe kwi-stack kwaye abazange basebenze ngokufanelekileyo koomatshini abatsha be-RISC. Ngenxa yoko, ngeenzame zeenjineli ezivela eBerkeley Labs, itekhnoloji entsha ye-BPF (i-Berkeley Packet Filters) yaphuhliswa, uyilo lomatshini olwenziwa ngokusekwe kwiprosesa ye-Motorola 6502 - ihashe lemveliso eyaziwayo njenge. Apple II okanye NES. Umatshini omtsha wenyani wandise ukusebenza kokucoca amashumi amaxesha xa kuthelekiswa nezisombululo ezikhoyo.

Uyilo lomatshini weBPF

Siza kuqhelana noyilo lwezakhiwo ngendlela esebenzayo, sihlalutya imizekelo. Nangona kunjalo, ukuqala, masithi umatshini uneerejista ezimbini ze-32-bit ezifikelelekayo kumsebenzisi, i-accumulator. A kunye nerejista yesalathiso X, i-64 bytes yememori (amagama ali-16), ekhoyo ngokubhala kunye nokufunda okulandelayo, kunye nenkqubo encinci yemiyalelo yokusebenza ngezi zinto. Imiyalelo ye-Jump yokuphumeza ukubonakaliswa kwemiqathango nayo yayikhona kwiiprogram, kodwa ukuqinisekisa ukugqitywa kwexesha leprogram, ukuxuma kungenziwa kuphela phambili, oko kukuthi, ngokukodwa, kwakungavunyelwe ukudala iilophu.

Iskimu esiqhelekileyo sokuqalisa umatshini simi ngolu hlobo lulandelayo. Umsebenzisi udala inkqubo yoyilo lweBPF kwaye, esebenzisa ezinye indlela yekernel (efana nenkqubo yokufowuna), ilayisha kwaye iqhagamshela inkqubo kuyo kwabanye kwi-generator yesiganeko kwi-kernel (umzekelo, isiganeko kukufika kwepakethe elandelayo kwikhadi lomnatha). Xa isiganeko sisenzeka, i kernel iqhuba inkqubo (umzekelo, kwitoliki), kwaye inkumbulo yomatshini ihambelana kwabanye ummandla wenkumbulo ye-kernel (umzekelo, idatha yepakethi engenayo).

Oku ngasentla kuya kukwanela ukuba siqale ukujonga imizekelo: siya kuqhelana nenkqubo kunye nefomathi yomyalelo njengoko kuyimfuneko. Ukuba ufuna ukufunda ngokukhawuleza inkqubo yomyalelo womatshini obonakalayo kwaye ufunde malunga nawo onke amandla ayo, ngoko unokufunda inqaku lokuqala. Isihluzi sePakethi ye-BSD kunye/okanye isiqingatha sokuqala sefayile Uxwebhu/uthungelwano/isihluzo.txt ukusuka kuxwebhu lwekernel. Ukongeza, unokufunda intetho libpcap: Indlela yoLwakhiwo kunye nokuPhuculwa kwePakethi yokuThatha iPakethi, apho uMcCanne, omnye wababhali be-BPF, uthetha ngembali yendalo libpcap.

Siqhubela phambili sithathela ingqalelo yonke imizekelo ebalulekileyo yokusebenzisa iBPF yakudala kwiLinux: tcpdump (libpcap), secomp, xt_bpf, cls_bpf.

wcpdump

Uphuhliso lwe-BPF lwenziwa ngokuhambelana nokuphuhliswa kwe-frontend yokucoca ipakethe - into eyaziwayo eyaziwayo. tcpdump. Kwaye, kuba lo ngowona mzekelo mdala kwaye udumileyo wokusebenzisa i-BPF yakudala, ekhoyo kwiinkqubo ezininzi zokusebenza, siya kuqalisa isifundo sethu setekhnoloji ngayo.

(Ndiqhube yonke imizekelo kweli nqaku kwiLinux 5.6.0-rc6. Imveliso yeminye imiyalelo ihlelwe ukuba ifundeke ngcono.)

Umzekelo: ukujonga iipakethi ze-IPv6

Masicinge ukuba sifuna ukujonga zonke iipakethi ze-IPv6 kujongano eth0. Ukwenza oku sinokuqhuba inkqubo tcpdump ngesihluzo esilula ip6:

$ sudo tcpdump -i eth0 ip6

ngoko ke tcpdump iqokelela isihluzo ip6 kwi-BPF ye-architecture bytecode kwaye uyithumele kwi-kernel (jonga iinkcukacha kwicandelo Tcpdump: iyalayisha). Isihluzi esilayishiweyo siya kuqhutywa kwipakethi nganye edlula kujongano eth0. Ukuba isihluzi sibuyisela ixabiso elingengo-zero n, emva koko ukuya n iibytes zepakethi ziya kukhutshelwa kwindawo yomsebenzisi kwaye siya kuyibona kwimveliso tcpdump.

I-BPF yabantwana abancinci, inxalenye ye-zero: i-BPF yakudala

Kuyavela ukuba sinokufumanisa ngokulula ukuba yeyiphi i-bytecode ethunyelwe kwi-kernel tcpdump ngoncedo lwe tcpdump, ukuba siyayiqhuba ngokhetho -d:

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

Kumgca we-zero siqhuba umyalelo ldh [12], emele β€œumthwalo kwirejista A isiqingatha segama (amasuntswana ali-16) abekwe kwidilesi 12” kwaye umbuzo okuphela kwawo ngowohlobo olunjani lwenkumbulo esithetha ngalo? Impendulo kukuba x iyaqala (x+1)i-byte yepakethi yenethiwekhi ehlalutyiweyo. Sifunda iipakethi kwi-interface ye-Ethernet eth0nale kuthethaukuba ipakethe ijongeka ngolu hlobo (ukwenza lula, sicinga ukuba akukho tags zeVLAN kwipakethi):

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

Ngoko emva kokuphumeza umyalelo ldh [12] kwirejista A kuya kubakho intsimi Ether Type β€” uhlobo lwepakethi ethunyelwe kule freyimu ye-Ethernet. Kumgca we-1 sithelekisa imixholo yerejista A (uhlobo lwepakethe) c 0x86ddnale kwaye ikhona Uhlobo esinomdla kulo yi IPv6. Kumgca woku-1, ukongeza kumyalelo wothelekiso, kukho iikholamu ezimbini ezingakumbi - jt 2 ΠΈ jf 3 - amanqaku ekufuneka uye kuwo ukuba uthelekiso luphumelele (A == 0x86dd) kwaye ayiphumelelanga. Ngoko, kwimeko ephumelelayo (IPv6) siya kumgca we-2, kwaye kwimeko engaphumeleli - ukuya kumgca 3. Kwi-3 inkqubo iphela ngekhowudi 0 (musa ukukopisha ipakethi), kumgca we-2 inkqubo iphela ngekhowudi. 262144 (ndikope ubuninzi bepakethe yeekhilobhayithi ezingama-256).

Umzekelo onzima ngakumbi: sijonga iipakethi ze-TCP nge-port yokuya

Makhe sibone ukuba isihluzi sijongeka njani esikhuphela zonke iipakethi ze-TCP ezinezibuko le-666. Siza kuqwalasela imeko ye-IPv4, kuba imeko ye-IPv6 ilula. Emva kokufunda lo mzekelo, ungajonga i IPv6 isihluzo ngokwakho njengomthambo (ip6 and tcp dst port 666) kunye nesihluzi somcimbi jikelele (tcp dst port 666). Ke, isihluzo esinomdla kuso sijongeka ngolu hlobo:

$ 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

Sele sisazi ukuba umgca 0 kunye no-1 wenza ntoni. Kumgca we-2 sele sihlolisise ukuba le yipakethe ye-IPv4 (Uhlobo lwe-Ether = 0x800) kwaye uyilayishe kwirejista A 24th byte yepakethi. Iphakheji yethu ibonakala ngathi

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

into ethetha ukuba silayisha kwirejista A iProtocol field ye-IP header, enengqiqo, kuba sifuna ukukopa kuphela iipakethi zeTCP. Sithelekisa iProtocol kunye 0x6 (IPPROTO_TCP) kumgca 3.

Kumgca wesi-4 kunye no-5 silayisha isiqingatha samagama abekwe kwidilesi yama-20 kwaye sisebenzise umyalelo jset khangela ukuba enye kwezithathu iseti iiflegi - ukunxiba imaski ekhutshwe jset amasuntswana amathathu abalulekileyo acinyiwe. Amasuntswana amabini amathathu asixelela ukuba ipakethi yinxalenye yepakethi ye-IP ecandekileyo, kwaye ukuba kunjalo, ingaba liqhekeza lokugqibela. Isuntswana lesithathu ligciniwe kwaye kufuneka libe nguziro. Asifuni ukujonga iipakethi ezingaphelelanga okanye ezaphukileyo, ngoko ke sijonga amasuntswana amathathu.

Umgca 6 ngowona unika umdla kolu luhlu. Ukuvakalisa ldxb 4*([14]&0xf) kuthetha ukuba silayisha kwirejista X amasuntswana amane abalulekileyo ebhayithi yeshumi elinesihlanu yepakethi iphindaphindwe ngo 4. Obona bancinci bezinto ezine zebyte yeshumi elinesihlanu yintsimi Ubude besihloko se-Intanethi IPv4 header, egcina ubude beheader emagameni, ngoko ke kufuneka uphindaphinde ngo 4. Okubangela umdla, intetho 4*([14]&0xf) lubizo lweskim seedilesi ezikhethekileyo ezinokusetyenziswa kuphela kule fomu kwaye kuphela kwirejista X, okt. nathi asinakutsho ldb 4*([14]&0xf) akukho ldxb 5*([14]&0xf) (singakhankanya kuphela i-offset eyahlukileyo, umzekelo, ldxb 4*([16]&0xf)). Kucacile ukuba esi sikimu seedilesi songezwa kwi-BPF ngokuchanekileyo ukuze sifumane X (irejista yesalathisi) IPv4 ubude besihloko.

Ngoko ke kumgca wesi-7 sizama ukulayisha isiqingatha segama kulo (X+16). Ukukhumbula ukuba ii-bytes ze-14 zihlala kwi-header ye-Ethernet, kunye X iqulathe ubude bentloko ye IPv4, siyaqonda ukuba kwi A Indawo yokufikela ye-TCP ilayishiwe:

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

Ekugqibeleni, kumgca we-8 sithelekisa i-port yendawo kunye nexabiso elifunekayo kwaye kwimigca ye-9 okanye ye-10 sibuyisela umphumo - nokuba ukukopisha ipakethi okanye cha.

Tcpdump: iyalayisha

Kwimizekelo yangaphambili, asikhange sihlale neenkcukacha malunga nendlela esilayisha ngayo i-BPF bytecode kwi-kernel yokucoca ipakethe. Ukuthetha jikelele, tcpdump ifakwe kwiinkqubo ezininzi kunye nokusebenza ngezihluzi tcpdump usebenzisa ithala leencwadi libpcap. Ngokufutshane, ukubeka isihluzo kujongano usebenzisa libpcap, kufuneka wenze oku kulandelayo:

Ukubona indlela umsebenzi pcap_setfilter iphunyezwe kwiLinux, siyisebenzisa strace (eminye imigca 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
...

Kwimigca emibini yokuqala yemveliso esiyidalayo isiseko ekrwada ukufunda zonke izakhelo ze-Ethernet kwaye uyibophelele kujongano eth0. Ukusuka umzekelo wethu wokuqala Siyazi ukuba isihluzo ip iya kuba nemiyalelo emine ye-BPF, kwaye kumgca wesithathu sibona indlela yokusebenzisa ukhetho SO_ATTACH_FILTER inkqubo ifowuni setsockopt silayisha kwaye sidibanise isihluzo sobude 4. Esi sisihluzo sethu.

Kuyafaneleka ukuba uqaphele ukuba kwi-BPF yakudala, ukulayishwa kunye nokudibanisa isihluzi kuhlala kwenzeka njengomsebenzi we-athomu, kwaye kwinguqu entsha ye-BPF, ukulayisha inkqubo kunye nokuyibophelela kwi-generator yesiganeko iyahlukana ngexesha.

Inyaniso Efihliweyo

Uguqulelo olugqibelele ngakumbi lwemveliso lujongeka ngolu hlobo:

$ 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
...

Njengoko kukhankanyiwe ngasentla, silayisha kwaye siqhagamshele isihluzo sethu kwisiseko kumgca wesi-5, kodwa kwenzeka ntoni kumgca wesi-3 kunye no-4? Kuvela ukuba oku libpcap uyasikhathalela-ukuze imveliso yethu yokucoca ayibandakanyi iipakethi ezinganelisiyo, ithala leencwadi idibanisa isihluzo se-dummy ret #0 (zilahla zonke iipakethi), utshintshe i-socket kwimodi yokungathinteli kwaye uzama ukukhupha zonke iipakethi ezinokuthi zihlale kwiihluzo zangaphambili.

Lilonke, ukuhluza iipakethe kwi-Linux usebenzisa i-BPF yakudala, kufuneka ube necebo lokucoca ngendlela yesakhiwo esinje struct sock_fprog kunye nesokethi evulekileyo, emva koko isihluzo sinokudityaniswa kwisokethi usebenzisa umnxeba wenkqubo setsockopt.

Okubangela umdla kukuba, isihluzi sinokudityaniswa nakweyiphi na isiseko, hayi nje eluhlaza. Apha mzekelo inkqubo esika zonke kodwa ezimbini zokuqala bytes kuzo zonke ezingenayo datagram UDP. (Ndongeze izimvo kwikhowudi ukuze ndingafaki inqaku.)

Iinkcukacha ezingakumbi malunga nokusetyenziswa setsockopt ukudibanisa izihluzi, bona isiseko(7), kodwa malunga nokubhala ezakho izihluzi njenge struct sock_fprog ngaphandle koncedo tcpdump siza kuthetha kwicandelo Ukucwangcisa iBPF ngezandla zethu.

I-BPF ye-Classic kunye nenkulungwane yama-21

I-BPF yafakwa kwi-Linux ngo-1997 kwaye iye yahlala ingumsebenzi onzima ixesha elide libpcap ngaphandle kotshintsho olukhethekileyo (utshintsho lweLinux, kunjalo, babekho, kodwa abazange bawutshintshe umfanekiso wehlabathi). Iimpawu zokuqala ezinzulu zokuba i-BPF iza kuvela ngo-2011, xa u-Eric Dumazet wenza isiphakamiso isiqaqa, eyongeza Kanye Ngexesha Lomqokeleli kwi-kernel - umguquleli wokuguqula i-BPF bytecode kwimveli x86_64 ikhowudi.

I-JIT compiler yaba ngowokuqala kwikhonkco lotshintsho: kwi-2012 yavela ukukwazi ukubhala izihluzi ze secomp, usebenzisa i-BPF, ngoJanuwari 2013 kwakukho yongezwa imodyuli xt_bpf, ekuvumela ukuba ubhale imithetho ye iptables ngoncedo lwe-BPF, kwaye ngo-Oktobha 2013 yaba yongezwa nayo imodyuli cls_bpf, ekuvumela ukuba ubhale abahluli bezithuthi usebenzisa i-BPF.

Siza kujonga yonke le mizekelo kwiinkcukacha ezithe vetshe kungekudala, kodwa okokuqala kuya kuba luncedo kuthi ukuba sifunde indlela yokubhala kunye nokuqulunqa iinkqubo ezingafanelekanga ze-BPF, ekubeni amandla anikwe lithala leencwadi. libpcap mda (umzekelo olula: isihluzo senziwe libpcap inokubuyisela amaxabiso amabini kuphela - 0 okanye 0x40000) okanye ngokubanzi, njengakwimeko ye-seccomp, ayisebenzi.

Ukucwangcisa iBPF ngezandla zethu

Masikhe siqhelane nefomati yokubini yemiyalelo ye-BPF, ilula kakhulu:

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

Umyalelo ngamnye uthatha iibhithi ezingama-64, apho iibhithi zokuqala eziyi-16 ziyikhowudi yomyalelo, emva koko kukho ii-indent ezimbini ezisibhozo, jt ΠΈ jf, kunye namasuntswana angama-32 engxabano K, injongo yayo iyahluka ukusuka kumyalelo ukuya kumyalelo. Umzekelo, umyalelo ret, ephelisa inkqubo inekhowudi 6, kwaye ixabiso lokubuyisela lithathwa kwisigxina K. Kwi-C, umyalelo omnye we-BPF umelwe njengesakhiwo

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

kwaye yonke inkqubo ikwimo yesakhiwo

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

Ngaloo ndlela, sinokubhala iinkqubo (umzekelo, siyazazi iikhowudi zomyalelo [1]). Le yindlela isihluzo esiya kujongeka ngayo ip6 ΠΈΠ· umzekelo wethu wokuqala:

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,
};

inkqubo prog sinokusebenzisa ngokusemthethweni kwifowuni

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

Iiprogram zokubhala ngendlela yeekhowudi zoomatshini akulula kakhulu, kodwa ngamanye amaxesha kuyimfuneko (umzekelo, ukulungisa umonakalo, ukudala iimvavanyo zeyunithi, ukubhala amanqaku kwi-HabrΓ©, njl.). Ukuze kube lula, kwifayile <linux/filter.h> iimacros ezincedisayo zichazwa - umzekelo ofanayo nongasentla ungaphinda ubhalwe njenge

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),
}

Nangona kunjalo, olu khetho alufanelekanga kakhulu. Oku koko abadwelisi benkqubo be-Linux kernel baqiqe, kwaye ke kulawulo tools/bpf iikernels ungazifumana iassembler kunye nedebugger ekusebenzeni ngeBPF yakudala.

Ulwimi lweNdibano lufana kakhulu nokukhutshwa kwempazamo tcpdump, kodwa ukongeza sinokukhankanya iilebhile ezifuziselayo. Umzekelo, nantsi inkqubo ewisa zonke iipakethi 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

Ngokungagqibekanga, i-assembler yenza ikhowudi kwifomathi <количСство инструкций>,<code1> <jt1> <jf1> <k1>,..., umzekelo wethu kunye ne-TCP iya kuba

$ 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,

Ukwenzela lula abadwelisi benkqubo beC, ifomathi yemveliso eyahlukileyo ingasetyenziswa:

$ 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 unokukhutshelwa kuhlobo lwenkcazo yesakhiwo struct sock_filter, njengoko senzile ekuqaleni kweli candelo.

Linux kunye netsniff-ng izandiso

Ukongeza kwi-BPF eqhelekileyo, iLinux kunye tools/bpf/bpf_asm inkxaso kunye iseti engekho mgangathweni. Ngokusisiseko, imiyalelo isetyenziselwa ukufikelela kwimimandla yesakhiwo struct sk_buff, echaza ipakethe yenethiwekhi kwi-kernel. Nangona kunjalo, kukho nezinye iintlobo zemiyalelo yomncedisi, umzekelo ldw cpu iya kulayisha kwirejista A isiphumo sokusebenzisa umsebenzi we-kernel raw_smp_processor_id(). (Kwinguqulelo entsha ye-BPF, ezi zandiso ezingekho mgangathweni ziye zandiswa ukunika iinkqubo kunye neqela labancedisi bekernel ukufikelela kwimemori, izakhiwo, kunye neziganeko zokuvelisa.) Nanku umzekelo onika umdla wesihluzi apho sikhuphela kuphela iiheader zepakethe kwisithuba somsebenzisi usebenzisa ulwandiso poff, intlawulo yokuhlawula:

ld poff
ret a

Izandiso ze-BPF azinakusetyenziswa kwi tcpdump, kodwa esi sisizathu esilungileyo sokuqhelana nempahla eluncedo netsniff-ng, ethi, phakathi kwezinye izinto, iqulethe inkqubo ephambili netsniff-ng, leyo, ngaphezu kokucoca usebenzisa i-BPF, ikwaqulethe i-generator ye-traffic esebenzayo, kunye ne-advanced ngaphezu tools/bpf/bpf_asm, i-assembler ye-BPF yafowuna bpfc. Ipakethe iqulathe amaxwebhu aneenkcukacha, jonga namakhonkco ekupheleni kwenqaku.

secomp

Ngoko ke, sele siyayazi indlela yokubhala iinkqubo ze-BPF zobunzima obungenasizathu kwaye sikulungele ukujonga imizekelo emitsha, eyokuqala iteknoloji ye-seccomp, evumela, ngokusebenzisa izihluzi ze-BPF, ukulawula isethi kunye neseti yeengxoxo zokufowuna kwenkqubo ekhoyo inkqubo enikiweyo kunye nenzala yayo.

Inguqulelo yokuqala ye-seccomp yongezwa kwi-kernel ngo-2005 kwaye yayingadumanga kakhulu, kuba ibonelele ngokhetho olunye kuphela-ukunciphisa iseti yeefowuni zenkqubo ekhoyo kwinkqubo koku kulandelayo: read, write, exit ΠΈ sigreturn, kwaye inkqubo eyaphula imithetho yabulawa kusetyenziswa SIGKILL. Nangona kunjalo, ngo-2012, i-seccomp yongeza amandla okusebenzisa izihluzi ze-BPF, ekuvumela ukuba uchaze isethi yeefowuni ezivumelekileyo kwaye wenze iitshekhi kwiingxoxo zabo. (Okwenza umdla kukuba, i-Chrome yayingomnye wabasebenzisi bokuqala bolu sebenzi, kwaye abantu be-Chrome ngoku baphuhlisa indlela ye-KRSI esekelwe kuguqulelo olutsha lwe-BPF kunye nokuvumela ukulungiswa kweeModyuli zoKhuseleko ze-Linux.) Uqhagamshelwano kumaxwebhu olongezelelweyo angafumaneka ekugqibeleni yenqaku.

Qaphela ukuba sele kukho amanqaku kwi-hub malunga nokusebenzisa i-seccomp, mhlawumbi umntu uya kufuna ukuzifunda ngaphambili (okanye endaweni) ukufunda la macandelwana alandelayo. Kwinqaku Izikhongozeli kunye nokhuseleko: seccomp inikeza imizekelo yokusebenzisa i-seccomp, zombini inguqulo ye-2007 kunye noguqulelo olusebenzisa i-BPF (izihluzi zenziwe ngokusebenzisa i-libseccomp), uthetha malunga nokuxhunywa kwe-seccomp kunye ne-Docker, kwaye inika izixhumanisi ezininzi eziluncedo. Kwinqaku Ukwahlula iidaemon nge-systemd okanye "awuyidingi iDocker ngale nto!" Igubungela, ngokukodwa, indlela yokongeza uluhlu lwabamnyama okanye uluhlu olumhlophe lweefowuni zenkqubo yeedaemon eziqhuba i-systemd.

Okulandelayo siza kubona indlela yokubhala kunye nokulayisha izihluzo seccomp kuC kunye nokusebenzisa ithala leencwadi libseccomp kwaye yintoni inzuzo kunye neengozi zokhetho ngalunye, kwaye ekugqibeleni, makhe sibone indlela i-seccomp esetyenziswa ngayo yiprogram strace.

Ukubhala kunye nokulayisha izihluzi ze-seccomp

Sele siyayazi indlela yokubhala iinkqubo ze-BPF, ngoko ke masiqale sijonge ujongano lwenkqubo ye-seccomp. Ungacwangcisa icebo lokucoca kwinqanaba lenkqubo, kwaye zonke iinkqubo zomntwana ziya kudla ilifa izithintelo. Oku kwenziwa ngokusebenzisa umnxeba wenkqubo seccomp(2):

seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)

apho &filter - esi sisalathiso kwisakhiwo esele siqhelekile kuthi struct sock_fprog, okt. Inkqubo ye-BPF.

Zahluke njani iinkqubo zeseccomp kwiinkqubo zeesokethi? Umxholo ogqithisiweyo. Kwimeko yeesokethi, sinikwe indawo yememori equkethe ipakethi, kwaye kwimeko ye-seccomp sinikwe isakhiwo esifana neso.

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

kuyinto nr linani lendlela yokufowuna ekufuneka iqaliswe, arch -i-architecture yangoku (ngaphezulu koku ngezantsi), args - ukuya kwiingxoxo ezintandathu zokubiza inkqubo, kunye instruction_pointer sisalatha kumyalelo wesithuba somsebenzisi owenze umnxeba wenkqubo. Ngaloo ndlela, umzekelo, ukulayisha inombolo yefowuni yenkqubo kwirejista A kufuneka sitsho

ldw [0]

Kukho ezinye iimpawu zeenkqubo ze-seccomp, umzekelo, umxholo unokufikelelwa kuphela ngolungelelwaniso lwe-32-bit kwaye awukwazi ukulayisha isiqingatha segama okanye i-byte - xa uzama ukulayisha isihluzo. ldh [0] inkqubo ifowuni seccomp uya kubuya EINVAL. Umsebenzi ujonga izihluzo ezilayishiwe seccomp_check_filter() iinkozo. (Into ehlekisayo kukuba, kwisibophelelo sokuqala esongeze umsebenzi we-seccomp, balibale ukongeza imvume yokusebenzisa umyalelo kulo msebenzi. mod (intsalela yolwahlulo) kwaye ayifumaneki ngoku kwiinkqubo ze-seccomp ze-BPF, okoko yongezwayo iya kwaphuka ABI.)

Ngokusisiseko, sele sisazi yonke into ukubhala nokufunda iinkqubo ze-seccomp. Ngokuqhelekileyo ingqiqo yeprogram icwangciswa njengoluhlu olumhlophe okanye olumnyama lweefowuni zenkqubo, umzekelo inkqubo

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

ijonga uluhlu olumnyama lweefowuni ezine ezinenombolo 304, 176, 239, 279. Zeziphi ezi fowuni zenkqubo? Asinakutsho ngokuqinisekileyo, ekubeni singazi ukuba le nkqubo yabhalelwa luphi uhlobo lwezakhiwo. Ngoko ke, ababhali be-seccomp nikela qala zonke iinkqubo ngokhangelo lolwakhiwo (uyilo lwangoku lubonisiwe kumxholo njengendawo arch Isakhiwo struct seccomp_data). Xa ulwakhiwo lukhangelwe, isiqalo somzekelo siya kujongeka ngolu hlobo:

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

kwaye ke iinombolo zethu zokufowuna zesixokelelwano ziyakufumana amaxabiso athile.

Sibhala kwaye silayishe izihluzi zokusebenzisa i-seccomp libseccomp

Ukubhala izihluzi kwikhowudi yemveli okanye kwindibano ye-BPF ikuvumela ukuba ube nolawulo olupheleleyo kwisiphumo, kodwa kwangaxeshanye, ngamanye amaxesha kukhethwa ukuba ube nekhowudi ephathekayo kunye/okanye efundekayo. Ithala leencwadi liya kusinceda kule nto libseccomp, ebonelela ngojongano olusemgangathweni lokubhala izihluzi ezimnyama okanye ezimhlophe.

Makhe, umzekelo, sibhale inkqubo eqhuba ifayile yokubini ekhethwe ngumsebenzisi, sele ifake ngaphambili uluhlu olumnyama lwendlela yokufowuna evela. eli nqaku lingasentla (inkqubo yenziwe lula ukuze ifundeke ngakumbi, inguqulelo epheleleyo inokufumaneka apha):

#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 uluhlu sys_numbers of 40+ iinombolo umnxeba inkqubo ukubhloka. Emva koko, qalisa umxholo ctx kwaye sixelele ithala leencwadi into esifuna ukuyivumela (SCMP_ACT_ALLOW) zonke iifowuni zesixokelelwano ngokungagqibekanga (kulula ukwakha uluhlu lwabamnyama). Emva koko, nganye nganye, songeza zonke iifowuni zenkqubo ukusuka kuluhlu olumnyama. Ukuphendula umnxeba wenkqubo ovela kuluhlu, siyacela SCMP_ACT_TRAP, kule meko i-seccomp iya kuthumela umqondiso kwinkqubo SIGSYS ngenkcazo yokuba yeyiphi inkqubo yokufowunelwa eyaphule imigaqo. Ekugqibeleni, silayisha inkqubo kwi-kernel usebenzisa seccomp_load, eya kuqulunqa inkqubo kwaye incamathele kwinkqubo usebenzisa umnxeba wenkqubo seccomp(2).

Ukuze kuqulunqwe ngempumelelo, inkqubo kufuneka inxulunyaniswe nethala leencwadi libseccomp, umzekelo:

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

Umzekelo wosungulo oluyimpumelelo:

$ ./seccomp_lib echo ok
ok

Umzekelo wendlela yokufowuna evaliweyo:

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

Sisebenzisa stracengeenkcukacha:

$ 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 njani ukuba inkqubo yapheliswa ngenxa yokusetyenziswa kwefowuni yenkqubo engekho mthethweni mount(2).

Ke, sibhale isihluzo sisebenzisa ithala leencwadi libseccomp, ukufaka ikhowudi engancinci kwimigca emine. Kulo mzekelo ungentla, ukuba kukho inani elikhulu leefowuni zenkqubo, ixesha lokuphumeza lingancitshiswa ngokubonakalayo, ekubeni itshekhi luluhlu nje lokuthelekisa. Ukulungiselela, i-libseccomp isandula ukuba nayo isiziba sibandakanyiwe, eyongeza inkxaso yophawu lokucoca SCMP_FLTATR_CTL_OPTIMIZE. Ukucwangcisa olu phawu lwesi-2 kuyakuguqula isihluzo sibe yinkqubo yokukhangela yokubini.

Ukuba ufuna ukubona ukuba zisebenza njani izihluzi zophendlo zokubini, jonga iskripthi esilula, eyenza iinkqubo ezinjalo kwi-BPF assembler ngokucofa iinombolo zokufowuna zesistim, umzekelo:

$ 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

Akunakwenzeka ukuba ubhale nantoni na ngokukhawuleza, kuba iinkqubo ze-BPF azikwazi ukwenza ukutsiba kwe-indentation (asikwazi ukwenza, umzekelo, jmp A okanye jmp [label+X]) kwaye ke ngoko zonke iinguqu zimile.

i-seccomp kunye nomtya

Wonke umntu uyayazi into eluncedo strace sisixhobo esifunekayo sokufunda ukuziphatha kweenkqubo kwi Linux. Nangona kunjalo, abaninzi baye beva malunga imiba yokusebenza xa usebenzisa olu ncedo. Inyaniso kukuba strace isetyenziswe ngokusetyenziswa ptrace(2), kwaye kule ndlela asikwazi ukucacisa ukuba yeyiphi isethi yeefowuni zenkqubo esizifunayo ukuyeka inkqubo, oko kukuthi, umzekelo, imiyalelo.

$ 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

ziqhubekekiswa malunga nexesha elinye, nangona kwimeko yesibini sifuna ukulandelela umnxeba wenkqubo enye kuphela.

Inketho entsha --seccomp-bpf, yongezwe kwi strace inguqulo 5.3, ikuvumela ukuba ukhawulezise inkqubo amaxesha amaninzi kwaye ixesha lokuqalisa phantsi komkhondo wenkqubo enye yokufowuna sele ithelekiswa nexesha lokuqalisa rhoqo:

$ 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

(Apha, ewe, kukho ubuqhetseba obuncinci kuba asilandeli umnxeba wenkqubo ephambili yalo myalelo. Ukuba besilanda, umzekelo, newfsstat, ngoko strace yayiza kuqhawuka kabuhlungu nje ngaphandle --seccomp-bpf.)

Lusebenza njani olu khetho? Ngaphandle kwakhe strace idibanisa kwinkqubo kwaye iqala ukuyisebenzisa PTRACE_SYSCALL. Xa inkqubo elawulwayo ikhupha (nayiphi na) umnxeba wenkqubo, ulawulo lugqithiselwa strace, ejonga iingxoxo zendlela yokufowuna kwaye iqhube ngayo PTRACE_SYSCALL. Emva kwexesha elithile, inkqubo igqiba umnxeba wenkqubo kwaye xa uphuma kuyo, ulawulo ludluliselwa kwakhona strace, ejonga kumaxabiso embuyekezo kwaye iqale inkqubo isebenzisa PTRACE_SYSCALL, kwaye nangokunjalo.

I-BPF yabantwana abancinci, inxalenye ye-zero: i-BPF yakudala

Ngeseccomp, nangona kunjalo, le nkqubo inokulungiswa kanye njengoko singathanda. Oko kukuthi, ukuba sifuna ukujonga kuphela umnxeba wenkqubo X, emva koko sinokubhala i-BPF yokucoca oko X ibuyisela ixabiso SECCOMP_RET_TRACE, kunye neefowuni ezingenamdla kuthi - SECCOMP_RET_ALLOW:

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

Kule meko strace ekuqaleni iqala inkqubo njengoko PTRACE_CONT, isihluzi sethu siqhubekekiswa kumnxeba wenkqubo nganye, ukuba umnxeba wenkqubo awukho X, ke inkqubo iyaqhubeka ukusebenza, kodwa ukuba oku X, emva koko i-seccomp iyakudlulisa ulawulo straceeya kujonga iingxoxo kwaye iqale inkqubo njenge PTRACE_SYSCALL (kuba i-seccomp ingenakho ukukwazi ukuqhuba inkqubo ekuphumeni kwifowuni yenkqubo). Xa umnxeba wenkqubo ubuya, strace izakuphinda iqale inkqubo isebenzisa PTRACE_CONT kwaye izakulinda imiyalezo emitsha evela kwiseccomp.

I-BPF yabantwana abancinci, inxalenye ye-zero: i-BPF yakudala

Xa usebenzisa ukhetho --seccomp-bpf kukho izithintelo ezimbini. Okokuqala, ayizukwenzeka ukujoyina inkqubo esele ikhona (ukhetho -p kwenkqubo strace), kuba oku akuxhaswanga yi-seccomp. Okwesibini, akukho nokwenzeka hayi jonga kwiinkqubo zomntwana, kuba izihluzi ze-seccomp zifunyanwa njengelifa zizo zonke iinkqubo zomntwana ngaphandle kokukwazi ukukhubaza oku.

Iinkcukacha ezingakumbi malunga nendlela ngokuchanekileyo strace isebenza kunye seccomp ingafumaneka kwi ingxelo yakutshanje. Kuthi, eyona nto inomdla kakhulu kukuba i-BPF yakudala emelwe yi-seccomp isasetyenziswa nanamhlanje.

xt_bpf

Ngoku masibuyele kwihlabathi lothungelwano.

Imvelaphi: kwakudala, ngo-2007, undoqo wawukho yongezwa imodyuli xt_u32 yokucoca umnatha. Yabhalwa ngothelekiso kunye nodidi lwetrafikhi lwamandulo nangakumbi cls_u32 kwaye ikuvumele ukuba ubhale imithetho yokubini engavumelekanga yee-iptables usebenzisa le misebenzi ilula ilandelayo: layisha amasuntswana angama-32 ukusuka kwiphakheji kwaye wenze uluhlu lwemisebenzi ye-arithmetic kuzo. Umzekelo,

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

Ilayisha amasuntswana angama-32 eheader ye-IP, ukuqala kwi-padding 6, kwaye ifake imaski kubo. 0xFF (thatha i-byte ephantsi). Lo mmandla protocol Intloko ye-IP kwaye siyithelekisa ne-1 (ICMP). Unokudibanisa iitshekhi ezininzi kumgaqo omnye, kwaye unokwenza nomsebenzisi @ β€” yisa iibhayithi zika-X ekunene. Umzekelo, umthetho

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

ijonga ukuba inombolo ye-TCP yolandelelwano ayilingani 0x29. Andiyi kungena kwiinkcukacha ngakumbi, kuba sele kucacile ukuba ukubhala imithetho enjalo ngesandla akulula kakhulu. Kwinqaku I-BPF - i-bytecode elityelweyo, kukho amakhonkco amaninzi anemizekelo yokusetyenziswa kunye nolawulo lokwenziwa kwe xt_u32. Bona kwakhona amakhonkco ekupheleni kweli nqaku.

Ukusukela ngo-2013 imodyuli endaweni yemodyuli xt_u32 ungasebenzisa imodyuli esekwe kwi-BPF xt_bpf. Nabani na oye wafunda oku kude kufuneka sele ecacile malunga nomgaqo wokusebenza kwawo: sebenzisa i-BPF bytecode njengemithetho ye-iptables. Unokwenza umthetho omtsha, umzekelo, ngolu hlobo:

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

apha <Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄> - le yikhowudi kwifomati yemveliso ye assembler bpf_asm ngokungagqibekanga, umzekelo,

$ 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

Kulo mzekelo sihluza zonke iipakethi ze-UDP. Umxholo wenkqubo ye-BPF kwimodyuli xt_bpf, ngokuqinisekileyo, ikhomba kwidatha yepakethe, kwimeko ye-iptables, ekuqaleni kwentloko ye-IPv4. Ixabiso lokubuyisela kwiprogram ye-BPF booleanphi false ithetha ukuba ipakethi ayingqamani.

Kucacile ukuba imodyuli xt_bpf ixhasa izihluzi ezintsonkothileyo kunomzekelo ongentla. Makhe sijonge imizekelo yokwenyani evela kwi-Cloudfare. Kude kube ngoku bebesebenzisa imodyuli xt_bpf ukukhusela kuhlaselo lweDDoS. Kwinqaku Ukwazisa ngezixhobo zeBPF bachaza indlela (kwaye kutheni) bevelisa izihluzi ze-BPF kwaye bapapashe amakhonkco kwiseti yezinto eziluncedo zokudala ezo zihluzo. Ngokomzekelo, ukusebenzisa imveliso bpfgen ungenza inkqubo yeBPF ehambelana nombuzo weDNS 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

Kwinkqubo silayisha kuqala kwirejista X ukuqala kwedilesi yomgca x04habrx03comx00 ngaphakathi kwedathagram ye-UDP kwaye emva koko ujonge isicelo: 0x04686162 <-> "x04hab" njalo njalo.

Kancinci kamva, i-Cloudfare yapapasha i-p0f -> ikhowudi yomqokeleli we-BPF. Kwinqaku Ukwazisa umqokeleli we-p0f BPF Bathetha malunga nokuba yintoni i-p0f kunye nendlela yokuguqula iisignesha ze-p0f zibe 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,
...

Okwangoku ayisasebenzisi Cloudfare xt_bpf, ekubeni bafudukela kwi-XDP - enye yeenketho zokusebenzisa uguqulelo olutsha lwe-BPF, bona. L4Drop: XDP DDoS Mitigations.

cls_bpf

Umzekelo wokugqibela wokusebenzisa i-BPF yakudala kwi-kernel ngumdidi cls_bpf yenkqubo esezantsi yolawulo lwendlela eLinux, yongezwe kwiLinux ekupheleni kuka-2013 kwaye ithatha indawo yakudala. cls_u32.

Nangona kunjalo, ngoku asiyi kuchaza umsebenzi cls_bpf, ekubeni ukusuka kwindawo yokujonga ulwazi malunga ne-BPF yakudala oku akuyi kusinika nantoni na - sele siqhelana nayo yonke imisebenzi. Ukongeza, kumanqaku alandelayo athetha nge-BPF eyandisiweyo, siya kudibana nalo mdidi ngaphezu kwesinye.

Esinye isizathu sokungathethi malunga nokusebenzisa i-BPF yakudala c cls_bpf Ingxaki kukuba, xa kuthelekiswa ne-BPF eyandisiweyo, ububanzi bokusebenza kule meko buncitshiswe kakhulu: iinkqubo zeklasikhi azikwazi ukutshintsha imixholo yeepakethe kwaye azikwazi ukugcina imeko phakathi kweefowuni.

Lixesha lokuvalelisa kwi-BPF yakudala kwaye ujonge kwikamva.

Sala kakuhle kwiBPF yakudala

Sijonge indlela iteknoloji ye-BPF, ephuhliswe ngayo kwiminyaka yamashumi asithoba, iphile ngempumelelo kwikota yekhulu kwaye de kube sekupheleni kwafumana izicelo ezintsha. Nangona kunjalo, kufana nokutshintsha ukusuka koomatshini be-stack ukuya kwi-RISC, esebenze njengenkuthazo yokuphuhliswa kwe-BPF yakudala, ngo-32 kwakukho utshintsho olusuka kwi-64-bit ukuya kumatshini we-XNUMX-bit kunye ne-BPF yakudala yaqala ukuphelelwa yisikhathi. Ukongeza, amandla e-BPF yakudala anqongophele kakhulu, kwaye ukongeza kuyilo lwakudala - asinakho ukukwazi ukugcina urhulumente phakathi kweefowuni kwiinkqubo ze-BPF, akukho nto inokwenzeka yokusebenzisana ngokuthe ngqo komsebenzisi, akukho ndlela yokunxibelelana. nge-kernel, ngaphandle kokufunda inani eliqingqiweyo lemimandla yesakhiwo sk_buff kwaye usungula eyona misebenzi ilula yomncedisi, awukwazi ukutshintsha imixholo yeepakethi kwaye uziqondise kwakhona.

Ngapha koko, okwangoku yonke into eseleyo ye-BPF yakudala kwiLinux lujongano lwe-API, kwaye ngaphakathi kwekernel zonke iinkqubo zakudala, nokuba zizihluzi zesokethi okanye izihluzi ze-seccomp, ziguqulelwa ngokuzenzekelayo kwifomathi entsha, i-BPF eyandisiweyo. (Siza kuthetha ngendlela okwenzeka ngayo kanye oko kwinqaku elilandelayo.)

Utshintsho kwisakhiwo esitsha saqala ngo-2013, xa u-Alexey Starovoitov ecebisa iskimu sohlaziyo lwe-BPF. Kwi-2014 iipetshi ezihambelanayo yaqala ukubonakala embindini. Ngokokuqonda kwam, isicwangciso sokuqala yayikukwandisa kuphela ulwakhiwo kunye nomqokeleli we-JIT ukuba asebenze ngokufanelekileyo ngakumbi koomatshini be-64-bit, kodwa endaweni yoko olu lungiso lwaphawula ukuqala kwesahluko esitsha kuphuhliso lweLinux.

Amanqaku angaphaya kolu ngcelele aya kugubungela uyilo kunye nokusetyenziswa kwetekhnoloji entsha, eyayibizwa ngokuba yi-BPF yangaphakathi, emva koko i-BPF eyandisiweyo, kwaye ngoku yi-BPF nje.

iimbekiselo

  1. USteven McCanne kunye noVan Jacobson, "Isihluzo sePakethi yeBSD: Uyilo olutsha lwePacket Capture yenqanaba lomsebenzisi", https://www.tcpdump.org/papers/bpf-usenix93.pdf
  2. USteven McCanne, "i-libpcap: iNdlela yoLwakhiwo kunye neNdlela yokuPhucula iPacket Capture", https://sharkfestus.wireshark.org/sharkfest.11/presentations/McCanne-Sharkfest'11_Keynote_Address.pdf
  3. tcpdump, libpcap: https://www.tcpdump.org/
  4. IPtable U32 Match Tutorial.
  5. I-BPF-i-bytecode elityelweyo: https://blog.cloudflare.com/bpf-the-forgotten-bytecode/
  6. Ukwazisa ngesixhobo se-BPF: https://blog.cloudflare.com/introducing-the-bpf-tools/
  7. bpf_cls: http://man7.org/linux/man-pages/man8/tc-bpf.8.html
  8. Isishwankathelo esincinci: https://lwn.net/Articles/656307/
  9. https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
  10. habr: Izikhongozeli kunye nokhuseleko: seccomp
  11. habr: Ukwahlula iidaemon nge-systemd okanye "awuyidingi iDocker ngale nto!"
  12. UPaul Chaignon, "umtya --seccomp-bpf: ukujonga phantsi kwe-hood", https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
  13. netsniff-ng: http://netsniff-ng.org/

umthombo: www.habr.com

Yongeza izimvo