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

Berkeley Packet Filters (BPF) on Linuxi tuumor, mis on juba mitu aastat olnud ingliskeelsete tehniliste vĂ€ljaannete esikĂŒlgedel. Konverentse on tĂ€is ettekandeid BPF-i kasutamise ja arendamise kohta. David Miller, Linuxi vĂ”rgu alamsĂŒsteemi hooldaja, nimetab oma ettekannet Linux Plumbers 2018. «See ettekanne ei kĂ€sitle XDP-d» (XDP on ĂŒks BPF-i kasutamise variante). Brendan Gregg peab ettekandeid, mille pealkiri on Linux BPF Superpowers. Toke HĂžiland-JĂžrgensen naerab, et tuuma on nĂŒĂŒd microkernel. Thomas Graf reklaamib ideed, et BPF on JavaScript tuuma jaoks..

HabrĂĄs ei ole veel sĂŒsteemset kirjeldust BPF-ist ja seetĂ”ttu pĂŒĂŒan ma oma artiklite seerias rÀÀkida tehnoloogia ajaloost, kirjeldada arhitektuuri ja arendusvahendeid, visandada kasutusalad ja BPF-i kasutamise tavad. Selles, nulls artiklis, antakse ĂŒlevaade klassikalise BPF-i ajaloost ja arhitektuurist, samuti paljastatakse tööpĂ”himĂ”tete saladused tcpdump, seccomp, strace, ja palju muud.

BPF-i arendust juhib Linuxi vÔrgu kogukond, peamised olemasolevad BPF-i rakendused on seotud vÔrkudega ja seetÔttu, lubades @eucariot, nimetas ma seeria "BPF kÔige vÀiksematele", kuulsale seeriale "VÔrgud kÔige vÀiksematele".

BPF-i ajalugu lĂŒhidalt (c)

Kaasaegne BPF-tehnoloogia on tĂ€iustatud ja tĂ€iustatud versioon vanast tehnoloogiast, mida nimetatakse nĂŒĂŒd, et vĂ€ltida segadust, klassikaliseks BPF-iks. Klassikalise BPF-i baasil on loodud tuntud tööriist tcpdump, mehhanism seccomp, samuti vĂ€hem tuntud moodul xt_bpf jaoks iptables ja klassifikaator cls_bpf. Kaasaegses Linuxis tĂ”lgitakse klassikalised BPF-programmid automaatselt uude vormi, kuid kasutaja seisukohalt on API jÀÀnud samaks ja klassikalise BPF-i uued rakendused, nagu me selle artikli kĂ€igus nĂ€eme, on endiselt olemas. SellepĂ€rast, samuti seetĂ”ttu, et klassikalise BPF-i ajaloo jĂ€lgimine Linuxis nĂ€itab, kuidas ja miks see on arenenud kaasaegsesse vormi, otsustasin alustada just klassikalise BPF-i artiklist.

KaheksakĂŒmnendate aastate lĂ”pus huvitusid tuntud Lawrence Berkeley Laboratori insenerid kĂŒsimusest, kuidas Ă”igesti filtreerida vĂ”rgu pakette tol ajal olemasolevatel seadmetel. Filtreerimise pĂ”hiidee, mis algselt realiseeriti CSPF (CMU/Stanford Packet Filter) tehnoloogias, seisnes selles, et filtreerida liigsed paketid nii varakult kui vĂ”imalik, st kernelis, kuna see vĂ”imaldab mitte kopeerida liigseid andmeid kasutaja ruumi. KĂ€itusaja turvalisuse tagamiseks kasutati kernelis kasutajakoode kĂ€itamiseks virtuaalmasinat — liivakasti.

Kuid virtuaalmasinad olemasolevatele filtritele olid projekteeritud töötama kuhja arhitektuuril ja uutel RISC masinatel töö olid vĂ€hem efektiivsed. LĂ”puks töötas Berkeley Labs'i inseneride jĂ”upingutustel vĂ€lja uus tehnoloogia BPF (Berkeley Packet Filters), mille virtuaalmasina arhitektuur oli projekteeritud Motorola 6502 protsessori pĂ”hjal — tööloom selliste tuntud toodete vĂ€ltel nagu Apple II vĂ”i NES. Uus virtuaalmasin suurendas filtrite jĂ”udlust mitmekĂŒmne korra vĂ”rreldes olemasolevate lahendustega.

BPF masina arhitektuur

Me tutvume masina arhitektuuriga tööalaselt, analĂŒĂŒsides nĂ€iteid. Kuid alustuseks ĂŒtlemine, et masinal oli kaks kasutajale ligipÀÀsetavat 32-bitist registrit, akumulaator A ja indeksregister X, 64 baiti mĂ€lu (16 sĂ”na), mis oli kirjutamiseks ja edaspidiseks lugemiseks saadaval, ning vĂ€ike kĂ€skude sĂŒsteem nende objektidega töötamiseks. Programmides olid saadaval ka hĂŒppeinstruktsioonid tingimuslike lause rakendamiseks, kuid programmi Ă”igeaegse lĂ”petamise tagamiseks tohtis hĂŒpata ainult edasi, st konkreetselt oli keelatud luua tsĂŒkleid.

