BPF kÔige vÀiksematele, osa null: klassikaline BPF

Berkeley Packet Filters (BPF) — on Linuxi tuumorihn, mis on mitu aastat jĂ€rjest esinenud ingliskeelsete tehniliste vĂ€ljaannete esikĂŒlgedel. Konverentsid on tĂ€is ettekandeid BPF-i kasutamisest ja arendamisest. David Miller, Linuxi vĂ”rgualaste alamsĂŒsteemide hoidja, nimetab oma ettekannet Linux Plumbers 2018. «See ettekande ei kĂ€sitle XDP-d» (XDP – on ĂŒks BPF-i kasutamise variante). Brendan Gregg teeb ettekande pealkirjaga Linux BPF Superpowers. Toke HĂžiland-JĂžrgensen naerab, et see on nĂŒĂŒd microkernel. Thomas Graf propageerib ideed, et BPF on Javascript tuumale..

Habr.ee-le pole siiani BPF-i sĂŒsteemset kirjeldust, seetĂ”ttu pĂŒĂŒan ma artiklite seerias rÀÀkida tehnoloogia ajaloost, kirjeldada arhitektuuri ja arendusvahendeid, mÀÀratleda kasutusvaldkondi ja praktikad BPF-i kasutamisel. Selles, null-ses artiklis, kĂ€sitletakse klassikalise BPF-i ajalugu ja arhitektuuri, samuti paljastatakse seccomp'i tööpĂ”himĂ”tted tcpdump, , ja palju muud., straceBPF-i arendust juhib Linuxi vĂ”rgu kogukond, ning peamised olemasolevad BPF-i rakendused on seotud vĂ”rguga ja seetĂ”ttu, @eucariot'i luba kĂŒsides, nimetasin seeriat "BPF kĂ”ige vĂ€iksematele" suurte seeriate auks.

BPF arendus toimub Linuxi vĂ”rguĂŒhenduse kogukonna jĂ€relevalve all, pĂ”hilised BPF rakendused on seotud vĂ”rkudega ja seetĂ”ttu, lubades @eucariot, nimetasime seeria "BPF vĂ€ikestele", austades suurt seeriat "VĂ€ikesed vĂ”rgud".

LĂŒhike BPF ajalugu (c)

Kaasaegne BPF tehnoloogia on tĂ€iustatud ja tĂ€iustatud versioon vana tehnoloogiast sama nimega, mida nimetatakse nĂŒĂŒd, et vĂ€ltida segadust, klassikaliseks BPF-iks. Klassikalise BPF-i baasil on loodud tuntud tööriistad, tcpdumpmehanismid , ja palju muud., samuti vĂ€hem tuntud moodulid xt_bpf kuna iptables ja klassifitseerija cls_bpf. Kaasaegses Linuxis tĂ”lgitakse klassikalised BPF programmid automaatselt uude vormi, kuid kasutajate vaatepunktist on API jÀÀnud paika ja klassikalise BPF uued rakendused, nagu me nĂ€eme selles artiklis, on endiselt olemas. Just seetĂ”ttu, et jĂ€lgides klassikalise BPF-i arengulugu Linuxis, selgub, kuidas ja miks see on arenenud kaasaegsesse vormi, otsustasin alustada just klassikalisest BPF-ist.

1980. aastate lĂ”pus hakkasid tuntud Lawrence Berkeley Laboratory insenerid uurima, kuidas Ă”igesti filtreerida vĂ”rgu pakette tollase arvutitehnika jaoks. Filtreerimise pĂ”hikontseptsioon, mis sai alguse CSPF (CMU/Stanford Packet Filter) tehnoloogiast, seisnes selles, et liigseid pakette filtreeriti vĂ”imalikult varakult, st tuumaruumi tasandil, et vĂ€ltida liigsete andmete kopeerimist kasutajaruumi. KĂ€ituse ohutuse tagamiseks, et kasutajakoodi saaks tuumaruumi kĂ€ivitada, kasutati virtuaalmasinat — liivakasti.

Kuid olemasolevate filtrite virtuaalmasinad olid kavandatud tööks virnastusega arhitektuuriga masinatel ja uutel RISC masinatel ei töötanud need nii efektiivselt. LĂ”puks Berkeley Labs'i inseneride jĂ”upingutuste tulemusena töötati vĂ€lja uus tehnoloogia BPF (Berkeley Packet Filters), mille virtuaalmasina arhitektuur oli projekteeritud Motorola 6502 protsessori pĂ”hjal — töö tegemiseks sellistes tuntud toodetes nagu Apple II vĂ”i NES. Uus virtuaalne masin suurendas filtrite jĂ”udlust kĂŒmneid kordi vĂ”rreldes olemasolevate lahendustega.

BPF masina arhitektuur

KĂ€ime lĂ€bi arhitektuuri tööstuslikult, analĂŒĂŒsides nĂ€iteid. Kuid kĂ”igepealt ĂŒtleme, et masinal oli kaks kasutajale juurdepÀÀsetavat 32-bitist registrit, akumulaaror A ja indeksregister X, 64 baiti mĂ€lu (16 sĂ”na), mis oli kirjutamiseks ja lugemiseks saadaval, ning vĂ€ike kĂ€skude sĂŒsteem nende objektidega töötamiseks. Programmid sisaldasid ka hĂŒpikdirektiive tingimuslike avalduste rakendamiseks, kuid programmid pidid lĂ”petama töö Ă”igeaegselt, seega oli ainult edasi liikumine lubatud, st tsĂŒklite loomine oli rangelt keelatud.

