BPF fun awọn ọmọ kekere, apakan odo: BPF Ayebaye

Awọn Ajọ Packet Berkeley (BPF) jẹ imọ-ẹrọ ekuro Linux kan ti o ti wa ni awọn oju-iwe iwaju ti awọn atẹjade imọ-ẹrọ Gẹẹsi fun ọpọlọpọ ọdun ni bayi. Awọn apejọ ti kun pẹlu awọn ijabọ lori lilo ati idagbasoke ti BPF. David Miller, olutọju ipilẹ eto nẹtiwọọki Linux, pe ọrọ rẹ ni Linux Plumbers 2018 "Ọrọ yii kii ṣe nipa XDP" (XDP jẹ ọran lilo kan fun BPF). Brendan Gregg funni ni awọn ọrọ ti o ni ẹtọ Linux BPF Superpowers. Toke Høiland-Jørgensen rerinpe ekuro jẹ microkernel bayi. Thomas Graf nse igbelaruge ero naa BPF jẹ JavaScript fun ekuro.

Ko si ijuwe ifinufindo ti BPF lori Habré, ati nitorinaa ninu lẹsẹsẹ awọn nkan Emi yoo gbiyanju lati sọrọ nipa itan-akọọlẹ imọ-ẹrọ, ṣapejuwe faaji ati awọn irinṣẹ idagbasoke, ati ṣe ilana awọn agbegbe ti ohun elo ati adaṣe ti lilo BPF. Nkan yii, odo, ninu jara, sọ itan-akọọlẹ ati faaji ti BPF Ayebaye, ati tun ṣafihan awọn aṣiri ti awọn ipilẹ iṣẹ rẹ. tcpdump, seccomp, strace, ati pupọ diẹ sii.

Idagbasoke BPF jẹ iṣakoso nipasẹ agbegbe Nẹtiwọọki Linux, awọn ohun elo akọkọ ti BPF ni ibatan si awọn nẹtiwọọki ati nitorinaa, pẹlu igbanilaaye @eucariot, Mo ti a npe ni jara "BPF fun awọn ọmọ kekere", ni ola ti awọn nla jara "Awọn nẹtiwọki fun awọn ọmọ kekere".

Ẹkọ kukuru kan ninu itan-akọọlẹ BPF (c)

Imọ-ẹrọ BPF ode oni jẹ ẹya imudara ati imugboroja ti imọ-ẹrọ atijọ pẹlu orukọ kanna, ni bayi ti a pe ni BPF Ayebaye lati yago fun iporuru. IwUlO ti a mọ daradara ni a ṣẹda da lori BPF Ayebaye tcpdump, siseto seccomp, bi daradara bi o kere mọ modulu xt_bpf fun iptables ati classifier cls_bpf. Ni Lainos ode oni, awọn eto BPF Ayebaye ni a tumọ laifọwọyi sinu fọọmu tuntun, sibẹsibẹ, lati oju wiwo olumulo, API ti wa ni aye ati awọn lilo tuntun fun BPF Ayebaye, bi a yoo rii ninu nkan yii, tun wa. Fun idi eyi, ati nitori pe atẹle itan ti idagbasoke ti BPF kilasika ni Linux, yoo di alaye diẹ sii bi ati idi ti o ṣe wa sinu fọọmu ode oni, Mo pinnu lati bẹrẹ pẹlu nkan kan nipa BPF kilasika.

Ni opin awọn ọgọrin ọdun ti o kẹhin, awọn onimọ-ẹrọ lati olokiki Lawrence Berkeley Laboratory ti nifẹ si ibeere ti bii o ṣe le ṣe àlẹmọ awọn apo-iwe nẹtiwọọki daradara lori ohun elo ti o jẹ igbalode ni awọn ọgọrin ọdun ti ọdun sẹhin. Ero ipilẹ ti sisẹ, ti ipilẹṣẹ ni ipilẹṣẹ ni imọ-ẹrọ CSPF (CMU/Stanford Packet Filter), ni lati ṣe àlẹmọ awọn apo-iwe ti ko wulo ni kutukutu bi o ti ṣee, ie. ni aaye kernel, nitori eyi yago fun didakọ data ti ko wulo sinu aaye olumulo. Lati pese aabo asiko-akoko fun ṣiṣiṣẹ koodu olumulo ni aaye kernel, ẹrọ foju-iyanrin ti a lo.

Sibẹsibẹ, awọn ẹrọ foju fun awọn asẹ ti o wa tẹlẹ jẹ apẹrẹ lati ṣiṣẹ lori awọn ẹrọ ti o da lori akopọ ati pe ko ṣiṣẹ daradara lori awọn ẹrọ RISC tuntun. Bi abajade, nipasẹ awọn akitiyan ti awọn onimọ-ẹrọ lati Berkeley Labs, imọ-ẹrọ BPF tuntun kan (Berkeley Packet Filters) ti ni idagbasoke, faaji ẹrọ foju eyiti o da lori ero isise Motorola 6502 - iṣẹ iṣẹ ti iru awọn ọja olokiki daradara bi Apple II tabi NES. Ẹrọ foju tuntun pọ si iṣẹ àlẹmọ awọn igba mẹwa ni akawe si awọn solusan ti o wa.

BPF ẹrọ faaji

A yoo faramọ pẹlu faaji ni ọna iṣẹ, n ṣatupalẹ awọn apẹẹrẹ. Bibẹẹkọ, lati bẹrẹ pẹlu, jẹ ki a sọ pe ẹrọ naa ni awọn iforukọsilẹ 32-bit meji ti o wa si olumulo, ikojọpọ kan. A ati iforukọsilẹ atọka X, 64 awọn baiti iranti (awọn ọrọ 16), wa fun kikọ ati kika atẹle, ati eto kekere ti awọn aṣẹ fun ṣiṣẹ pẹlu awọn nkan wọnyi. Awọn ilana fo fun imuse awọn ikosile majemu tun wa ninu awọn eto, ṣugbọn lati ṣe iṣeduro ipari akoko ti eto naa, awọn fo le ṣee ṣe siwaju nikan, ie, ni pataki, o jẹ ewọ lati ṣẹda awọn loops.