Masina töö ĂŒldskeem on jĂ€rgmine. Kasutaja koostab programmi BPF arhitektuurile ja, kasutades mingit kernelimehhanismi (nĂ€iteks sĂŒsteemi kĂ”ne), laadib ja ĂŒhendab programmi mingi sĂŒndmuste generaatoriga kernelis (nĂ€iteks sĂŒndmus — jĂ€rgmise paketi saabumine vĂ”rgu kaardile). SĂŒndmuse tekkimisel kĂ€ivitab kernel programmi (nĂ€iteks tĂ”lgendi kaudu), samal ajal kui masina mĂ€lu on kooskĂ”las mingi tuuma mĂ€lu tuumast (nĂ€iteks saabunud paketi andmetest).

Ülaltoodud piisab meile, et alustada nĂ€idete uurimist: vajaduse korral tutvume sĂŒsteemi ja kĂ€skude vorminguga. Kui aga soovite kohe teada saada virtuaalmasina kĂ€skude sĂŒsteemi ja selle kĂ”ikidest vĂ”imalustest, siis saate lugeda originaalartiklit BSD paketikott ja/vĂ”i faili esimesest poolest Dokumentatsioon/networking/filter.txt tuuma dokumentatsioonist. Lisaks saab tutvuda esitlustega libpcap: Paketi puuri arhitektuur ja optimeerimise metodoloogia, kus McCanne, ĂŒks BPF autoritest, rÀÀgib selle loomise ajaloost libpcap.

KĂ€ime nĂŒĂŒd lĂ€bi kĂ”ik olulised klassikalise BPF rakendused Linuxis: tcpdump (libpcap), seccomp, xt_bpf, cls_bpf.

tcpdump

BPF arendamine toimus samaaegselt tuntud paketikottide filtreerimise tööriista - kĂ”igile teada oleva utiliidi - arendamisega. tcpdump. Kuna see on vanim ja kĂ”ige tuntum klassikalise BPF rakendustest, saadaval paljudes operatsioonisĂŒsteemides, alustame tehnoloogia uurimist just sellest.

(KÔiki selle artikli nÀiteid jooksutasin Linuxis 5.6.0-rc6. MÔnede kÀskude vÀljund on muudetud suurema loetavuse saavutamiseks.)

NÀide: jÀlgime IPv6 pakette

Kujutage ette, et soovime jÀlgida kÔiki IPv6 pakette liideses eth0. Selleks saame kÀivitada programmi tcpdump lihtsa filtriga ip6:

$ sudo tcpdump -i eth0 ip6

Selle juures tcpdump kompileerib filtri ip6 BPF arhitektuuri baitkoodiks ja saadab selle tuumale (vt ĂŒksikasju peatĂŒkis Tcpdump: laadimine). Laaditud filter kĂ€ivitatakse iga paketi jaoks, mis lĂ€bib liidest eth0. Kui filter tagastab mitte nullvÀÀrtuse n, siis n paketi baitidest kopeeritakse kasutaja ruumi ja nĂ€eme seda vĂ€ljundis tcpdump.

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

Selgub, et saame lihtsalt teada, millist baitkoodi tuumale saatsime tcpdump kasutades 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

Esimesel real kĂ€ivitame kĂ€su ldh [12], mis deĆĄifreeritakse kui "lae registrisse A pool-sĂ”na (16 bitti), mis asub aadressil 12" ja ainus kĂŒsimus on, millisest mĂ€lust me rÀÀgime? Vastus on see, et aadressil x alustatakse (x+1)-ndat baiti analĂŒĂŒsitavast vĂ”rgu paketist. Me loeme pakette Etherneti liidese kaudu eth0, ja see tĂ€hendab tĂ€hendab, et pakett nĂ€eb vĂ€lja jĂ€rgmine (lihtsuse huvides oletame, et pakett ei sisalda VLAN silte):

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

Nii et pĂ€rast kĂ€su tĂ€itmist ldh [12] registreerimise A tuleb vĂ€lja vĂ€li Ether Type — edastatava paketi tĂŒĂŒp, mis sisaldub selles Etherneti raamises. Reedel 1 vĂ”rreldame registri sisu A (paketi tĂŒĂŒp) c 0x86dd, ja see tĂ€hendab ja see on meie huvi pakkuv IPv6 tĂŒĂŒp. Reedel 1 on lisaks vĂ”rdluskĂ€sule veel kaks veergu — jt 2 ja jf 3 — silte, kuhu tuleb liikuda eduka vĂ”rdluse korral (A == 0x86dd) ja ebaeduka korral. Nii et eduka juhtumi (IPv6) korral liigume reele 2, ebaeduka korral reele 3. Reedel 3 lĂ”petab programm koodiga 0 (paketti ei kopeerita), reedel 2 lĂ”petab programm koodiga 262144 (kopeeri mulle maksimaalselt 256 kilobaiti paketti).

Veidi keerulisem nÀide: vaatame TCP pakette sihtporti lÀbi

Vaadake, kuidas filtreerija, mis kopeerib kĂ”ik TCP paketid sihtporti 666. Uurime IPv4 juhtumit, kuna IPv6 juhtum on lihtsam. PĂ€rast selle nĂ€ite uurimist vĂ”ite harjutusena iseseisvalt uurida IPv6 filtri (ip6 and tcp dst port 666) ja filtri ĂŒldise juhtumi (tcp dst port 666). Nii et meie huvi pakkuv filter nĂ€eb vĂ€lja jĂ€rgmiselt:

$ 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

Mida teevad read 0 ja 1, me juba teame. Reedel 2 oleme juba kontrollinud, et see on IPv4 pakett (Ether Type = 0x800) ja laadime registrisse A paketi 24. baiti. Meie pakett nÀeb vÀlja nagu

       14            8      1     1