Üldine masina kĂ€ivitamise skeem on jĂ€rgmine. Kasutaja loob BPF arhitektuuri jaoks programmi ja mingi mehhanismi kernel (nĂ€iteks sĂŒsteemikĂ”ne) abil laadib ja ĂŒhendab programmi mingi millele sĂŒndmuste generaator tuumas (nĂ€iteks sĂŒndmus on uue paketi saabumine vĂ”rguadapterisse). SĂŒndmuse tekkimisel kĂ€ivitab tuum programmi (nĂ€iteks tĂ”lgendis), samal ajal kui masina mĂ€lu vastab millele tuuma mĂ€lu piirkonnale (nĂ€iteks saabunud paketi andmetele).

Ülaltoodust piisab, et alustada nĂ€idete kĂ€sitlemist: tutvume sĂŒsteemi ja kĂ€skude vorminguga vastavalt vajadusele. Kui aga soovite kohe uurida virtuaalmasina kĂ€susĂŒsteemi ja teada kĂ”iki selle vĂ”imalusi, siis saate lugeda originaalartiklit BSD Packet Filter ja/vĂ”i faili esimest poolt Dokumentatsioon/networking/filter.txt tuuma dokumentatsioonist. Lisaks sellele vĂ”ite tutvuda esitusega libpcap: An Architecture and Optimization Methodology for Packet Capture, kus McCanne, ĂŒks BPF autoritest, rÀÀgib loomise ajaloost libpcap.

Me liigume edasi, et kÀsitleda kÔiki olulisi klassikalise BPF rakendamise nÀiteid Linuxis: tcpdump (libpcap), seccomp, xt_bpf, cls_bpf.

tcpdump

BPF arendamine toimus paralleelselt pakettide filtreerimise frontendi, ĂŒldiselt tuntud utiliidi, vĂ€ljatöötamisega. tcpdump. Kuna see on kĂ”ige vanem ja kĂ”ige tuntum klassikalise BPF kasutamise nĂ€ide, mis on saadaval mitmetes operatsioonisĂŒsteemides, alustame tehnoloogia Ă”ppimist just selle pealt.

(KÔik nÀited kÀivitasin ma Linuxis 5.6.0-rc6. MÔnede kÀskude vÀljund on suurema loetavuse tagamiseks muudetud.)

NĂ€ide: vaatleme IPv6 pakette

Kujutame ette, et soovime jÀlgida kÔiki IPv6 pakette liidesel eth0. Selleks vÔime kÀivitada programmi tcpdump lihtsa filtriga ip6:

$ sudo tcpdump -i eth0 ip6

Samal ajal tcpdump kompileerib filtri ip6 BPF arhitektuuri baitkoodiks ja saadab selle kĂ€rku (vaata lisainfot jaotisest Tcpdump: laadimine). Laaditud filtrit kĂ€itatakse iga paketi puhul, mis liigub lĂ€bi liidese eth0. Kui filter tagastab mittetĂŒhja vÀÀrtuse n, siis n paketi baitide koopia kopeeritakse kasutajaruumi ja nĂ€eme seda vĂ€ljundis. tcpdump.

BPF kÔige vÀiksematele, osa null: klassikaline BPF

Selgub, et me saame hÔlpsasti teada, millist baitkoodi me kÀrku saatsime tcpdump kasutades iseennast tcpdump, kui kÀivitame selle valikuga -d:

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

Esimeses reas kĂ€ivitame kĂ€su ldh [12], mis tĂ”lgitakse kui „laadi registrisse“ A pool-sĂ”nad (16 bitti) asuvad aadressil 12» ja ainus kĂŒsimus on, millist mĂ€lu me aadresseerime? Vastus on see, et aadressil x alustab (x+1)-ndat baiti analĂŒĂŒsitavas vĂ”rgu paketis. Loeme pakette Etherneti liidesest eth0, ja see on tĂ€hendab, mis pakett vĂ€lja nĂ€eb (lihtsuse huvides oletame, et paketis ei ole VLAN silte):

       6              6          2
|Siht MAC|Allika MAC|Ether Type|...|

Seega, pĂ€rast kĂ€su tĂ€itmist ldh [12] registreerimisel A on vĂ€li Ether Type — edastatava Ethernet-raami paketi tĂŒĂŒp. Real 1 vĂ”rreldakse registri sisu A (paketi tĂŒĂŒp) c 0x86dd, ja see on ja on meid huvitav tĂŒĂŒpi IPv6. Reas 1, lisaks vĂ”rdlus kĂ€sule, on veel kaks veergu — jt 2 ja jf 3 — mĂ€rgid, kuhu minna, kui vĂ”rdlus on edukas (A == 0x86dd) ja ebaĂ”nnestub. Nii et, edukal juhul (IPv6) liikume reale 2, ja ebaĂ”nnestumisel — reale 3. Reas 3 lĂ”petatakse programm koodiga 0 (Ă€rge kopeerige paketti), reaas 2 lĂ”petatakse programm koodiga 262144 (kopeerige mulle maksimaalselt 256 kilobaiti paketti).

Veidi keerukam nÀide: vaatame TCP pakette sihtporti

Vaadake, kuidas töötab filter, mis kopeerib kĂ”ik TCP paketid sihtportiga 666. Keskendume IPv4 puhul, kuna IPv6 on lihtsam. PĂ€rast seda nĂ€idet vĂ”ite harjutuseks ise uurida filterit IPv6 jaoks (ip6 and tcp dst port 666) ja filtri ĂŒldiseks juhtumiks (tcp dst port 666). Seega nĂ€eb meid huvitav filter vĂ€lja jĂ€rgmine:

$ 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

Ridade 0 ja 1 kohta teame me juba. Reas 2 oleme juba kontrollinud, et tegemist on IPv4 paketiga (Ether Type = 0x800) ja laadime registrisse A paketi 24. bait. Meie pakett nÀeb vÀlja nagu

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

