BPF para sa mga gagmay, bahin zero: classic BPF

Ang Berkeley Packet Filters (BPF) usa ka teknolohiya sa kernel sa Linux nga naa sa unahan nga mga panid sa mga publikasyon sa teknolohiya nga English-pinulongan sa daghang tuig na karon. Ang mga komperensya napuno sa mga taho bahin sa paggamit ug pagpalambo sa BPF. Si David Miller, Linux network subsystem maintainer, nagtawag sa iyang pakigpulong sa Linux Plumbers 2018 "Kini nga pakigpulong dili bahin sa XDP" (Ang XDP usa ka kaso sa paggamit alang sa BPF). Si Brendan Gregg naghatag ug mga pakigpulong nga nag-ulohang Linux BPF Superpowers. Toke HΓΈiland-JΓΈrgensen mikatawanga ang kernel karon usa na ka microkernel. Gipasiugda ni Thomas Graf ang ideya nga Ang BPF kay javascript para sa kernel.

Wala pa'y sistematikong paghulagway sa BPF sa HabrΓ©, ug busa sa usa ka serye sa mga artikulo akong sulayan nga hisgutan ang kasaysayan sa teknolohiya, ihulagway ang arkitektura ug mga himan sa pagpalambo, ug gilatid ang mga bahin sa aplikasyon ug praktis sa paggamit sa BPF. Kini nga artikulo, zero, sa serye, nagsulti sa kasaysayan ug arkitektura sa klasiko nga BPF, ug nagpadayag usab sa mga sekreto sa mga prinsipyo sa operasyon niini. tcpdump, seccomp, strace, ug daghan pa.

Ang pag-uswag sa BPF kontrolado sa Linux networking community, ang nag-unang kasamtangan nga aplikasyon sa BPF may kalabutan sa mga network ug busa, uban ang pagtugot @eucariot, Gitawag nako ang serye nga "BPF alang sa mga gagmay", agig pasidungog sa dagkong serye "Mga network alang sa gagmay nga mga bata".

Usa ka mubo nga kurso sa kasaysayan sa BPF (c)

Ang modernong teknolohiya sa BPF usa ka gipaayo ug gipalapad nga bersyon sa daan nga teknolohiya nga adunay parehas nga ngalan, karon gitawag nga klasiko nga BPF aron malikayan ang kalibog. Ang usa ka ilado nga utility gihimo base sa klasiko nga BPF tcpdump, mekanismo seccomp, ingon man ang dili kaayo nailhan nga mga module xt_bpf alang sa iptables ug classifier cls_bpf. Sa modernong Linux, ang mga klasiko nga BPF nga mga programa awtomatik nga gihubad ngadto sa bag-ong porma, bisan pa, gikan sa punto sa panglantaw sa user, ang API nagpabilin sa lugar ug ang mga bag-ong gamit alang sa classic nga BPF, ingon sa atong makita niini nga artikulo, makita gihapon. Tungod niini, ug tungod usab sa pagsunod sa kasaysayan sa pag-uswag sa klasikal nga BPF sa Linux, mahimong mas klaro kung giunsa ug ngano nga kini milambo sa modernong porma, nakahukom ako nga magsugod sa usa ka artikulo bahin sa klasikal nga BPF.

Sa katapusan sa mga eighties sa miaging siglo, ang mga inhenyero gikan sa bantog nga Lawrence Berkeley Laboratory nahimong interesado sa pangutana kon sa unsang paagi sa husto nga pagsala sa network packet sa hardware nga moderno sa ulahing bahin sa eighties sa miaging siglo. Ang sukaranan nga ideya sa pagsala, nga orihinal nga gipatuman sa CSPF (CMU/Stanford Packet Filter) nga teknolohiya, mao ang pagsala sa wala kinahanglana nga mga pakete sa sayo kutob sa mahimo, i.e. sa kernel space, tungod kay kini naglikay sa pagkopya sa wala kinahanglana nga datos ngadto sa user space. Aron mahatagan ang seguridad sa runtime alang sa pagpadagan sa code sa gumagamit sa wanang sa kernel, gigamit ang usa ka sandboxed virtual machine.

Bisan pa, ang mga virtual nga makina alang sa naglungtad nga mga pagsala gidesinyo nga modagan sa mga stack-based nga makina ug dili maayo nga modagan sa mas bag-ong mga makina sa RISC. Ingon usa ka sangputanan, pinaagi sa mga paningkamot sa mga inhenyero gikan sa Berkeley Labs, usa ka bag-ong teknolohiya sa BPF (Berkeley Packet Filters) ang naugmad, ang arkitektura sa virtual machine nga gidisenyo base sa processor sa Motorola 6502 - ang workhorse sa mga iladong produkto sama sa. Apple II o NES. Ang bag-ong virtual machine nagdugang sa performance sa filter napulo ka beses kon itandi sa kasamtangan nga mga solusyon.

Ang arkitektura sa makina sa BPF

Masinati namon ang arkitektura sa usa ka nagtrabaho nga paagi, pag-analisar sa mga pananglitan. Bisan pa, sa pagsugod, ingnon ta nga ang makina adunay duha ka 32-bit nga mga rehistro nga ma-access sa tiggamit, usa ka accumulator. A ug index register X, 64 bytes sa memorya (16 ka pulong), magamit alang sa pagsulat ug sa sunod nga pagbasa, ug usa ka gamay nga sistema sa mga sugo alang sa pagtrabaho uban niini nga mga butang. Ang mga instruksyon sa paglukso alang sa pagpatuman sa mga conditional nga ekspresyon anaa usab sa mga programa, apan aron magarantiya ang tukma sa panahon nga pagkompleto sa programa, ang mga paglukso mahimo lamang nga himoon sa unahan, i.e., ilabi na, gidid-an ang paghimo og mga galong.

Ang kinatibuk-ang laraw sa pagsugod sa makina mao ang mosunod. Naghimo ang user og programa para sa arkitektura sa BPF ug, gamit ang uban mekanismo sa kernel (sama sa tawag sa sistema), nagkarga ug nagkonektar sa programa sa sa pipila ngadto sa generator sa panghitabo sa kernel (pananglitan, ang usa ka panghitabo mao ang pag-abot sa sunod nga pakete sa network card). Kung mahitabo ang usa ka panghitabo, ang kernel nagpadagan sa programa (pananglitan, sa usa ka tighubad), ug ang memorya sa makina katumbas sa sa pipila rehiyon sa memorya sa kernel (pananglitan, datos sa umaabot nga pakete).

Ang sa ibabaw igo na alang kanato sa pagsugod sa pagtan-aw sa mga panig-ingnan: kita makasinati sa sistema ug command format kon gikinahanglan. Kung gusto nimo nga tun-an dayon ang command system sa usa ka virtual machine ug mahibal-an ang tanan nga mga kapabilidad niini, mahimo nimong basahon ang orihinal nga artikulo Ang BSD Packet Filter ug/o ang unang katunga sa file Dokumentasyon/networking/filter.txt gikan sa dokumentasyon sa kernel. Dugang pa, mahimo nimong tun-an ang presentasyon libpcap: Usa ka Arkitektura ug Pamaagi sa Pag-optimize alang sa Pagkuha sa Packet, diin si McCanne, usa sa mga tagsulat sa BPF, naghisgot bahin sa kasaysayan sa paglalang libpcap.

Nagpadayon kami aron ikonsiderar ang tanan nga hinungdanon nga mga pananglitan sa paggamit sa klasiko nga BPF sa Linux: tcpdump (libpcap), seccom, xt_bpf, cls_bpf.

tcpdump

Ang pag-uswag sa BPF gihimo dungan sa pag-uswag sa frontend alang sa packet filtering - usa ka ilado nga utility tcpdump. Ug, tungod kay kini ang labing karaan ug labing inila nga pananglitan sa paggamit sa klasiko nga BPF, nga magamit sa daghang mga operating system, magsugod kami sa among pagtuon sa teknolohiya uban niini.

(Akong gipadagan ang tanan nga mga pananglitan niini nga artikulo sa Linux 5.6.0-rc6. Ang output sa pipila ka mga sugo gi-edit para sa mas maayong pagkabasa.)

Pananglitan: pag-obserbar sa IPv6 packet

Hunahunaa nga gusto natong tan-awon ang tanang IPv6 packet sa usa ka interface eth0. Aron mahimo kini mahimo naton nga daganon ang programa tcpdump nga adunay usa ka yano nga filter ip6:

$ sudo tcpdump -i eth0 ip6

Mao kini ang tcpdump nag-compile sa filter ip6 ngadto sa BPF architecture bytecode ug ipadala kini sa kernel (tan-awa ang mga detalye sa seksyon Tcpdump: nagkarga). Ang gikarga nga filter ipadagan alang sa matag pakete nga moagi sa interface eth0. Kung ang filter nagbalik usa ka dili zero nga kantidad n, unya hangtod sa n Ang mga byte sa packet makopya sa user space ug makita nato kini sa output tcpdump.

BPF para sa mga gagmay, bahin zero: classic BPF

Kini nahimo nga dali ra naton mahibal-an kung unsang bytecode ang gipadala sa kernel tcpdump uban sa tabang sa tcpdump, kon atong daganon kini sa opsyon -d:

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

Sa linya zero among gipadagan ang mando ldh [12], nga nagpasabot sa β€œload into register A tunga sa pulong (16 bits) nga nahimutang sa adres nga 12” ug ang pangutana lang unsa nga matang sa memorya ang atong gitubag? Ang tubag mao nga sa x nagsugod (x+1)th byte sa na-analisa nga network packet. Gibasa namon ang mga pakete gikan sa interface sa Ethernet eth0ug kini paaginga ang packet ingon niini (alang sa kayano, atong gihunahuna nga walay mga VLAN tag sa pakete):

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

Busa human sa pagpatuman sa sugo ldh [12] sa rehistro A naay umahan Ether Type β€” ang tipo sa packet nga gipasa sa kini nga frame sa Ethernet. Sa linya 1 atong itandi ang mga sulod sa rehistro A (matang sa pakete) c 0x86ddug kini ug adunay Ang tipo nga interesado kami mao ang IPv6. Sa linya 1, dugang sa komand sa pagtandi, adunay duha pa nga mga kolum - jt 2 ΠΈ jf 3 β€” mga marka nga kinahanglan nimong adtoan kung malampuson ang pagtandi (A == 0x86dd) ug wala molampos. Busa, sa usa ka malampuson nga kaso (IPv6) moadto kami sa linya 2, ug sa usa ka dili malampuson nga kaso - sa linya 3. Sa linya 3 ang programa natapos sa code 0 (ayaw kopyaha ang pakete), sa linya 2 ang programa natapos sa code 262144 (kopya ako ug maximum nga 256 kilobytes nga pakete).

Usa ka mas komplikado nga pananglitan: atong tan-awon ang TCP packets sa destinasyon nga pantalan

Atong tan-awon kung unsa ang hitsura sa usa ka filter nga nagkopya sa tanan nga TCP packet nga adunay destinasyon nga port 666. Atong tagdon ang IPv4 nga kaso, tungod kay ang IPv6 nga kaso mas simple. Human sa pagtuon niini nga pananglitan, mahimo nimong tukion ang IPv6 filter sa imong kaugalingon isip usa ka ehersisyo (ip6 and tcp dst port 666) ug usa ka filter alang sa kinatibuk-ang kaso (tcp dst port 666). Mao nga, ang filter nga gusto namon tan-awon sama niini:

$ 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

Nahibal-an na naton kung unsa ang buhaton sa mga linya 0 ug 1. Sa linya 2 gisusi na namo nga kini usa ka IPv4 packet (Ether Type = 0x800) ug i-load kini sa rehistro A Ika-24 nga byte sa pakete. Ang among package murag

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

nga nagpasabut nga kita nagkarga sa rehistro A ang Protocol field sa IP header, nga lohikal, tungod kay gusto namong kopyahon ang mga TCP packets. Atong itandi ang Protocol sa 0x6 (IPPROTO_TCP) sa linya 3.

Sa linya 4 ug 5 gikarga namo ang mga halfword nga nahimutang sa address 20 ug gigamit ang command jset susiha kon ang usa sa tulo gitakda mga bandera - pagsul-ob sa maskara nga gihatag jset ang tulo ka labing mahinungdanon nga mga piraso gitangtang. Ang duha sa tulo ka mga bits nagsulti kanato kon ang packet kabahin sa usa ka fragmented IP packet, ug kung mao, kung kini ang katapusan nga fragment. Ang ikatulo nga bit gireserba ug kinahanglan nga zero. Dili namo gusto nga susihon ang dili kompleto o guba nga mga pakete, mao nga among susihon ang tanan nga tulo ka piraso.

Ang Linya 6 mao ang labing makaiikag niini nga listahan. Pagpahayag ldxb 4*([14]&0xf) nagpasabot nga nagkarga kami sa rehistro X ang labing gamay nga mahinungdanon nga upat ka bits sa ikanapulo ug lima nga byte sa pakete nga gipadaghan sa 4. Ang labing gamay nga mahinungdanon nga upat ka mga bit sa ikanapulo ug lima nga byte mao ang field Internet Header Gitas-on IPv4 header, nga nagtipig sa gitas-on sa header sa mga pulong, mao nga kinahanglan nimo nga padaghanon sa 4. Makaiikag, ang ekspresyon 4*([14]&0xf) mao ang usa ka pagtudlo alang sa usa ka espesyal nga addressing scheme nga magamit lamang niini nga porma ug alang lamang sa usa ka rehistro X, i.e. dili sab ta makaingon ldb 4*([14]&0xf) dili ldxb 5*([14]&0xf) (mahimo ra namon nga ipiho ang lahi nga offset, pananglitan, ldxb 4*([16]&0xf)). Klaro nga kini nga pamaagi sa pagtubag gidugang sa BPF nga tukma aron makadawat X (index register) IPv4 header gitas-on.

Mao nga sa linya 7 gisulayan namon nga i-load ang tunga sa pulong sa (X+16). Ang paghinumdom nga ang 14 bytes giokupahan sa Ethernet header, ug X naglangkob sa gitas-on sa IPv4 header, atong nasabtan nga sa A Ang destinasyon nga pantalan sa TCP gikarga:

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

Sa katapusan, sa linya 8 atong itandi ang destinasyon nga pantalan sa gitinguha nga bili ug sa mga linya 9 o 10 atong ibalik ang resulta - kon kopyahon ang pakete o dili.

Tcpdump: nagkarga

Sa nangaging mga pananglitan, espesipikong wala kami maghisgot sa detalye kung giunsa namo pagkarga ang BPF bytecode sa kernel para sa packet filtering. Sa kinatibuk-an, tcpdump gi-port sa daghang mga sistema ug alang sa pagtrabaho sa mga pagsala tcpdump naggamit sa librarya libpcap. Sa mubo, sa pagbutang sa usa ka filter sa usa ka interface gamit libpcap, kinahanglan nimo buhaton ang mosunud:

Aron makita kung giunsa ang function pcap_setfilter gipatuman sa Linux, among gigamit strace (pipila ka linya gitangtang):

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

Sa unang duha ka linya sa output atong gimugna hilaw nga socket aron mabasa ang tanan nga mga frame sa Ethernet ug ihigot kini sa interface eth0... gikan sa atong unang ehemplo nahibal-an namon nga ang filter ip maglangkob sa upat ka mga panudlo sa BPF, ug sa ikatulo nga linya atong makita kung giunsa ang paggamit sa kapilian SO_ATTACH_FILTER tawag sa sistema setsockopt nagkarga kami ug nagkonektar sa usa ka filter nga may gitas-on nga 4. Kini ang among filter.

Angay nga matikdan nga sa klasiko nga BPF, ang pagkarga ug pagkonektar sa usa ka filter kanunay nga mahitabo ingon usa ka atomic nga operasyon, ug sa bag-ong bersyon sa BPF, ang pagkarga sa programa ug pagbugkos niini sa generator sa panghitabo gibulag sa oras.

Tinago nga Kamatuoran

Ang usa ka gamay nga mas kompleto nga bersyon sa output ingon niini:

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

Sama sa gihisgutan sa ibabaw, among gikarga ug gikonektar ang among filter sa socket sa linya 5, apan unsa ang mahitabo sa mga linya 3 ug 4? Kini nahimo nga kini libpcap nag-atiman kanamo - aron ang output sa among filter dili maglakip sa mga pakete nga dili makatagbaw niini, ang librarya nagkonektar dummy filter ret #0 (ihulog ang tanang packet), ibalhin ang socket ngadto sa non-blocking mode ug sulayan nga ibawas ang tanang packet nga mahimong magpabilin gikan sa nangaging mga filter.

Sa kinatibuk-an, aron ma-filter ang mga pakete sa Linux gamit ang klasiko nga BPF, kinahanglan nimo nga adunay usa ka filter sa porma sa usa ka istruktura sama struct sock_fprog ug usa ka bukas nga suksokanan, pagkahuman ang salaan mahimong i-attach sa socket gamit ang usa ka tawag sa sistema setsockopt.

Makapainteres, ang filter mahimong ilakip sa bisan unsang socket, dili lang hilaw. Dinhi usa ka panig-ingnan usa ka programa nga nagputol sa tanan gawas sa unang duha ka byte gikan sa tanang umaabot nga UDP datagrams. (Gidugangan nako ang mga komentaryo sa code aron dili kalat ang artikulo.)

Dugang nga mga detalye bahin sa paggamit setsockopt alang sa pagkonektar sa mga filter, tan-awa socket(7), apan bahin sa pagsulat sa imong kaugalingon nga mga pagsala sama sa struct sock_fprog walay tabang tcpdump magstorya ta sa section Pagprograma sa BPF gamit ang among kaugalingon nga mga kamot.

Classic BPF ug ang ika-XNUMX nga siglo

Ang BPF gilakip sa Linux kaniadtong 1997 ug nagpabilin nga usa ka workhorse sa dugay nga panahon libpcap nga walay bisan unsang espesyal nga mga pagbag-o (mga pagbag-o nga piho sa Linux, siyempre, kini mao ang, apan wala nila usba ang tibuok kalibutan nga hulagway). Ang unang seryoso nga mga timailhan nga ang BPF molambo niabot sa 2011, sa dihang gisugyot ni Eric Dumazet pag-patch, nga nagdugang sa Just In Time Compiler sa kernel - usa ka tighubad alang sa pag-convert sa BPF bytecode ngadto sa lumad x86_64 Code.

Ang JIT compiler mao ang una sa kadena sa mga pagbag-o: kaniadtong 2012 nagpakita abilidad sa pagsulat sa mga filter alang sa seccom, gamit ang BPF, sa Enero 2013 adunay gidugang modyul xt_bpf, nga nagtugot kanimo sa pagsulat sa mga lagda alang sa iptables uban sa tabang sa BPF, ug sa Oktubre 2013 mao ang gidugang usa usab ka module cls_bpf, nga nagtugot kanimo sa pagsulat sa mga klasipikasyon sa trapiko gamit ang BPF.

Atong tan-awon ang tanan niini nga mga pananglitan sa mas detalyado sa dili madugay, apan una kini mapuslanon alang kanato nga makat-on unsaon pagsulat ug pag-compile sa mga arbitraryong programa alang sa BPF, tungod kay ang mga kapabilidad nga gihatag sa librarya. libpcap limitado (simple nga pananglitan: filter nga nahimo libpcap makabalik lamang sa duha ka mga kantidad - 0 o 0x40000) o sa kinatibuk-an, sama sa kaso sa seccomp, dili magamit.

Pagprograma sa BPF gamit ang among kaugalingon nga mga kamot

Atong pamilyar ang binary nga format sa mga panudlo sa BPF, kini yano ra:

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

Ang matag instruksyon nag-okupar sa 64 ka bit, diin ang unang 16 ka bits mao ang instruction code, unya adunay duha ka walo ka bit indents, jt ΠΈ jf, ug 32 bits alang sa argumento K, ang katuyoan niini managlahi gikan sa sugo ngadto sa sugo. Pananglitan, ang sugo ret, nga nagtapos sa programa adunay code 6, ug ang pagbalik nga bili gikuha gikan sa makanunayon K. Sa C, ang usa ka panudlo sa BPF girepresentahan ingon usa ka istruktura

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

ug ang tibuok nga programa anaa sa porma sa usa ka istruktura

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

Sa ingon, mahimo na naton isulat ang mga programa (pananglitan, nahibal-an namon ang mga code sa panudlo gikan sa [1]). Mao kini ang hitsura sa filter ip6 gikan sa atong unang ehemplo:

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

programa prog legal namong magamit sa usa ka tawag

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

Ang pagsulat sa mga programa sa porma sa mga code sa makina dili kaayo kombenyente, apan usahay gikinahanglan (pananglitan, alang sa pag-debug, paghimo sa mga pagsulay sa yunit, pagsulat sa mga artikulo sa HabrΓ©, ug uban pa). Alang sa kasayon, sa file <linux/filter.h> Ang helper macros gihubit - ang sama nga pananglitan sa ibabaw mahimong isulat pag-usab ingon

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

Bisan pa, kini nga kapilian dili kaayo kombenyente. Mao kini ang nangatarungan sa mga programmer sa Linux kernel, ug busa sa direktoryo tools/bpf kernels makit-an nimo ang usa ka assembler ug debugger alang sa pagtrabaho kauban ang klasiko nga BPF.

Ang pinulongan sa Assembly susama kaayo sa output sa debug tcpdump, apan dugang pa mahimo natong ipiho ang simbolikong mga label. Pananglitan, ania ang usa ka programa nga naghulog sa tanan nga mga pakete gawas sa TCP/IPv4:

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

Sa kasagaran, ang assembler nagmugna og code sa format <количСство инструкций>,<code1> <jt1> <jf1> <k1>,..., alang sa atong panig-ingnan sa TCP kini mahimong

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

Alang sa kasayon ​​​​sa mga C programmer, usa ka lahi nga format sa output ang magamit:

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

Kini nga teksto mahimong kopyahon ngadto sa kahulugan sa istruktura sa tipo struct sock_filter, sama sa among gibuhat sa sinugdanan niini nga seksyon.

Linux ug netsniff-ng mga extension

Dugang pa sa standard BPF, Linux ug tools/bpf/bpf_asm suporta ug non-standard nga set. Sa panguna, ang mga panudlo gigamit aron ma-access ang mga natad sa usa ka istruktura struct sk_buff, nga naghulagway sa usa ka network packet sa kernel. Bisan pa, adunay uban pang mga lahi sa mga panudlo sa katabang, pananglitan ldw cpu i-load sa rehistro A resulta sa pagpadagan sa usa ka kernel function raw_smp_processor_id(). (Sa bag-ong bersyon sa BPF, kini nga dili standard nga mga extension gipalapdan aron mahatagan ang mga programa sa usa ka hugpong sa mga kernel helper alang sa pag-access sa memorya, istruktura, ug pagmugna og mga panghitabo.) Ania ang usa ka makapaikag nga panig-ingnan sa usa ka filter diin gikopya lang namon ang packet header ngadto sa user space gamit ang extension poff, payload offset:

ld poff
ret a

Ang mga extension sa BPF dili magamit sa tcpdump, apan kini usa ka maayong rason aron masinati ang utility package netsniff-ng, nga, lakip sa ubang mga butang, adunay usa ka advanced nga programa netsniff-ng, nga, dugang sa pagsala sa paggamit sa BPF, naglangkob usab sa usa ka epektibo nga traffic generator, ug mas abante kay sa tools/bpf/bpf_asm, usa ka BPF assembler nga gitawag bpfc. Ang pakete adunay daghang detalyado nga dokumentasyon, tan-awa usab ang mga link sa katapusan sa artikulo.

seccom

Busa, nahibal-an na nato kung unsaon pagsulat ang mga programa sa BPF sa arbitraryong pagkakomplikado ug andam nga motan-aw sa bag-ong mga pananglitan, ang una niini mao ang teknolohiya sa seccomp, nga nagtugot, gamit ang mga filter sa BPF, sa pagdumala sa set ug set sa mga argumento sa tawag sa sistema nga anaa sa usa ka gihatag nga proseso ug ang mga kaliwat niini.

Ang unang bersyon sa seccomp gidugang ngadto sa kernel niadtong 2005 ug dili kaayo popular, tungod kay naghatag lamang kini og usa ka opsyon - aron limitahan ang set sa mga tawag sa sistema nga anaa sa usa ka proseso ngadto sa mosunod: read, write, exit ΠΈ sigreturn, ug ang proseso nga nakalapas sa mga lagda gipatay gamit SIGKILL. Bisan pa, kaniadtong 2012, gidugang sa seccomp ang abilidad sa paggamit sa mga filter sa BPF, nga nagtugot kanimo sa paghubit sa usa ka hugpong sa gitugotan nga mga tawag sa sistema ug bisan sa paghimo sa mga pagsusi sa ilang mga argumento. (Makapainteres, ang Chrome mao ang usa sa unang mga tiggamit niini nga gamit, ug ang mga tawo sa Chrome sa pagkakaron nagpalambo sa mekanismo sa KRSI base sa bag-ong bersyon sa BPF ug nagtugot sa pag-customize sa Linux Security Modules.) Ang mga link sa dugang nga dokumentasyon makita sa katapusan sa artikulo.

Timan-i nga aduna nay mga artikulo sa hub bahin sa paggamit sa seccom, basin adunay gustong mobasa niini sa dili pa (o imbes) nga basahon ang mosunod nga mga subseksyon. Sa artikulo Mga sudlanan ug seguridad: seccom naghatag mga pananglitan sa paggamit sa seccomp, ang 2007 nga bersyon ug ang bersyon gamit ang BPF (mga filter gihimo gamit ang libseccomp), naghisgot bahin sa koneksyon sa seccomp sa Docker, ug naghatag usab daghang mapuslanon nga mga link. Sa artikulo Pag-isolate sa mga daemon nga adunay systemd o "dili nimo kinahanglan ang Docker alang niini!" Naglangkob kini, labi na, kung giunsa pagdugang ang mga blacklist o mga whitelist sa mga tawag sa sistema alang sa mga daemon nga nagpadagan sa systemd.

Sunod atong tan-awon kon unsaon pagsulat ug pagkarga sa mga filter seccomp sa hubo nga C ug gamit ang library libseccomp ug unsa ang mga bentaha ug disbentaha sa matag kapilian, ug sa katapusan, atong tan-awon kung giunsa ang seccomp gigamit sa programa strace.

Pagsulat ug pagkarga sa mga filter para sa seccom

Nahibal-an na nato kung unsaon pagsulat ang mga programa sa BPF, busa atong tan-awon una ang interface sa seccom programming. Mahimo nimong itakda ang usa ka filter sa lebel sa proseso, ug ang tanan nga mga proseso sa bata makapanunod sa mga pagdili. Gihimo kini gamit ang usa ka tawag sa sistema seccomp(2):

seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)

diin &filter - kini usa ka pointer sa usa ka istruktura nga pamilyar na kanato struct sock_fprog, i.e. BPF nga programa.

Sa unsang paagi ang mga programa alang sa seccom lahi sa mga programa alang sa mga socket? Gipasa nga konteksto. Sa kaso sa mga socket, gihatagan kami usa ka lugar sa panumduman nga adunay sulud, ug sa kaso sa seccom gihatagan kami usa ka istruktura sama sa

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

kini mao ang nr mao ang numero sa tawag sa sistema nga ilunsad, arch - kasamtangan nga arkitektura (dugang niini sa ubos), args - hangtod sa unom ka argumento sa tawag sa sistema, ug instruction_pointer usa ka pointer sa instruksiyon sa user space nga naghimo sa system call. Sa ingon, pananglitan, i-load ang numero sa tawag sa sistema sa rehistro A kinahanglan natong isulti

ldw [0]

Adunay uban nga mga bahin alang sa mga programa sa seccom, pananglitan, ang konteksto ma-access lamang pinaagi sa 32-bit nga pag-align ug dili ka maka-load sa tunga sa usa ka pulong o usa ka byte - kung mosulay sa pag-load sa usa ka filter. ldh [0] tawag sa sistema seccomp mobalik EINVAL. Gisusi sa function ang gikarga nga mga filter seccomp_check_filter() mga lugas. (Ang kataw-anan mao, sa orihinal nga commit nga nagdugang sa seccomp functionality, nakalimot sila sa pagdugang sa pagtugot sa paggamit sa instruksyon niini nga function. mod (division remainder) ug dili na magamit alang sa seccom BPF nga mga programa, sukad sa pagdugang niini mabuak ABI.)

Sa panguna, nahibal-an na naton ang tanan sa pagsulat ug pagbasa sa mga programa sa seccom. Kasagaran ang lohika sa programa gihan-ay ingon usa ka puti o itom nga lista sa mga tawag sa sistema, pananglitan ang programa

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

nagsusi sa usa ka blacklist sa upat ka sistema sa tawag nga may numero nga 304, 176, 239, 279. Unsa kini nga mga tawag sa sistema? Dili kami makaingon nga sigurado, tungod kay wala kami nahibal-an kung unsang arkitektura ang gisulat sa programa. Busa, ang mga tagsulat sa seccom tanyag pagsugod sa tanan nga mga programa nga adunay pagsusi sa arkitektura (ang kasamtangan nga arkitektura gipakita sa konteksto ingon usa ka uma arch mga istruktura struct seccomp_data). Uban sa arkitektura nga gisusi, ang sinugdanan sa panig-ingnan sama sa:

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

ug unya ang among mga numero sa tawag sa sistema makakuha og piho nga mga kantidad.

Kami nagsulat ug nagkarga sa mga filter alang sa paggamit sa seccom libseccomp

Ang pagsulat sa mga filter sa lumad nga code o sa BPF nga asembliya nagtugot kanimo nga adunay bug-os nga pagkontrol sa resulta, apan sa samang higayon, usahay mas maayo nga adunay madaladala ug/o mabasa nga code. Ang librarya makatabang kanato niini libseccomp, nga naghatag ug standard interface para sa pagsulat sa itom o puti nga mga filter.

Atong, pananglitan, pagsulat sa usa ka programa nga nagpadagan sa usa ka binary file nga gipili sa user, nga kaniadto nag-install sa usa ka itom nga lista sa mga tawag sa sistema gikan sa sa ibabaw nga artikulo (ang programa gipasayon ​​alang sa mas sayon ​​nga pagbasa, ang tibuok nga bersyon makita dinhi):

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

Una atong gihubit ang usa ka array sys_numbers sa 40+ nga mga numero sa tawag sa sistema aron babagan. Dayon, pagsugod sa konteksto ctx ug isulti sa librarya kung unsa ang gusto namon tugutan (SCMP_ACT_ALLOW) ang tanan nga mga tawag sa sistema pinaagi sa default (mas dali ang paghimo og mga blacklist). Dayon, usa-usa, among idugang ang tanang tawag sa sistema gikan sa blacklist. Agig tubag sa usa ka tawag sa sistema gikan sa lista, among gihangyo SCMP_ACT_TRAP, sa kini nga kaso ang seccom magpadala usa ka signal sa proseso SIGSYS nga adunay usa ka paghulagway kung unsang tawag sa sistema ang nakalapas sa mga lagda. Sa katapusan, among gikarga ang programa sa kernel gamit seccomp_load, nga mag-compile sa programa ug i-attach kini sa proseso gamit ang system call seccomp(2).

Alang sa malampuson nga paghugpong, ang programa kinahanglan nga nalambigit sa librarya libseccompsama pananglit:

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

Pananglitan sa malampuson nga paglusad:

$ ./seccomp_lib echo ok
ok

Pananglitan sa usa ka gibabagan nga tawag sa sistema:

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

Gigamit namo stracepara sa mga detalye:

$ 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

unsaon man nato pagkahibalo nga na-terminate ang program tungod sa paggamit ug illegal system call mount(2).

Mao nga, nagsulat kami usa ka filter gamit ang librarya libseccomp, mohaom sa dili-trivial nga code ngadto sa upat ka linya. Sa pananglitan sa ibabaw, kung adunay daghang gidaghanon sa mga tawag sa sistema, ang oras sa pagpatuman mahimong mamatikdan nga pagkunhod, tungod kay ang tseke usa ra ka lista sa mga pagtandi. Alang sa pag-optimize, ang libseccomp bag-o lang adunay gilakip ang patch, nga nagdugang suporta para sa filter attribute SCMP_FLTATR_CTL_OPTIMIZE. Ang pagbutang niini nga attribute ngadto sa 2 mag-convert sa filter ngadto sa binary search program.

Kung gusto nimo makita kung giunsa ang pagtrabaho sa binary search filter, tan-awa simple nga script, nga nagmugna sa ingon nga mga programa sa BPF assembler pinaagi sa pag-dial sa mga numero sa tawag sa sistema, pananglitan:

$ 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

Imposible nga magsulat og bisan unsa nga mas paspas, tungod kay ang mga programa sa BPF dili makahimo sa paglukso sa indentation (dili namo mahimo, pananglitan, jmp A o jmp [label+X]) ug busa ang tanang transisyon kay static.

seccom ug strace

Ang tanan nahibalo sa utility strace usa ka kinahanglanon nga himan alang sa pagtuon sa pamatasan sa mga proseso sa Linux. Bisan pa, daghan usab ang nakadungog bahin mga isyu sa performance sa paggamit niini nga utility. Ang kamatuoran mao kana strace gipatuman gamit ang ptrace(2), ug niini nga mekanismo dili nato matino kung unsa nga set sa mga tawag sa sistema ang kinahanglan natong hunongon ang proseso, i.e., pananglitan, mga sugo

$ 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

giproseso sa halos parehas nga oras, bisan kung sa ikaduha nga kaso gusto namon nga masubay ang usa ra ka tawag sa sistema.

Bag-ong kapilian --seccomp-bpf, gidugang sa strace nga bersyon 5.3, nagtugot kanimo sa pagpadali sa proseso sa daghang mga higayon ug ang oras sa pagsugod ubos sa pagsubay sa usa ka tawag sa sistema ikatandi na sa panahon sa usa ka regular nga pagsugod:

$ 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

(Dinhi, siyempre, adunay gamay nga limbong nga wala naton gisubay ang panguna nga tawag sa sistema sa kini nga mando. Kung gisubay naton, pananglitan, newfsstat, dayon strace mag brake nga sama kakusog sa wala --seccomp-bpf.)

Giunsa kini nga kapilian molihok? Kung wala siya strace nagkonektar sa proseso ug nagsugod kini sa paggamit PTRACE_SYSCALL. Kung ang usa ka pagdumala nga proseso nag-isyu sa usa ka (bisan unsang) tawag sa sistema, ang kontrol gibalhin sa strace, nga nagtan-aw sa mga argumento sa tawag sa sistema ug nagpadagan niini PTRACE_SYSCALL. Human sa pipila ka panahon, ang proseso makompleto ang tawag sa sistema ug sa paggawas niini, ang kontrol gibalhin pag-usab strace, nga nagtan-aw sa pagbalik nga mga kantidad ug nagsugod sa proseso gamit PTRACE_SYSCALL, ug uban pa.

BPF para sa mga gagmay, bahin zero: classic BPF

Uban sa seccom, bisan pa, kini nga proseso mahimong ma-optimize sa eksakto nga gusto namon. Sa ato pa, kung gusto naton tan-awon lang ang tawag sa sistema X, unya kita makasulat ug BPF filter nga para sa X mibalik og bili SECCOMP_RET_TRACE, ug alang sa mga tawag nga dili interesado kanamo - SECCOMP_RET_ALLOW:

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

Sa kini nga kaso strace sa sinugdanan magsugod ang proseso ingon PTRACE_CONT, giproseso ang among filter para sa matag tawag sa sistema, kung dili ang tawag sa sistema X, nan ang proseso nagpadayon sa pagdagan, apan kung kini X, unya ang seccom mobalhin sa kontrol stracenga motan-aw sa mga argumento ug magsugod sa proseso sama sa PTRACE_SYSCALL (tungod kay ang seccom walay katakus sa pagpadagan sa usa ka programa sa paggawas gikan sa usa ka tawag sa sistema). Kung mobalik ang tawag sa sistema, strace i-restart ang proseso gamit ang PTRACE_CONT ug maghulat alang sa mga bag-ong mensahe gikan sa seccom.

BPF para sa mga gagmay, bahin zero: classic BPF

Kung gigamit ang kapilian --seccomp-bpf adunay duha ka mga pagdili. Una, dili mahimo ang pag-apil sa naa na nga proseso (opsyon -p mga programa strace), tungod kay wala kini gisuportahan sa seccom. Ikaduha, walay posibilidad dili tan-awa ang mga proseso sa bata, tungod kay ang mga filter sa seccom napanunod sa tanan nga mga proseso sa bata nga wala’y katakus sa pag-disable niini.

Usa ka gamay nga detalye kung giunsa gyud strace pagtrabaho kauban seccomp makita gikan sa bag-o nga report. Alang kanamo, ang labing makapaikag nga kamatuoran mao nga ang klasiko nga BPF nga girepresentahan sa seccomp gigamit gihapon karon.

xt_bpf

Balik ta karon sa kalibutan sa mga network.

Background: dugay na ang milabay, sa 2007, ang kinauyokan mao gidugang modyul xt_u32 para sa netfilter. Gisulat kini pinaagi sa pagtandi sa usa ka mas karaan nga classifier sa trapiko cls_u32 ug gitugotan ka sa pagsulat sa arbitraryong binary nga mga lagda alang sa mga iptable gamit ang mosunod nga yano nga mga operasyon: load 32 bits gikan sa usa ka pakete ug paghimo sa usa ka set sa aritmetika nga mga operasyon niini. Pananglitan,

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

Nag-load sa 32 bits sa IP header, sugod sa padding 6, ug nag-apply og maskara ngadto kanila 0xFF (kuhaa ang ubos nga byte). Kini nga kapatagan protocol IP header ug atong itandi kini sa 1 (ICMP). Mahimo nimong isagol ang daghang mga tseke sa usa ka lagda, ug mahimo usab nimo ipatuman ang operator @ β€” ibalhin ang X bytes sa tuo. Pananglitan, ang lagda

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

susihon kung ang TCP Sequence Number dili parehas 0x29. Dili na ako moadto sa mga detalye, tungod kay klaro na nga ang pagsulat sa ingon nga mga lagda pinaagi sa kamot dili kaayo kombenyente. Sa artikulo BPF - ang nakalimtan nga bytecode, adunay daghang mga link nga adunay mga pananglitan sa paggamit ug pagmugna sa lagda alang sa xt_u32. Tan-awa usab ang mga link sa katapusan niini nga artikulo.

Sukad sa 2013 module imbes nga module xt_u32 pwede ka mugamit ug BPF based module xt_bpf. Bisan kinsa nga nakabasa niini kinahanglan nga klaro na bahin sa prinsipyo sa operasyon niini: pagdagan ang BPF bytecode ingon mga lagda sa iptables. Makahimo ka og bag-ong lagda, pananglitan, sama niini:

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

dinhi <Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄> - kini ang code sa assembler output format bpf_asm sa default, pananglitan,

$ 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

Sa kini nga pananglitan gisala namon ang tanan nga mga pakete sa UDP. Konteksto para sa usa ka BPF nga programa sa usa ka module xt_bpf, siyempre, nagpunting sa packet data, sa kaso sa mga iptables, ngadto sa sinugdanan sa IPv4 header. Ibalik nga bili gikan sa BPF nga programa booleandiin false nagpasabot nga ang pakete wala magkatugma.

Klaro nga ang module xt_bpf nagsuporta sa mas komplikado nga mga pagsala kay sa pananglitan sa ibabaw. Atong tan-awon ang tinuod nga mga pananglitan gikan sa Cloudfare. Hangtud bag-o lang ilang gigamit ang module xt_bpf aron mapanalipdan batok sa mga pag-atake sa DDoS. Sa artikulo Pagpaila sa BPF Tools gipatin-aw nila kung giunsa (ug ngano) nagmugna sila og mga filter sa BPF ug nagpatik sa mga link sa usa ka hugpong sa mga kagamitan alang sa paghimo sa ingon nga mga pagsala. Pananglitan, gamit ang utility bpfgen makahimo ka og BPF nga programa nga mohaum sa DNS nga pangutana alang sa usa ka ngalan 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

Sa programa una natong gikarga sa rehistro X pagsugod sa adres sa linya x04habrx03comx00 sulod sa usa ka UDP datagram ug unya susiha ang hangyo: 0x04686162 <-> "x04hab" ug uban pa.

Wala madugay, gipatik sa Cloudfare ang p0f -> BPF compiler code. Sa artikulo Gipaila ang p0f BPF compiler Naghisgot sila kung unsa ang p0f ug kung giunsa ang pag-convert sa mga pirma sa p0f sa 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,
...

Sa pagkakaron wala na naggamit Cloudfare xt_bpf, tungod kay mibalhin sila sa XDP - usa sa mga kapilian sa paggamit sa bag-ong bersyon sa BPF, tan-awa. L4Drop: XDP DDoS Mitigations.

cls_bpf

Ang katapusang pananglitan sa paggamit sa classic BPF sa kernel mao ang classifier cls_bpf alang sa subsystem sa pagkontrol sa trapiko sa Linux, gidugang sa Linux sa katapusan sa 2013 ug gipulihan sa konsepto ang karaang cls_u32.

Apan, dili na nato ihulagway ang trabaho cls_bpf, tungod kay gikan sa punto sa panglantaw sa kahibalo bahin sa klasiko nga BPF dili kini maghatag kanamo bisan unsa - pamilyar na kami sa tanan nga gamit. Dugang pa, sa sunod nga mga artikulo nga naghisgot bahin sa Extended BPF, atong mahimamat kini nga classifier labaw sa kausa.

Laing rason nga dili maghisgot mahitungod sa paggamit sa classic BPF c cls_bpf Ang problema mao nga, kon itandi sa Extended BPF, ang kasangkaran sa paggamit niini nga kaso mao ang radically pig-ot: klasikal nga mga programa dili makausab sa mga sulod sa mga pakete ug dili makaluwas sa estado sa taliwala sa mga tawag.

Mao nga panahon na aron manamilit sa klasiko nga BPF ug tan-awon ang umaabot.

Panamilit sa klasiko nga BPF

Among gitan-aw kung giunsa ang teknolohiya sa BPF, nga naugmad sa sayong bahin sa nineties, malampuson nga nabuhi sa usa ka quarter sa usa ka siglo ug hangtod sa katapusan nakit-an ang mga bag-ong aplikasyon. Apan, susama sa transisyon gikan sa stack machines ngadto sa RISC, nga nagsilbi nga usa ka impetus alang sa pagpalambo sa classic BPF, sa 32s adunay usa ka transisyon gikan sa 64-bit ngadto sa XNUMX-bit nga mga makina ug classic BPF nagsugod nga dili na magamit. Dugang pa, ang mga kapabilidad sa classic BPF limitado kaayo, ug dugang pa sa outdated nga arkitektura - wala kami'y katakus sa pagluwas sa estado tali sa mga tawag sa mga programa sa BPF, walay posibilidad sa direktang interaksiyon sa user, walay posibilidad nga makig-uban. uban sa kernel, gawas sa pagbasa sa limitado nga gidaghanon sa mga natad sa istruktura sk_buff ug paglansad sa pinakasimple nga mga function sa katabang, dili nimo mabag-o ang sulud sa mga pakete ug i-redirect kini.

Sa tinuud, sa pagkakaron ang tanan nga nahabilin sa klasiko nga BPF sa Linux mao ang interface sa API, ug sa sulod sa kernel ang tanan nga mga klasiko nga programa, ma-socket filter o seccomp filter, awtomatiko nga gihubad sa usa ka bag-ong format, Extended BPF. (Atong hisgotan ang eksakto kung giunsa kini mahitabo sa sunod nga artikulo.)

Ang transisyon ngadto sa usa ka bag-ong arkitektura nagsugod sa 2013, sa diha nga si Alexey Starovoitov misugyot sa usa ka BPF update scheme. Sa 2014 ang katugbang nga mga patch nagsugod sa pagpakita sa kinauyokan. Sa akong nasabtan, ang inisyal nga plano mao lamang ang pag-optimize sa arkitektura ug JIT compiler aron modagan nga mas episyente sa 64-bit nga mga makina, apan sa baylo kini nga mga pag-optimize nagtimaan sa pagsugod sa usa ka bag-ong kapitulo sa pagpalambo sa Linux.

Ang dugang nga mga artikulo niini nga serye maglakip sa arkitektura ug mga aplikasyon sa bag-ong teknolohiya, nga sa sinugdan nailhan nga internal nga BPF, unya gipalugway ang BPF, ug karon BPF na lang.

mga pakisayran

  1. Steven McCanne ug Van Jacobson, "Ang BSD Packet Filter: Usa ka Bag-ong Arkitektura para sa User-level Packet Capture", https://www.tcpdump.org/papers/bpf-usenix93.pdf
  2. Steven McCanne, "libpcap: Usa ka Arkitektura ug Pamaagi sa Pag-optimize alang sa Pagkuha sa Packet", 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 - ang nakalimtan nga bytecode: https://blog.cloudflare.com/bpf-the-forgotten-bytecode/
  6. Pagpaila sa BPF Tool: https://blog.cloudflare.com/introducing-the-bpf-tools/
  7. bpf_cls: http://man7.org/linux/man-pages/man8/tc-bpf.8.html
  8. Usa ka kinatibuk-ang panan-aw sa seccom: https://lwn.net/Articles/656307/
  9. https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
  10. habr: Mga sudlanan ug seguridad: seccom
  11. habr: Pag-isolate sa mga daemon gamit ang systemd o "dili nimo kinahanglan ang Docker alang niini!"
  12. Paul Chaignon, "strace --seccomp-bpf: a look under the hood", https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
  13. netsniff-ng: http://netsniff-ng.org/

Source: www.habr.com

Idugang sa usa ka comment