|etherneti pea|ip vÀljad|ttl|protokoll|...

seega laadime registrisse A IP peaaia Protokoll, mis on mÔistetav, sest me tahame kopeerida ainult TCP pakette. Me vÔrdleme Protokolli 0x6 (IPPROTO_TCP) reedetel 3.

Reedel 4 ja 5 laadime pool sĂ”na, mis asub aadressil 20, ja kĂ€su abil jset kontrollime, kas ega ĂŒks kolmest lipukesest — antud maskis jset on kolm kĂ”ige tĂ€htsamat bitti puhastamata. Kaks kolme bittide hulgast annavad meile teada, kas pakett on fraktsioonitud IP paketi osa, ja kui jah, kas see on viimane fraktsioon. Kolmas bitt on reserveeritud ja peab olema null. Me ei soovi kontrollida ei tĂ€is- ega vigased pakette, seetĂ”ttu kontrollime kĂ”iki kolme bitti.

Reede 6 on selle loendi kĂ”ige huvitavam. Avaldus ldxb 4*([14]&0xf) tĂ€hendab, et laadime registrisse X neljandad madalamad bitid viieteistkĂŒmnendas baitis, korrutatud 4. Neljandad madalamad bitid viieteistkĂŒmnendas baitis on vĂ€li Internet Header Length IPv4 pĂ€ises, kus salvestatakse pĂ€ise pikkus sĂ”nades, seetĂ”ttu tuleb see hiljem korrutada 4-ga. Huvi pakub, et vĂ€ljend 4*([14]&0xf) on eriline adresseerimise skeem, mida saab kasutada ainult sellisel kujul ja ainult registri puhul X, st me ei saa öelda ei ldb 4*([14]&0xf) ei ldxb 5*([14]&0xf) (saame ainult mĂ€rkida teise offseti, nĂ€iteks ldxb 4*([16]&0xf)). Selge on, et see adresseerimise skeem lisati BPF just selleks, et jĂ”uda X (indekseerimisregister) IPv4 pĂ€ise pikkuseni.

Nii et real 7 proovime laadida pool-sÔna aadressilt (X+16). Meenutades, et 14 baiti hÔlmab Etherneti pÀist, ja X sisaldab IPv4 pÀise pikkust, mÔistame, et A laaditakse TCP sihtport:

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

LĂ”puks, real 8 vĂ”rdleme sihtporti soovitud vÀÀrtusega ja ridadel 9 vĂ”i 10 tagastame tulemuse — kas kopeerida pakett vĂ”i mitte.

Tcpdump: laadimine

Eelnevates nĂ€idetes ei peatunud me tĂ€pselt sellel, kuidas me laadime BPF bytecode'i kernelisse pakettide filtreerimiseks. Üldiselt, tcpdump on see portiteeritud paljudele sĂŒsteemidele ja filtreid kasutades tcpdump , tĂ€psemalt — kirjutame kaks funktsiooni: ĂŒks pseudo-ristkĂŒlikulise maatriksi kasutamisega (mida ei soovitata praktiliselt, kuna see on arvutuslikult keeruline ja ebatavaline), teine maatrikuvĂ”rrandi abil. libpcap. LĂŒhidalt, et panna filter liidesele kasutades libpcap, tuleb teha jĂ€rgmiselt:

Kuna nÀha, kuidas funktsioon pcap_setfilter on Linuxis teostatud, 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 toores soketi kĂ”igi Etherneti kaadrite lugemiseks ja seome selle liidesega eth0. Meie esimesest nĂ€itest teame, et filter ip koosneb neljast BPF kĂ€sklusest, ja kolmandal real nĂ€eme, kuidas lĂ€bi SO_ATTACH_FILTER system call setsockopt laadime ja ĂŒhendame 4-pikkuse filtri. Just see on meie filter.

On tuleb mĂ€rkida, et klassikalises BPF-is toimub filtri laadimine ja liitmine alati aatomaarse operatsioonina, samas kui BPF-i uues versioonis on programmi laadimine ja selle sidumine sĂŒndmuste generaatoriga ajaliselt eraldatud.

Peidetud tÔde

Veidi tÀielikum versioon vÀljundist on jÀrgmine:

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

Nagu eespool mainitud, laadime ja liidame meie filtri soketiga real 5, kuid mis toimub ridadel 3 ja 4? Selgub, et see libpcap muretseb meie eest — et meie filtri vĂ€ljundisse ei satuks pakette, mis sellele ei vasta, raamatukogu liidab vale filtri ret #0 (kĂ”ik paketid visata kĂ”rvale), muudab soketi mitteblokeerivaks ja proovib lugeda kĂ”ik paketid, mis vĂ”isid jÀÀda eelmistelt filtritelt.

Seega, et filtreerida pakette Linuxis klassikalise BPF-i kaudu, on vajalik filter struktuuri tĂŒĂŒbina struct sock_fprog ja avatud soket, pĂ€rast mida saab filtri soketiga siduda sĂŒsteemikĂ”ne abil setsockopt.

On huvitav, et filter saab liita igasuguste soketitega, mitte ainult raw. Siin on nÀide programm, mis lÔikab kÔik vÀlja, vÀlja arvatud kaks esimest bitti kÔigist sissetulevatest UDP datagrammidest. (Kommentaarid olen lisanud koodi, et artiklit mitte koormata.)

Rohkem teavet filtri setsockopt sidumise kohta vt socket(7), ja oma filtrite kirjutamise kohta struct sock_fprog ilma abita tcpdump rÀÀgime jaotises BPF-i programmeerimine oma kÀtega.

Klassikaline BPF ja XXI sajand

BPF lisati Linuxisse 1997. aastal ja pĂŒsis kaua aega tööhobuse rollis libpcap ilma eriliste muudatusteta (Linuxi-spetsiifilised muudatused, muidugi, olid, kuid need ei muutnud globaalses pildis midagi). Esimesed tĂ”sised mĂ€rgid, et BPF hakkab arenema, ilmusid 2011. aastal, kui Eric Dumazet pakkus patĆĄ, mis lisas kernelisse Just In Time Compileri — tĂ”lkija BPF-i bytecode-i muundamiseks natiivseks x86_64 koodiks.

JIT kompilaator oli esimeseks muutuste ahelas: 2012. aastal on oli vÔimalik kirjutada filtreid seccomp, kasutades BPF-i, jaanuaris 2013 ilmus on lisatud moodul xt_bpf, mis vÔimaldas kirjutada reegleid iptables BPF-i abil, ja oktoobris 2013 ilmus on lisatud ka moodul cls_bpf, vÔimaldades BPF-i abil liiklusklassifikaatoreid kirjutada.

Kuna vĂ”imalused, mille raamatukogu pakub, on piiratud (lihtne nĂ€ide: filtreer, mis on genereeritud libpcap vĂ”ib tagastada ainult kaks vÀÀrtust — 0 vĂ”i 0x40000) vĂ”i ei ole ĂŒldse kohaldatavad, nagu seccompi puhul. libpcap Tutvume BPF-i binaarfaili formaadiga, mis on vĂ€ga lihtne:

BPF-i programmeerimine oma kÀtega

16 8 8 32 | kood | jt | jf | k |

   Iga kĂ€sk vĂ”tab 64 bitti, kus esimesed 16 bitti on kĂ€su kood, seejĂ€rel kaks 8-bitist lĂŒlitust,

jt jf ja , ja 32 bitti argumendi jaoks,, mille tĂ€hendus muutub vastavalt kĂ€sklusele. NĂ€iteks kĂ€sk K, mis lĂ”petab programmi, omab koodi ret, ja tagastatav vÀÀrtus vĂ”etakse konstandist 6. C keeles esindatakse ĂŒhte BPF-i kĂ€sku struktuurina Kstruct sock_filter { __u16 kood; __u8 jt; __u8 jf; __u32 k; }

ja tervet programmi struktuurina

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

Nii et me saame juba kirjutada programme (kÀskude koodid on meil juba teada

). Nii vÀlja nÀeb filter [1]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, }; ip6 API-s esimesest nÀitest:

prog

Programm saame seaduseselt kasutada funktsioonis setsockopt(sk, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog))

Programme masina koodina kirjutamine ei ole vĂ€ga mugav, kuid vahel on see vajalik (nĂ€iteks silumise, ĂŒksuste testide loomise, artiklite kirjutamise ajal jne). Mugavuse huvides mÀÀratakse failis

<linux/filter.h> abil abimakrosid — sama nĂ€ide, mis eespool, vĂ”iks ĂŒmber kirjutada kui 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 ka seda varianti ei saa mugavaks nimetada. Nii arvasid ka Linuxi kerneli arendajad, seetÔttu vÔib kernelikataloogist

tools/bpf leida assembleri ja debuggeri klassikalise BPF-i jaoks. Assembleri keel sarnaneb vÀga silumise vÀljundiga

, kuid lisaks saame mÀÀrata sĂŒmboolseid silte. NĂ€iteks programm, mis viskab kĂ”ik paketid, vĂ€lja arvatud TCP/IPv4: tcpdump$ 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

Vaikimisi genereerib assembler koodi formaadis , ,..., meie TCP nÀite puhul saadakse

$ 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 vÔib 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 tĂŒĂŒbi struktuuri mÀÀratlemisse struct sock_filter, nagu me kĂ€esoleva jaotise alguses tegime.

Linuxi ja netsniff-ng laiendused

Lisaks standardsetele BPF kĂ€skudele toetavad Linux ja tools/bpf/bpf_asm ka mittestandardset komplekti. Peamiselt teenivad kĂ€skud nĂ”utud struktuuri laagri vĂ€ljadele pÀÀsemiseks struct sk_buff, mis kirjeldab vĂ”rkpakkide struktuuri tuumas. Samas on ka teise tĂŒĂŒbi abikĂ€skud, nĂ€iteks ldw cpu laadib registrisse A tuuma funktsiooni kĂ€itamise tulemuse raw_smp_processor_id().(Uues BPF versioonis on neid mittestandardseid laiendusi laiendatud programmide paaride ja kernel helpers kogumi kaudu mĂ€lule, struktuuridele ning sĂŒndmuste genereerimisele.) Siin on huvitav nĂ€ide filterist, kus kopeerime kasutajaruumi ainult pakettide pĂ€ised, kasutades laiendust poff, koormuse offset:

ld poff
ret a

BPF laiendusi ei saa kasutada tcpdump, aga see on hea pĂ”hjus tutvuda utiliitide paketiga netsniff-ng, mis sisaldab, muu hulgas, ka tĂ€iustatud programmi netsniff-ng, mis, peale BPF-ga filtreerimise, sisaldab ka efektiivset liikluse genereerijat ja sageli paremat BPF assemblerit nimega tools/bpf/bpf_asmbpfc. Paketis on ĂŒsna pĂ”hjalik dokumentatsioon, vt ka artikli lĂ”pus olevad lingid.Nii et me oskame juba kirjutada BPF programme mistahes keerukusega ja oleme valmis vaatama uusi nĂ€iteid, esimene neist on tehnoloogia seccomp, mis vĂ”imaldab BPF filterite kaudu hallata mitmeid ja sĂŒsteemikutsungite argumendi komplekti, mis on selle protsessi ja tema jĂ€reltulijate jaoks kĂ€ttevĂ”imalik.

seccomp

Esimene seccomp versioon lisati tuuma 2005. aastal ning see ei olnud suurt populaarsust saavutanud, kuna pakkus ainult ĂŒht vĂ”imalust — piirata mitmeid sĂŒsteemikutsungite varustust, mis sellele protsessile on kĂ€ttevĂ”imalik:

sigreturn lugema, kirjutama, exit ja , kuid protsess, mis reegleid rikkus, surmatiSIGKILL SIGKILL. Kuid 2012. aastal lisati seccompi vĂ”imalus kasutada BPF filtreid, mis vĂ”imaldavad mÀÀrata arvukalt lubatud sĂŒsteemikutseid ning isegi kontrollida nende argumente. (Huvitav on, et Chrome oli ĂŒks esimesi, kes seda funktsionaalsust kasutas, ja praegu töötavad Chrome'i inimesed vĂ€lja KRSI mehhanismi, mis pĂ”hineb uuemal BPF versioonil ja vĂ”imaldab kohandada Linuxi turvamooduleid.) Lisadokumendi viidatud leidub artikli lĂ”pus.

Oluline on ĂŒles mĂ€rkida, et Habril on juba olnud artikleid seccompi kasutamise kohta, vĂ”ib-olla tahab keegi neid lugeda enne (vĂ”i selle asemel), kui liigub edasi jĂ€rgmistele alajaotustele. Artiklis Konteinerid ja turvalisus: seccomp toodud nĂ€ited seccompi kasutamisest nii 2007. aasta versiooni kui ka BPF kasutamise versiooni kohta (filtrid genereeritakse libseccompi abil), rÀÀgitakse seccompi seosest Dockeriga ning antakse palju kasulikke viiteid. Artiklis Isoleerime sĂŒsteemid systemd-ga vĂ”i "sul ei ole Dockerit selle jaoks vaja!" rÀÀgitakse eelkĂ”ige sellest, kuidas lisada sĂŒsteemikutsed mustadesse vĂ”i valgetesse nimekirjadesse systemd halduses oleva sĂŒsteemi jaoks.

Edasi vaatame, kuidas kirjutada ja laadida filtreid seccomp puhta C keele abil ja libseccompi raamatukogust vÀlja. libseccomp ja millised on iga variandi plussid ja miinused; lÔpuks vaatame, kuidas seccompi kasutab programm. strace.

Kirjutame ja laadime seccompi filtreid

Me oskame juba kirjutada BPF programme, seega vaatame esmalt seccomp'i programmiliidest. Filtri saab seadistada protsessi tasemel, kus kĂ”ik lasteprotsessid pĂ€rivad piirangud. See toimub sĂŒsteemikutsungi abil seccomp(2):

seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)

kus &filter — see on viide juba tuttavale struktuurile struct sock_fprog, st BPF programmile.

Kuidas erinevad seccompi programmid soketiprogrammidest? Edastatava konteksti poolest. Sokettide puhul edastati meile mĂ€luala, mis sisaldas paketti, kuid seccompi puhul edastatakse meile struktuur tĂŒĂŒbiga

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

Siin nr — see on kĂ€ivitatava sĂŒsteemikutse number, arch — praegune arhitektuur (sellest allpool), args — kuni kuue sĂŒsteemikutsesse kuuluva argumendiga, ja instruction_pointer — see on viide kasutaja ruumis entsĂŒklilise kĂ€su jaoks, mis tegi selle sĂŒsteemikĂ”ne. Seega peame nĂ€iteks sĂŒsteemikĂ”ne numbri registreerimiseks ĂŒtlema A me peame ĂŒtlema

ldw [0]