mis tÀhendab, et laadime registrisse A IP pealkirja Protocol vÀlja, mis on loogiline, kuna soovime kopeerida ainult TCP pakette. VÔrdleme Protocol'i 0x6 (IPPROTO_TCP) reas 3.

Ridades 4 ja 5 laadime poole sĂ”na, mis asub aadressil 20, ja kasutame kĂ€sku jset kontrollime, kas ĂŒks kolmest on seatud lippude — antud maskis jset kolm kĂ”rgeimat bitti on puhastatud. Kaks bitti kolmest ĂŒtlevad meile, kas pakk on fragmentiseeritud IP-paketi osa ja kui jah, siis kas see on viimane fragment. Kolmas bitt on reserveeritud ja peab olema null. Me ei soovi kontrollida ei mitteotsi ega rikutud pakette, seega kontrollime kĂ”iki kolme bitti.

Rida 6 on kĂ”ige huvitavam selles loendis. VĂ€ljend ldxb 4*([14]&0xf) tĂ€hendab, et laadime registrisse X nelja madalaima bitti viieteistkĂŒmnendast baitist pakett, korrutatud 4-ga. Neli madalaimat bitti viieteistkĂŒmnendast baitist on vĂ€li Internet Header Length IPv4 pĂ€ises, kus hoitakse pĂ€ise pikkust sĂ”nades, seega tuleb korrutada 4-ga. Huvi pakub, et vĂ€ljend 4*([14]&0xf) on erilise adresseerimise skeemi mĂ€rgistus, mida saab kasutada ainult sellisel kujul ja ainult registri jaoks X, st me ei saa öelda ei ldb 4*([14]&0xf) ei ldxb 5*([14]&0xf) (saame vaid mÀÀrata teise nihke, nĂ€iteks ldxb 4*([16]&0xf)). Selge on, et see adresseerimise skeem lisati BPF-s tĂ€pselt selleks, et saada X (indeksiregister) IPv4 pĂ€ise pikkust.

Seega, real 7 pĂŒĂŒame laadida poole sĂ”na aadressilt (X+16). Meenutades, et Etherneti pĂ€is vĂ”tab 14 baiti, ja X SEE sisaldab IPv4 pĂ€ise pikkust, mĂ”istame, et A laetakse TCP sihtport:

       14           X           2             2
|ethernet pÀis|ip pÀis|allikas|sihtport|

LĂ”puks, real 8 vĂ”rdleme sihtporti otsitava vÀÀrtusega ning ridadel 9 vĂ”i 10 tagastame tulemuse — kas koopida paketti vĂ”i mitte.

Tcpdump: laadimine

Eelnevatel nĂ€idetel ei peatunud me pĂ”hjalikult sellel, kuidas me laadime BPF baitkoodi tuuma pakettide filtreerimiseks. Üldiselt, tcpdump on portitud paljudele sĂŒsteemidele ja tööks filtritega tcpdump kasutab raamatukogu libpcap. LĂŒhidalt, et rakendada filtrit liidese kaudu, libpcap, peate tegema jĂ€rgmist:

Kuna soovime nÀha, kuidas funktsioon pcap_setfilter on Linuxis rakendatud, kasutame strace (mÔned read on eemaldatud):

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

Esimese kahe rea vĂ€ljundis loome raw-soketi kĂ”igi Etherneti raamide lugemiseks ja seome selle eth0. Shotcutist on esile tĂ”stetav mitme takistusega redigeerimisvĂ”ime, mis vĂ”imaldab koostada videoid fragmentidest erinevates algvormingutes, ilma nende eelneva sissetoomise vĂ”i ĂŒmberkodeerimiseta. On olemas sisseehitatud vahendid ekraanikaamerate loomiseks, pilditöötluseks veebikaamerast ja voogedastuse video vastuvĂ”tmiseks. Kasutajaliidese loomiseks kasutatakse Qt5. Kood meie esimese nĂ€ite liidesele me teame, et filter ip koosneb neljast BPF kĂ€sklusest, ja kolmandal real nĂ€eme, kuidas kasutades valikut SO_ATTACH_FILTER sĂŒsteemikĂ”ne setsockopt laadime ja ĂŒhendame 4-pikuse filtri. See on meie filter.

Tasub mĂ€rkida, et klassikalises BPF-s toimub filtri laadimine ja ĂŒhendamine alati aatomaarse tehinguna, samas kui uue BPF versioonis on programmi laadimine ja selle sidumine sĂŒndmuste generaatoriga ajaliselt eraldi.

Peidetud tÔde

Veidi tÀielikum vÀljund nÀeb vÀlja nii:

$ 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 (Ressurss on ajutiselt saadaval)
setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, {len=4, filter=0xb00bb00bb00b}, 16) = 0
...

Nagu eelpool toodud, laadime ja ĂŒhendame meie filtri soketiga real 5, kuid mis toimub ridades 3 ja 4? Tundub, et see libpcap hooldus meie jaoks — et meie filtri vĂ€ljundisse ei satu paketid, mis ei vasta standarditele, raamatukogu ĂŒhendab vale filter ret #0 (langetada kĂ”ik paketid), ĂŒle viib soketi mitte-blokeerivasse reĆŸiimi ja pĂŒĂŒab lugeda kĂ”ik paketid, mis vĂ”isid jÀÀda eelmistelt filtritelt.

KokkuvĂ”ttes, et filtreerida pakette Linuxis klassikalise BPF abil, peab olema filter struktuuri tĂŒĂŒbina struct sock_fprog ja avatud soket, seejĂ€rel saab filtri soketiga ĂŒhendada sĂŒsteemikutsungi abil setsockopt.

Huvitav on see, et filtri saab ĂŒhendada igasuguste soketitega, mitte ainult toorega. Siin on an example programm, mis kĂ€rbib kĂ”ik vĂ€lja, peale kahe esimese baidi kĂ”igist sissetulevatest UDP datagrammidest. (Kommentaarid on koodis lisatud, et artiklit mitte ĂŒle koormata.)

Rohkem kasutamise kohta setsockopt filtrite ĂŒhendamiseks vt socket(7), ja oma filtrite kirjutamise kohta struct sock_fprog ilma abita tcpdump rÀÀgime peatĂŒkis Programmeerime BPF oma kĂ€tega.

Klassikaline BPF ja XXI sajand

BPF lisati Linuxisse 1997. aastal ja pĂŒsis kaua tööhobuse rollis libpcap ilma eriliste muudatusteta (Linuxi-spetsiifilised muudatused muidugi, oli, kuid nad ei muutnud maailmapilti). Esimesed tĂ”sised mĂ€rgid, et BPF hakkab arenema, ilmusid 2011. aastal, kui Eric Dumazet tutvustas plekk, tuues kernelisse Just In Time Compileri — tĂ”lkija, mis tĂ”lgib BPFi bytecode'i kohalikku x86_64 koodi.

JIT kompilaator oli esimene muudatuste ahelas: 2012. aastal ilmus ilmus vĂ”imalus kirjutada filtreid , ja palju muud., kasutades BPFi, jaanuaris 2013 ilmus lisatud mooduli xt_bpf, mis vĂ”imaldas kirjutada reegleid iptables BPF abil, ja oktoobris 2013 ilmus lisatud veel ĂŒks moodul cls_bpf, mis vĂ”imaldas kirjutada BPF abil liiklusklassifitseerijaid.

KĂŒlastame neid nĂ€iteid peagi lĂ€hemalt, kuid esmalt on kasulik Ă”ppida kirjutama ja kompileerima omavoli BPF programme, kuna raamatukogu poolt pakutavad vĂ”imalused libpcap on piiratud (lihtne nĂ€ide: filter, mille genereerib libpcap vĂ”ib naasta ainult kaks vÀÀrtust — 0 vĂ”i 0x40000) vĂ”i ĂŒldse, nagu seccompi puhul, ei ole kohaldatavad.

Programmeerime BPF oma kÀtega

Tutvume BPF kÀskude binaarformaadiga, see on vÀga lihtne:

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

Iga juhis vĂ”tab 64 bitti, millest esimesed 16 bitti on kĂ€skude kood, seejĂ€rel tulevad kaks kaheksa-bitteviidet, jt ja jf, ja 32 bitti argumendi jaoks K, mille tĂ€henduses, mis muutub meeskonnast meeskonda. NĂ€iteks meeskond ret, mis lĂ”petab programmi töö, on koodiga 6, ja tagastatav vÀÀrtus saadakse konstantidest K. Keeles C esindab ĂŒks BPF kĂ€sk struktuuri

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

ja terve programm — struktuuri

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

Nii saame juba kirjutada programme (kÀskude koodid, oletame, et teame neid [1]). Nii nÀeb filter vÀlja ip6 kohast meie esimese nÀite liidesele:

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 saame seaduslikult kasutada kÔnes

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

Programmide kirjutamine masinkoodidena ei ole eriti mugav, kuid mĂ”nikord on see vajalik (nĂ€iteks silumiseks, ĂŒksuse testide loomiseks, artiklite kirjutamiseks Habr'is jne). Mugavuse nimel failis <linux/filter.h> defineeritakse abimakrod — sama nĂ€idet, nagu eespool, saaks ĂŒmber kirjutada jĂ€rgmiselt

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

Kuid selline variant ei ole kuigi mugav. Nii arvasid ka Linuxi tuuma programmeerijad ning selle tÔttu on kataloogis tools/bpf tuumas saadaval assembler ja debuggeri klassikalise BPF-i jaoks.

Assembleerimiskeel on vĂ€ga sarnane tĂ”rkevĂ€ljastusele tcpdump, kuid lisaks saame mÀÀrata sĂŒmboolsed sildid. NĂ€iteks siin on programm, mis blokeerib kĂ”ik paketid, vĂ€lja arvatud TCP/IPv4:

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

Vaikimisi genereerib assembler koodi formaadis , ,..., meie TCP juhtumi jaoks on tulemus

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

C programmeerijate mugavuse huvides saab kasutada teistsugust vÀljundformaati:

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

Seda teksti saab kopeerida struktuuri mÀÀratlemiseks, tĂŒĂŒbi struct sock_filter, nagu me kĂ€esoleva peatĂŒki alguses tegime.

Linuxi ja netsniff-ng laiendused

Lisaks standardsetele BPF juhistele, Linux ja tools/bpf/bpf_asm toetavad ja ebatavaline komplekt. Peamiselt teenivad juhised struktuuri vĂ€ljadele juurdepÀÀsu tagamiseks struct sk_buff, mis kirjeldab vĂ”rgupaketti kernelis. Kuid on ka abijuhiseid teist tĂŒĂŒpi, nĂ€iteks ldw cpu laeb registrisse A tuuma funktsiooni kĂ€ivitamise tulemuse raw_smp_processor_id(). (Uues BPF versioonis on neid ebatavalisi laiendusi laiendatud, pakkudes programmidele kernel helpers pakettide andmete, struktuuride ja sĂŒndmuste genereerimise juurde pÀÀsemiseks.) Siin on huvitav nĂ€ide filtrist, kus kopeerime kasutaja ruumi ainult pakettide pĂ€ised, kasutades laiendust poff, koormuse offset:

ld poff
ret a

BPF laiendusi ei saa kasutada tcpdump, kuid see on hea pĂ”hjus tutvuda utiliitide paketiga netsniff-ng, mis sisaldab muuhulgas ka arenenud programmi netsniff-ng, mis lisaks BPF kaudu filtreerimisele sisaldab ka tĂ”husat liiklusgeneraatorit, ja on keerukam, kui tools/bpf/bpf_asm, BPF assemblçisi nimega bpfc. Pakett sisaldab ĂŒsna pĂ”hjalikku dokumentatsiooni, vt ka viiteid artikli lĂ”pus.

, ja palju muud.

Nii et, me oskame juba kirjutada BPF programme suvalise keerukusega ja oleme valmis vaatama uusi nĂ€iteid, millest esimene on tehnoloogia seccomp, mis vĂ”imaldab BPF filtrite abil hallata hulka ja argumentide kogumit sĂŒstemaatilistele kutsungitele, mis on saadaval antud protsessile ja tema jĂ€reltulijatele.

Esimene versioon seccomp'ist lisati kernelisse 2005. aastal ja ei olnud eriti populaarne, kuna pakkus vaid ĂŒhte vĂ”imalust — piirata hulka sĂŒstemaatilisi kutsungeid, mis on protsessile kĂ€ttesaadavad, jĂ€rgmiselt: read, write, exit ja sigreturn, ja protsess, mis rikkus reegleid, tapeti kasutades SIGKILL. Kuid 2012. aastal lisati seccomp'isse vĂ”imalus kasutada BPF filtreid, mis vĂ”imaldavad mÀÀrata hulga lubatud sĂŒstemaatilisi kutsungeid ja isegi kontrollida nende argumente. (Huvitav, et ĂŒks esimesi selle funktsionaalsuse kasutajaid oli Chrome, ja hetkel töötavad Chrome'i inimesed uue BPF versiooni pĂ”hjal mehhanismi KRSI, mis vĂ”imaldab kohandada Linuxi turvamooduleid.) Lingid tĂ€iendavale dokumentatsioonile leiate artikli lĂ”pust.

Tasub mĂ€rkida, et HabrĂ© on juba olnud artikleid seccomp'i kasutamise kohta, vĂ”ib-olla soovib keegi neid lugeda enne (vĂ”i selle asemel), kui liigub jĂ€rgmiste alajaotuste juurde. Artiklis Konteinerid ja turvalisus: seccomp on toodud nĂ€ited seccomp'i kasutamisest, nii 2007. aasta versioonide kui ka BPF-i kasutamise versioonide kohta (filtrid genereeritakse libseccomp'i abil), rÀÀgitakse seccomp'i seostest Dockeriga ja tuuakse vĂ€lja palju kasulikke linke. Artiklis Isoleerime deemonid systemd-ga vĂ”i "selleks ei ole Dockerit vaja!" rÀÀgitakse muu hulgas sellest, kuidas lisada mustaid vĂ”i valgeid loendeid sĂŒsteemi kutsungitele systemd'i halduses olevate deemonite jaoks.

Edasi vaatame, kuidas kirjutada ja laadida filtreid , ja palju muud. tavalise C keele ja libseccomp'i abil ning millised on iga variandi plussid ja miinused, ning lÔpuks vaatame, kuidas seccomp'i kasutab programm strace.

Kirjutame ja laadime filtreid seccomp'i jaoks

Me juba oskame kirjutada BPF programme ja seega vaatame esmalt seccomp'i programmiliidest. Filtri saab seadistada protsessi tasemel, samal ajal kui kĂ”ik alamprotsessid pĂ€rivad piirangud. Seda tehakse sĂŒsteemi kutsungi abil seccomp(2):

seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)

kus &filter — on viidatud juba tuntud struktuurile struct sock_fprog, st. BPF programmile.

Kuidas erinevad seccomp programmid sokettide programmiingest? Edastatav kontekst. Sokettide puhul edastati meile mÀlu piirkond, mis sisaldas paketti, kuid seccompi puhul edastatakse meile struktuur, mis nÀeb vÀlja jÀrgmine

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

Siit nr — see on kĂ€ivitatava sĂŒsteemi kutse number, arch — praegune arhitektuur (sellest allpool), args — kuni kuus sĂŒsteemi kutse argumenti, ja instruction_pointer — see on viidatud juhisele kasutajaruumi, mis tegi antud sĂŒsteemikutsumise. Seega, nĂ€iteks, et laadida sĂŒsteemikutsumise number registrisse A peame ĂŒtlema

ldw [0]

Seccomp programmide puhul on veel muid omadusi, nĂ€iteks on juurdepÀÀs kontekstile vĂ”imalik ainult 32-bitise ĂŒhtluse jĂ€rgi ning ei saa laadida pool-sĂ”na ega baiti — kui ĂŒritate laadida filtrit ldh [0] sĂŒsteemikutsumine , ja palju muud. tagastab EINVAL. Laetavate filtrite kontrolli teostab funktsioon seccomp_check_filter() tuumad. (Naljakas on see, et algses kommitees, mis lisas seccomp'i funktsionaalsuse, unustati see kĂ€sklus lubada lisada. mod (jÀÀk) ja nĂŒĂŒd pole see seccomp BPF programmidele kĂ€tte saadav, kuna selle lisamine katkestaks ABI.)

PĂ”himĂ”tteliselt teame me juba kĂ”ike, et kirjutada ja lugeda seccomp programme. Tavaliselt on programmi loogika ĂŒles ehitatud nagu valge vĂ”i must nimekiri sĂŒsteemi kutsest, nĂ€iteks programm

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

kontrollib musta nimekirja neljast sĂŒsteemi kutsest numbritega 304, 176, 239, 279. Mis need sĂŒsteemi kutsed on? Me ei saa öelda tĂ€pselt, kuna me ei tea, millise arhitektuuri jaoks programm kirjutati. Seega seccomp autorid pakuvad peavad kĂ”iki programme alustama arhitektuuri kontrollimisega (praegune arhitektuur on kontekstis mÀÀratletud kui vĂ€li arch struktuurid struct seccomp_data). Arhitektuuri kontrollimisega nĂ€eks nĂ€ide vĂ€lja nagu:

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

ja siis oleksid meie sĂŒsteemi kutsed kindlate vÀÀrtustega.

Kirjutame ja laadime seccomp filtreid kasutades. libseccomp'i abil

Masinkoodide vĂ”i BPF assembleri filtrite kirjutamine vĂ”imaldab saavutada tĂ€ielikku kontrolli tulemuste ĂŒle, kuid vahel on eelistatum omada ĂŒlekantavat ja/vĂ”i loetavat koodi. Siin tuleb appi raamatukogu libseccomp'i abil, mis pakub standardset liidest mustade vĂ”i valge filtrite kirjutamiseks.

VĂ”tame nĂ€iteks, et kirjutame programmi, mis kĂ€ivitab binaarfaili, valides kasutaja, eelnevalt seadistades sĂŒsteemikutsungite musta nimekirja ĂŒlepoolmainitud artiklist (programm on lihtsustatud suurema loetavuse huvides, tĂ€ieliku variandi leiate siin):

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

Alustuseks mÀÀrame massiivi sys_numbers ĂŒle 40 sĂŒsteemikutsungi numbriga, mida blokeerida. SeejĂ€rel initsialiseerime konteksti ctx ja ĂŒtleme raamatukogule, et tahame lubada (SCMP_ACT_ALLOW) kĂ”ik sĂŒsteemikutsungid vaikimisi (mustade nimekirjade koostamine on lihtsam). SeejĂ€rel lisame, ĂŒks haaval, kĂ”ik mustade nimekirja sĂŒsteemikutsungid. Vastusena loetletud sĂŒsteemikutsungile kĂŒsime SCMP_ACT_TRAP, sel juhul saadab seccomp protsessile signaali SIGSYS sĂŒsteemikĂ”ne, mis rikkus reegleid. LĂ”puks laadime programmi tuumale lĂ€bi seccomp_load, mis kompileerib programmi ja seob selle protsessiga sĂŒsteemikĂ”ne abil seccomp(2).

Eduka kompileerimise jaoks peab programm olema seotud raamatukoguga libseccomp'i abil, nÀiteks:

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

Edukate kÀivituste nÀide:

$ ./seccomp_lib echo ok
ok

Blokeeritud sĂŒsteemikĂ”ne nĂ€ide:

$ sudo ./seccomp_lib mount -t bpf bpf /tmp
Halb sĂŒsteemikĂ”ne

Kasutame strace, et saada rohkem teavet:

$ 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} ---
+++ SIGSYS tÔttu tapetud (kernel dump) +++
Halb sĂŒsteemikĂ”ne

millest saame teada, et programm lĂ”petati keelatud sĂŒsteemikĂ”ne kasutamise tĂ”ttu mount(2).

KokkuvĂ”ttes kirjutasime filtri lĂ€bi raamatukogu libseccomp'i abil, mahutades keerulise koodi nelja rida. Eespooltoodud nĂ€ites, kui on palju sĂŒsteemikĂ”nesid, vĂ”ib tĂ€itmiskiirus mĂ€rgatavalt vĂ€heneda, kuna kontrollimine on lihtsalt loend vĂ”rdlustest. Optimeerimise jaoks on hiljuti libseccompis kasutusele vĂ”etud plaastrit, lisades filtri atribuutide toe SCMP_FLTATR_CTL_OPTIMIZE. Kui seate selle atribuudi vÀÀrtuseks 2, muutub filter binaarse otsingu programmiks.

Kui soovite nĂ€ha, kuidas binaarse otsingu filtrid töötavad, vaadake lihtsat skripti, mis genereerib selliseid BPF-i assemblerprogramme sĂŒsteemikutsungite nimekirja pĂ”hjal, nĂ€iteks:

$ 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

Mitte midagi oluliselt kiiremat kirjutada ei Ônnestu, kuna BPF-programmid ei saa haruteed teha (me ei saa nÀiteks teha, jmp A vÔi jmp [label+X]) ja seetÔttu on kÔik harud staatilised.

seccomp ja strace

KĂ”ik teavad utiliiti strace — asendamatu tööriist protsesside kĂ€itumise uurimisel Linuxis. Kuid paljud on ka teadlikud toimivuse probleemidest selle utiliidi kasutamisega. Asi on selles, et strace on teostatud ptrace(2), ja selles mehhanismis ei saa me mÀÀrata, millistel sĂŒsteemikutsungite kogumitel peame protsessi peatama, st nĂ€iteks kĂ€sud

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

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

ja

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

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

toimivad umbes sama aja jooksul, kuigi teisel juhul soovime jĂ€lgida ainult ĂŒhte sĂŒsteemikĂ”net.

Uus valik --seccomp-bpf, mis lisati strace versioonis 5.3, vĂ”imaldab oluliselt kiirendada protsessi ja ĂŒhe sĂŒsteemikĂ”ne jĂ€lgimise kĂ€ivitusaeg on juba vĂ”rreldav tavalise kĂ€ivitamise ajaga:

$ 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

(Siin on muidugi vĂ€ike vale, et me ei jĂ€lgi selle kĂ€su peamist sĂŒsteemikĂ”net. Kui me jĂ€lgiksime nĂ€iteks newfsstat, siis strace tĂ”kestaks ta nii palju kui ka ilma --seccomp-bpf.)

Kuidas see valik töötab? Ilma selleta strace ĂŒhendab protsessi ja kĂ€ivitab selle abil PTRACE_SYSCALL. Kui juhitav protsess kĂ€ivitab (iga) sĂŒsteemikĂ”ne, antakse juhtimine strace, mis vaatab sĂŒsteemikĂ”ne argumendid ĂŒle ja kĂ€ivitab selle abil PTRACE_SYSCALL. MĂ”ne aja pĂ€rast lĂ”petab protsess sĂŒsteemikĂ”ne ja vĂ€ljudes antakse juhtimine taas strace, mis vaatab tagastatavad vÀÀrtused ĂŒle ja kĂ€ivitab protsessi abil PTRACE_SYSCALL, jne.

BPF kÔige vÀiksematele, osa null: klassikaline BPF

Seccomp'i abilitesega saame selle protsessi optimeerida just nii, nagu me soovime. Kui soovime keskenduda ainult sĂŒsteemikĂ”nedele, X, saame kirjutada BPF filtri, mis X tagastab vÀÀrtuse SECCOMP_RET_TRACE, samas kui meile mittehuvitavad kĂ”ned — SECCOMP_RET_ALLOW:

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

Sel juhul strace kĂ€ivitame protsessi esmalt kui PTRACE_CONT, iga sĂŒsteemikĂ”ne kohaselt töötab meie filter. Kui sĂŒsteemikĂ”ne ei X, siis protsess jĂ€tkab töötamist, kuid kui see on X, siis seccomp edastab kontrolli strace, mis vaatab argumentoone ja kĂ€ivitab protsessi kui PTRACE_SYSCALL (kuna seccomp ei vĂ”imalda kĂ€ivitada programmi sĂŒsteemikĂ”ne vĂ€ljundist). Kui sĂŒsteemikĂ”ne naaseb, strace kĂ€ivitab protsessi uuesti PTRACE_CONT ja ootab uusi sĂ”numeid seccompilt.

BPF kÔige vÀiksematele, osa null: klassikaline BPF

Valiku kasutamisel --seccomp-bpf on kaks piirangut. Esiteks, ei saa liituda juba olemasoleva protsessiga (valik -p programmede strace), kuna seda ei toeta seccomp. Teiseks, ei ole vĂ”imalik ei vaadata tĂŒtarprotsesse, kuna seccomp filtrid pĂ€randatakse kĂ”igile tĂŒtarprotsessidele, ilma vĂ”imaluseta see vĂ€lja lĂŒlitada.

Veidi rohkem teavet selle kohta, kuidas strace töötleb , ja palju muud. saab teada hiljutisest aruandest. Meie jaoks on kÔige huvitavam fakt see, et klassikaline BPF, esindatud seccomp'iga, leiab endiselt rakendamist.

xt_bpf

Mineme nĂŒĂŒd tagasi vĂ”rkude maailma.

Eellugu: ammu, 2007. aastal, lisati tuuma lisatud mooduli xt_u32 netfilter'ile. See kirjutati analoogia alusel veelgi vanema liikluse klassifikaatoriga cls_u32 ja vÔimaldas kirjutada mis tahes binaarseid reegleid iptables'i abil jÀrgmiste lihtsate toimingute kaudu: laadida 32 bitti paketist ja teha nendega hulga aritmeetilisi operatsioone. NÀiteks,

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

Laeb 32 bitti IP-peast, alustades nihkest 6, ja rakendab sellele maski 0xFF (vĂ”ta madalam bait). See on IP-ape ja me vĂ”rreldame seda 1-ga (ICMP). Ühes reeglites saab kombineerida palju kontrolle ja samuti saab teha operaatori protocol — liikuda X bitti paremale. NĂ€iteks, reegel @ iptables -m u32 --u32 "6&0xFF=0x6 && 0>>22&0x3C@4=0x29"

kontrollib, kas TCP jÀrjestuse number

. Ei hakka rohkem detailidesse minema, kuna on juba selge, et kĂ€sitsi selliseid reegleid kirjutada pole eriti mugav. Artiklis 0x29BPF — unustatud baitkood BPF — unustatud bytecode, on mitmeid linke, mis sisaldavad nĂ€iteid eeskirjade rakendamise ja genereerimise kohta, xt_u32. Vaata ka allolevaid linke artikli lĂ”pus.

Alates 2013. aastast on mooduli asemel saadaval xt_u32 BPF-pÔhine moodul, xt_bpf. KÔigile, kes siiani on lugenud, peab olema selge selle tööpÔhimÔte: BPF-bytecode kÀivitamine iptables reeglite kujul. Uue reegli saab luua nÀiteks jÀrgmiselt:

iptables -A INPUT -m bpf --bytecode  -j LOG

siit <баĐčтĐșĐŸĐŽ> — see on assembleri vĂ€ljundformaadis kood bpf_asm vaikesĂ€tetega, nĂ€iteks,

$ 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

Selles nĂ€ites filtreerime kĂ”ik UDP paketid. BPF programmi kontekst moodulis xt_bpf, nĂ€itab loomulikult paketi andmeid, iptables puhul IPv4 pealkirja algust. BPF-programmist tagastatav vÀÀrtus boolean, kus false tĂ€hendab, et pakett ei ĂŒhti.

On selge, et moodul xt_bpf toetab keerukamaid filtreid kui eespool toodud nĂ€ites. Vaatame tĂ”elisi nĂ€iteid ettevĂ”ttelt Cloudflare. Veel hiljuti kasutasid nad moodulit xt_bpf DDoS rĂŒnnakute kaitsmiseks. Artiklis Introducing the BPF Tools nad rÀÀgitakse, kuidas (ja miks) nad genereerivad BPF filtreid ja avaldavad linke tööriistade kogumile nende filtrite loomiseks. NĂ€iteks tööriista abil bpfgen saab luua BPF programmi, mis matĆĄib DNS-pĂ€ringu nimega 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

Programmis laadime me alguses registrisse X stringi alguspunkti aadressi x04habrx03comx00 UDP-datagrammi sees ja seejÀrel kontrollime pÀringut: 0x04686162 "x04hab" Kui kaua aega kulub vÀljastamiseks?

Veidi hiljem avaldas Cloudfare p0f kompilaatori koodi -> BPF. Artiklis Introducing the p0f BPF compiler rÀÀgitakse, mis on p0f ja kuidas p0f allkirju BPF-ks teisendada:

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

Praegu ei kasuta Cloudfare enam xt_bpf, kuna nad on ĂŒle kolinud XDP-le — ĂŒks vĂ”imalustest kasutada BPF uue versiooni, vt. L4Drop: XDP DDoS leevendused.

cls_bpf

Viimane klassikalise BPF kasutamise nĂ€ide tuumas on klassifikaator cls_bpf Linuxi liikluse kontrolli alamsĂŒsteemis, mis lisati Linuxisse 2013. aasta lĂ”pus ja asendas kontseptuaalselt vana cls_u32.

Me ei hakka praegu klassikalise BPF toimimist kirjeldama. cls_bpf, kuna selle klassikalise BPF ĂŒlevaade ei anna meile uusi teadmisi — oleme juba tutvunud kĂ”igi funktsioonidega. Lisaks kohtame edasistes artiklites, mis rÀÀgivad Extended BPF-st, selle klassifikaatoriga veel korduvalt.

Veel ĂŒks pĂ”hjus, miks klassikalise BPF kasutamisest mitte rÀÀkida, cls_bpf on see, et vĂ”rreldes Extended BPF-iga on selle kasutusala oluliselt kitsendatud: klassikalised programmid ei saa pakettide sisu muuta ega saa sĂ€ilitada olekut kutsungite vahel.

Nii et on aeg klassikalisest BPF-ist lahkuda ja tulevikku vaatama.

HĂŒvasti klassikalise BPF-ga

Oleme vaadanud, kuidas BPF tehnoloogia, mille arendasid vĂ€lja 90ndate alguses, on edukalt ĂŒle elanud veeranda sajandi ja leidnud uusi kasutusvĂ”imalusi. Kuid just nagu siirdumine virnamasinatelt RISC-le, mis andis tĂ”uke klassikalise BPF arendusele, toimus 2000ndatel ĂŒleminek 32-bitistelt 64-bitiste masinatele ning klassikaline BPF hakkas vananema. Peale selle on klassikalise BPF vĂ”imalused tugevalt piiratud: koos vananenud arhitektuuriga — meil puudub vĂ”imalus salvestada olekut BPF programmide vahel, puudub vĂ”imalus otse kasutajaga suhelda, ning meil puudub interaktsioon tuumaga, vĂ€lja arvatud piiratud struktuuri vĂ€ljade lugemine. sk_buff ja kĂ”ige lihtsamate abifunktsioonide kĂ€ivitamine, ei saa pakettide sisu muuta ega neid suunata.

Tegelikult on tÀnapÀeval klassikalisest BPF-st Linuxis jÀÀnud vaid API-liides, samas kui kÔik klassikalised programmid, olgu need siis sokli filtrid vÔi seccomp filtrid, tÔlgitakse automaatselt uude formaati, Extended BPF. (Me rÀÀgime, kuidas see tÀpselt toimub jÀrgmisel artiklil.)

Uue arhitektuuri ĂŒleminek algas 2013. aastal, kui Aleksei Starovoitov pakkus vĂ€lja BPF-i uuendamise skeemi. 2014. aastal alanud vastavad patchid hakavad ilmuma kerneles. Nii palju, kui ma tean, oli algselt plaanis vaid arhitektuuri ja JIT-kompilaatori optimeerimine, et saavutada tĂ”husam töö 64-bitistes masinates, kuid selle asemel andsid need optimeerimised uue peatĂŒki alguse Linuxi arenduses.

Edasi jĂ€rgmistes artiklites selgitatakse uue tehnoloogia arhitektuuri ja rakendusi, mis algselt oli tuntud kui internal BPF, hiljem extended BPF ja nĂŒĂŒd lihtsalt BPF.

Lingid

  1. Steven McCanne ja Van Jacobson, "BSD Packet Filter: Uus arhitektuur kasutaja tasemel paketikaaperduseks", https://www.tcpdump.org/papers/bpf-usenix93.pdf
  2. Steven McCanne, "libpcap: Arhitektuuri ja optimeerimise metodologia paketikaaperduseks", https://sharkfestus.wireshark.org/sharkfest.11/presentations/McCanne-Sharkfest'11_Keynote_Address.pdf
  3. tcpdump, libpcap: https://www.tcpdump.org/
  4. IPtable U32 Match Ôpetus.
  5. BPF — unustatud baitkood: https://blog.cloudflare.com/bpf-the-forgotten-bytecode/
  6. BPF tööriista tutvustus: https://blog.cloudflare.com/introducing-the-bpf-tools/
  7. bpf_cls: http://man7.org/linux/man-pages/man8/tc-bpf.8.html
  8. Seccomp ĂŒlevaade: https://lwn.net/Articles/656307/
  9. https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
  10. habr: Konteinerid ja turvalisus: seccomp
  11. habr: Isolatsioon demoonide abil systemd-s vĂ”i „selleks pole teil Dockerit vaja!”
  12. Paul Chaignon, "strace —seccomp-bpf: pilk kapoti alla" https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
  13. netsniff-ng: http://netsniff-ng.org/

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster