BPF ee kuwa yaryar, qayb eber: BPF caadiga ah

Berkeley Packet Filters (BPF) waa tignoolajiyada kernel-ka Linux oo ku jirtay boggaga hore ee daabacaadaha tignoolajiyada luqadda Ingiriisiga dhowr sano hadda. Shirarka waxaa ka buuxa warbixinno ku saabsan isticmaalka iyo horumarinta BPF. David Miller, ilaaliyeha shabakadaha shabakadaha Linux, wuxuu hadalkiisa ku wacay Linux Plumbers 2018 "Hadalkani maaha mid ku saabsan XDP" (XDP waa hal kiis oo la isticmaalo BPF). Brendan Gregg waxa uu bixinayaa wadahadal uu xaq u leeyahay Linux BPF Superpowers. Toke HΓΈiland-JΓΈrgensen qosolin kernelku hadda yahay microkernel. Thomas Graf wuxuu kor u qaadaa fikradda BPF waa javascript ee kernel-ka.

Weli ma jiro sharraxaad nidaamsan oo BPF ah oo ku saabsan HabrΓ©, sidaas darteed maqaallo taxane ah waxaan isku dayi doonaa inaan ka hadlo taariikhda tignoolajiyada, sharaxo qalabka dhismaha iyo horumarinta, oo aan qeexo meelaha codsiga iyo ku dhaqanka isticmaalka BPF. Maqaalkan, eber, ee taxanaha ah, wuxuu sheegayaa taariikhda iyo qaab dhismeedka BPF ee caadiga ah, sidoo kale wuxuu muujinayaa siraha mabaadi'da hawlgalka. tcpdump, seccomp, strace, iyo qaar kaloo badan.

Horumarinta BPF waxaa gacanta ku haya bulshada isku xirka Linux, codsiyada ugu weyn ee jira ee BPF waxay la xiriiraan shabakadaha, sidaas darteed, ogolaansho. @eucariot, Waxaan ugu yeeray taxanaha "BPF ee kuwa yaryar", oo lagu sharfayo taxanaha weyn "Shabakadaha carruurta yaryar".

Koorso gaaban oo taariikhda BPF ahc)

Tiknoolajiyada casriga ah ee BPF waa nooc la wanaajiyey oo la ballaariyey oo ah tignoolajiyada hore ee isla magaca, hadda loo yaqaan BPF classic si looga fogaado jahawareer. Utility si fiican loo yaqaan ayaa la sameeyay iyadoo lagu salaynayo BPF-ga caadiga ah tcpdump, farsamaynta seccomp, iyo sidoo kale qaybo yar oo la yaqaan xt_bpf si ay u iptables iyo kalasaar cls_bpf. Linux-ka casriga ah, barnaamijyada BPF-ga caadiga ah ayaa si toos ah loogu tarjumaa qaabka cusub, si kastaba ha ahaatee, marka laga eego aragtida isticmaalaha, API-gu wuu sii jirayaa iyo isticmaalka cusub ee BPF-ga caadiga ah, sida aan ku arki doono maqaalkan, weli waa la helayaa. Sababtan awgeed, iyo sidoo kale iyadoo la raacayo taariikhda horumarinta BPF ee Linux, waxay noqon doontaa mid cad sida iyo sababta ay u kobcisay qaabkeeda casriga ah, waxaan go'aansaday inaan ku bilaabo maqaal ku saabsan BPF-ga caadiga ah.

Dhammaadkii siddeetameeyadii qarnigii la soo dhaafay, injineerada ka socda Shaybaadhka caanka ah ee Lawrence Berkeley ayaa xiiseynaya su'aasha ah sida saxda ah ee loo shaandheeyo xirmooyinka shabakada ee qalabka casriga ah ee dabayaaqadii siddeetameeyadii qarnigii la soo dhaafay. Fikradda aasaasiga ah ee shaandhaynta, oo asal ahaan lagu hirgeliyay tignoolajiyada CSPF (CMU/Stanford Packet Filter), waxay ahayd in la shaandheeyo baakadaha aan loo baahnayn sida ugu dhaqsaha badan, i.e. meel bannaan oo kernel ah, maadaama tani ay ka fogaanayso in xogta aan loo baahnayn lagu koobiyeeyo booska isticmaalaha. Si loo helo badbaadada runtime ee ku socodsiinta koodka isticmaalaha booska kernel-ka, mashiinka farsamada gacanta ayaa la isticmaalay.

Si kastaba ha ahaatee, mishiinada casriga ah ee filtarrada jira waxaa loogu talagalay inay ku shaqeeyaan mishiinada ku salaysan is dulsaarka oo si hufan ugumay shaqayn mashiinada RISC ee cusub. Natiijo ahaan, iyada oo loo marayo dadaalka injineerada Berkeley Labs, tignoolajiyada cusub ee BPF (Berkeley Packet Filters) ayaa la sameeyay, qaab dhismeedka mashiinka farsamada kaas oo loo qaabeeyey iyadoo lagu saleynayo processor-ka Motorola 6502 - faraska shaqada ee alaabooyinka caanka ah sida Apple II ama NES. Mashiinka casriga ah ee cusub wuxuu kordhiyey waxqabadka shaandhada tobanaan jeer marka la barbar dhigo xalalka jira.

Nashqada mashiinka BPF

Waxaan u baran doonaa qaab-dhismeedka qaab shaqo, anagoo falanqaynayna tusaalooyinka. Si kastaba ha ahaatee, si aan ku bilowno, aynu nidhaahno mashiinku wuxuu lahaa laba diiwaan oo 32-bit ah oo ay heli karaan isticmaaluhu, accumulator. A iyo diiwaanka tusmada X. Tilmaamaha boodboodka ee hirgelinta tibaaxaha shuruudaha ayaa sidoo kale laga heli karaa barnaamijyada, laakiin si loo dammaanad qaado dhamaystirka wakhtiga barnaamijka, boodada waxaa la samayn karaa oo kaliya, tusaale ahaan, gaar ahaan, waxaa mamnuuc ah in la abuuro wareegyo.

Nidaamka guud ee bilaabista mishiinka waa sida soo socota. Isticmaaluhu wuxuu u abuuraa barnaamij qaab dhismeedka BPF iyo, isagoo isticmaalaya qaar habka kernel-ka (sida nidaamka wicista), wuxuu ku shubaa oo ku xidhaa barnaamijka qaarna koronto dhaliyaha ku jira kernel-ka (tusaale ahaan, dhacdo waa imaatinka xirmada xiga ee kaadhka shabakada). Marka ay dhacdo dhacdo, kernel-ku waxa uu wadaa barnaamijka (tusaale ahaan, turjumaanka), xusuusta mishiinkuna waxa ay u dhigantaa qaarna Gobolka xusuusta kernel (tusaale, xogta xirmada soo socota).

Kuwa kore ayaa nagu filnaan doona inaan bilowno fiirinta tusaalooyinka: waxaan baran doonaa nidaamka iyo qaabka amarka sida loo baahdo. Haddii aad rabto inaad si dhakhso ah u barato nidaamka amarka mashiinka farsamada oo aad wax ka barato dhammaan awoodaheeda, markaa waxaad akhrin kartaa maqaalka asalka ah Shaandhaynta Xirmada BSD iyo/ama qaybta hore ee faylka Dukumeenti/shabakad/filter.txt laga bilaabo dukumentiyada kernel-ka. Intaa waxaa dheer, waxaad baran kartaa bandhigga libpcapHabka Dhismaha iyo Wanaajinta ee Qabashada Xidhmada, kaas oo McCanne, oo ka mid ah qorayaasha BPF, uu kaga hadlayo taariikhda abuurista libpcap.

Hadda waxaan u dhaqaaqnay inaan tixgelinno dhammaan tusaalooyinka muhiimka ah ee isticmaalka BPF-ga caadiga ah ee Linux: tcpdump (libpcap), labaad, xt_bpf, cls_bpf.

tcpdump

Horumarinta BPF waxaa lagu fuliyay si la mid ah horumarinta hore ee shaandhaynta baakadaha - utility si fiican loo yaqaan. tcpdump. Iyo, maadaama kani yahay tusaalaha ugu da'da weyn uguna caansan ee isticmaalka BPF-ga caadiga ah, oo laga heli karo habab badan oo hawlgal ah, waxaan ku bilaabi doonaa daraasaddeena tignoolajiyada iyada.

(Waxaan ku orday dhammaan tusaalooyinka maqaalkan Linux 5.6.0-rc6. Soo saarida amarada qaar ayaa loo tafatiray si loo akhriyo si ka wanaagsan.)

Tusaale: la socoshada xirmooyinka IPv6

Aynu qiyaasno inaan rabno inaan eegno dhammaan baakadaha IPv6 ee interface-ka eth0. Si taas loo sameeyo waxaan socodsiin karnaa barnaamijka tcpdump oo leh filtar fudud ip6:

$ sudo tcpdump -i eth0 ip6

Sayidka tcpdump wuxuu ururiyaa filtarka ip6 geli BPF bytecode qaab dhismeedka oo u dir kernel-ka (eeg faahfaahinta qaybta Tcpdump: rarista). Filterka la raray waxaa loo maamuli doonaa baakad kasta oo dhexmarta interface-ka eth0. Haddii filtarku soo celiyo qiime aan eber ahayn n, ka dibna ilaa n Bayt ee xirmada waxaa lagu koobiyeynayaa booska isticmaalaha waxaana ku arki doonaa wax soo saarka tcpdump.

BPF ee kuwa yaryar, qayb eber: BPF caadiga ah

Waxaa soo baxday in aan si fudud u ogaan karno bytecode loo soo diray kernel-ka tcpdump iyadoo gacan laga helayo tcpdump, haddii aan ku maamulno ikhtiyaarka -d:

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

Eber khadka ah waxaan ku wadnaa amarka ldh [12], oo u taagan "load into record A nus kelmad (16 bits) oo ku yaala ciwaanka 12" su'aasha kaliya ayaa ah xasuus noocee ah ayaan ka hadlaynaa? Jawaabtu waa taas x bilaabmaa (x+1)th byte ee xirmada shabakada la falanqeeyay. Waxaan akhrinay baakado ka yimid interface Ethernet eth0, iyo kan macnaheedu waain baakidhku sidan u ekaado (fududnaanta, waxaanu u qaadanaynaa in aanay xidhmada ku jirin calaamado VLAN):

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

Markaa kadib fulinta amarka ldh [12] diiwaanka ku jira A waxaa jiri doona beer Ether Type - nooca baakooyinka lagu kala qaado qaabkan Ethernet. Sadarka 1 waxaan is barbar dhigeynaa waxa ku jira diiwaanka A (nooc xirmo) c 0x86dd, iyo kan waxaana jira Nooca aan xiiseyneyno waa IPV6. Sadarka 1, marka lagu daro amarka isbarbardhigga, waxaa jira laba tiir oo kale - jt 2 ΠΈ jf 3 - calaamado aad u baahan tahay inaad tagto haddii isbarbardhigga lagu guuleysto (A == 0x86dd) oo aan guulaysan. Sidaa darteed, kiis guuleysta (IPv6) waxaan u tagnaa safka 2, iyo kiis aan guulaysan - ilaa 3. Sadarka 3 barnaamijku wuxuu ku joojinayaa code 0 (ha koobiyn baakidhka), khadka 2 barnaamijku wuxuu ku joojinayaa koodka. 262144 (i koobbi ugu badnaan xirmo 256 kilobytes ah).

Tusaalo aad u adag: waxaan ku eegeynaa baakadaha TCP ee dekada loo socdo

Aynu aragno sida filtarku u eg yahay nuqullada dhammaan baakadaha TCP ee leh dekedda 666. Waxaan tixgelin doonaa kiiska IPV4, maadaama kiis IPV6 uu ka fudud yahay. Ka dib markaad barato tusaalahan, waxaad naftaada u sahamin kartaa shaandhada IPv6 sida jimicsi (ip6 and tcp dst port 666iyo shaandhaynta kiiska guud (tcp dst port 666). Haddaba, filtarka aanu xiisaynaynaa wuxuu u eg yahay sidan:

$ 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

Waxaan horey u ognahay waxa ay sameeyaan sadarrada 0 iyo 1. Sadarka 2 waxaan mar hore ku hubinnay in kani yahay xirmo IPv4 ah (Ether Type = 0x800) oo ku shub diiwaanka A 24th byte ee xirmada. Xidhmadayadu waxay u egtahay

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

taas oo macnaheedu yahay in aanu ku shubanay diiwaanka A goobta Protocol-ka ee cinwaanka IP-ga, taas oo macquul ah, sababtoo ah waxaan rabnaa in aan nuqul ka sameysanno kaliya xirmooyinka TCP. Waxaan is barbar dhignaa Protocol-ka 0x6 (IPPROTO_TCP) line 3.

Sadarka 4 iyo 5 waxaan ku shubnaa ereyada kala bar ee ku yaal ciwaanka 20 waxaana isticmaalnaa amarka jset hubi haddii mid ka mid ah saddexda la dhigay calanka - xidhashada maaskaro la soo saaray jset saddexda qaybood ee ugu muhiimsan waa la nadiifiyaa. Laba ka mid ah saddexda bits ayaa noo sheegaya in baakidhku yahay qayb ka mid ah baakidh IP ah oo jajaban, iyo haddii ay sidaas tahay, inay tahay jajabkii ugu dambeeyay. Qaybta saddexaad waa la xafiday waana inay eber noqotaa. Ma rabno inaan hubinno baakooyinka aan dhameystirneyn ama jaban, marka waxaan hubineynaa dhammaan seddexda jajab.

Sadarka 6 waa kan ugu xiisaha badan liiskan. Odhaahda ldxb 4*([14]&0xf) macneheedu waxa weeye in aanu galno diiwaanka X Afarta ugu yar ee baytka shan iyo tobnaad ee baakidhka lagu dhufto 4. Afarta ugu yar ee muhiimka ah ee byte shan iyo tobnaad waa garoonka Dhererka Madaxa Internetka Madaxa IPV4, kaas oo ku kaydiya dhererka madaxa ereyada, markaa waxaad u baahan tahay inaad ku dhufato 4. Waxa xiiso leh, odhaahda 4*([14]&0xf) waa habayn loogu talagalay qorshe ciwaan gaar ah oo loo isticmaali karo kaliya foomkan oo keliya diiwaan-gelinta X, i.e. midna ma dhihi karno ldb 4*([14]&0xf) iyo sidoo kale ldxb 5*([14]&0xf) (waxaanu qeexi karnaa kaliya dhimis ka duwan, tusaale ahaan, ldxb 4*([16]&0xf)). Way caddahay in nidaamkan wax ka qabashada lagu daray BPF si sax ah si loo helo X (diiwaanka tusmada) IPV4 dhererka madaxa.

Markaa safka 7 waxaan isku dayeynaa inaan ku shubno kelmad kala bar (X+16). Xusuusnow in 14 bytes uu ku jiro madaxa Ethernet, iyo X waxaa ku jira dhererka madaxa IPV4, waan fahamsanahay in A Deked u socota TCP waa la rartay:

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

Ugu dambeyntii, sadarka 8 waxaan isbarbar dhig ku sameyneynaa dekedda ku socota qiimaha la rabo iyo xariiqyada 9 ama 10 waxaan ku celineynaa natiijada - haddii la koobiyo baakidhka iyo haddii kale.

Tcpdump: rarista

Tusaalooyinka hore, gaar ahaan si faahfaahsan ugamaanaan hadlin sida saxda ah ee aan ugu shubno BPF bytecode kernel si loo shaandheeyo baakadaha. Guud ahaan, tcpdump loo gudbiyay habab badan iyo la shaqaynta filtarrada tcpdump adeegsada maktabadda libpcap. Si kooban, si aad shaandhada ugu dhejiso interface-ka adigoo isticmaalaya libpcap, waxaad u baahan tahay inaad sameyso waxyaabaha soo socda:

Si aad u aragto sida ay u shaqeyso pcap_setfilter lagu hirgeliyay Linux, waxaan isticmaalnaa strace (khadadka qaar waa la saaray):

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

Labada xariiq ee ugu horreeya ee wax soo saarka waxaan abuurnaa godad ceeriin si aad u akhrido dhammaan fiilooyinka Ethernet oo aad ku xidho interface-ka eth0. Ka Tusaalahayaga ugu horreeya waxaan ognahay in filtarka ip Waxay ka koobnaan doontaa afar tilmaamood oo BPF ah, iyo xariiqda saddexaad waxaan aragnaa sida loo isticmaalo ikhtiyaarka SO_ATTACH_FILTER nidaamka call setsockopt waanu ku shubnaa oo isku xidhaa filtar dhererkeedu yahay 4. Tani waa shaandhayntayada.

Waxaa xusid mudan in BPF-ga caadiga ah, rarista iyo isku xirka shaandhada ay had iyo jeer u dhacdo sida hawlgalka atomikada, iyo nooca cusub ee BPF, ku xidhida barnaamijka iyo ku xidhida koronto-dhaliyaha dhacdada ayaa la kala saaraa waqtiga.

Xaqiiqda Dahsoon

Nuqul ka yara dhammaystiran ee wax-soo-saarka ayaa u eg sidan:

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

Sida kor ku xusan, waxaan ku shubaneynaa oo ku xireynaa shaandhadayada godka 5-aad, laakiin maxaa ku dhacaya sadarrada 3 iyo 4? Waxaa soo baxday in tani libpcap na daryeela - si wax-soo-saarka shaandhayntayadu aanay ku jirin baakado aan ku qancin, maktabadda isku xira shaandhaynta dhumucda ret #0 (dhamaan baakadaha oo dhan), u beddela godka qaabka aan xannibin oo isku dayaa inuu ka gooyo dhammaan baakadaha ka hadhi kara filtarrada hore.

Isku soo wada duuboo, si aad u shaandhayso baakooyinka Linux adoo isticmaalaya BPF-ga caadiga ah, waxaad u baahan tahay inaad haysato shaandhayn qaab dhismeed ah oo kale ah struct sock_fprog iyo godad furan, ka dib shaandhada waxaa lagu dhejin karaa godka iyadoo la isticmaalayo nidaamka wicitaanka setsockopt.

Waxa xiiso leh, filtarka ayaa lagu dhejin karaa godad kasta, ma aha oo kaliya ceeriin. Halkan Tusaale barnaamij ka jaraya dhammaan marka laga reebo labada bytes ee ugu horreeya dhammaan xogta UDP ee soo socota. (Waxaan ku daray faallooyinka koodka si aysan u qasin maqaalka.)

Faahfaahin dheeraad ah oo ku saabsan isticmaalka setsockopt isku xirka filtarrada, eeg godka(7), laakiin ku saabsan qorista filtarradaada sida struct sock_fprog gargaar la'aan tcpdump waxaan kaga hadli doonaa qaybta Ku barnaamijyada BPF gacmaheena.

BPF Classic iyo qarnigii XNUMXaad

BPF waxaa lagu soo daray Linux 1997 waxayna sii ahaan jirtay faras shaqo muddo dheer libpcap iyada oo aan wax isbeddel ah oo gaar ah lahayn (isbeddellada Linux-gaar ah, dabcan, Waxa ay ahayd, laakiin ma aysan beddelin sawirka caalamiga ah). Calaamadihii ugu horreeyay ee halista ah ee BPF ay soo baxayso waxay yimaaddeen 2011, markii Eric Dumazet uu soo jeediyay balastar, kaas oo ku daraya Just In Time Compiler kernel-ka oo ah tarjumaha u beddelaya bytecode BPF x86_64 code.

Isku-duwaha JIT wuxuu ahaa kii ugu horreeyay ee silsiladda isbeddellada: 2012 muuqday kartida u qorida filtarrada seccop, iyadoo la adeegsanayo BPF, Janaayo 2013 waxaa jiray ku daray moduleka xt_bpf, kaas oo kuu ogolaanaya inaad u qorto xeerar iptables iyadoo la kaashanayo BPF, iyo October 2013 ahaa ku daray sidoo kale module ah cls_bpf, kaas oo kuu ogolaanaya inaad qorto kala-soocidda taraafikada adoo isticmaalaya BPF.

Waxaan eegi doonaa dhammaan tusaalooyinkan si faahfaahsan dhawaan, laakiin marka hore waxay noo noqon doontaa faa'iido inaan barano sida loo qoro oo loo ururiyo barnaamijyada aan sharciga ahayn ee BPF, maaddaama awoodaha ay bixiso maktabaddu libpcap xaddidan (tusaale fudud: filtar ayaa la sameeyay libpcap soo celin karaa oo kaliya laba qiyamka - 0 ama 0x40000) ama guud ahaan, sida kiiska seccomp, ma khuseyso.

Ku barnaamijyada BPF gacmaheena

Aynu barano qaabka binary ee tilmaamaha BPF, aad bay u fududahay:

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

Tilmaam kastaa wuxuu ka kooban yahay 64 bits, kaas oo 16-ka ugu horreeya ee XNUMX-bit ay yihiin koodhka tilmaamaha, ka dibna waxaa jira laba siddeed-bits, jt ΠΈ jf, iyo 32 bits ee doodda K, ujeeddaduna way ku kala duwan tahay amarka. Tusaale ahaan, amarka ret, kaas oo joojiya barnaamijka ayaa leh koodka 6, iyo qiimaha soo celinta waxaa laga soo qaatay joogtada ah K. C, hal tilmaam oo BPF ah ayaa u taagan qaab dhismeed ahaan

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

barnaamijka oo dhanna waa qaab dhismeed

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

Markaa, waxaan horeyba u qori karnaa barnaamijyada (tusaale ahaan, waxaan ka naqaanaa koodhadhka tilmaamaha [1]). Tani waa sida filtarku u ekaan doono ip6 ka Tusaalahayaga ugu horreeya:

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

barnaamijka prog Waxaan si sharci ah u isticmaali karnaa wicitaanka

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

Qoritaanka barnaamijyada qaab koodhadhka mashiinka maaha mid aad u habboon, laakiin mararka qaarkood waa lagama maarmaan (tusaale ahaan, qaladka, abuurista tijaabooyinka cutubka, qorista maqaallada HabrΓ©, iwm.). Si ku habboon, gudaha faylka <linux/filter.h> Macros caawiye ayaa la qeexay - tusaale la mid ah kan sare ayaa dib loo qori karaa sida

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

Si kastaba ha ahaatee, doorashadani maaha mid aad u habboon. Tani waa waxa ay ku sababeeyeen barnaamij-bixiyeyaasha kernel-ka Linux, oo markaa ku jira buugga tools/bpf kernels waxaad ka heli kartaa isku-duwaha iyo cilladaha si aad ula shaqeyso BPF-ga caadiga ah.

Luuqadda golaha waxa ay aad ula mid tahay soo saarista cilladaha tcpdump, laakiin marka lagu daro waxaan qeexi karnaa calaamado calaamad ah. Tusaale ahaan, halkan waa barnaamij daadiya dhammaan baakadaha marka laga reebo TCP/IPv4:

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

Sida caadiga ah, ururiyaha ayaa soo saaraya kood qaabka <количСство инструкций>,<code1> <jt1> <jf1> <k1>,..., tusaale ahaan TCP waxay noqon doontaa

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

Si ay ugu habboonaato barnaamijyada C, qaab wax soo saar oo kala duwan ayaa loo isticmaali karaa:

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

Qoraalkan waxa lagu koobiyn karaa qaabka qeexidda qaab-dhismeedka struct sock_filter, sidii aan ku samaynay bilowgii qaybtan.

Linux iyo netsniff-ng kordhinta

Intaa waxaa dheer BPF caadiga ah, Linux iyo tools/bpf/bpf_asm taageero iyo set aan caadi ahayn. Asal ahaan, tilmaamaha waxaa loo isticmaalaa in lagu galo goobaha dhismaha struct sk_buff, kaas oo qeexaya baakad shabakadeed oo ku jirta kernel. Si kastaba ha ahaatee, waxa kale oo jira noocyo kale oo tilmaamo caawiye ah, tusaale ahaan ldw cpu ku shubi doona diiwaanka A natiijada socodsiinta shaqada kernel raw_smp_processor_id(). (Nooca cusub ee BPF, kuwan kordhinta aan caadiga ahayn ayaa la kordhiyay si ay u bixiyaan barnaamijyo leh qalab caawiyayaasha kernel si ay u helaan xusuusta, qaababka, iyo dhacdooyinka soo saarista madax xirmo galay booska isticmaalaha isticmaalaya kordhinta poff, dhimista rarka:

ld poff
ret a

Kordhinta BPF looma isticmaali karo gudaha tcpdump, laakiin tani waa sabab wanaagsan oo lagu baran karo xirmada tamarta netsniff-ng, kaas oo, iyo waxyaabo kale, ka kooban yahay barnaamij horumarsan netsniff-ng, kaas oo, marka lagu daro shaandhaynta isticmaalaya BPF, sidoo kale ka kooban yahay dhaliye taraafikada wax ku ool ah, oo ka horumarsan marka loo eego tools/bpf/bpf_asm, isku-duwaha BPF ee loo yaqaan bpfc. Xirmada waxaa ku jira dukumeenti aad u faahfaahsan, sidoo kale eeg xiriirinta dhamaadka maqaalka.

seccop

Sidaa darteed, waxaan horeyba u ognahay sida loo qoro barnaamijyada BPF ee kakanaanta aan macquul ahayn waxayna diyaar u yihiin inay eegaan tusaalooyin cusub, marka hore waa tignoolajiyada seccomp, taas oo u oggolaanaysa, iyadoo la adeegsanayo filtarrada BPF, si loo maareeyo go'aanka iyo nidaamka doodaha wacitaanka ee la heli karo hab la siiyey iyo farcankiisa.

Nooca ugu horreeya ee seccomp waxaa lagu daray kernel 2005 oo aan caan ahayn, maadaama ay bixisay hal ikhtiyaar oo keliya - si loo xaddido wicitaannada nidaamka ee loo heli karo geeddi-socodka kuwan soo socda: read, write, exit ΠΈ sigreturn, iyo habka ku xadgudubka xeerarka waa la dilay iyadoo la adeegsanayo SIGKILL. Si kastaba ha noqotee, 2012, seccomp wuxuu ku daray awoodda isticmaalka filtarrada BPF, taasoo kuu oggolaaneysa inaad qeexdo go'an wicitaannada nidaamka la oggol yahay oo xitaa sameyso hubinno doodooda. (Waxa xiiso leh, Chrome wuxuu ahaa mid ka mid ah isticmaalayaasha ugu horreeya ee shaqadan, dadka Chrome-ka waxay hadda horumarinayaan habka KRSI ee ku salaysan nooca cusub ee BPF iyo u oggolaanaya habeynta Modules Security Linux.) Xiriirinta dukumeenti dheeraad ah ayaa laga heli karaa dhamaadka ee maqaalka.

Ogsoonow in ay jireen maqaallo ku saabsan xuddunta oo ku saabsan isticmaalka seccomp, laga yaabee in qof doonayo inuu akhriyo ka hor (ama halkii) akhrinta qaybaha soo socda. In maqaalka Konteenarada iyo amniga: seccomp waxay bixisaa tusaalooyin isticmaalka seccomp, labadaba nooca 2007 iyo nooca iyadoo la adeegsanayo BPF (filiyaasha waxaa la soo saaray iyadoo la adeegsanayo libseccomp), waxay ka hadlaysaa isku xirka seccomp ee Docker, iyo sidoo kale waxay bixisaa xiriiro badan oo faa'iido leh. In maqaalka Go'doominta daemons-ka leh systemd ama "Uma baahnid Docker kan!" Waxay dabooshaa, gaar ahaan, sida loogu daro liiska madow ama liisaska cad ee wicitaanada nidaamka daemons ee ku shaqeeya systemd.

Marka xigta waxaan arki doonaa sida loo qoro oo loo raro filtarrada seccomp oo qaawan C iyo isticmaalka maktabadda libseccomp iyo waa maxay faa'iidooyinka iyo khasaaraha ikhtiyaar kasta, iyo ugu dambeyntii, aan aragno sida seccomp loo isticmaalo barnaamijka strace.

Qorista iyo rarista filtarrada ee seccomp

Waxaan hore u naqaannay sida loo qoro barnaamijyada BPF, marka aan marka hore eegno barnaamijka seccomp interface interface. Waxaad dejin kartaa shaandhada heerka habsocodka, dhammaan hababka ilmahu waxay dhaxli doonaan xannibaadaha. Tan waxaa lagu sameeyaa iyadoo la isticmaalayo nidaamka wicitaanka seccomp(2):

seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)

halkaas oo &filter - tani waxay tilmaan u tahay qaab-dhismeedkii horeba aannu naqaannay struct sock_fprog, i.e. Barnaamijka BPF.

Sidee bay barnaamijyada seccomp uga duwan yihiin barnaamijyada saldhigyada? Macnaha la kala qaado. Dhinaca saldhigyada, waxa nala siiyay meel xusuus ah oo baakidhku ku jiro, halka seccomp-na nala siiyay qaab dhismeed oo kale ah.

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

waa nr waa lambarka nidaamka wicitaanka ee la bilaabayo, arch - qaab dhismeedka hadda (wax badan oo ku saabsan kan hoose), args - ilaa lix hab dood call, iyo instruction_pointer waa tilmaame tilmaame booska isticmaalaha kaas oo sameeyay wicitaanka nidaamka. Sidaas darteed, tusaale ahaan, si aad ugu shubto nambarka wac nidaamka diiwaanka A waa inaan dhahnaa

ldw [0]

Waxaa jira sifooyin kale oo loogu talagalay barnaamijyada seccomp, tusaale ahaan, macnaha guud waxaa lagu geli karaa oo keliya 32-bit alignment mana awoodid inaad ku shubto nus kelmad ama byte - markaad isku dayeyso inaad rarayso shaandhada ldh [0] nidaamka call seccomp soo laaban doona EINVAL. Shaqadu waxay hubisaa filtarrada raran seccomp_check_filter() kernels. (Arrinta qosolka leh ayaa ah, ballan-qaadkii asalka ahaa ee ku daray shaqeynta seccomp, waxay illoobeen inay ku daraan oggolaanshaha si ay u adeegsadaan tilmaamaha shaqadan mod (qaybinta hadhaaga) oo hadda lama heli karo barnaamijyada seccomp BPF, tan iyo markii lagu daray jabi doona ABI.)

Asal ahaan, waxaan horay u naqaanay wax walba oo lagu qoro oo aan akhriyo barnaamijyada seccomp. Caadi ahaan macquulka barnaamijka waxaa loo habeeyaa sida liiska cad ama madow ee wicitaanada nidaamka, tusaale ahaan barnaamijka

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

Wuxuu hubiyaa liiska madow ee afar hab oo la wacay oo lambarkiisu yahay 304, 176, 239, 279. Waa maxay wicitaannada nidaamkan? Dhab ahaan ma odhan karno, maadaama aynaan garanayn naqshadda barnaamijka loo qoray. Sidaa darteed, qorayaasha seccomp bixinta ku bilow dhammaan barnaamijyada adiga oo ku eegaya qaab-dhismeedka (nashqadaha hadda jira waxa lagu tilmaamay goob ahaan arch dhismayaasha struct seccomp_data). Iyada oo la hubiyay qaab-dhismeedka, bilowga tusaaluhu wuxuu u ekaan lahaa:

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

ka dibna nambarada wicitaanka nidaamkayaga waxay heli lahaayeen qiyam gaar ah.

Waxaan qornaa oo ku shubnaa filtarrada si loo isticmaalo seccomp libseccomp

Qorista filtarrada ee koodka asalka ah ama golaha BPF wuxuu kuu ogolaanayaa inaad si buuxda u maamusho natiijada, laakiin isla mar ahaantaana, waxaa mararka qaarkood la door bidaa inaad haysato kood la qaadi karo iyo/ama la akhriyi karo. Maktabadu waxay naga caawin doontaa tan libseccomp, kaas oo bixiya interface caadiga ah ee qorista filtarrada madow ama caddaanka ah.

Aynu, tusaale ahaan, qorno barnaamij socodsiiya faylka binary ee xulashada isticmaaluhu, isagoo hore ugu rakibay liis madow oo wicitaannada nidaamka ah maqaalka kore (barnaamijka waa la fududeeyay si loo akhriyo, nooca buuxa waa la heli karaa halkan):

#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]);
}

Marka hore waxaynu qeexnaa array sys_numbers oo ah 40+ nambarada wicitaanka nidaamka si loo xannibo. Kadib, bilow macnaha guud ctx oo u sheeg maktabadda waxaan rabno inaan u oggolaano (SCMP_ACT_ALLOW) Dhammaan wicitaanada nidaamka habaysan (waa ay fududahay in la dhiso liisaska madow). Kadib, mid mid, waxaan ku darnaa dhammaan wicitaanada nidaamka ee liiska madow. Annaga oo ka jawaabayna nidaamka wicitaanka liiska, waxaan codsaneynaa SCMP_ACT_TRAPXaaladdan oo kale seccomp ayaa calaamad u soo diri doonta habka SIGSYS iyada oo sharraxaad ka bixinaysa nidaamka wicitaanku jabiyay xeerarka. Ugu dambeyntii, waxaan ku shubnaa barnaamijka kernel-ka anagoo adeegsanayna seccomp_load, kaas oo ururin doona barnaamijka oo ku lifaaqi doona habka adoo isticmaalaya nidaamka wicitaanka seccomp(2).

Isku-dubbarid guul leh, barnaamijka waa in lagu xidhaa maktabadda libseccomp, tusaale ahaan:

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

Tusaalaha bilaabista guusha leh:

$ ./seccomp_lib echo ok
ok

Tusaalaha wicitaanka nidaamka xiran:

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

Waxaan isticmaalnaa straceFaahfaahinta:

$ 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

sidee ku ogaan karnaa in barnaamijkii la joojiyay iyadoo la adeegsanayo hab-raac sharci-darro ah mount(2).

Markaa, waxaanu ku qornay shaandhada anagoo adeegsanayna maktabadda libseccomp, ku dhejinta koodka aan fududayn afar sadar. Tusaalaha kore, haddii ay jiraan tiro badan oo wicitaanno nidaam ah, waqtiga fulinta ayaa si muuqata loo dhimi karaa, maadaama jeeggu yahay kaliya liiska isbarbardhigga. Hagaajinta, libseccomp ayaa dhawaan lahayd balastar lagu daray, kaas oo ku daraya taageerada sifada shaandhada SCMP_FLTATR_CTL_OPTIMIZE. Dejinta sifadan 2 waxay u rogi doontaa shaandhada barnaamijka raadinta binary.

Haddii aad rabto inaad aragto sida filtarrada raadinta binary u shaqeeyaan, eeg qoraal fudud, kaas oo ka soo saara barnaamijyada noocaan ah isku-duwaha BPF isagoo garaacaya nambarada wicitaanka nidaamka, tusaale ahaan:

$ 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

Suurtagal maaha in si degdeg ah wax loo qoro, maadaama barnaamijyada BPF aysan samayn karin boodada boodboodka (ma samayn karno, tusaale ahaan, jmp A ama jmp [label+X]) oo sidaas darteed dhammaan isbeddellada ayaa ah kuwo taagan.

seccomp iyo xadhig

Qof kastaa wuu yaqaan utility strace waa qalab lagama maarmaan u ah barashada hab-dhaqanka hababka Linux. Si kastaba ha ahaatee, qaar badan ayaa sidoo kale maqlay arrimaha waxqabadka marka la isticmaalayo utility this. Xaqiiqdu waxay tahay strace la hirgeliyey iyadoo la isticmaalayo ptrace(2), iyo habkan kuma qeexi karno nooca nidaamka wicitaanada waxaan u baahanahay inaan joojino habka, tusaale ahaan, amarrada

$ 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

Waxa la farsameeyaa ku dhawaad ​​isku wakhti, in kasta oo kiiska labaad aanu doonayno in aanu raad raacno hal wicitaan oo keliya.

Doorasho cusub --seccomp-bpf, lagu daray strace Nooca 5.3, wuxuu kuu ogolaanayaa inaad dardar geliso geeddi-socodka marar badan iyo wakhtiga bilowga ee hoos yimaada raadraaca hal wicitaan oo horeyba u dhigma wakhtiga bilowga caadiga ah:

$ 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

(Halkan, dabcan, waxaa jira khiyaano yar oo ah inaanan raadinayn nidaamka ugu muhiimsan ee amarkan. Haddii aan raadinaynay, tusaale ahaan, newfsstat, ka dibna strace jabi lahaa si la mid ah sida la'aanta --seccomp-bpf.)

Sidee doorashadani u shaqeysaa? La'aanteed strace wuxuu ku xiraa habka oo uu ku bilaabo isticmaalka PTRACE_SYSCALL. Marka habka la maareeyay uu soo saaro (mid kasta) wicitaanka nidaamka, xakamaynta ayaa loo wareejiyaa strace, kaas oo eegaya doodaha nidaamka wicitaanka oo ku shaqeeya isticmaalka PTRACE_SYSCALL. Muddo ka dib, nidaamku wuxuu dhamaystiraa wicitaanka nidaamka iyo marka laga baxo, xakamaynta ayaa mar kale la wareejiyaa strace, kaas oo eegaya qiyamka soo noqoshada oo bilaabaya habka isticmaalaya PTRACE_SYSCALL, iyo wixi la mida.

BPF ee kuwa yaryar, qayb eber: BPF caadiga ah

Si kastaba ha ahaatee, seccomp, si kastaba ha ahaatee, habkan waxaa loo hagaajin karaa sida aan rabno. Tusaale ahaan, haddii aan rabno inaan eegno kaliya wac nidaamka X, markaas waxaan u qori karnaa shaandhada BPF taas oo loogu talagalay X soo celisa qiimaha SECCOMP_RET_TRACE, iyo baaqyo aan dan noo ahayn - SECCOMP_RET_ALLOW:

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

Xaaladdan strace marka hore waxay ku bilaabataa habka PTRACE_CONT, filter our waxaa loo habeeyey loogu talagalay wicitaan kasta oo nidaamka, haddii wicitaanka nidaamka ma aha X, ka dibna geeddi-socodku wuu sii socdaa, laakiin haddii tani X, ka dibna seccomp ayaa wareejin doona xakamaynta straceKaas oo eegi doona doodaha oo bilaabi doona habka sida PTRACE_SYSCALL (maadaama seccomp aanu lahayn awood uu ku socodsiiyo barnaamij ka bixitaanka nidaamka call). Marka nidaamka wicitaanku soo noqdo, strace dib u bilaabi doona habsocodka isticmaalaya PTRACE_CONT waxayna sugi doonaan fariimaha cusub ee seccomp.

BPF ee kuwa yaryar, qayb eber: BPF caadiga ah

Marka la isticmaalayo ikhtiyaarka --seccomp-bpf waxaa jira laba xayiraad. Marka hore, suurtogal ma noqon doonto in lagu biiro hanaan hore u jiray (ikhtiraac -p barnaamijyada strace), mar haddii tani aysan taageerin seccomp. Marka labaad, ma jirto wax suurtagal ah ma U fiirso hababka ilmaha, maadaama filtarrada seccomp ay dhaxlaan dhammaan hababka ilmaha iyaga oo aan awood u lahayn inay tan joojiyaan.

Faahfaahin yar oo ku saabsan sida saxda ah strace la shaqee seccomp waxaa laga heli karaa warbixin dhawaan. Annaga, xaqiiqda ugu xiisaha badan ayaa ah in BPF-ga caadiga ah ee uu matalo seccomp wali la isticmaalo maanta.

xt_bpf

Aynu hadda ku noqonno dunida shabakadaha.

Sooyaalka: wakhti dheer ka hor, 2007, xudunta u ahayd ku daray moduleka xt_u32 netfilter. Waxa loo qoray si isbarbardhig leh oo xitaa ka sii qadiimi ah kala soocida taraafikada cls_u32 wuxuuna kuu oggolaaday inaad u qorto xeerarka binary-ga ee iptables adigoo isticmaalaya hawlgalladan fudud ee soo socda: 32-bits ka soo qaado xirmo oo ku samee tiro hawlgallo xisaabeed ah. Tusaale ahaan,

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

Waxay ku shubtaa 32-bit ee madaxa IP-ga, ka bilaabma suufka 6, oo ku dabaqaa maaskaro iyaga 0xFF (qaado byte hoose). Garoonkan protocol Cinwaanka IP-ga waxaanu barbar dhignaa 1 (ICMP). Waxaad isku dari kartaa jeegag badan hal xeer, waxaad sidoo kale fulin kartaa hawlwadeenka @ - U dhaqaaq X bytes dhanka midig. Tusaale ahaan, qaanuunka

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

hubi haddii Lambarka Taxanaha TCP aanu sinnayn 0x29. Faahfaahin dheeraad ah ma gelin doono, maadaama ay horeba u caddaatay in qorista xeerarkan oo kale aysan ahayn mid aad u habboon. In maqaalka BPF - bytecode la illoobay, waxaa jira dhowr xiriiriye oo leh tusaalooyin isticmaalka iyo jiilka qaanuunka xt_u32. Sidoo kale eeg xiriirinta dhamaadka maqaalkan.

Tan iyo 2013 module halkii module xt_u32 waxaad isticmaali kartaa BPF module ah xt_bpf. Qof kasta oo ilaa hadda akhriyay waa inuu hore u caddeeyaa mabda'a hawlgalkiisa: ku socodsii BPF bytecode sida xeerarka iptables. Waxaad abuuri kartaa xeer cusub, tusaale ahaan, sida tan:

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

halkan <Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄> - kani waa koodka qaabka wax soo saarka ururiyaha bpf_asm sida caadiga ah, tusaale ahaan,

$ 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

Tusaalahan waxaan ku shaandheyneynaa dhammaan baakadaha UDP. Macnaha guud ee barnaamijka BPF ee cutubka xt_bpf, Dabcan, waxay tilmaamaysaa xogta baakidhka, marka la eego iptables, bilawga madaxa IPV4. Ka soo celi qiimaha barnaamijka BPF booliyanhalkaas oo false macneheedu waa baakidhku isma toosin.

Waxaa cad in moduleka xt_bpf waxay taageertaa filtarrada ka adag tusaalaha kore. Aynu eegno tusaalooyin dhab ah oo ka yimid Cloudfare. Ilaa dhawaan waxay isticmaaleen moduleka xt_bpf si looga ilaaliyo weerarada DDoS. In maqaalka Soo bandhigida Aaladaha BPF waxay sharxayaan sida (iyo sababta) ay u abuuraan filtarrada BPF oo ay u daabacaan xiriirinta qalabyo kala duwan oo loogu talagalay abuurista filtarradaas. Tusaale ahaan, adigoo isticmaalaya utility bpfgen waxaad samayn kartaa barnaamij BPF ah oo ku habboon weydiinta DNS ee magaca 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

Barnaamijka waxaan marka hore gelinaa diiwaanka X bilawga ciwaanka khadka x04habrx03comx00 gudaha UDP datagram ka dibna hubi codsiga: 0x04686162 <-> "x04hab" iyo wixii la mid ah.

Wax yar ka dib, Cloudfare ayaa daabacday p0f -> koodhka isku xidhka BPF. In maqaalka Soo bandhigida isku xidhka p0f BPF waxay ka hadlaan waxa p0f yahay iyo sida loogu badalo saxeexyada p0f 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,
...

Hadda ma isticmaaleyso Cloudfare xt_bpf, tan iyo markii ay u guureen XDP - mid ka mid ah fursadaha isticmaalka nooca cusub ee BPF, fiiri. L4Drop: XDP DDoS Yaraynta.

cls_bpf

Tusaalaha ugu dambeeya ee isticmaalka BPF-ga caadiga ah ee kernelka waa kala soocida cls_bpf nidaamka hoosaadka taraafikada ee Linux, oo lagu daray Linux dhamaadkii 2013 oo fikrad ahaan bedelaya kii hore cls_u32.

Si kastaba ha ahaatee, hadda ma qeexi doono shaqada cls_bpf, Tan iyo markii laga eego aragtida aqoonta ku saabsan BPF-ga caadiga ah tani waxba naguma siin doonto - waxaan horeyba u barannay dhammaan shaqeynta. Intaa waxaa dheer, maqaallada soo socda ee ka hadlaya Extended BPF, waxaan la kulmi doonaa kala-soociddan in ka badan hal mar.

Sabab kale oo aan looga hadlin isticmaalka caadiga ah ee BPF c cls_bpf Dhibaatadu waxay tahay, marka la barbar dhigo Extended BPF, baaxadda ku habboonaanta kiiskan si weyn ayaa loo soo koobay: barnaamijyada qadiimiga ah ma beddeli karaan waxa ku jira xirmooyinka mana badbaadin karaan gobolka u dhexeeya wicitaannada.

Markaa waa waqtigii lagu macsalaamayn lahaa BPF-ga caadiga ah oo la eegi lahaa mustaqbalka.

Nabadgelyo BPF-ga caadiga ah

Waxaan eegnay sida tignoolajiyada BPF, oo la sameeyay horraantii sagaashamaadkii, si guul leh u noolaatay rubuc qarni iyo ilaa dhamaadka laga helay codsiyo cusub. Si kastaba ha ahaatee, waxay la mid tahay ka gudubka mishiinada qashinka ilaa RISC, kaas oo u adeegay sidii dhiirigelinta horumarinta BPF-ga caadiga ah, 32-meeyadii waxaa jiray isbeddel ka yimid 64-bit ilaa XNUMX-bit machines iyo BPF-ga caadiga ah waxay bilaabeen inay noqdaan kuwo duugoobay. Intaa waxaa dheer, awoodaha BPF ee caadiga ah aad ayey u xaddidan yihiin, marka lagu daro qaab dhismeedka duugoobay - ma lihin awood aan ku badbaadino gobolka u dhexeeya wicitaannada barnaamijyada BPF, ma jirto suurtogalnimada isdhexgalka tooska ah ee isticmaalaha, ma jirto wax suurtagal ah oo isdhexgalka. la kernel-ka, marka laga reebo akhrinta tiro xaddidan ee goobaha qaab-dhismeedka sk_buff iyo bilaabista hawlaha caawiye ee ugu fudud, ma bedeli kartid waxa ku jira baakadaha oo dib u habayn kartid.

Dhab ahaantii, hadda waxa haray oo dhan BPF-ga caadiga ah ee Linux waa interface API, iyo gudaha kernel dhammaan barnaamijyada caadiga ah, ha ahaadaan filtarrada godka ama filtarrada seccomp, ayaa si toos ah loogu tarjumay qaab cusub, BPF Dheeraad ah. (Waxaan uga hadli doonaa sida saxda ah ee ay tani u dhacdo maqaalka soo socda.)

U gudubka qaab dhismeedka cusub wuxuu bilaabmay 2013, markii Alexey Starovoitov soo jeediyay nidaamka cusboonaysiinta BPF. 2014-ka balastar u dhigma bilaabay inuu soo muuqdo xudunta u ah. Ilaa hadda inta aan fahmayo, qorshaha asalka ah wuxuu ahaa kaliya in la hagaajiyo qaab-dhismeedka iyo isku-dariyeyaasha JIT si ay si hufan ugu shaqeeyaan mashiinnada 64-bit, laakiin taa beddelkeeda hagaajintaani waxay calaamad u tahay bilowga cutub cusub oo horumarinta Linux ah.

Maqaalo dheeri ah oo taxanahan ah ayaa dabooli doona qaab dhismeedka iyo codsiyada tignoolajiyada cusub, oo markii hore loo yaqaan BPF gudaha, ka dibna BPF la kordhiyay, oo hadda si fudud BPF.

tixraacyada

  1. Steven McCanne iyo Van Jacobson, "Shandhaynta Xirmada BSD: Nashqada Cusub ee Xidhmada Heerka Adeegsiga", https://www.tcpdump.org/papers/bpf-usenix93.pdf
  2. Steven McCanne, "libpcap: Habka Dhismaha iyo Wanaajinta ee Qabashada Xidhmada", 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. BPF - bytecode-ka la iloobay: https://blog.cloudflare.com/bpf-the-forgotten-bytecode/
  6. Soo bandhigida Qalabka BPF: https://blog.cloudflare.com/introducing-the-bpf-tools/
  7. bpf_cls: http://man7.org/linux/man-pages/man8/tc-bpf.8.html
  8. Dulmar ilbiriqsi: https://lwn.net/Articles/656307/
  9. https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
  10. habr: Haamaha iyo ammaanka: seccomp
  11. habr: Go'doomin daemons leh systemd ama "Uma baahnid Docker kan!"
  12. Paul Chaignon, "strace --seccomp-bpf: fiiri daboolka hoostiisa", https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
  13. netsniff-ng: http://netsniff-ng.org/

Source: www.habr.com

Add a comment