Seccomp programmide jaoks on olemas ka teisi eripĂ€ra, nĂ€iteks on juurdepÀÀs kontekstile vĂ”imalik ainult 32-bitise eraldatuse korral ja ei saa laadida poole sĂ”na vĂ”i bait — filtri laadimise katse ldh [0] sĂŒsteemikĂ”ne seccomp tagastab EINVAL. Laadimise filtrite kontrolli teostab funktsioon seccomp_check_filter() kernis. (Naljakana, algses commit'is, mis lisas seccomp funktsionaalsuse, unustati sellele funktsioonile anda loa kasutada instruktsiooni mod (jÀÀk) ja nĂŒĂŒd ei ole see seccomp BPF programmidele saadaval, kuna selle lisamine rikub ABI.)

PĂ”himĂ”tteliselt teame juba kĂ”ike, et kirjutada ja lugeda seccomp programme. Tavaliselt on programmi loogika ĂŒles ehitatud nagu sĂŒsteemikĂ”nede must nimekiri vĂ”i valge nimekiri, 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ĂŒsteemikĂ”nest numbritega 304, 176, 239, 279. Millised need sĂŒsteemikĂ”ned on? Me ei saa tĂ€pselt öelda, kuna me ei tea, millise arhitektuuri jaoks programm kirjutati. SeetĂ”ttu peavad seccomp autorid pakuvad kĂ”iki programme alustama arhitektuuri kontrollimisega (praegune arhitektuur on kontekstis vĂ€lja toodud valdkonnas arch struktuurid struct seccomp_data). Arhitektuuri kontrollimisega vĂ”iks nĂ€ite algus vĂ€lja nĂ€ha nagu:

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

ja siis saaksime meie sĂŒsteemikĂ”nede numbrid kindlad vÀÀrtused.

Kirjutame ja laadime seccomp filtreid kasutades libseccomp

Filtide kirjutamine masinkoodina vĂ”i BPF assembleri jaoks vĂ”imaldab tĂ€ielikku kontrolli tulemuse ĂŒle, kuid samas on mĂ”nikord eelistatavam omada kantavat ja/vĂ”i loetavat koodi. Sellega aitab meil raamatukogu libseccomp, mis pakub standardset liidest mustade vĂ”i valgete filtrite kirjutamiseks.

Kirjutame nĂ€iteks programmi, mis kĂ€ivitab kasutaja valitud binaarfaili, seadistades eelnevalt musta nimekirja sĂŒsteemikĂ”nedest ĂŒles nimetatud artiklist (programm on lihtsustatud parema loetavuse nimel, tĂ€ielikku varianti saab leida siit):

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

Alguses defineerime massiivi sys_numbers ĂŒle 40 sĂŒsteemikĂ”ne numbri blokeerimiseks. Siis initsialiseerime konteksti ctx ja rÀÀgime teegile, et soovime lubada (SCMP_ACT_ALLOW) kĂ”iki sĂŒsteemi kĂ”nesid vaikimisi (mustade nimekirjade koostamine on lihtsam). SeejĂ€rel lisame ĂŒkshaaval kĂ”ik sĂŒsteemi kĂ”ned musta nimekirja. Vastuseks mustal nimekirjal olevale sĂŒsteemi kĂ”nele kĂŒsime SCMP_ACT_TRAP, sel juhul saadab seccomp protsessile signaali SIGSYS kirjeldusega, milline sĂŒsteemi kĂ”ne reegleid rikkus. LĂ”puks laadime programmi kĂ€rku kasutades seccomp_load, mis kompileerib programmi ja ĂŒhendab selle protsessiga sĂŒsteemi kĂ”ne abil seccomp(2).

Eduka kompileerimise jaoks tuleb programm lingida teegiga libseccomp, nÀiteks:

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

NÀide edukast kÀivitamisest:

$ .\/seccomp_lib echo ok
ok

NĂ€ide blokeeritud sĂŒsteemi kĂ”nest:

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

Kasutame strace, et teada saada rohkem:

$ 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 poolt tapetud (mÀlukogumine) +++
Halb sĂŒsteemi kĂ”ne

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

KokkuvĂ”ttes oleme kirjutanud filtri kasutades teeki libseccomp, mahtudes mittetĂŒĂŒpilisse koodi nelja rida. Ülaltoodud nĂ€ites vĂ”ib sĂŒsteemi kĂ”nede arvul olla oluline mĂ”ju tĂ€itmise ajale, kuna kontrollimine on lihtsalt loendite vĂ”rdlemine. Optimeerimiseks on hiljuti libseccompi lisatud plaaster, mis lisab toetuse filtri atribuudile SCMP_FLTATR_CTL_OPTIMIZE. Kui seadistate selle atribuudiks 2, muudetakse filter binaarse otsingu programmina.

Kui soovite nĂ€ha, kuidas töötavad binaarse otsinguga filtrid, vaadake lihtsat skripti, mis genereerib selliseid programmi assembler BPF sĂŒsteemi kĂ”nede numbrite kogumi 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

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

seccomp ja strace

KĂ”ik teavad utiliiti strace — asendamatu tööriist protsesside kĂ€itumise uurimisel Linuxis. Kuid paljud on ka kuulnud jĂ”udlusprobleemid selle tööriista kasutamise korral. Asi on selles, et strace on rakendatud ptrace(2), kuid selles mehhanismis ei saa me mÀÀrata, millistel tĂ€pselt sĂŒsteemi kutsungitel me protsessi peame 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

töötavad enam-vĂ€hem sama ajaga, kuigi teises variandis tahame jĂ€lgida ainult ĂŒhte sĂŒsteemi kutsungit.

Uus valik --seccomp-bpf, lisatud strace versioonis 5.3, vĂ”imaldab protsessi kiirusel korduvalt suureneda ja ĂŒhe sĂŒsteemi kutsungi jĂ€lgimise kĂ€ivitamise aeg on nĂŒĂŒd 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 loomulikult vĂ€ike petmine, et me ei jĂ€lgi selle kĂ€su peamist sĂŒsteemi kutsungit. Kui me jĂ€lgiksime nĂ€iteks newfsstat, siis strace peaks töötama sama aeglaselt kui ilma --seccomp-bpf.)

Kuidas see valik toimib? Ilma selleta strace ĂŒhendub protsessiga ja kĂ€ivitab selle PTRACE_SYSCALL. Kui hallatav protsess kĂ€ivitab (mille tahes) sĂŒsteemi kutsungi, antakse juhtimine strace, mis vaatab sĂŒsteemi kutsungi argumente ja kĂ€ivitab selle PTRACE_SYSCALL. MĂ”ne aja pĂ€rast lĂ”petab protsess sĂŒsteemi kutsungi ja vĂ€ljudes antakse juhtimine jĂ€lle strace, mis vaatab tagastatud vÀÀrtusi ja kĂ€ivitab protsessi PTRACE_SYSCALL, jne.

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

Kuid seccompi abil saab seda protsessi optimeerida just nii, nagu me soovime. Nimelt, kui tahame vaadata ainult sĂŒsteemi kutsungit X, saame kirjutada BPF filtri, mis X tagastab vÀÀrtuse SECCOMP_RET_TRACE, ja mittesoovitavate kutsungite jaoks — SECCOMP_RET_ALLOW:

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

Sellisel juhul strace kĂ€ivitab alguses protsessi kui PTRACE_CONT, iga sĂŒsteemi kutsungi korral töötab meie filter, kui sĂŒsteemi kutsung ei X, siis protsess jĂ€tkab tööd, kuid kui see X, siis seccomp edastab juhtimise strace, mis vaatab argumente ja kĂ€ivitab protsessi nagu PTRACE_SYSCALL (kuna seccompis ei ole vĂ”imalik programmi kĂ€ivitada sĂŒsteemi kutsungi vĂ€ljumisel). Kui sĂŒsteemi kutsung naaseb, strace kĂ€ivitab protsessi uuesti PTRACE_CONT ja ootab uusi teateid seccompilt.

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

valiku kasutamisel --seccomp-bpf on kaks piirangut. Esiteks ei saa ĂŒhendada juba toimivale protsessile (valik -p programmide strace), kuna seda ei toetata seccomp. Teiseks, puudub vĂ”imalus ei vaadata alaprotsesse, kuna seccomp filtrid pĂ€randuvad kĂ”igile alaprotsessidele ilma vĂ”imaluseta seda vĂ€lja lĂŒlitada.

Veidi rohkem ĂŒksikasju selle kohta, kuidas tĂ€pselt strace töötab seccomp saab teada meie viimasest aruandest . Meie jaoks on kĂ”ige huvitavam fakt see, et klassikaline BPF seccomp kujul leiab endiselt rakendust.Liigume nĂŒĂŒd tagasi vĂ”rkude maailma.

xt_bpf

Taust: ammu, 2007. aastal, murdis tuuma

xt_u32 on lisatud moodul netfilter jaoks. See kirjutati sarnases stiilis nagu veelgi vana liikluse klassifikaator cls_u32 ja vÔimaldas kirjutada suvalisi binaarreegleid iptables'i abil, kasutades jÀrgmisi lihtsaid operatsioone: laadida 32 bitti paketist ja teha neile rida aritmeetilisi operatsioone. NÀiteks, sudo iptables -A INPUT -m u32 --u32 "6&0xFF=1" -j LOG --log-prefix "seen-by-xt_u32"

Laadib 32 bitti IP-pealkirjast, alustades nihkest 6, ja rakendab neile maske

0xFF (vĂ”tab alumise baidi). See on IP-pealkirja piirkond ja me vĂ”rdleme seda 1-ga (ICMP). Ühes reeglites saab koos kombineerida palju kontrolle ning samuti saab teha operatsiooni — liikuda X bitti paremale. NĂ€iteks reegel protocol iptables -m u32 --u32 "6&0xFF=0x6 && 0>>22&0x3C@4=0x29" @ kontrollib, kas TCP jĂ€rjestusnumber on

. Ma ei hakka sisse minema rohkem ĂŒksikasjadesse, kuna on juba selge, et kĂ€sitsi selliste reeglite kirjutamine ei ole just mugav. Artiklis

BPF — unustatud baitkood 0x29, on mitmeid linke nĂ€idiste ja reeglite genereerimise kohta . Vaata ka lingid artikli lĂ”pust.Alates 2013. aastast saab mooduli asemel kasutada BPF-pĂ”hist moodulit. netfilter jaoks. See kirjutati sarnases stiilis nagu veelgi vana liikluse klassifikaatorKuni siia lugenud, peaks pĂ”himĂ”te olema selge: kĂ€ivitada BPF baitkood iptables'i reeglite puhul. Uue reegli loomine on vĂ”imalik nĂ€iteks nii:

iptables -A INPUT -m bpf --bytecode -j LOG netfilter jaoks. See kirjutati sarnases stiilis nagu veelgi vana liikluse klassifikaator saab kasutada BPF-pÔhist moodulit xt_bpfon assemblatori vÀljundformaat bpf_asm

vaikimisi, nÀiteks,

siin $ 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Ă”iki UDP pakette. BPF programmi kontekst moodulis , viitab loomulikult paketi andmetele, iptables'i puhul — IPv4 pealkirja algusele. BPF programmi tagastatav vÀÀrtus boolean

tÀhendab, et pakett ei vastanud.

. xt_bpf. ., kus false .

Selge, et moodul xt_bpf toetab keerukamaid filtre kui ĂŒlaltoodud nĂ€ites. Vaatame tĂ”elisi nĂ€iteid ettevĂ”ttelt Cloudflare. Kuni hiljutise ajani kasutasid nad moodulit xt_bpf DDoS rĂŒnnakute kaitseks. Artiklis Tutvustame BPF tööriistu rÀÀgivad nad, kuidas (ja miks) nad genereerivad BPF filtreid ja publitseerivad linke tööriistade komplektile selliste filtrite loomise jaoks. NĂ€iteks tööriista abil bpfgen vĂ”ib luua BPF programmi, mis sobitab DNS-pĂ€ringu nime 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 kÔigepealt registrisse X stringi alguse aadressi x04habrx03comx00 UDP-datagrammi sees ja seejÀrel kontrollime pÀringut: 0x04686162 "x04hab" jne.

Hiljem avaldas Cloudflare p0f kompilaatori koodi -> BPF. Artiklis Tutvustame p0f BPF kompilaatorit rÀÀgivad nad, mis on p0f ja kuidas muuta p0f allkirju BPF-iks:

$ ./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 Cloudflare enam xt_bpf, kuna nad on kolinud XDP-le — ĂŒks variant uut BPF versiooni kasutada, vt. L4Drop: XDP DDoS leevendused.

cls_bpf

Viimane klassikalise BPF nĂ€ide tuumas on klassifikaator cls_bpf Linuxi liikluse kontrollimise alamsĂŒsteemi jaoks, mis lisati Linuxi 2013. aasta lĂ”pus ja asendas kontseptuaalselt vana ja vĂ”imaldas kirjutada suvalisi binaarreegleid iptables'i abil, kasutades jĂ€rgmisi lihtsaid operatsioone: laadida 32 bitti paketist ja teha neile rida aritmeetilisi operatsioone. NĂ€iteks,.

Me ei kavatse praegu seda tööd kirjeldada cls_bpf, kuna klassikalise BPF-i tundmise seisukohalt ei anna see meile midagi — oleme juba tuttavad kogu funktsionaalsusega. Lisaks, jĂ€rgnevates artiklites, mis kĂ€sitlevad laiendatud BPF-i, kohtume me selle klassifikaatoriga veel korduvalt.

Veel ĂŒks pĂ”hjus, miks mitte rÀÀkida klassikalise BPF-i kasutamisest on see, et vĂ”rreldes laiendatud BPF-iga on selle puhul rakendatavuse ulatus oluliselt kitsenenud: klassikalised programmid ei saa muuta pakettide sisu ja ei saa salvestada olekut kutsungite vahel. cls_bpf Nii et on aeg hĂŒvasti jĂ€tta klassikalisest BPF-ist ja vaadata tulevikku.

HĂŒvasti klassikalise BPF-iga

HĂŒvasti klassikaline BPF

Oleme vaadanud, kuidas 1990. aastate alguses vĂ€lja töötatud BPF-tehnoloogia on edukalt kestnud veerand sajandit ja leidnud uusi rakendusi. Kuid sarnaselt siirdega virnastatud masinatelt RISC-ile, mis andis tĂ”uke klassikalise BPF-i vĂ€ljatöötamiseks, leidis 2000ndatel aset ĂŒleminek 32-bitiselt 64-bitisele arhitektuurile, mistĂ”ttu klassikaline BPF hakkas ajale jalgu jÀÀma. Lisaks on klassikalise BPF-i vĂ”imalused tugevalt piiratud ning lisaks vananenud arhitektuurile puudub meil vĂ”imalus salvestada olekut BPF-programmide vahel, ei ole vĂ”imalik otseselt suhelda kasutajaga ega suhtelda tuumaga, vĂ€lja arvatud piiratud arvu struktuuri vĂ€ljade lugemine. sk_buff ja kĂ€ivitada lihtsamaid abifunktsioone, ei saa pakettide sisu muuta ega neid suunata.

Tegelikult on praegu Linuxis klassikalisest BPF-ist jÀÀnud jÀrgi ainult API-liides, samas kui kogu klassikalised programmid, olgu need siis socket-filterid vÔi seccomp-filterid, tÔlgitakse automaatselt uude vormingusse, Extended BPF. (Kuidas seda tÀpselt tehakse, kirjeldame jÀrgmisel artiklil.)

Uuele arhitektuurile ĂŒleminek algas 2013. aastal, kui Aleksei Starovoitov pakkus vĂ€lja BPF-i vĂ€rskendamise skeemi. 2014. aastal hakkasid vastavad plaastrid ilmuma tuumas. Nii palju tean, et algselt oli plaanis vaid optimeerida arhitektuuri ja JIT-kompileerijat efektiivsemaks tööks 64-bitistel masinatel, kuid selle asemel andsid need optimeerimised alguse uuele peatĂŒkile Linuxi arenduses.

Uurivad artiklid selles sarjas rÀÀgivad uue tehnoloogia arhitektuurist ja rakendustest, mis algselt oli tuntud kui internal BPF, seejĂ€rel extended BPF ning nĂŒĂŒd lihtsalt BPF.

Viidatud lingid

  1. Steven McCanne ja Van Jacobson, "The BSD Packet Filter: Uus arhitektuur kasutaja tasemel pakettide pĂŒĂŒdmiseks", https://www.tcpdump.org/papers/bpf-usenix93.pdf
  2. Steven McCanne, "libpcap: Arhitektuur ja optimeerimisvĂ€gitegu pakettide pĂŒĂŒdmiseks", 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 — 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: IsolatsioonisĂŒsteemid systemd abil vĂ”i "sulle ei ole vaja Dockerit selleks!"
  12. Paul Chaignon, "strace —seccomp-bpf: pilguheit kapoti alla", https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
  13. netsniff-ng: http://netsniff-ng.org/

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster