BPF għaż-żgħar, parti żero: BPF klassika

Berkeley Packet Filters (BPF) hija teknoloġija Linux kernel li ilha fuq il-faċċata tal-pubblikazzjonijiet tat-teknoloġija tal-lingwa Ingliża għal bosta snin issa. Il-konferenzi huma mimlija b'rapporti dwar l-użu u l-iżvilupp tal-BPF. David Miller, il-mantenitur tas-subsistema tan-netwerk Linux, isejjaħ it-taħdita tiegħu fil-Linux Plumbers 2018 "Din it-taħdita mhix dwar XDP" (XDP huwa każ ta' użu wieħed għal BPF). Brendan Gregg jagħti taħditiet intitolati Linux BPF Superpotenzi. Toke Høiland-Jørgensen jidħakli l-qalba issa hija mikrokernel. Thomas Graf jippromwovi l-idea li BPF huwa javascript għall-qalba.

Għad m'hemm l-ebda deskrizzjoni sistematika ta 'BPF fuq Habré, u għalhekk f'serje ta' artikli se nipprova nitkellem dwar l-istorja tat-teknoloġija, niddeskrivi l-arkitettura u l-għodod ta 'żvilupp, u niddeskrivi l-oqsma ta' applikazzjoni u prattika tal-użu ta 'BPF. Dan l-artikolu, żero, fis-serje, jirrakkonta l-istorja u l-arkitettura tal-BPF klassika, u jiżvela wkoll is-sigrieti tal-prinċipji operattivi tiegħu. tcpdump, seccomp, strace, u ħafna aktar.

L-iżvilupp ta 'BPF huwa kkontrollat ​​mill-komunità tan-netwerking Linux, l-applikazzjonijiet ewlenin eżistenti ta' BPF huma relatati man-netwerks u għalhekk, bil-permess @eucariota, Sejjaħt is-serje "BPF għaż-żgħar", f'ġieħ is-serje kbira "Netwerks għaż-żgħar".

Kors qasir fl-istorja tal-BPF(c)

It-teknoloġija moderna tal-BPF hija verżjoni mtejba u estiża tat-teknoloġija l-antika bl-istess isem, issa msejħa BPF klassika biex tiġi evitata l-konfużjoni. Inħolqot utilità magħrufa bbażata fuq il-BPF klassika tcpdump, mekkaniżmu seccomp, kif ukoll moduli inqas magħrufa xt_bpf għall- iptables u klassifikatur cls_bpf. Fil-Linux modern, programmi BPF klassiċi huma awtomatikament tradotti fil-forma l-ġdida, madankollu, mil-lat tal-utent, l-API baqgħet f'postha u użi ġodda għal BPF klassika, kif se naraw f'dan l-artikolu, għadhom qed jinstabu. Għal din ir-raġuni, u wkoll minħabba li wara l-istorja tal-iżvilupp tal-BPF klassiku fil-Linux, se jsir aktar ċar kif u għaliex evolviet fil-forma moderna tiegħu, iddeċidejt li nibda b'artiklu dwar BPF klassiku.

Fl-aħħar tas-snin tmenin tas-seklu li għadda, inġiniera mill-Laboratorju famuż Lawrence Berkeley saru interessati fil-kwistjoni ta 'kif jiffiltraw sew il-pakketti tan-netwerk fuq ħardwer li kien modern fl-aħħar tas-snin tmenin tas-seklu li għadda. L-idea bażika tal-filtrazzjoni, oriġinarjament implimentata fit-teknoloġija CSPF (CMU/Stanford Packet Filter), kienet li jiġu ffiltrati pakketti mhux meħtieġa kmieni kemm jista 'jkun, i.e. fl-ispazju tal-kernel, peress li dan jevita li tikkopja data mhux meħtieġa fl-ispazju tal-utent. Biex tipprovdi sigurtà runtime għat-tħaddim tal-kodiċi tal-utent fl-ispazju tal-kernel, intużat magna virtwali sandboxed.

Madankollu, il-magni virtwali għall-filtri eżistenti kienu ddisinjati biex jaħdmu fuq magni bbażati fuq munzell u ma ħadmux b'mod effiċjenti fuq magni RISC aktar ġodda. Bħala riżultat, permezz tal-isforzi tal-inġiniera minn Berkeley Labs, ġiet żviluppata teknoloġija ġdida BPF (Berkeley Packet Filters), li l-arkitettura tal-magni virtwali tagħha kienet iddisinjata bbażata fuq il-proċessur Motorola 6502 - il-workhorse ta 'prodotti magħrufa bħal dawn Apple II jew NES. Il-magna virtwali l-ġdida żiedet il-prestazzjoni tal-filtru għexieren ta 'darbiet meta mqabbla ma' soluzzjonijiet eżistenti.

Arkitettura tal-magni BPF

Aħna se jiffamiljarizzaw ruħhom mal-arkitettura b'mod ta 'ħidma, janalizzaw eżempji. Madankollu, biex tibda, ejja ngħidu li l-magna kellha żewġ reġistri 32-bit aċċessibbli għall-utent, akkumulatur A u reġistru tal-indiċi X, 64 bytes ta 'memorja (16-il kelma), disponibbli għall-kitba u qari sussegwenti, u sistema żgħira ta' kmandi biex taħdem ma 'dawn l-oġġetti. L-istruzzjonijiet tal-qabża għall-implimentazzjoni ta 'espressjonijiet kondizzjonali kienu wkoll disponibbli fil-programmi, iżda biex jiggarantixxu t-tlestija f'waqtha tal-programm, il-qbiż setgħu jsiru biss 'il quddiem, jiġifieri, b'mod partikolari, kien ipprojbit li jinħolqu loops.

L-iskema ġenerali għall-bidu tal-magna hija kif ġej. L-utent joħloq programm għall-arkitettura BPF u, bl-użu xi wħud mekkaniżmu tal-qalba (bħal sejħa tas-sistema), jgħabbi u jgħaqqad il-programm lil xi wħud lill-ġeneratur tal-avvenimenti fil-qalba (per eżempju, avveniment huwa l-wasla tal-pakkett li jmiss fuq il-karta tan-netwerk). Meta jseħħ avveniment, il-kernel imexxi l-programm (pereżempju, f'interpretu), u l-memorja tal-magna tikkorrispondi għal lil xi wħud reġjun tal-memorja tal-kernel (per eżempju, data ta 'pakkett li jkun dieħel).

Dan ta 'hawn fuq se jkun biżżejjed biex nibdew inħarsu lejn l-eżempji: aħna se nkunu familjari mas-sistema u l-format tal-kmand kif meħtieġ. Jekk trid tistudja immedjatament is-sistema ta 'kmand ta' magna virtwali u titgħallem dwar il-kapaċitajiet kollha tagħha, allura tista 'taqra l-artiklu oriġinali Il-Filtru tal-Pakkett BSD u/jew l-ewwel nofs tal-fajl Dokumentazzjoni/netwerking/filter.txt mid-dokumentazzjoni tal-kernel. Barra minn hekk, tista 'tistudja l-preżentazzjoni libpcap: Metodoloġija ta' Arkitettura u Ottimizzazzjoni għall-Qbid ta' Pakketti, li fiha McCanne, wieħed mill-awturi ta 'BPF, titkellem dwar l-istorja tal-ħolqien libpcap.

Issa nkomplu nikkunsidraw l-eżempji sinifikanti kollha tal-użu tal-BPF klassiku fuq Linux: tcpdump (libpcap), seccomp, xt_bpf, cls_bpf.

tcpdump

L-iżvilupp tal-BPF sar b'mod parallel mal-iżvilupp tal-frontend għall-iffiltrar tal-pakketti - utilità magħrufa sew tcpdump. U, peress li dan huwa l-eqdem u l-aktar eżempju famuż ta 'użu ta' BPF klassika, disponibbli fuq ħafna sistemi operattivi, aħna se nibdew l-istudju tagħna tat-teknoloġija magħha.

(Għamejt l-eżempji kollha f'dan l-artikolu fuq Linux 5.6.0-rc6. L-output ta’ xi kmandi ġie editjat għal leġibilità aħjar.)

Eżempju: osservazzjoni ta' pakketti IPv6

Ejja nimmaġinaw li rridu nħarsu lejn il-pakketti IPv6 kollha fuq interface eth0. Biex nagħmlu dan nistgħu nħaddmu l-programm tcpdump b'filtru sempliċi ip6:

$ sudo tcpdump -i eth0 ip6

F'dan il-każ, tcpdump jikkompila l-filtru ip6 fil-bytecode tal-arkitettura BPF u ibgħatha lill-kernel (ara d-dettalji fit-taqsima Tcpdump: tagħbija). Il-filtru mgħobbi se jitħaddem għal kull pakkett li jgħaddi mill-interface eth0. Jekk il-filtru jirritorna valur mhux żero n, imbagħad sa n bytes tal-pakkett se jiġu kkupjati fl-ispazju tal-utent u narawha fl-output tcpdump.

BPF għaż-żgħar, parti żero: BPF klassika

Jirriżulta li nistgħu faċilment insibu liema bytecode intbagħat lill-kernel tcpdump bl-għajnuna tal- tcpdump, jekk inħaddmu bl-għażla -d:

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

Fuq il-linja żero nħaddmu l-kmand ldh [12], li tirrappreżenta “load into register A nofs kelma (16-il bit) li tinsab fl-indirizz 12” u l-unika mistoqsija hija x’tip ta’ memorja qed nindirizzaw? It-tweġiba hija li fi x jibda (x+1)th byte tal-pakkett tan-netwerk analizzat. Naqraw pakketti mill-interface Ethernet eth0, u dan ifisserli l-pakkett jidher bħal dan (għal sempliċità, nassumu li m'hemm l-ebda tikketti VLAN fil-pakkett):

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

Allura wara li tesegwixxi l-kmand ldh [12] fir-reġistru A se jkun hemm għalqa Ether Type — it-tip ta' pakkett trażmess f'dan il-qafas Ethernet. Fuq il-linja 1 inqabblu l-kontenut tar-reġistru A (tip ta' pakkett) c 0x86dd, u dan u għandhom It-tip li aħna interessati fih huwa IPv6. Fuq il-linja 1, minbarra l-kmand tat-tqabbil, hemm żewġ kolonni oħra - jt 2 и jf 3 — marki li għalihom trid tmur jekk il-paragun jirnexxi (A == 0x86dd) u mingħajr suċċess. Allura, f'każ ta 'suċċess (IPv6) immorru għal-linja 2, u f'każ li ma rnexxiex - għal-linja 3. Fuq il-linja 3 il-programm jintemm bil-kodiċi 0 (ma tikkopja l-pakkett), fuq il-linja 2 il-programm jintemm bil-kodiċi 262144 (kopjani massimu ta' pakkett ta' 256 kilobytes).

Eżempju aktar ikkumplikat: inħarsu lejn pakketti TCP skont il-port tad-destinazzjoni

Ejja naraw kif jidher filtru li jikkopja l-pakketti TCP kollha bil-port tad-destinazzjoni 666. Se nikkunsidraw il-każ IPv4, peress li l-każ IPv6 huwa aktar sempliċi. Wara li tistudja dan l-eżempju, tista' tesplora l-filtru IPv6 lilek innifsek bħala eżerċizzju (ip6 and tcp dst port 666) u filtru għall-każ ġenerali (tcp dst port 666). Allura, il-filtru li aħna interessati fih jidher bħal dan:

$ 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

Diġà nafu x'jagħmlu l-linji 0 u 1. Fuq il-linja 2 diġà vverifikajna li dan huwa pakkett IPv4 (Ether Type = 0x800) u tagħbijaha fir-reġistru A 24 byte tal-pakkett. Il-pakkett tagħna jidher

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

li jfisser li aħna tagħbija fir-reġistru A il-qasam tal-Protokoll tal-header tal-IP, li huwa loġiku, għaliex irridu nikkopjaw biss pakketti TCP. Aħna nqabblu Protokoll ma 0x6 (IPPROTO_TCP) fuq il-linja 3.

Fuq il-linji 4 u 5 aħna tagħbija n-nofs kliem li jinsabu fl-indirizz 20 u nużaw il-kmand jset iċċekkja jekk wieħed mit-tlieta huwiex issettjat bnadar - liebes il-maskra maħruġa jset it-tliet bits l-aktar sinifikanti huma kklerjati. Tnejn mit-tliet bits jgħidulna jekk il-pakkett huwiex parti minn pakkett IP frammentat, u jekk iva, jekk huwiex l-aħħar framment. It-tielet bit huwa riżervat u għandu jkun żero. Ma rridux niċċekkjaw pakketti mhux kompluti jew imkissrin, għalhekk niċċekkjaw it-tliet bits.

Linja 6 hija l-aktar interessanti f'din il-lista. Espressjoni ldxb 4*([14]&0xf) ifisser li aħna tagħbija fir-reġistru X l-inqas erba 'bits sinifikanti tal-ħmistax-il byte tal-pakkett immultiplikat b'4. L-inqas erba' bits sinifikanti tal-ħmistax-il byte huwa l-field Tul tal-Intestatura tal-Internet Header IPv4, li jaħżen it-tul tal-header fi kliem, għalhekk imbagħad ikollok bżonn timmultiplika b'4. Interessanti, l-espressjoni 4*([14]&0xf) hija nomina għal skema ta' indirizzar speċjali li tista' tintuża biss f'din il-formola u għal reġistru biss X, i.e. ma nistgħux ngħidu lanqas ldb 4*([14]&0xf) u lanqas ldxb 5*([14]&0xf) (nistgħu biss nispeċifikaw offset differenti, pereżempju, ldxb 4*([16]&0xf)). Huwa ċar li din l-iskema ta 'indirizzar ġiet miżjuda ma' BPF preċiżament sabiex tirċievi X (reġistru tal-indiċi) Tul tal-header IPv4.

Allura fuq il-linja 7 nippruvaw tagħbija nofs kelma fuq (X+16). Ftakar li 14 bytes huma okkupati mill-header Ethernet, u X fih it-tul tal-header IPv4, nifhmu li fi A Il-port tad-destinazzjoni TCP huwa mgħobbi:

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

Fl-aħħarnett, fuq il-linja 8 inqabblu l-port tad-destinazzjoni mal-valur mixtieq u fuq il-linji 9 jew 10 nirritornaw ir-riżultat - jekk nikkopja l-pakkett jew le.

Tcpdump: tagħbija

Fl-eżempji ta 'qabel, aħna speċifikament ma noqogħdux fid-dettall dwar eżattament kif tagħbija BPF bytecode fil-qalba għall-iffiltrar tal-pakketti. B'mod ġenerali, tcpdump portabbli għal ħafna sistemi u għal xogħol bil-filtri tcpdump juża l-librerija libpcap. Fil-qosor, biex tpoġġi filtru fuq interface bl-użu libpcap, trid tagħmel dan li ġej:

Biex tara kif il-funzjoni pcap_setfilter implimentati fil-Linux, nużaw strace (xi linji tneħħew):

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

Fuq l-ewwel żewġ linji ta 'output noħolqu sokit mhux maħdum biex taqra l-frejms Ethernet kollha u torbotha mal-interface eth0. Minn l-ewwel eżempju tagħna nafu li l-filtru ip se jikkonsisti minn erba 'struzzjonijiet BPF, u fuq it-tielet linja naraw kif tuża l-għażla SO_ATTACH_FILTER sejħa tas-sistema setsockopt aħna tagħbija u qabbad filtru ta 'tul 4. Dan huwa filtru tagħna.

Ta 'min jinnota li fil-BPF klassika, it-tagħbija u l-konnessjoni ta' filtru dejjem iseħħ bħala operazzjoni atomika, u fil-verżjoni l-ġdida ta 'BPF, it-tagħbija tal-programm u l-irbit mal-ġeneratur tal-avvenimenti huma separati fil-ħin.

Verità Moħbija

Verżjoni kemmxejn aktar kompleta tal-output tidher bħal din:

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

Kif imsemmi hawn fuq, aħna tagħbija u qabbad il-filtru tagħna mas-sokit fuq il-linja 5, imma x'jiġri fuq il-linji 3 u 4? Jirriżulta li dan libpcap jieħu ħsiebna - sabiex l-output tal-filtru tagħna ma jinkludix pakketti li ma jissodisfawx, il-librerija jgħaqqad filtru finta ret #0 (Waqqa 'l-pakketti kollha), jaqleb is-sokit għal mod li ma jimblokkax u jipprova jnaqqas il-pakketti kollha li jistgħu jibqgħu mill-filtri preċedenti.

B'kollox, biex tiffiltra pakketti fuq Linux billi tuża BPF klassika, jeħtieġ li jkollok filtru fil-forma ta' struttura bħal struct sock_fprog u sokit miftuħ, wara li l-filtru jista 'jitwaħħal mas-sokit bl-użu ta' sejħa tas-sistema setsockopt.

Interessanti, il-filtru jista 'jitwaħħal ma' kwalunkwe sokit, mhux biss mhux maħdum. Hawn eżempju programm li jaqta' l-bytes kollha ħlief l-ewwel żewġ bytes mid-datagrams UDP kollha li jidħlu. (Żidt kummenti fil-kodiċi biex ma nħammx l-artiklu.)

Aktar dettalji dwar l-użu setsockopt għall-konnessjoni tal-filtri, ara sokit (7), iżda dwar il-kitba tal-filtri tiegħek simili struct sock_fprog mingħajr għajnuna tcpdump nitkellmu fit-taqsima Nipprogrammaw BPF bl-idejn tagħna stess.

BPF klassiku u s-seklu 21

BPF ġie inkluż fil-Linux fl-1997 u baqa' żiemel tax-xogħol għal żmien twil libpcap mingħajr ebda tibdil speċjali (bidliet speċifiċi għal Linux, ovvjament, Konna, iżda ma bidlux l-istampa globali). L-ewwel sinjali serji li BPF se jevolvi ġew fl-2011, meta Eric Dumazet ippropona garża, li żżid Just In Time Compiler mal-qalba - traduttur għall-konverżjoni tal-bytecode BPF għal indiġeni x86_64 kodiċi.

Il-kompilatur JIT kien l-ewwel fil-katina tal-bidliet: fl-2012 deher abbiltà li tikteb filtri għal seccomp, bl-użu ta 'BPF, f'Jannar 2013 kien hemm miżjud modulu xt_bpf, li jippermettilek tikteb regoli għal iptables bl-għajnuna tal-BPF, u f’Ottubru 2013 kien miżjud wkoll modulu cls_bpf, li jippermettilek tikteb klassifikaturi tat-traffiku billi tuża BPF.

Aħna ser inħarsu lejn dawn l-eżempji kollha f'aktar dettall dalwaqt, iżda l-ewwel ikun utli għalina li nitgħallmu kif niktbu u niġbru programmi arbitrarji għal BPF, peress li l-kapaċitajiet ipprovduti mil-librerija libpcap limitat (eżempju sempliċi: filtru ġġenerat libpcap jista 'jirritorna biss żewġ valuri - 0 jew 0x40000) jew ġeneralment, bħal fil-każ ta' seccomp, mhumiex applikabbli.

Nipprogrammaw BPF bl-idejn tagħna stess

Ejja niffamiljarizzaw ruħhom mal-format binarju tal-istruzzjonijiet BPF, huwa sempliċi ħafna:

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

Kull istruzzjoni tokkupa 64 bit, li fihom l-ewwel 16-il bit huma l-kodiċi tal-istruzzjoni, allura hemm żewġ inċiżi ta 'tmien bit, jt и jf, u 32 bit għall-argument K, li l-iskop tiegħu jvarja minn kmand għal kmand. Per eżempju, il-kmand ret, li jtemm il-programm għandu l-kodiċi 6, u l-valur tar-ritorn jittieħed mill-kostanti K. F'Ċ, istruzzjoni BPF waħda hija rappreżentata bħala struttura

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

u l-programm kollu huwa fil-forma ta 'struttura

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

Għalhekk, nistgħu diġà niktbu programmi (per eżempju, nafu l-kodiċi tal-istruzzjoni minn [1]). Dan huwa kif se jidher il-filtru ip6 ta ' l-ewwel eżempju tagħna:

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

programm prog nistgħu nużaw legalment f'sejħa

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

Il-kitba ta 'programmi fil-forma ta' kodiċi tal-magni mhix konvenjenti ħafna, iżda xi drabi hija meħtieġa (pereżempju, għad-debugging, il-ħolqien ta 'testijiet tal-unità, il-kitba ta' artikli fuq Habré, eċċ.). Għall-konvenjenza, fil-fajl <linux/filter.h> helper macros huma definiti - l-istess eżempju bħal hawn fuq jista 'jinkiteb mill-ġdid bħala

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

Madankollu, din l-għażla mhix konvenjenti ħafna. Dan huwa dak li l-programmaturi tal-kernel tal-Linux irraġunaw, u għalhekk fid-direttorju tools/bpf qlub tista 'ssib assembler u debugger biex taħdem ma' BPF klassika.

Il-lingwa tal-assemblaġġ hija simili ħafna għall-output tad-debug tcpdump, iżda barra minn hekk nistgħu nispeċifikaw tikketti simboliċi. Pereżempju, hawn programm li jwaqqa' l-pakketti kollha ħlief TCP/IPv4:

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

B'mod awtomatiku, l-assemblatur jiġġenera kodiċi fil-format <количество инструкций>,<code1> <jt1> <jf1> <k1>,..., għall-eżempju tagħna ma 'TCP se jkun

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

Għall-konvenjenza tal-programmaturi C, jista 'jintuża format ta' output differenti:

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

Dan it-test jista' jiġi kkupjat fid-definizzjoni tal-istruttura tat-tip struct sock_filter, kif għamilna fil-bidu ta’ din it-taqsima.

Linux u estensjonijiet netsniff-ng

Minbarra BPF standard, Linux u tools/bpf/bpf_asm appoġġ u sett mhux standard. Bażikament, l-istruzzjonijiet jintużaw biex jaċċessaw l-oqsma ta 'struttura struct sk_buff, li jiddeskrivi pakkett tan-netwerk fil-qalba. Madankollu, hemm ukoll tipi oħra ta 'struzzjonijiet helper, pereżempju ldw cpu se jgħabbi fir-reġistru A riżultat tat-tħaddim ta' funzjoni tal-qalba raw_smp_processor_id(). (Fil-verżjoni l-ġdida ta' BPF, dawn l-estensjonijiet mhux standard ġew estiżi biex jipprovdu programmi b'sett ta' helpers tal-kernel biex jaċċessaw memorja, strutturi, u jiġġeneraw avvenimenti.) Hawn hu eżempju interessanti ta' filtru li fih nikkopjaw biss il- headers tal-pakketti fl-ispazju tal-utent bl-użu tal-estensjoni poff, offset tat-tagħbija:

ld poff
ret a

L-estensjonijiet tal-BPF ma jistgħux jintużaw tcpdump, iżda din hija raġuni tajba biex issir familjari mal-pakkett ta 'utilità netsniff-ng, li, fost affarijiet oħra, fih programm avvanzat netsniff-ng, li, minbarra l-filtrazzjoni bl-użu ta 'BPF, fih ukoll ġeneratur tat-traffiku effettiv, u aktar avvanzat minn tools/bpf/bpf_asm, assemblatur BPF imsejjaħ bpfc. Il-pakkett fih dokumentazzjoni pjuttost dettaljata, ara wkoll il-links fl-aħħar tal-artikolu.

seccomp

Għalhekk, aħna diġà nafu kif niktbu programmi BPF ta 'kumplessità arbitrarja u lesti li nħarsu lejn eżempji ġodda, l-ewwel waħda minnhom hija t-teknoloġija seccomp, li tippermetti, bl-użu ta' filtri BPF, li timmaniġġja s-sett u s-sett ta 'argumenti tas-sejħa tas-sistema disponibbli għal proċess partikolari u d-dixxendenti tiegħu.

L-ewwel verżjoni ta 'seccomp ġiet miżjuda mal-kernel fl-2005 u ma kinitx popolari ħafna, peress li pprovdiet biss għażla waħda - biex tillimita s-sett ta' sejħiet tas-sistema disponibbli għal proċess għal dan li ġej: read, write, exit и sigreturn, u l-proċess li kiser ir-regoli nqatel bl-użu SIGKILL. Madankollu, fl-2012, seccomp żied il-kapaċità li juża filtri BPF, li jippermettilek tiddefinixxi sett ta 'sejħiet ta' sistema permessi u anke twettaq kontrolli fuq l-argumenti tagħhom. (Interessanti, Chrome kien wieħed mill-ewwel utenti ta 'din il-funzjonalità, u n-nies tal-Chrome bħalissa qed jiżviluppaw mekkaniżmu KRSI ibbażat fuq verżjoni ġdida ta' BPF u li jippermetti l-adattament tal-Moduli tas-Sigurtà Linux.) Links għal dokumentazzjoni addizzjonali jistgħu jinstabu fl-aħħar. tal-artikolu.

Innota li diġà kien hemm artikli fuq il-hub dwar l-użu tas-seccomp, forsi xi ħadd ikun irid jaqrahom qabel (jew minflok) jaqra s-subsezzjonijiet li ġejjin. Fl-artiklu Kontenituri u sigurtà: seccomp jipprovdi eżempji tal-użu tas-seccomp, kemm il-verżjoni tal-2007 kif ukoll il-verżjoni li tuża BPF (il-filtri huma ġġenerati bl-użu tal-libseccomp), titkellem dwar il-konnessjoni tas-seccomp ma 'Docker, u tipprovdi wkoll ħafna links utli. Fl-artiklu L-iżolament tad-daemons b'systemd jew "m'għandekx bżonn Docker għal dan!" Dan ikopri, b'mod partikolari, kif iżżid listi suwed jew whitelists ta' sejħiet tas-sistema għal daemons li jħaddmu systemd.

Sussegwentement naraw kif tikteb u tagħbija filtri għal seccomp f'C bare u bl-użu tal-librerija libseccomp u x'inhuma l-vantaġġi u l-iżvantaġġi ta 'kull għażla, u finalment, ejja naraw kif seccomp jintuża mill-programm strace.

Kitba u tagħbija filtri għal seccomp

Diġà nafu kif niktbu programmi BPF, allura ejja l-ewwel inħarsu lejn l-interface tal-ipprogrammar seccomp. Tista 'tissettja filtru fil-livell tal-proċess, u l-proċessi tfal kollha jirtu r-restrizzjonijiet. Dan isir bl-użu ta' sejħa tas-sistema seccomp(2):

seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)

fejn &filter - dan huwa punter għal struttura diġà familjari għalina struct sock_fprog, i.e. programm BPF.

Kif ivarjaw programmi għal seccomp minn programmi għas-sokits? Kuntest trażmess. Fil-każ tas-sockets, ingħatajna żona tal-memorja li fiha l-pakkett, u fil-każ tas-seccomp ingħatajna struttura bħal

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

Hawnhekk nr huwa n-numru tas-sejħa tas-sistema li għandha titnieda, arch - arkitettura kurrenti (aktar dwar dan hawn taħt), args - sa sitt argumenti tas-sejħa tas-sistema, u instruction_pointer huwa pointer għall-istruzzjoni tal-ispazju tal-utent li għamlet is-sejħa tas-sistema. Għalhekk, pereżempju, biex jgħabbi n-numru tas-sejħa tas-sistema fir-reġistru A irridu ngħidu

ldw [0]

Hemm karatteristiċi oħra għall-programmi seccomp, pereżempju, il-kuntest jista' jiġi aċċessat biss b'allinjament ta' 32-bit u ma tistax tagħbija nofs kelma jew byte - meta tipprova tagħbija filtru ldh [0] sejħa tas-sistema seccomp se jirritorna EINVAL. Il-funzjoni tiċċekkja l-filtri mgħobbija seccomp_check_filter() qlub. (Ħaġa umoristiċi hija, fil-kommit oriġinali li żied il-funzjonalità seccomp, insew iżidu l-permess biex jużaw l-istruzzjoni għal din il-funzjoni mod (il-bqija tad-diviżjoni) u issa mhux disponibbli għall-programmi seccomp BPF, peress li ż-żieda tagħha se jinkiser ABI.)

Bażikament, diġà nafu kollox biex niktbu u naqraw programmi seccomp. Normalment il-loġika tal-programm hija rranġata bħala lista bajda jew sewda ta 'sejħiet tas-sistema, pereżempju l-programm

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

jiċċekkja lista sewda ta' erba' sejħiet tas-sistema bin-numru 304, 176, 239, 279. X'inhuma dawn is-sejħiet tas-sistema? Ma nistgħux ngħidu żgur, peress li ma nafux għal liema arkitettura nkiteb il-programm. Għalhekk, l-awturi ta 'seccomp offerta ibda l-programmi kollha b'verifika tal-arkitettura (l-arkitettura attwali hija indikata fil-kuntest bħala qasam arch strutturi struct seccomp_data). Bl-arkitettura kkontrollata, il-bidu tal-eżempju jkun jidher bħal:

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

u allura n-numri tas-sejħa tas-sistema tagħna jiksbu ċerti valuri.

Aħna niktbu u tagħbija filtri għall seccomp bl-użu libseccomp

Filtri tal-kitba f'kodiċi nattiv jew f'assemblaġġ BPF jippermettilek li jkollok kontroll sħiħ fuq ir-riżultat, iżda fl-istess ħin, xi drabi huwa preferibbli li jkollok kodiċi portabbli u/jew li jinqara. Il-librerija se tgħinna f’dan libseccomp, li jipprovdi interface standard għall-kitba ta 'filtri iswed jew abjad.

Ejja, pereżempju, niktbu programm li jmexxi fajl binarju tal-għażla tal-utent, wara li qabel installa lista sewda ta 'sejħiet tas-sistema minn l-artikolu hawn fuq (il-programm ġie ssimplifikat għal aktar leġibilità, il-verżjoni sħiħa tista 'tinstab hawn):

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

L-ewwel niddefinixxu firxa sys_numbers ta' 40+ numri tas-sejħa tas-sistema biex timblokka. Imbagħad, inizjalizza l-kuntest ctx u għid lill-librerija dak li rridu nippermettu (SCMP_ACT_ALLOW) is-sejħiet kollha tas-sistema awtomatikament (huwa aktar faċli li tibni listi suwed). Imbagħad, wieħed wieħed, inżidu s-sejħiet kollha tas-sistema mil-lista sewda. Bi tweġiba għal sejħa tas-sistema mil-lista, nitolbu SCMP_ACT_TRAP, f'dan il-każ seccomp se jibgħat sinjal lill-proċess SIGSYS b'deskrizzjoni ta' liema sejħa tas-sistema kisret ir-regoli. Fl-aħħarnett, aħna tagħbija l-programm fil-kernel bl-użu seccomp_load, li se tiġbor il-programm u tehmeż mal-proċess billi tuża sejħa tas-sistema seccomp(2).

Għal kumpilazzjoni b'suċċess, il-programm għandu jkun marbut mal-librerija libseccompper eżempju:

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

Eżempju ta' tnedija b'suċċess:

$ ./seccomp_lib echo ok
ok

Eżempju ta' sejħa tas-sistema mblukkata:

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

Aħna nużaw stracegħad-dettalji:

$ 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

kif nistgħu nafu li l-programm ġie tterminat minħabba l-użu ta 'sejħa illegali tas-sistema mount(2).

Allura, ktibna filtru bl-użu tal-librerija libseccomp, twaħħil kodiċi mhux trivjali f'erba 'linji. Fl-eżempju ta 'hawn fuq, jekk ikun hemm numru kbir ta' sejħiet tas-sistema, il-ħin ta 'eżekuzzjoni jista' jitnaqqas b'mod notevoli, peress li l-kontroll huwa biss lista ta 'paraguni. Għall-ottimizzazzjoni, libseccomp reċentement kellu garża inkluża, li żżid l-appoġġ għall-attribut tal-filtru SCMP_FLTATR_CTL_OPTIMIZE. L-issettjar ta 'dan l-attribut għal 2 se jikkonverti l-filtru fi programm ta' tfittxija binarju.

Jekk trid tara kif jaħdmu l-filtri tat-tiftix binarju, agħti ħarsa lejn skript sempliċi, li tiġġenera programmi bħal dawn fl-assemblatur BPF billi tisselezzjona numri tas-sejħa tas-sistema, pereżempju:

$ 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

M'intix tkun tista' tikteb xejn b'mod sinifikanti aktar mgħaġġel, peress li l-programmi BPF ma jistgħux iwettqu qbiż ta' indentazzjoni (ma nistgħux nagħmlu, pereżempju, jmp A jew jmp [label+X]) u għalhekk it-tranżizzjonijiet kollha huma statiċi.

seccomp u strace

Kulħadd jaf l-utilità strace hija għodda indispensabbli għall-istudju tal-imġieba tal-proċessi fuq Linux. Madankollu, ħafna wkoll semgħu dwar kwistjonijiet ta' prestazzjoni meta tuża din l-utilità. Il-fatt hu li strace implimentati bl-użu ptrace(2), u f'dan il-mekkaniżmu ma nistgħux nispeċifikaw f'liema sett ta' sejħiet ta' sistema għandna bżonn nieqfu l-proċess, jiġifieri, pereżempju, kmandi

$ 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

jiġu pproċessati bejn wieħed u ieħor fl-istess ħin, għalkemm fit-tieni każ irridu ntraċċaw sejħa tas-sistema waħda biss.

Għażla ġdida --seccomp-bpf, miżjuda ma' strace verżjoni 5.3, tippermettilek tħaffef il-proċess ħafna drabi u l-ħin tal-istartjar taħt it-traċċa ta 'sejħa tas-sistema waħda diġà huwa komparabbli mal-ħin ta' startup regolari:

$ 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

(Hawn, ovvjament, hemm qerq żgħir fis-sens li m'aħniex intraċċaw is-sejħa ewlenija tas-sistema ta 'dan il-kmand. Kieku konna qed intraċċaw, pereżempju, newfsstat, Imbagħad strace ikun ibbrejkja daqskemm mingħajr --seccomp-bpf.)

Kif taħdem din l-għażla? Mingħajrha strace jgħaqqad mal-proċess u jibda jużah PTRACE_SYSCALL. Meta proċess immaniġġjat joħroġ (kwalunkwe) sejħa tas-sistema, il-kontroll jiġi trasferit strace, li tħares lejn l-argumenti tas-sejħa tas-sistema u tmexxiha bl-użu PTRACE_SYSCALL. Wara xi żmien, il-proċess itemm is-sejħa tas-sistema u meta joħroġ minnha, il-kontroll jerġa 'jiġi trasferit strace, li tħares lejn il-valuri tar-ritorn u tibda l-proċess bl-użu PTRACE_SYSCALL, u l-bqija.

BPF għaż-żgħar, parti żero: BPF klassika

B'seccomp, madankollu, dan il-proċess jista 'jiġi ottimizzat eżatt kif nixtiequ. Jiġifieri, jekk irridu nħarsu biss lejn is-sejħa tas-sistema X, allura nistgħu niktbu filtru BPF li għal X jirritorna valur SECCOMP_RET_TRACE, u għal sejħiet li mhumiex ta' interess għalina - SECCOMP_RET_ALLOW:

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

F'dan il-każ strace inizjalment jibda l-proċess bħala PTRACE_CONT, il-filtru tagħna jiġi pproċessat għal kull sejħa tas-sistema, jekk is-sejħa tas-sistema mhix X, allura l-proċess ikompli għaddej, imma jekk dan X, imbagħad seccomp se jittrasferixxi l-kontroll straceli se tħares lejn l-argumenti u tibda l-proċess simili PTRACE_SYSCALL (peress li seccomp m'għandux il-ħila li jmexxi programm mal-ħruġ minn sejħa tas-sistema). Meta s-sejħa tas-sistema terġa' lura, strace se jerġa 'jibda l-proċess bl-użu PTRACE_CONT u se tistenna messaġġi ġodda minn seccomp.

BPF għaż-żgħar, parti żero: BPF klassika

Meta tuża l-għażla --seccomp-bpf hemm żewġ restrizzjonijiet. L-ewwelnett, mhux se jkun possibbli li tissieħeb fi proċess diġà eżistenti (għażla -p programmi strace), peress li dan mhux appoġġjat minn seccomp. It-tieni, m'hemm l-ebda possibbiltà ebda Ħares lejn il-proċessi tfal, peress li l-filtri seccomp jintirtu mill-proċessi tfal kollha mingħajr il-kapaċità li jiskonnettjaw dan.

Ftit aktar dettall dwar kif eżattament strace jaħdem magħhom seccomp jistgħu jinstabu minn rapport riċenti. Għalina, l-aktar fatt interessanti huwa li l-BPF klassiku rappreżentat minn seccomp għadu jintuża llum.

xt_bpf

Ejja issa mmorru lura għad-dinja tan-netwerks.

Sfond: żmien twil ilu, fl-2007, il-qalba kienet miżjud modulu xt_u32 għal netfilter. Inkiteb b'analoġija ma' klassifikatur tat-traffiku saħansitra aktar antik cls_u32 u ppermettilek tikteb regoli binarji arbitrarji għal iptables billi tuża l-operazzjonijiet sempliċi li ġejjin: tagħbija 32 bit minn pakkett u twettaq sett ta 'operazzjonijiet aritmetiċi fuqhom. Pereżempju,

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

Tgħabbi t-32 bit tal-header tal-IP, li tibda mill-ikkuttunar 6, u tapplika maskra għalihom 0xFF (ħu l-byte baxx). Dan il-qasam protocol IP header u nqabbluha ma '1 (ICMP). Tista 'tgħaqqad ħafna kontrolli f'regola waħda, u tista' wkoll tesegwixxi l-operatur @ — iċċaqlaq X bytes lejn il-lemin. Per eżempju, ir-regola

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

jiċċekkja jekk in-Numru tas-Sekwenza TCP mhuwiex ugwali 0x29. Mhux se nidħol aktar fid-dettalji, peress li diġà huwa ċar li l-kitba ta 'regoli bħal dawn bl-idejn mhix konvenjenti ħafna. Fl-artiklu BPF - il-bytecode minsija, hemm diversi links b'eżempji ta' użu u ġenerazzjoni ta' regoli għal xt_u32. Ara wkoll il-links fl-aħħar ta 'dan l-artikolu.

Mill-2013 modulu minflok modulu xt_u32 tista' tuża modulu bbażat fuq BPF xt_bpf. Kull min qara s'issa għandu jkun diġà ċar dwar il-prinċipju tat-tħaddim tiegħu: mexxi BPF bytecode bħala regoli iptables. Tista' toħloq regola ġdida, pereżempju, bħal din:

iptables -A INPUT -m bpf --bytecode <байткод> -j LOG

hawn <байткод> - dan huwa l-kodiċi fil-format tal-output tal-assemblatur bpf_asm awtomatikament, pereżempju,

$ 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

F'dan l-eżempju qed niffiltraw il-pakketti UDP kollha. Kuntest għal programm BPF f'modulu xt_bpf, ovvjament, jindika d-data tal-pakkett, fil-każ ta 'iptables, għall-bidu tal-header IPv4. Valur tar-ritorn mill-programm BPF booleanfejn false ifisser li l-pakkett ma kienx jaqbel.

Huwa ċar li l-modulu xt_bpf jappoġġja filtri aktar kumplessi mill-eżempju ta 'hawn fuq. Ejja nħarsu lejn eżempji reali minn Cloudfare. Sa ftit ilu kienu jużaw il-modulu xt_bpf biex tipproteġi kontra attakki DDoS. Fl-artiklu L-introduzzjoni tal-Għodod tal-BPF jispjegaw kif (u għaliex) jiġġeneraw filtri BPF u jippubblikaw links għal sett ta 'utilitajiet għall-ħolqien ta' filtri bħal dawn. Per eżempju, billi tuża l-utilità bpfgen tista' toħloq programm BPF li jaqbel ma' mistoqsija DNS għal isem 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

Fil-programm aħna l-ewwel tagħbija fir-reġistru X bidu tal-indirizz tal-linja x04habrx03comx00 ġewwa datagramma UDP u mbagħad iċċekkja t-talba: 0x04686162 <-> "x04hab" eċċ

Ftit aktar tard, Cloudfare ippubblika l-kodiċi tal-kompilatur p0f -> BPF. Fl-artiklu L-introduzzjoni tal-kompilatur p0f BPF huma jitkellmu dwar x'inhu p0f u kif jikkonvertu firem p0f għal 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,
...

Bħalissa m'għadhiex tuża Cloudfare xt_bpf, peress li mxew għal XDP - waħda mill-għażliet għall-użu tal-verżjoni l-ġdida ta 'BPF, ara. L4Drop: XDP DDoS Mitigazzjonijiet.

cls_bpf

L-aħħar eżempju ta 'użu ta' BPF klassika fil-qalba huwa l-klassifikatur cls_bpf għas-subsistema tal-kontroll tat-traffiku fil-Linux, miżjuda mal-Linux fl-aħħar tal-2013 u kunċettwalment tissostitwixxi l-antik cls_u32.

Madankollu, issa mhux se niddeskrivu x-xogħol cls_bpf, peress li mil-lat ta 'għarfien dwar BPF klassika dan mhu se jagħtina xejn - diġà sirna familjari mal-funzjonalità kollha. Barra minn hekk, f'artikoli sussegwenti li jitkellmu dwar Extended BPF, se niltaqgħu ma 'dan il-klassifikatur aktar minn darba.

Raġuni oħra biex ma titkellimx dwar l-użu ta 'BPF klassika c cls_bpf Il-problema hija li, meta mqabbel ma 'Extended BPF, l-ambitu tal-applikabilità f'dan il-każ huwa radikalment imdejjaq: programmi klassiċi ma jistgħux ibiddlu l-kontenut tal-pakketti u ma jistgħux jiffrankaw l-istat bejn is-sejħiet.

Għalhekk wasal iż-żmien li ngħidu addiju lill-BPF klassika u nħarsu lejn il-futur.

Adieu lill-BPF klassika

Ħarsa lejn kif it-teknoloġija BPF, żviluppata fil-bidu tad-disgħinijiet, għexet b’suċċess għal kwart ta’ seklu u sal-aħħar sabet applikazzjonijiet ġodda. Madankollu, simili għat-tranżizzjoni minn magni stack għal RISC, li serva bħala impetu għall-iżvilupp ta 'BPF klassika, fis-snin 32 kien hemm tranżizzjoni minn magni 64-bit għal XNUMX-bit u BPF klassika bdiet issir skaduta. Barra minn hekk, il-kapaċitajiet tal-BPF klassika huma limitati ħafna, u minbarra l-arkitettura skaduta - m'għandniex il-ħila li nissejvjaw l-istat bejn sejħiet għal programmi BPF, m'hemm l-ebda possibbiltà ta 'interazzjoni diretta tal-utent, m'hemm l-ebda possibbiltà ta' interazzjoni mal-qalba, ħlief għall-qari ta’ numru limitat ta’ oqsma tal-istruttura sk_buff u tniedi l-aktar funzjonijiet helper sempliċi, ma tistax tbiddel il-kontenut tal-pakketti u tindirizzahom mill-ġdid.

Fil-fatt, bħalissa dak kollu li jibqa 'mill-BPF klassika fil-Linux huwa l-interface tal-API, u ġewwa l-kernel il-programmi klassiċi kollha, kemm jekk ikunu filtri tas-socket jew filtri seccomp, huma awtomatikament tradotti f'format ġdid, Extended BPF. (Aħna nitkellmu dwar eżattament kif dan jiġri fl-artiklu li jmiss.)

It-tranżizzjoni għal arkitettura ġdida bdiet fl-2013, meta Alexey Starovoitov ippropona skema ta 'aġġornament tal-BPF. Fl-2014 l-irqajja korrispondenti bdew jidhru fil-qalba. Sa fejn nifhem jien, il-pjan inizjali kien biss li jottimizza l-arkitettura u l-kompilatur JIT biex jaħdem b'mod aktar effiċjenti fuq magni 64-bit, iżda minflok dawn l-ottimizzazzjonijiet immarkaw il-bidu ta 'kapitolu ġdid fl-iżvilupp tal-Linux.

Artikli oħra f'din is-serje se jkopru l-arkitettura u l-applikazzjonijiet tat-teknoloġija l-ġdida, inizjalment magħrufa bħala BPF intern, imbagħad BPF estiż, u issa sempliċement BPF.

referenzi

  1. Steven McCanne u Van Jacobson, "The BSD Packet Filter: A New Architecture for User-level Packet Capture", https://www.tcpdump.org/papers/bpf-usenix93.pdf
  2. Steven McCanne, "libpcap: Metodoloġija ta' Arkitettura u Ottimizzazzjoni għall-Qbid ta' Pakketti", https://sharkfestus.wireshark.org/sharkfest.11/presentations/McCanne-Sharkfest'11_Keynote_Address.pdf
  3. tcpdump, libpcap: https://www.tcpdump.org/
  4. Tutorial tal-Match IPtable U32.
  5. BPF - il-bytecode minsija: https://blog.cloudflare.com/bpf-the-forgotten-bytecode/
  6. L-introduzzjoni tal-Għodda BPF: https://blog.cloudflare.com/introducing-the-bpf-tools/
  7. bpf_cls: http://man7.org/linux/man-pages/man8/tc-bpf.8.html
  8. Ħarsa ġenerali ta' seccomp: https://lwn.net/Articles/656307/
  9. https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
  10. habr: Kontenituri u sigurtà: seccomp
  11. habr: Iżola d-daemons b'systemd jew "m'għandekx bżonn Docker għal dan!"
  12. Paul Chaignon, "strace --seccomp-bpf: ħarsa taħt il-barnuża", https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
  13. netsniff-ng: http://netsniff-ng.org/

Sors: www.habr.com

Żid kumment