Ilana gbogbogbo fun ibẹrẹ ẹrọ jẹ bi atẹle. Olumulo naa ṣẹda eto kan fun faaji BPF ati, lilo diẹ ninu awọn siseto ekuro (gẹgẹbi ipe eto), awọn ẹru ati so eto pọ mọ si diẹ ninu awọn si olupilẹṣẹ iṣẹlẹ ni ekuro (fun apẹẹrẹ, iṣẹlẹ kan jẹ dide ti apo atẹle lori kaadi nẹtiwọki). Nigbati iṣẹlẹ ba waye, ekuro n ṣiṣẹ eto naa (fun apẹẹrẹ, ninu onitumọ), ati pe iranti ẹrọ ni ibamu si si diẹ ninu awọn Ekun iranti ekuro (fun apẹẹrẹ, data ti apo ti nwọle).

Eyi ti o wa loke yoo to fun wa lati bẹrẹ wiwo awọn apẹẹrẹ: a yoo faramọ eto ati ọna kika aṣẹ bi o ṣe pataki. Ti o ba fẹ lati ṣe iwadi lẹsẹkẹsẹ eto aṣẹ ti ẹrọ foju kan ki o kọ ẹkọ nipa gbogbo awọn agbara rẹ, lẹhinna o le ka nkan atilẹba Ajọ Packet BSD ati/tabi idaji akọkọ ti faili naa Documentation/nẹtiwọki/filter.txt lati iwe kernel. Ni afikun, o le ṣe iwadi igbejade libpcap: Ilana faaji ati Imudara julọ fun Gbigba Packet, ninu eyiti McCanne, ọkan ninu awọn onkọwe ti BPF, sọrọ nipa itan-akọọlẹ ti ẹda libpcap.

Bayi a tẹsiwaju lati gbero gbogbo awọn apẹẹrẹ pataki ti lilo BPF Ayebaye lori Lainos: tcpdump (libpcap), iṣẹju-aaya, xt_bpf, cls_bpf.

tcpdump

Idagbasoke ti BPF ni a ṣe ni afiwe pẹlu idagbasoke ti iwaju iwaju fun sisẹ apo - ohun elo ti a mọ daradara tcpdump. Ati pe, niwọn bi eyi jẹ apẹẹrẹ akọbi ati olokiki julọ ti lilo BPF Ayebaye, ti o wa lori ọpọlọpọ awọn ọna ṣiṣe, a yoo bẹrẹ ikẹkọ wa ti imọ-ẹrọ pẹlu rẹ.

(Mo ran gbogbo awọn apẹẹrẹ ninu nkan yii lori Linux 5.6.0-rc6. Ijade ti diẹ ninu awọn aṣẹ ni a ti ṣatunkọ fun kika to dara julọ.)

Apeere: n ṣakiyesi awọn apo-iwe IPv6

Jẹ ki a fojuinu pe a fẹ lati wo gbogbo awọn apo-iwe IPv6 lori wiwo kan eth0. Lati ṣe eyi a le ṣiṣe eto naa tcpdump pẹlu kan ti o rọrun àlẹmọ ip6:

$ sudo tcpdump -i eth0 ip6

Nibo tcpdump akopọ àlẹmọ ip6 sinu BPF faaji bytecode ki o firanṣẹ si ekuro (wo awọn alaye ni apakan Tcpdump: ikojọpọ). Ajọ ti kojọpọ yoo ṣiṣẹ fun gbogbo soso ti o kọja nipasẹ wiwo naa eth0. Ti àlẹmọ ba pada iye ti kii ṣe odo n, lẹhinna to n Awọn baiti ti apo-iwe naa yoo daakọ si aaye olumulo ati pe a yoo rii ninu iṣelọpọ tcpdump.

BPF fun awọn ọmọ kekere, apakan odo: BPF Ayebaye

O wa ni wi pe a le ni irọrun rii iru koodu bytecode ti a firanṣẹ si ekuro tcpdump pẹlu iranlọwọ ti awọn tcpdump, ti a ba ṣiṣẹ pẹlu aṣayan -d:

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

Lori laini odo a ṣiṣe awọn pipaṣẹ ldh [12], eyi ti o duro fun "load into register A idaji ọrọ (16 die-die) ti o wa ni adirẹsi 12 "ati ibeere nikan ni iru iranti wo ni a n sọrọ? Idahun si ni wipe ni x bẹrẹ (x+1)th baiti ti awọn atupale nẹtiwọki soso. A ka awọn apo-iwe lati inu wiwo Ethernet eth0ati eyi tumo sipe idii naa dabi eyi (fun ayedero, a ro pe ko si awọn ami VLAN ninu apo):

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

Nitorina lẹhin ṣiṣe pipaṣẹ naa ldh [12] ninu iforukọsilẹ A oko yoo wa Ether Type - awọn iru ti soso zqwq ni yi àjọlò fireemu. Lori laini 1 a ṣe afiwe awọn akoonu ti iforukọsilẹ A (oriṣi idii) c 0x86ddati eyi ki o si jẹ Iru ti a nifẹ si jẹ IPv6. Lori laini 1, ni afikun si aṣẹ lafiwe, awọn ọwọn meji miiran wa - jt 2 и jf 3 - awọn aami si eyiti o nilo lati lọ ti afiwera ba ṣaṣeyọri (A == 0x86dd) ati pe ko ni aṣeyọri. Nitorina, ninu ọran aṣeyọri (IPv6) a lọ si laini 2, ati ninu ọran ti ko ni aṣeyọri - si laini 3. Lori laini 3 eto naa pari pẹlu koodu 0 (ma ṣe daakọ apo), lori ila 2 eto naa pari pẹlu koodu. 262144 (da mi o pọju 256 kilobytes package).

Apeere idiju diẹ sii: a wo awọn apo-iwe TCP nipasẹ ibudo opin irin ajo

Jẹ ká wo ohun ti a àlẹmọ dabi wipe idaako gbogbo TCP awọn apo-iwe pẹlu nlo ibudo 666. A yoo ro awọn IPv4 irú, niwon awọn IPv6 irú jẹ rọrun. Lẹhin kika apẹẹrẹ yii, o le ṣawari àlẹmọ IPv6 funrararẹ bi adaṣe (ṣe adaṣe).ip6 and tcp dst port 666) ati àlẹmọ fun ọran gbogbogbo (tcp dst port 666). Nitorinaa, àlẹmọ ti a nifẹ si dabi eyi:

$ 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

A ti mọ kini awọn ila 0 ati 1 ṣe. Lori laini 2 a ti ṣayẹwo tẹlẹ pe eyi jẹ apo IPv4 kan (Ether Type = 0x800) ki o si gbe e sinu iforukọsilẹ A 24. baiti ti awọn soso. package wa dabi

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

eyi ti o tumo a fifuye sinu Forukọsilẹ A aaye Ilana ti akọsori IP, eyiti o jẹ ọgbọn, nitori a fẹ daakọ awọn apo-iwe TCP nikan. A afiwe Protocol pẹlu 0x6 (IPPROTO_TCP) lori ila 3.

Lori awọn ila 4 ati 5 a fifuye awọn idaji awọn ọrọ ti o wa ni adirẹsi 20 ati lo aṣẹ naa jset ṣayẹwo boya ọkan ninu awọn mẹta ti ṣeto awọn asia - wọ awọn ti oniṣowo boju jset awọn mẹta julọ significant die-die ti wa ni nso. Meji ninu awọn die-die mẹta sọ fun wa boya idii naa jẹ apakan ti apo IP ti a pin, ati ti o ba jẹ bẹ, boya o jẹ ajẹkù ti o kẹhin. bit kẹta wa ni ipamọ ati pe o gbọdọ jẹ odo. A ko fẹ lati ṣayẹwo boya awọn apo-iwe ti ko pe tabi fifọ, nitorinaa a ṣayẹwo gbogbo awọn die-die mẹta.

Laini 6 jẹ ohun ti o nifẹ julọ ninu atokọ yii. Ikosile ldxb 4*([14]&0xf) tumo si a fifuye sinu Forukọsilẹ X awọn die-die mẹrin pataki ti o kere ju ti baiti kẹdogun ti apo-iwe naa ni isodipupo nipasẹ 4. Awọn iwọn mẹrin pataki ti o kere ju ti baiti kẹdogun ni aaye naa. Internet Akọsori Ipari Akọsori IPv4, eyiti o tọju gigun akọsori ni awọn ọrọ, nitorinaa o nilo lati isodipupo nipasẹ 4. O yanilenu, ikosile naa 4*([14]&0xf) ni a yiyan fun pataki kan sọrọ eni ti o le nikan ṣee lo ni yi fọọmu ati ki o nikan fun a Forukọsilẹ X, i.e. a ko le sọ boya ldb 4*([14]&0xf) bẹni ldxb 5*([14]&0xf) (a le pato aiṣedeede ti o yatọ nikan, fun apẹẹrẹ, ldxb 4*([16]&0xf)). O han gbangba pe ero adirẹsi yii ni a ṣafikun si BPF ni pipe lati le gba X (Iforukọsilẹ atọka) Ipari akọsori IPv4.

Nitorina lori laini 7 a gbiyanju lati fifuye idaji ọrọ kan ni (X+16). Ranti wipe 14 baiti ti wa ni tẹdo nipasẹ awọn àjọlò akọsori, ati X ni ipari ti akọsori IPv4, a loye pe ninu A Ti kojọpọ ibudo ibudo TCP:

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

Ni ipari, lori laini 8 a ṣe afiwe ibudo opin irin ajo pẹlu iye ti o fẹ ati lori awọn laini 9 tabi 10 a da abajade pada - boya lati daakọ apo-iwe naa tabi rara.

Tcpdump: ikojọpọ

Ninu awọn apẹẹrẹ ti tẹlẹ, a ni pataki ko gbe ni alaye lori bi a ṣe n gbe koodu bytecode BPF sinu ekuro fun sisẹ apo. Ni gbogbogbo, tcpdump ported si ọpọlọpọ awọn ọna šiše ati fun ṣiṣẹ pẹlu awọn Ajọ tcpdump nlo ìkàwé libpcap. Ni soki, lati gbe àlẹmọ sori wiwo nipa lilo libpcap, o nilo lati ṣe atẹle naa:

Lati wo bi iṣẹ naa ṣe ṣe pcap_setfilter muse ni Linux, a lo strace (awọn ila kan ti yọ kuro):

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

Lori akọkọ meji ila ti o wu a ṣẹda aise iho lati ka gbogbo awọn fireemu Ethernet ki o si dè e si wiwo eth0... Ti apẹẹrẹ akọkọ wa a mọ pe àlẹmọ ip yoo ni awọn ilana BPF mẹrin, ati lori laini kẹta a rii bii lilo aṣayan naa SO_ATTACH_FILTER ipe eto setsockopt a fifuye ki o si so a àlẹmọ ti ipari 4. Eleyi jẹ wa àlẹmọ.

O tọ lati ṣe akiyesi pe ni BPF Ayebaye, ikojọpọ ati sisopọ àlẹmọ nigbagbogbo waye bi iṣẹ atomiki, ati ninu ẹya tuntun ti BPF, ikojọpọ eto naa ati dipọ mọ olupilẹṣẹ iṣẹlẹ ti yapa ni akoko.

Òtítọ́ farasin

Ẹya pipe diẹ diẹ sii ti iṣelọpọ dabi eyi:

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

Gẹgẹbi a ti sọ loke, a fifuye ati so àlẹmọ wa si iho lori laini 5, ṣugbọn kini o ṣẹlẹ lori awọn laini 3 ati 4? O wa ni jade wipe yi libpcap n ṣe abojuto wa - ki abajade ti àlẹmọ wa ko pẹlu awọn apo-iwe ti ko ni itẹlọrun rẹ, ile-ikawe naa sopọ idinwon àlẹmọ ret #0 (ju gbogbo awọn apo-iwe silẹ), yipada iho si ipo ti kii ṣe idilọwọ ati gbiyanju lati yọkuro gbogbo awọn apo-iwe ti o le wa lati awọn asẹ iṣaaju.

Ni apapọ, lati ṣe àlẹmọ awọn idii lori Lainos nipa lilo BPF Ayebaye, o nilo lati ni àlẹmọ ni irisi igbekalẹ bii struct sock_fprog ati iho ṣiṣi, lẹhin eyi ti àlẹmọ le so mọ iho nipa lilo ipe eto kan setsockopt.

O yanilenu, àlẹmọ le so pọ si eyikeyi iho, kii ṣe aise nikan. Nibi apẹẹrẹ eto ti o ge gbogbo kuro ṣugbọn awọn baiti meji akọkọ lati gbogbo awọn datagram UDP ti nwọle. (Mo ṣafikun awọn asọye ninu koodu naa ki o má ba ṣe idi nkan naa.)

Awọn alaye diẹ sii nipa lilo setsockopt fun pọ Ajọ, wo iho (7), sugbon nipa kikọ ara rẹ Ajọ bi struct sock_fprog laisi iranlọwọ tcpdump a yoo sọrọ ni apakan Siseto BPF pẹlu ọwọ ara wa.

BPF Ayebaye ati XNUMXst orundun

BPF wa ninu Lainos ni ọdun 1997 ati pe o ti wa ẹṣin iṣẹ fun igba pipẹ libpcap laisi awọn ayipada pataki (awọn iyipada-Linux pato, dajudaju, , ṣugbọn wọn ko yi aworan agbaye pada). Awọn ami pataki akọkọ ti BPF yoo wa ni 2011, nigbati Eric Dumazet dabaa alemo, eyi ti o ṣe afikun Just In Time Compiler si ekuro - onitumọ kan fun iyipada BPF bytecode si abinibi x86_64 koodu.

Akopọ JIT jẹ akọkọ ninu pq awọn ayipada: ni ọdun 2012 farahan agbara lati kọ Ajọ fun iṣẹju-aaya, lilo BPF, ni January 2013 nibẹ wà fi kun modulu xt_bpf, eyi ti o faye gba o lati kọ awọn ofin fun iptables pẹlu iranlọwọ ti awọn BPF, ati ni October 2013 je fi kun tun kan module cls_bpf, eyiti o fun ọ laaye lati kọ awọn ikasi ijabọ nipa lilo BPF.

A yoo wo gbogbo awọn apẹẹrẹ wọnyi ni awọn alaye diẹ sii laipẹ, ṣugbọn akọkọ yoo wulo fun wa lati kọ bi a ṣe le kọ ati ṣajọ awọn eto lainidii fun BPF, nitori awọn agbara ti a pese nipasẹ ile-ikawe libpcap lopin (apẹẹrẹ rọrun: ti ipilẹṣẹ àlẹmọ libpcap le pada awọn iye meji nikan - 0 tabi 0x40000) tabi ni gbogbogbo, bi ninu ọran ti seccomp, ko wulo.

Siseto BPF pẹlu ọwọ ara wa

Jẹ ki a ni imọran pẹlu ọna kika alakomeji ti awọn ilana BPF, o rọrun pupọ:

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

Ilana kọọkan wa ni awọn iwọn 64, ninu eyiti akọkọ 16 die-die jẹ koodu itọnisọna, lẹhinna awọn indents mẹjọ-bit meji wa, jt и jf, ati 32 die-die fun ariyanjiyan K, idi ti o yatọ lati aṣẹ si aṣẹ. Fun apẹẹrẹ, aṣẹ naa ret, eyi ti o fopin si eto ni o ni awọn koodu 6, ati awọn pada iye ti wa ni ya lati awọn ibakan K. Ni C, ilana BPF kan jẹ aṣoju bi eto kan

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

ati gbogbo eto wa ni irisi eto kan

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

Nitorinaa, a le kọ awọn eto tẹlẹ (fun apẹẹrẹ, a mọ awọn koodu itọnisọna lati [1]). Eyi ni ohun ti àlẹmọ yoo dabi ip6 ati bẹbẹ lọ apẹẹrẹ akọkọ wa:

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

eto prog a le lo ofin si ipe kan

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

Awọn eto kikọ ni irisi awọn koodu ẹrọ ko rọrun pupọ, ṣugbọn nigbami o jẹ dandan (fun apẹẹrẹ, fun n ṣatunṣe aṣiṣe, ṣiṣẹda awọn idanwo ẹyọkan, kikọ awọn nkan lori Habré, bbl). Fun irọrun ninu faili naa <linux/filter.h> Macros oluranlọwọ ti wa ni asọye - apẹẹrẹ kanna bi loke le jẹ tunkọ bi

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

Sibẹsibẹ, aṣayan yii ko rọrun pupọ. Eyi ni ohun ti awọn olupilẹṣẹ ekuro Linux ṣe ipinnu, ati nitorinaa ninu itọsọna naa tools/bpf awọn kernels o le wa apejọ ati yokokoro fun ṣiṣẹ pẹlu BPF Ayebaye.

Ede apejọ jọra pupọ si iṣẹjade yokokoro tcpdump, ṣugbọn ni afikun a le pato awọn aami aami. Fun apẹẹrẹ, eyi ni eto ti o ju gbogbo awọn apo-iwe silẹ ayafi TCP/IPv4:

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

Nipa aiyipada, olupilẹṣẹ ṣe ipilẹṣẹ koodu ni ọna kika <количество инструкций>,<code1> <jt1> <jf1> <k1>,..., fun apẹẹrẹ wa pẹlu TCP yoo jẹ

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

Fun wewewe ti awọn pirogirama C, ọna kika ti o yatọ le ṣee lo:

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

Yi ọrọ le ti wa ni dakọ sinu iru be definition struct sock_filter, gẹgẹ bi a ti ṣe ni ibẹrẹ ti apakan yii.

Lainos ati netsniff-ng awọn amugbooro

Ni afikun si boṣewa BPF, Lainos ati tools/bpf/bpf_asm support ati ti kii-bošewa ṣeto. Ni ipilẹ, awọn itọnisọna ni a lo lati wọle si awọn aaye ti eto kan struct sk_buff, eyi ti o ṣe apejuwe apo-iwe nẹtiwọki kan ninu ekuro. Sibẹsibẹ, awọn oriṣi miiran ti awọn itọnisọna oluranlọwọ tun wa, fun apẹẹrẹ ldw cpu yoo fifuye sinu Forukọsilẹ A abajade ti ṣiṣe iṣẹ ekuro kan raw_smp_processor_id(). (Ninu ẹya tuntun ti BPF, awọn amugbooro ti kii ṣe boṣewa wọnyi ti gbooro lati pese awọn eto pẹlu ṣeto awọn oluranlọwọ kernel fun iraye si iranti, awọn ẹya, ati awọn iṣẹlẹ ti ipilẹṣẹ.) Eyi ni apẹẹrẹ ti o nifẹ si ti àlẹmọ ninu eyiti a daakọ nikan awọn akọle apo sinu aaye olumulo nipa lilo itẹsiwaju poff, aiṣedeede isanwo:

ld poff
ret a

Awọn amugbooro BPF ko le ṣee lo ninu tcpdump, ṣugbọn eyi jẹ idi ti o dara lati ni imọran pẹlu package IwUlO netsniff-ng, eyiti, ninu awọn ohun miiran, ni eto ilọsiwaju ninu netsniff-ng, eyiti, ni afikun si sisẹ nipa lilo BPF, tun ni olupilẹṣẹ ijabọ ti o munadoko, ati ilọsiwaju diẹ sii ju tools/bpf/bpf_asm, Apejọ BPF ti a npe ni bpfc. Package naa ni awọn iwe alaye pupọ, wo tun awọn ọna asopọ ni ipari nkan naa.

iṣẹju-aaya

Nitorinaa, a ti mọ tẹlẹ bi a ṣe le kọ awọn eto BPF ti idiju lainidii ati pe o ṣetan lati wo awọn apẹẹrẹ tuntun, akọkọ eyiti o jẹ imọ-ẹrọ seccomp, eyiti o fun laaye laaye, lilo awọn asẹ BPF, lati ṣakoso ṣeto ati ṣeto awọn ariyanjiyan ipe eto ti o wa si ilana ti a fun ati awọn ọmọ rẹ.

Ẹya akọkọ ti seccomp ni a ṣafikun si ekuro ni ọdun 2005 ati pe ko gbajumọ pupọ, nitori pe o pese aṣayan kan ṣoṣo - lati fi opin si ṣeto awọn ipe eto ti o wa si ilana kan si atẹle: read, write, exit и sigreturn, ati ilana ti o rú awọn ofin ti a pa lilo SIGKILL. Sibẹsibẹ, ni ọdun 2012, seccomp ṣafikun agbara lati lo awọn asẹ BPF, gbigba ọ laaye lati ṣalaye ṣeto awọn ipe eto ti a gba laaye ati paapaa ṣe awọn sọwedowo lori awọn ariyanjiyan wọn. (O yanilenu, Chrome jẹ ọkan ninu awọn olumulo akọkọ ti iṣẹ ṣiṣe yii, ati pe awọn eniyan Chrome n ṣe agbekalẹ ilana KRSI lọwọlọwọ ti o da lori ẹya tuntun ti BPF ati gbigba isọdi ti Awọn modulu Aabo Linux.) Awọn ọna asopọ si awọn iwe afikun ni a le rii ni ipari. ti article.

Ṣe akiyesi pe awọn nkan ti wa tẹlẹ lori ibudo nipa lilo seccomp, boya ẹnikan yoo fẹ lati ka wọn ṣaaju (tabi dipo) kika awọn abala atẹle wọnyi. Ninu nkan naa Awọn apoti ati aabo: seccomp pese awọn apẹẹrẹ ti lilo seccomp, mejeeji ẹya 2007 ati ẹya nipa lilo BPF (awọn asẹ ti ipilẹṣẹ nipa lilo libseccomp), sọrọ nipa asopọ ti seccomp pẹlu Docker, ati tun pese ọpọlọpọ awọn ọna asopọ to wulo. Ninu nkan naa Iyasọtọ daemons pẹlu systemd tabi “iwọ ko nilo Docker fun eyi!” O ni wiwa, ni pataki, bii o ṣe le ṣafikun awọn blacklists tabi awọn atokọ funfun ti awọn ipe eto fun awọn daemons nṣiṣẹ systemd.

Nigbamii ti a yoo rii bi a ṣe le kọ ati fifuye awọn asẹ fun seccomp ni igboro C ati lilo ìkàwé libseccomp ati kini awọn anfani ati alailanfani ti aṣayan kọọkan, ati nikẹhin, jẹ ki a wo bii eto naa ṣe nlo seccomp strace.

Ajọ kikọ ati ikojọpọ fun seccomp

A ti mọ tẹlẹ bi a ṣe le kọ awọn eto BPF, nitorinaa jẹ ki a kọkọ wo wiwo siseto seccomp. O le ṣeto àlẹmọ ni ipele ilana, ati gbogbo awọn ilana ọmọ yoo jogun awọn ihamọ. Eyi ni a ṣe nipa lilo ipe eto kan seccomp(2):

seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)

nibi ti &filter - Eyi jẹ itọka si eto ti o ti mọ tẹlẹ si wa struct sock_fprog, i.e. Eto BPF.

Bawo ni awọn eto fun seccomp ṣe yatọ si awọn eto fun awọn iho? Itumọ ti gbigbe. Ninu ọran ti awọn iho, a fun wa ni agbegbe iranti ti o ni apo-iwe, ati ninu ọran ti seccomp a fun wa ni eto bii

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

o ti wa ni nr jẹ nọmba ti ipe eto lati ṣe ifilọlẹ, arch - faaji lọwọlọwọ (diẹ sii lori eyi ni isalẹ), args - soke si mefa eto awọn ariyanjiyan ipe, ati instruction_pointer jẹ itọka si itọnisọna aaye olumulo ti o pe eto naa. Nitorinaa, fun apẹẹrẹ, lati fifuye nọmba ipe eto sinu iforukọsilẹ A a ni lati sọ

ldw [0]

Awọn ẹya miiran wa fun awọn eto seccomp, fun apẹẹrẹ, ọrọ-ọrọ le wọle nikan nipasẹ titete 32-bit ati pe o ko le gbe idaji ọrọ kan tabi baiti kan - nigbati o n gbiyanju lati gbe àlẹmọ kan ldh [0] ipe eto seccomp yoo pada EINVAL. Iṣẹ naa n ṣayẹwo awọn asẹ ti kojọpọ seccomp_check_filter() ekuro. (Ohun ti o dun ni, ninu adehun atilẹba ti o ṣafikun iṣẹ ṣiṣe keji, wọn gbagbe lati ṣafikun igbanilaaye lati lo itọnisọna si iṣẹ yii mod (iku pipin) ati pe ko si ni bayi fun awọn eto BPF iṣẹju-aaya, niwon afikun rẹ yoo fọ ABI.)

Ni ipilẹ, a ti mọ ohun gbogbo lati kọ ati ka awọn eto seccomp. Maa eto kannaa eto ti wa ni idayatọ bi funfun tabi dudu akojọ ti awọn ipe eto, fun apẹẹrẹ awọn eto

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

sọwedowo a blacklist ti mẹrin awọn ipe eto nọmba 304, 176, 239, 279. Kini awọn ipe eto wọnyi? A ko le sọ ni idaniloju, nitori a ko mọ iru faaji ti a kọ eto naa. Nitorina, awọn onkọwe ti seccomp ipese bẹrẹ gbogbo awọn eto pẹlu ayẹwo faaji (itumọ faaji lọwọlọwọ ni itọkasi ni aaye bi aaye kan arch awọn ẹya struct seccomp_data). Pẹlu iṣayẹwo faaji, ibẹrẹ apẹẹrẹ yoo dabi:

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

ati lẹhinna awọn nọmba ipe eto wa yoo gba awọn iye kan.

A kọ ati fifuye Ajọ fun seccomp lilo libseccomp

Awọn asẹ kikọ ni koodu abinibi tabi ni apejọ BPF ngbanilaaye lati ni iṣakoso ni kikun lori abajade, ṣugbọn ni akoko kanna, o dara nigba miiran lati ni koodu to ṣee gbe ati/tabi kika. Awọn ìkàwé yoo ran wa pẹlu yi libseccomp, eyi ti o pese a boṣewa ni wiwo fun kikọ dudu tabi funfun Ajọ.

Jẹ ki a, fun apẹẹrẹ, kọ eto kan ti o nṣiṣẹ faili alakomeji ti yiyan olumulo, ti fi sori ẹrọ tẹlẹ atokọ dudu ti awọn ipe eto lati ọdọ. awọn loke article (eto naa ti jẹ irọrun fun kika kika nla, ẹya kikun le ṣee rii nibi):

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

Ni akọkọ a setumo orun sys_numbers ti 40+ eto awọn nọmba ipe lati dènà. Lẹhinna, bẹrẹ ọrọ-ọrọ naa ctx ki o si sọ fun ile-ikawe ohun ti a fẹ gba laaye (SCMP_ACT_ALLOW) gbogbo awọn ipe eto nipasẹ aiyipada (o rọrun lati kọ awọn akojọ dudu). Lẹhinna, ọkan nipasẹ ọkan, a ṣafikun gbogbo awọn ipe eto lati inu akojọ dudu. Ni idahun si ipe eto lati atokọ, a beere SCMP_ACT_TRAP, ninu apere yi seccomp yoo fi kan ifihan agbara si awọn ilana SIGSYS pẹlu apejuwe eyi ti ipe eto rú awọn ofin. Ni ipari, a gbe eto naa sinu ekuro nipa lilo seccomp_load, eyi ti yoo ṣe akopọ eto naa ki o si so mọ ilana naa nipa lilo ipe eto kan seccomp(2).

Fun akojọpọ aṣeyọri, eto naa gbọdọ ni asopọ pẹlu ile-ikawe naa libseccompfun apẹẹrẹ:

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

Apẹẹrẹ ti ifilọlẹ aṣeyọri:

$ ./seccomp_lib echo ok
ok

Apẹẹrẹ ipe eto ti dinamọ:

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

A nlo stracefun alaye:

$ 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

bawo ni a ṣe le mọ pe eto naa ti pari nitori lilo ipe eto ti ko tọ mount(2).

Nitorina, a kowe kan àlẹmọ lilo awọn ìkàwé libseccomp, ibamu koodu ti kii-bintin sinu awọn ila mẹrin. Ninu apẹẹrẹ ti o wa loke, ti nọmba nla ti awọn ipe eto ba wa, akoko ipaniyan le dinku ni akiyesi, nitori ayẹwo jẹ atokọ ti awọn afiwera nikan. Fun iṣapeye, libseccomp laipe ni alemo to wa, eyi ti o ṣe afikun atilẹyin fun abuda àlẹmọ SCMP_FLTATR_CTL_OPTIMIZE. Ṣiṣeto abuda yii si 2 yoo yi àlẹmọ pada sinu eto wiwa alakomeji.

Ti o ba fẹ wo bi awọn asẹ wiwa alakomeji ṣe n ṣiṣẹ, wo o rọrun akosile, eyiti o ṣe agbekalẹ iru awọn eto ni apejọ BPF nipasẹ titẹ awọn nọmba ipe eto, fun apẹẹrẹ:

$ 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

Ko ṣee ṣe lati kọ ohunkohun ni iyara pupọ, nitori awọn eto BPF ko le ṣe awọn fo indentation (a ko le ṣe, fun apẹẹrẹ, jmp A tabi jmp [label+X]) ati nitori naa gbogbo awọn iyipada jẹ aimi.

seccomp ati strace

Gbogbo eniyan mọ ohun elo naa strace jẹ ohun elo ti ko ṣe pataki fun kikọ ihuwasi ti awọn ilana lori Lainos. Sibẹsibẹ, ọpọlọpọ tun ti gbọ nipa awọn oran iṣẹ nigba lilo yi IwUlO. Otitọ ni pe strace imuse lilo ptrace(2), ati ninu ẹrọ yii a ko le pato ni iru eto awọn ipe eto ti a nilo lati da ilana naa duro, ie, fun apẹẹrẹ, awọn aṣẹ.

$ 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

ti wa ni ilọsiwaju ni isunmọ akoko kanna, botilẹjẹpe ninu ọran keji a fẹ lati wa kakiri ipe eto kan nikan.

Aṣayan tuntun --seccomp-bpf, kun si strace Ẹya 5.3, ngbanilaaye lati yara ilana naa ni ọpọlọpọ igba ati akoko ibẹrẹ labẹ itọpa ti ipe eto kan ti jẹ afiwera si akoko ibẹrẹ deede:

$ 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

(Nibi, nitorinaa, ẹtan diẹ wa ni pe a ko wa ipe eto eto akọkọ ti aṣẹ yii. Ti a ba wa kakiri, fun apẹẹrẹ, newfsstatlẹhinna strace yoo ṣẹ egungun gẹgẹ bi lile bi laisi --seccomp-bpf.)

Bawo ni aṣayan yii ṣe n ṣiṣẹ? Laisi rẹ strace sopọ si ilana ati bẹrẹ lilo rẹ PTRACE_SYSCALL. Nigbati ilana iṣakoso ba n ṣalaye ipe eto (eyikeyi), iṣakoso ti gbe si strace, eyi ti o wo awọn ariyanjiyan ti ipe eto ati ṣiṣe pẹlu PTRACE_SYSCALL. Lẹhin akoko diẹ, ilana naa pari ipe eto ati nigbati o ba jade, iṣakoso ti gbe lẹẹkansi strace, eyiti o wo awọn iye ipadabọ ati bẹrẹ ilana nipa lilo PTRACE_SYSCALL, ati bẹbẹ lọ.

BPF fun awọn ọmọ kekere, apakan odo: BPF Ayebaye

Pẹlu seccomp, sibẹsibẹ, ilana yii le jẹ iṣapeye ni deede bi a ṣe fẹ. Eyun, ti a ba fẹ lati wo nikan ni ipe eto X, lẹhinna a le kọ àlẹmọ BPF pe fun X iye pada SECCOMP_RET_TRACE, ati fun awọn ipe ti ko ni anfani si wa - SECCOMP_RET_ALLOW:

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

Fun idi eyi strace lakoko bẹrẹ ilana bi PTRACE_CONT, Ajọ wa ni ilọsiwaju fun ipe eto kọọkan, ti ipe eto ko ba jẹ X, lẹhinna ilana naa tẹsiwaju lati ṣiṣẹ, ṣugbọn ti eyi ba X, lẹhinna seccomp yoo gbe iṣakoso straceeyi ti yoo wo awọn ariyanjiyan ati bẹrẹ ilana bi PTRACE_SYSCALL (niwọn igba ti seccomp ko ni agbara lati ṣiṣe eto kan ni ijade lati ipe eto). Nigbati ipe eto ba pada, strace yoo tun bẹrẹ ilana nipa lilo PTRACE_CONT ati pe yoo duro fun awọn ifiranṣẹ titun lati iṣẹju-aaya.

BPF fun awọn ọmọ kekere, apakan odo: BPF Ayebaye

Nigba lilo aṣayan --seccomp-bpf awọn ihamọ meji wa. Ni akọkọ, kii yoo ṣee ṣe lati darapọ mọ ilana ti o wa tẹlẹ (aṣayan -p eto naa strace), nitori eyi ko ṣe atilẹyin nipasẹ seccomp. Ẹlẹẹkeji, nibẹ ni ko si seese kii ṣe wo awọn ilana ọmọ, niwon awọn asẹ seccomp ti jogun nipasẹ gbogbo awọn ilana ọmọ laisi agbara lati mu eyi ṣiṣẹ.

Apejuwe diẹ diẹ sii lori bii gangan strace ṣiṣẹ pẹlu awọn seccomp le ri lati laipe iroyin. Fun wa, otitọ ti o nifẹ julọ ni pe BPF Ayebaye ti o ṣojuuṣe nipasẹ seccomp jẹ ṣi lo loni.

xt_bpf

Jẹ ki a pada sẹhin si agbaye ti awọn nẹtiwọọki.

Background: igba pipẹ seyin, ni 2007, awọn mojuto wà fi kun modulu xt_u32 fun netfilter. O ti kọ nipasẹ afiwe pẹlu ẹya ani diẹ atijọ ijabọ classifier cls_u32 ati gba ọ laaye lati kọ awọn ofin alakomeji lainidii fun awọn iptables ni lilo awọn iṣẹ ti o rọrun wọnyi: fifuye awọn iwọn 32 lati apo kan ki o ṣe eto awọn iṣẹ ṣiṣe iṣiro lori wọn. Fun apere,

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

Kojọpọ awọn ege 32 ti akọsori IP, ti o bẹrẹ ni padding 6, o si kan iboju-boju si wọn 0xFF (mu awọn kekere baiti). Aaye yii protocol Akọsori IP ati pe a ṣe afiwe rẹ pẹlu 1 (ICMP). O le darapọ ọpọlọpọ awọn sọwedowo ni ofin kan, ati pe o tun le ṣiṣẹ oniṣẹ @ - gbe X baiti si ọtun. Fun apẹẹrẹ, ofin

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

sọwedowo ti Nọmba Ọkọọkan TCP ko dọgba 0x29. Emi kii yoo lọ sinu awọn alaye siwaju sii, nitori o ti han gbangba pe kikọ iru awọn ofin pẹlu ọwọ ko rọrun pupọ. Ninu nkan naa BPF - awọn gbagbe bytecode, Awọn ọna asopọ pupọ wa pẹlu awọn apẹẹrẹ ti lilo ati iran ofin fun xt_u32. Wo tun awọn ọna asopọ ni opin nkan yii.

Niwon 2013 module dipo ti module xt_u32 o le lo BPF orisun module xt_bpf. Ẹnikẹni ti o ba ti ka eyi jina yẹ ki o han gbangba nipa ilana ti iṣiṣẹ rẹ: ṣiṣe BPF bytecode gẹgẹbi awọn ofin iptables. O le ṣẹda ofin tuntun, fun apẹẹrẹ, bii eyi:

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

nibi <байткод> - eyi ni koodu ni ọna kika apejo bpf_asm nipa aiyipada, fun apẹẹrẹ,

$ 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

Ni apẹẹrẹ yii a n ṣe sisẹ gbogbo awọn apo-iwe UDP. Awọn ọrọ fun a BPF eto ni a module xt_bpf, dajudaju, tọka si data apo-iwe, ninu ọran ti iptables, si ibẹrẹ ti akọle IPv4. Pada iye lati BPF eto booliannibo false tumo si wipe apo ko baramu.

O jẹ wipe ko module xt_bpf ṣe atilẹyin awọn asẹ eka sii ju apẹẹrẹ loke. Jẹ ki a wo awọn apẹẹrẹ gidi lati Cloudfare. Titi laipe wọn lo module xt_bpf lati daabobo lodi si awọn ikọlu DDoS. Ninu nkan naa Ṣafihan Awọn irinṣẹ BPF wọn ṣe alaye bii (ati idi ti) wọn ṣe awọn asẹ BPF ati ṣe atẹjade awọn ọna asopọ si ṣeto awọn ohun elo fun ṣiṣẹda iru awọn asẹ. Fun apẹẹrẹ, lilo ohun elo bpfgen o le ṣẹda eto BPF kan ti o baamu ibeere DNS fun orukọ kan 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

Ninu eto a akọkọ fifuye sinu iforukọsilẹ X ibere adirẹsi ila x04habrx03comx00 inu datagram UDP kan lẹhinna ṣayẹwo ibeere naa: 0x04686162 <-> "x04hab" ati bẹbẹ lọ.

Ni igba diẹ, Cloudfare ṣe atẹjade p0f -> koodu akojọpọ BPF. Ninu nkan naa Ṣafihan alakojo p0f BPF wọn sọrọ nipa kini p0f jẹ ati bii o ṣe le yi awọn ibuwọlu p0f pada si 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,
...

Lọwọlọwọ ko lo Cloudfare mọ xt_bpf, niwon wọn ti lọ si XDP - ọkan ninu awọn aṣayan fun lilo ẹya tuntun ti BPF, wo. L4Drop: XDP DDoS Mitigations.

cls_bpf

Apeere ti o kẹhin ti lilo BPF Ayebaye ninu ekuro jẹ olutọpa cls_bpf fun eto iṣakoso ijabọ ni Lainos, ti a ṣafikun si Linux ni opin ọdun 2013 ati ni imọran rọpo atijọ cls_u32.

A kii yoo, sibẹsibẹ, ṣe apejuwe iṣẹ ni bayi cls_bpf, niwon lati oju-ọna ti oye nipa BPF Ayebaye eyi kii yoo fun wa ni ohunkohun - a ti mọ tẹlẹ pẹlu gbogbo iṣẹ-ṣiṣe. Ni afikun, ninu awọn nkan ti o tẹle ti n sọrọ nipa BPF ti o gbooro, a yoo pade iyasọtọ yii diẹ sii ju ẹẹkan lọ.

Idi miiran ti kii ṣe lati sọrọ nipa lilo BPF Ayebaye c cls_bpf Iṣoro naa ni pe, ni akawe si BPF ti o gbooro, ipari ti iwulo ninu ọran yii ti dinku ni ipilẹṣẹ: awọn eto kilasika ko le yi awọn akoonu ti awọn idii pada ati pe ko le fi ipo pamọ laarin awọn ipe.

Nitorinaa o to akoko lati sọ o dabọ si BPF Ayebaye ati wo ọjọ iwaju.

Idagbere si BPF Ayebaye

A wo bii imọ-ẹrọ BPF, ti o dagbasoke ni ibẹrẹ awọn ọgọọgọrun ọdun, ṣaṣeyọri gbe fun idamẹrin ọdun kan ati titi di ipari ti rii awọn ohun elo tuntun. Bibẹẹkọ, iru si iyipada lati awọn ẹrọ akopọ si RISC, eyiti o jẹ iwuri fun idagbasoke BPF Ayebaye, ni awọn ọdun 32 iyipada kan wa lati awọn ẹrọ 64-bit si awọn ẹrọ XNUMX-bit ati BPF Ayebaye bẹrẹ lati di atijo. Ni afikun, awọn agbara ti BPF Ayebaye jẹ opin pupọ, ati ni afikun si faaji ti igba atijọ - a ko ni agbara lati ṣafipamọ ipo laarin awọn ipe si awọn eto BPF, ko ṣeeṣe ti ibaraenisepo olumulo taara, ko si iṣeeṣe ibaraenisepo. pẹlu ekuro, ayafi fun kika nọmba to lopin ti awọn aaye eto sk_buff ati ifilọlẹ awọn iṣẹ oluranlọwọ ti o rọrun julọ, iwọ ko le yi awọn akoonu ti awọn apo-iwe pada ki o tun ṣe atunṣe wọn.

Ni otitọ, lọwọlọwọ gbogbo ohun ti o ku ti BPF Ayebaye ni Lainos ni wiwo API, ati inu ekuro gbogbo awọn eto Ayebaye, boya awọn asẹ iho tabi awọn asẹ seccomp, ni a tumọ laifọwọyi sinu ọna kika tuntun, BPF gbooro. (A yoo sọrọ nipa gangan bi eyi ṣe ṣẹlẹ ninu nkan ti nbọ.)

Iyipada si faaji tuntun bẹrẹ ni ọdun 2013, nigbati Alexey Starovoitov dabaa ero imudojuiwọn BPF kan. Ni 2014 awọn abulẹ ti o baamu bẹrẹ si han ninu mojuto. Gẹgẹ bi mo ti loye, ero akọkọ jẹ nikan lati mu faaji ati akopọ JIT ṣiṣẹ daradara siwaju sii lori awọn ẹrọ 64-bit, ṣugbọn dipo awọn iṣapeye wọnyi samisi ibẹrẹ ti ipin tuntun ni idagbasoke Linux.

Awọn nkan diẹ sii ninu jara yii yoo bo faaji ati awọn ohun elo ti imọ-ẹrọ tuntun, lakoko ti a mọ ni BPF ti inu, lẹhinna BPF ti o gbooro, ati ni bayi ni irọrun BPF.

jo

  1. Steven McCanne ati Van Jacobson, "Àlẹmọ Packet BSD: Iṣẹ-ọna Tuntun fun Gbigba Packet Ipele Olumulo", https://www.tcpdump.org/papers/bpf-usenix93.pdf
  2. Steven McCanne, "libpcap: Ohun elo faaji ati Ilana Imudara fun Gbigba Packet", https://sharkfestus.wireshark.org/sharkfest.11/presentations/McCanne-Sharkfest'11_Keynote_Address.pdf
  3. tcpdump, libpcap: https://www.tcpdump.org/
  4. IPtable U32 Baramu Tutorial.
  5. BPF - bytecode gbagbe: https://blog.cloudflare.com/bpf-the-forgotten-bytecode/
  6. Ṣafihan Irinṣẹ BPF: https://blog.cloudflare.com/introducing-the-bpf-tools/
  7. bpf_cls: http://man7.org/linux/man-pages/man8/tc-bpf.8.html
  8. Akopọ iṣẹju-aaya: https://lwn.net/Articles/656307/
  9. https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
  10. habr: Awọn apoti ati aabo: seccomp
  11. habr: Iyasọtọ daemons pẹlu systemd tabi “iwọ ko nilo Docker fun eyi!”
  12. Paul Chaignon, "strace --seccomp-bpf: wo labẹ awọn Hood", https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
  13. netsniff-ng: http://netsniff-ng.org/

orisun: www.habr.com

Fi ọrọìwòye kun