Berkeley Packet Filters (BPF) нь Линуксийн цөмийн технологи бөгөөд англи хэл дээрх технологийн хэвлэлүүдийн нүүрэнд хэдэн жилийн турш байсаар ирсэн. Бага хурал нь BPF-ийн хэрэглээ, хөгжлийн талаархи тайлангаар дүүрэн байдаг. Линукс сүлжээний дэд системийн засварлагч Дэвид Миллер Linux Plumbers 2018 дээр илтгэл тавьж байна.
Habré дээрх BPF-ийн талаар системчилсэн тайлбар хараахан гараагүй байгаа тул би цуврал нийтлэлд технологийн түүхийн талаар ярих, архитектур, хөгжлийн хэрэгслүүдийг тайлбарлах, BPF-ийн хэрэглээний талбар, практикийг тоймлохыг хичээх болно. Цуврал дахь "XNUMX" нийтлэл нь сонгодог BPF-ийн түүх, архитектурын тухай өгүүлэхээс гадна түүний үйл ажиллагааны зарчмуудын нууцыг илчилдэг. tcpdump
, seccomp
, strace
, болон бусад олон.
BPF-ийн хөгжлийг Линукс сүлжээний нийгэмлэг хянадаг бөгөөд BPF-ийн одоо байгаа үндсэн програмууд нь сүлжээнүүдтэй холбоотой байдаг тул зөвшөөрөлтэй байдаг.
BPF-ийн түүхийн богино курс(c)
Орчин үеийн BPF технологи нь төөрөгдлөөс зайлсхийхийн тулд одоо сонгодог BPF гэж нэрлэгддэг ижил нэртэй хуучин технологийн сайжруулсан, өргөтгөсөн хувилбар юм. Сонгодог BPF дээр үндэслэн алдартай хэрэгсэл бүтээгдсэн tcpdump
, механизм seccomp
, түүнчлэн бага мэддэг модулиуд xt_bpf
нь iptables
ба ангилагч cls_bpf
. Орчин үеийн Линукс дээр сонгодог BPF програмууд автоматаар шинэ хэлбэрт хөрвүүлэгддэг боловч хэрэглэгчийн үүднээс авч үзвэл API хэвээр байгаа бөгөөд сонгодог BPF-ийн шинэ хэрэглээг бид энэ нийтлэлээс үзэх болно. Энэ шалтгааны улмаас, мөн Линукс дээр сонгодог BPF-ийн хөгжлийн түүхийг дагаж энэ нь хэрхэн, яагаад орчин үеийн хэлбэрт шилжсэн нь илүү тодорхой болох тул би сонгодог BPF-ийн тухай өгүүллээр эхлэхээр шийдлээ.
Өнгөрсөн зууны наяад оны сүүлээр алдарт Лоуренс Беркли лабораторийн инженерүүд өнгөрсөн зууны наяад оны сүүлчээр орчин үеийн техник хангамж дээр сүлжээний пакетуудыг хэрхэн зөв шүүх вэ гэсэн асуултыг сонирхож эхэлсэн. CSPF (CMU/Stanford Packet Filter) технологид анх хэрэглэгдэж байсан шүүлтийн үндсэн санаа нь шаардлагагүй пакетуудыг аль болох эрт шүүх явдал байв. цөмийн орон зайд, учир нь энэ нь шаардлагагүй өгөгдлийг хэрэглэгчийн орон зайд хуулахаас зайлсхийдэг. Цөмийн зайд хэрэглэгчийн кодыг ажиллуулахын тулд ажиллах үеийн аюулгүй байдлыг хангахын тулд хамгаалагдсан хязгаарлагдмал виртуал машин ашигласан.
Гэсэн хэдий ч одоо байгаа шүүлтүүрт зориулсан виртуал машинууд нь стек дээр суурилсан машинууд дээр ажиллахаар бүтээгдсэн бөгөөд шинэ RISC машинууд дээр тийм ч үр дүнтэй ажилладаггүй. Үүний үр дүнд Berkeley Labs-ийн инженерүүдийн хүчин чармайлтаар BPF (Berkeley Packet Filters) шинэ технологийг боловсруулж, виртуал машины архитектурыг Motorola 6502 процессор - зэрэг алдартай бүтээгдэхүүнүүдийн үндсэн дээр бүтээсэн.
BPF машины бүтэц
Бид жишээн дээр дүн шинжилгээ хийх замаар архитектуртай танилцах болно. Гэсэн хэдий ч, эхлээд энэ машин нь хэрэглэгчдэд хүртээмжтэй 32 битийн хоёр регистр, аккумлятортой байсан гэж үзье. A
болон индексийн бүртгэл X
, 64 байт санах ой (16 үг), бичих болон дараа нь унших боломжтой, эдгээр объектуудтай ажиллах командын жижиг системтэй. Нөхцөлт илэрхийллийг хэрэгжүүлэх үсрэх заавар нь програмуудад бас байдаг боловч хөтөлбөрийг цаг тухайд нь дуусгахын тулд үсрэлтийг зөвхөн урагшлуулж болно, тухайлбал гогцоо үүсгэхийг хориглосон.
Машиныг эхлүүлэх ерөнхий схем нь дараах байдалтай байна. Хэрэглэгч нь BPF архитектурт зориулсан програмыг бий болгож, ашиглан зарим нь цөмийн механизм (системийн дуудлага гэх мэт), програмыг ачаалж, холбодог заримд нь цөм дэх үйл явдлын генератор руу (жишээлбэл, үйл явдал нь сүлжээний карт дээрх дараагийн пакет ирэх явдал юм). Үйл явдал тохиолдоход цөм нь програмыг ажиллуулдаг (жишээлбэл, орчуулагч дээр), машины санах ой нь заримд нь цөмийн санах ойн бүс (жишээлбэл, ирж буй пакетийн өгөгдөл).
Дээрх нь жишээг үзэж эхлэхэд хангалттай байх болно: шаардлагатай бол бид систем болон тушаалын форматтай танилцах болно. Хэрэв та виртуал машины командын системийг нэн даруй судалж, түүний бүх боломжийн талаар мэдэхийг хүсч байвал анхны нийтлэлийг уншиж болно. libpcap
: Пакет барихад зориулсан архитектур ба оновчлолын арга зүйlibpcap
.
Одоо бид Линукс дээр сонгодог BPF ашиглах бүх чухал жишээг авч үзэх болно. tcpdump
(libpcap
), seccomp, xt_bpf
, cls_bpf
.
tcpdump
BPF-ийг хөгжүүлэх нь багц шүүлтүүрийн урд талын программыг боловсруулахтай зэрэгцэн явагдсан - алдартай хэрэгсэл tcpdump
. Энэ бол олон үйлдлийн системүүд дээр байдаг сонгодог BPF ашиглах хамгийн эртний бөгөөд хамгийн алдартай жишээ тул бид технологийн талаар судалж эхлэх болно.
(Би энэ нийтлэл дэх бүх жишээг Линукс дээр ажиллуулсан 5.6.0-rc6
. Уншихад илүү хялбар болгох үүднээс зарим командын гаралтыг зассан.)
Жишээ нь: IPv6 пакетуудыг ажиглах
Бид интерфэйс дээрх бүх IPv6 пакетуудыг харахыг хүсч байна гэж төсөөлөөд үз дээ eth0
. Үүнийг хийхийн тулд бид програмыг ажиллуулж болно tcpdump
энгийн шүүлтүүрээр ip6
:
$ sudo tcpdump -i eth0 ip6
Иймээс tcpdump
шүүлтүүрийг эмхэтгэдэг ip6
BPF архитектурын байт код руу оруулаад цөм рүү илгээнэ үү (хэсэг дэх дэлгэрэнгүй мэдээллийг үзнэ үү eth0
. Хэрэв шүүлтүүр нь тэгээс өөр утгыг буцаавал n
, дараа нь хүртэл n
пакетийн байт нь хэрэглэгчийн орон зайд хуулах бөгөөд бид үүнийг гаралт дээр харах болно tcpdump
.
Цөм рүү аль байт код илгээгдсэнийг бид хялбархан олж мэдэх боломжтой болж байна tcpdump
-ийн тусламжтайгаар tcpdump
, хэрэв бид үүнийг сонголтоор ажиллуулбал -d
:
$ sudo tcpdump -i eth0 -d ip6
(000) ldh [12]
(001) jeq #0x86dd jt 2 jf 3
(002) ret #262144
(003) ret #0
Тэг мөрөнд бид тушаалыг ажиллуулдаг ldh [12]
, энэ нь “бүртгэлд ачаалах A
Хагас үг (16 бит) 12" хаяг дээр байрладаг бөгөөд цорын ганц асуулт бол бид ямар санах ойд хандаж байна вэ? Хариулт нь тэр цагт x
эхэлдэг (x+1)
Шинжилсэн сүлжээний багцын байт. Бид Ethernet интерфейсээс пакетуудыг уншдаг eth0
, бөгөөд энэ нь
6 6 2
|Destination MAC|Source MAC|Ether Type|...|
Тиймээс тушаалыг гүйцэтгэсний дараа ldh [12]
бүртгэлд A
талбай байх болно Ether Type
— энэ Ethernet фреймд дамжуулагдсан пакетийн төрөл. 1-р мөрөнд бид бүртгэлийн агуулгыг харьцуулна A
(багцын төрөл) c 0x86dd
, бөгөөд энэ нь jt 2
и jf 3
- харьцуулалт амжилттай болсон тохиолдолд очих ёстой тэмдэгтүүд (A == 0x86dd
) мөн амжилтгүй болсон. Тиймээс, амжилттай тохиолдолд (IPv6) бид 2-р мөрөнд, амжилтгүй тохиолдолд 3-р мөрөнд очно. 3-р мөрөнд програм 0 кодоор дуусгавар болно (пакетийг хуулж болохгүй), 2-р мөрөнд програм кодоор дуусгавар болно. 262144 (хамгийн ихдээ 256 килобайт багцыг надад хуулна уу).
Илүү төвөгтэй жишээ: бид TCP пакетуудыг очих портоор нь хардаг
Зорилтот порт 666-тай бүх TCP пакетуудыг хуулдаг шүүлтүүр ямар байхыг харцгаая. IPv4 тохиолдол илүү энгийн тул бид IPv6 тохиолдлыг авч үзэх болно. Энэ жишээг судалсны дараа та IPv6 шүүлтүүрийг дасгал болгон үзэж болно (ip6 and tcp dst port 666
) болон ерөнхий тохиолдлын шүүлтүүр (tcp dst port 666
). Тиймээс бидний сонирхож буй шүүлтүүр дараах байдалтай байна.
$ 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
0 ба 1 мөрүүд юу хийдгийг бид аль хэдийн мэддэг болсон. 2-р мөрөнд бид энэ нь IPv4 пакет мөн эсэхийг аль хэдийн шалгасан (Ether Type = 0x800
) болон бүртгэлд ачаална уу A
Пакетийн 24 байт. Манай багц иймэрхүү харагдаж байна
14 8 1 1
|ethernet header|ip fields|ttl|protocol|...|
Энэ нь бид бүртгэлд ачаална гэсэн үг юм A
IP толгой хэсгийн Protocol талбар нь логик юм, учир нь бид зөвхөн TCP пакетуудыг хуулахыг хүсч байна. Бид протоколыг харьцуулж байна 0x6
(IPPROTO_TCP
4, 5-р мөрөнд бид 20-р хаяг дээр байрлах хагас үгийг ачаалж, командыг ашиглана jset
гурвын аль нэг нь тохируулагдсан эсэхийг шалгана уу jset
хамгийн чухал гурван бит арилсан. Гурван битийн хоёр нь пакет нь хуваагдсан IP пакетийн нэг хэсэг мөн эсэхийг, хэрэв тийм бол энэ нь сүүлчийн фрагмент мөн эсэхийг хэлж өгдөг. Гурав дахь бит нь хадгалагдсан бөгөөд тэг байх ёстой. Бид дутуу эсвэл эвдэрсэн пакетуудыг шалгахыг хүсэхгүй байгаа тул бүх гурван битийг шалгадаг.
Энэ жагсаалтын 6-р мөр нь хамгийн сонирхолтой юм. Илэрхийлэл ldxb 4*([14]&0xf)
бид бүртгэлд ачаална гэсэн үг X
Пакетийн арван тав дахь байтын хамгийн бага ач холбогдолтой дөрвөн битийг 4-өөр үржүүлсэн. Арван тав дахь байтын хамгийн бага ач холбогдолтой дөрвөн бит нь талбар юм. 4*([14]&0xf)
Энэ нь зөвхөн энэ хэлбэрээр, зөвхөн бүртгэлд ашиглах боломжтой тусгай хаяглалтын схемийн тэмдэглэгээ юм X
, өөрөөр хэлбэл бид бас хэлж чадахгүй ldb 4*([14]&0xf)
үгүй ldxb 5*([14]&0xf)
(бид зөвхөн өөр офсетийг зааж өгч болно, жишээлбэл, ldxb 4*([16]&0xf)
). Энэхүү хаягжуулалтын схемийг хүлээн авахын тулд BPF-д яг нэмж оруулсан нь тодорхой байна X
(индекс бүртгэл) IPv4 толгойн урт.
Тиймээс 7-р мөрөнд бид хагас үгийг ачаалахыг хичээдэг (X+16)
. Ethernet толгой нь 14 байт эзэлдэг гэдгийг санаарай, мөн X
IPv4 толгойн уртыг агуулж байгаа тул бид үүнийг ойлгож байна A
TCP очих порт ачаалагдсан:
14 X 2 2
|ethernet header|ip header|source port|destination port|
Эцэст нь 8-р мөрөнд бид очих портыг хүссэн утгатай харьцуулж, 9 эсвэл 10-р мөрөнд багцыг хуулах эсэхээс үл хамааран үр дүнг буцаана.
Tcpdump: ачаалж байна
Өмнөх жишээнүүдэд бид BPF байт кодыг пакет шүүлтүүрийн цөмд яг хэрхэн ачаалах талаар дэлгэрэнгүй авч үзээгүй. Ерөнхийдөө, tcpdump
олон системд шилжүүлж, шүүлтүүртэй ажиллахад зориулагдсан tcpdump
libpcap
libpcap
, та дараах зүйлийг хийх хэрэгтэй.
- төрөл тодорхойлогч үүсгэх
pcap_t
интерфэйсийн нэрээс: ,pcap_create
- интерфэйсийг идэвхжүүлэх:
,pcap_activate
- эмхэтгэх шүүлтүүр:
,pcap_compile
- шүүлтүүрийг холбох:
.pcap_setfilter
Функц хэрхэн ажилладагийг харахын тулд pcap_setfilter
Линукс дээр хэрэгжсэн, бид ашигладаг strace
(зарим мөрийг хассан):
$ 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
...
Гаралтын эхний хоёр мөрөнд бид үүсгэдэг eth0
Байна. нь ip
нь дөрвөн BPF заавраас бүрдэх бөгөөд гурав дахь мөрөнд бид сонголтыг хэрхэн ашиглахыг харна SO_ATTACH_FILTER
setsockopt
бид 4 урттай шүүлтүүрийг ачаалж холбодог. Энэ бол бидний шүүлтүүр юм.
Сонгодог BPF-д шүүлтүүрийг ачаалах, холбох нь үргэлж атомын үйлдлээр явагддаг бөгөөд BPF-ийн шинэ хувилбарт програмыг ачаалж, үйл явдлын үүсгэгчтэй холбох нь цаг хугацааны хувьд тусгаарлагдсан байдаг гэдгийг тэмдэглэх нь зүйтэй.
Далд үнэн
Гаралтын арай илүү бүрэн хувилбар нь дараах байдалтай байна.
$ 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
...
Дээр дурдсанчлан бид шүүлтүүрээ 5-р мөрөнд залгуурт ачаалж, холбодог, гэхдээ 3, 4-р мөрөнд юу болох вэ? Энэ нь харагдаж байна libpcap
биднийг халамжилдаг - ингэснээр манай шүүлтүүрийн гаралт нь түүнд нийцэхгүй байгаа пакетуудыг оруулахгүй, номын сан ret #0
(бүх пакетуудыг хаях), залгуурыг блоклохгүй горимд шилжүүлж, өмнөх шүүлтүүрүүдээс үлдэж болох бүх пакетуудыг хасахыг оролддог.
Линукс дээрх багцуудыг сонгодог BPF ашиглан шүүхийн тулд та ийм бүтэцтэй шүүлтүүртэй байх хэрэгтэй. struct sock_fprog
мөн нээлттэй залгуур, үүний дараа шүүлтүүрийг системийн дуудлага ашиглан залгуурт холбож болно setsockopt
.
Сонирхолтой нь шүүлтүүрийг зөвхөн түүхий биш, ямар ч залгуурт холбож болно. Энд
Хэрэглээний талаарх дэлгэрэнгүй мэдээлэл setsockopt
шүүлтүүрийг холбохын тулд үзнэ үү struct sock_fprog
тусламжгүйгээр tcpdump
хэсэгт бид ярилцах болно
Сонгодог BPF ба XNUMX-р зуун
BPF нь 1997 онд Линукс системд багтсан бөгөөд удаан хугацааны туршид ажилчин хэвээр байна libpcap
ямар ч тусгай өөрчлөлтгүйгээр (Мэдээжийн хэрэг, Линуксийн онцлог өөрчлөлтүүд, x86_64
код.
JIT хөрвүүлэгч нь өөрчлөлтүүдийн гинжин хэлхээний анхных нь байсан: 2012 онд xt_bpf
, энэ нь танд дүрэм бичих боломжийг олгодог iptables
BPF-ийн тусламжтайгаар 2013 оны XNUMX-р сард болсон cls_bpf
, энэ нь танд BPF ашиглан хөдөлгөөний ангилагч бичих боломжийг олгодог.
Бид удахгүй эдгээр бүх жишээг илүү дэлгэрэнгүй авч үзэх болно, гэхдээ эхлээд номын сангаас өгсөн боломжууд нь BPF-д дурын програм бичиж, эмхэтгэхийг сурах нь бидэнд ашигтай байх болно. libpcap
хязгаарлагдмал (энгийн жишээ: шүүлтүүр үүсгэсэн libpcap
зөвхөн хоёр утгыг буцааж болно - 0 эсвэл 0x40000) эсвэл ерөнхийдөө seccomp-ийн хувьд хамаарахгүй.
Өөрийнхөө гараар BPF програмчлах
BPF зааврын хоёртын форматтай танилцацгаая, энэ нь маш энгийн:
16 8 8 32
| code | jt | jf | k |
Заавар бүр 64 бит эзэлдэг бөгөөд эхний 16 бит нь зааврын код, дараа нь хоёр найман битийн доголтой, jt
и jf
, мөн аргументийн хувьд 32 бит K
, зорилго нь тушаал болгонд өөр өөр байдаг. Жишээлбэл, тушаал ret
, програмыг зогсоодог кодтой 6
, мөн буцах утгыг тогтмолоос авна K
. C хэлэнд BPF-ийн нэг заавар нь бүтэц хэлбэрээр илэрхийлэгддэг
struct sock_filter {
__u16 code;
__u8 jt;
__u8 jf;
__u32 k;
}
мөн бүх программ нь бүтэц хэлбэртэй байна
struct sock_fprog {
unsigned short len;
struct sock_filter *filter;
}
Тиймээс бид аль хэдийн програм бичиж болно (жишээлбэл, бид зааврын кодыг мэддэг ip6
нь
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,
};
хөтөлбөр prog
бид хууль ёсны дагуу дуудлага хийх боломжтой
setsockopt(sk, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog))
Машины код хэлбэрээр програм бичих нь тийм ч тохиромжтой биш боловч заримдаа шаардлагатай байдаг (жишээлбэл, дибаг хийх, нэгжийн тест үүсгэх, Habré дээр нийтлэл бичих гэх мэт). Файлд тав тухтай байлгах үүднээс <linux/filter.h>
Туслах макронууд тодорхойлогдсон - дээрхтэй ижил жишээг гэж дахин бичиж болно
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),
}
Гэсэн хэдий ч энэ сонголт нь тийм ч тохиромжтой биш юм. Линуксийн цөмийн программистууд ийм үндэслэлтэй байсан тул лавлахад ийм байна tools/bpf
Ассемблей хэл нь дибаг хийх гаралттай маш төстэй tcpdump
, гэхдээ үүнээс гадна бид бэлгэдлийн шошгыг зааж өгч болно. Жишээлбэл, энд TCP/IPv4-ээс бусад бүх пакетуудыг буулгадаг програм байна:
$ cat /tmp/tcp-over-ipv4.bpf
ldh [12]
jne #0x800, drop
ldb [23]
jneq #6, drop
ret #-1
drop: ret #0
Анхдагч байдлаар ассемблер нь кодыг форматаар үүсгэдэг <количество инструкций>,<code1> <jt1> <jf1> <k1>,...
, бидний TCP-тэй жишээний хувьд ийм байх болно
$ 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,
Си програмистуудын тав тухыг хангах үүднээс өөр гаралтын форматыг ашиглаж болно:
$ 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 },
Энэ текстийг төрлийн бүтцийн тодорхойлолт руу хуулж болно struct sock_filter
, бид энэ хэсгийн эхэнд хийсэн шиг.
Linux болон netsniff-ng өргөтгөлүүд
Стандарт BPF-ээс гадна Линукс болон tools/bpf/bpf_asm
дэмжлэг ба struct sk_buff
, цөм дэх сүлжээний багцыг дүрсэлсэн. Гэсэн хэдий ч, жишээлбэл, бусад төрлийн туслах заавар байдаг ldw cpu
бүртгэлд ачаалагдах болно A
цөмийн функцийг ажиллуулсны үр дүн raw_smp_processor_id()
. (BPF-ийн шинэ хувилбарт эдгээр стандарт бус өргөтгөлүүдийг программуудад санах ой, бүтэц, үйл явдлуудад хандахад зориулсан цөмийн туслах хэрэгслүүдээр хангах зорилгоор өргөтгөсөн.) Энд бид зөвхөн файлуудыг хуулдаг шүүлтүүрийн сонирхолтой жишээг үзүүлэв. өргөтгөл ашиглан хэрэглэгчийн орон зайд пакет толгойг оруулна poff
, ачааллыг нөхөх:
ld poff
ret a
BPF өргөтгөлүүдийг ашиглах боломжгүй tcpdump
, гэхдээ энэ нь хэрэглээний багцтай танилцах сайн шалтгаан юм netsniff-ng
netsniff-ng
, энэ нь BPF ашиглан шүүхээс гадна үр дүнтэй траффик үүсгэгчийг агуулдаг бөгөөд илүү дэвшилтэт tools/bpf/bpf_asm
, BPF ассемблер дуудсан bpfc
. Багц нь нэлээд нарийвчилсан баримт бичгийг агуулсан бөгөөд нийтлэлийн төгсгөлд байгаа холбоосыг үзнэ үү.
секкомпьютер
Тиймээс бид дурын нарийн төвөгтэй BPF програмуудыг хэрхэн бичихийг аль хэдийн мэддэг болсон бөгөөд шинэ жишээнүүдийг үзэхэд бэлэн байгаа бөгөөд тэдгээрийн эхнийх нь BPF шүүлтүүрийг ашиглан системийн дуудлагын аргументуудын багц болон багцыг удирдах боломжийг олгодог seccomp технологи юм. өгөгдсөн үйл явц ба түүний үр удам.
Seccomp-ийн анхны хувилбар нь 2005 онд цөмд нэмэгдсэн бөгөөд тийм ч түгээмэл биш байсан, учир нь энэ нь зөвхөн нэг л сонголтоор хангагдсан байсан - процесст ашиглах боломжтой системийн дуудлагын багцыг дараах байдлаар хязгаарлах: read
, write
, exit
и sigreturn
, мөн дүрмийг зөрчсөн үйл явцыг ашиглан амь насаа алдсан SIGKILL
. Гэсэн хэдий ч, 2012 онд seccomp нь BPF шүүлтүүрийг ашиглах боломжийг нэмсэн нь зөвшөөрөгдсөн системийн дуудлагын багцыг тодорхойлох, тэр ч байтугай тэдгээрийн аргументуудыг шалгах боломжийг олгодог. (Сонирхолтой нь, Chrome нь энэ функцийг ашигласан анхны хэрэглэгчдийн нэг байсан бөгөөд Chrome-ын хүмүүс одоогоор BPF-ийн шинэ хувилбар дээр суурилсан KRSI механизмыг хөгжүүлж, Линукс аюулгүй байдлын модулиудыг өөрчлөх боломжийг олгож байна.) Нэмэлт баримт бичгийн холбоосыг төгсгөлд нь харж болно. нийтлэлийн.
Seccomp-ийг ашиглах талаар төв дээр нийтлэлүүд аль хэдийн гарч байсныг анхаарна уу, магадгүй хэн нэгэн нь дараах дэд хэсгүүдийг уншихаас өмнө (эсвэл оронд нь) уншихыг хүсэх байх. Нийтлэлд
Дараа нь бид шүүлтүүрийг хэрхэн бичих, ачаалахыг харах болно seccomp
нүцгэн C болон номын сан ашиглаж байна libseccomp
сонголт бүрийн давуу болон сул талууд юу вэ, эцэст нь seccomp програмыг хэрхэн ашигладаг болохыг харцгаая. strace
.
Seccomp-д зориулсан шүүлтүүр бичих, ачаалах
Бид BPF программуудыг хэрхэн бичихийг аль хэдийн мэддэг тул эхлээд seccomp програмчлалын интерфейсийг харцгаая. Та процессын түвшинд шүүлтүүр тохируулах боломжтой бөгөөд бүх хүүхдийн процессууд хязгаарлалтыг өвлөн авах болно. Энэ нь системийн дуудлага ашиглан хийгддэг seccomp(2)
seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)
хаана &filter
- энэ бол бидэнд аль хэдийн танил болсон бүтцийн заагч юм struct sock_fprog
, өөрөөр хэлбэл BPF хөтөлбөр.
Seccomp-д зориулсан програмууд нь залгуурт зориулсан програмуудаас юугаараа ялгаатай вэ? Дамжуулсан контекст. Сокетуудын хувьд бидэнд пакет агуулсан санах ойн талбар өгсөн бол seccomp-ийн хувьд бидэнд иймэрхүү бүтэц өгсөн.
struct seccomp_data {
int nr;
__u32 arch;
__u64 instruction_pointer;
__u64 args[6];
};
энд nr
нь эхлүүлэх системийн дуудлагын дугаар, arch
- одоогийн архитектур (энэ талаар доор дэлгэрэнгүй), args
- зургаан хүртэлх системийн дуудлагын аргументууд, мөн instruction_pointer
нь системийн дуудлагыг хийсэн хэрэглэгчийн зайны зааврын заагч юм. Жишээлбэл, системийн дуудлагын дугаарыг бүртгэлд оруулах A
бид хэлэх ёстой
ldw [0]
Seccomp програмуудад зориулсан бусад боломжууд байдаг, жишээлбэл, контекст зөвхөн 32 битийн тохируулгаар хандах боломжтой бөгөөд шүүлтүүрийг ачаалах гэж оролдох үед та хагас үг эсвэл байт ачаалах боломжгүй. ldh [0]
системийн дуудлага seccomp
буцаж ирнэ EINVAL
. Функц нь ачаалагдсан шүүлтүүрүүдийг шалгадаг seccomp_check_filter()
mod
(хуваалтын үлдэгдэл) бөгөөд нэмсэнээс хойш seccomp BPF хөтөлбөрт ашиглах боломжгүй
Үндсэндээ бид seccomp програм бичих, унших бүх зүйлийг аль хэдийн мэддэг болсон. Ихэвчлэн програмын логик нь системийн дуудлагын цагаан эсвэл хар жагсаалт, тухайлбал программ хэлбэрээр зохион байгуулагддаг
ld [0]
jeq #304, bad
jeq #176, bad
jeq #239, bad
jeq #279, bad
good: ret #0x7fff0000 /* SECCOMP_RET_ALLOW */
bad: ret #0
304, 176, 239, 279 дугаартай системийн дөрвөн дуудлагын хар жагсаалтыг шалгадаг. Эдгээр системийн дуудлага юу вэ? Програмыг аль архитектурт зориулж бичсэнийг мэдэхгүй тул бид тодорхой хэлж чадахгүй. Тиймээс seccomp-ийн зохиогчид arch
бүтэц struct seccomp_data
). Архитектурыг шалгаснаар жишээний эхлэл дараах байдалтай байна.
ld [4]
jne #0xc000003e, bad_arch ; SCMP_ARCH_X86_64
Дараа нь манай системийн дуудлагын дугаарууд тодорхой утгыг авах болно.
Бид seccomp ашиглах шүүлтүүрийг бичиж, ачаалдаг libseccomp
Шүүлтүүрийг эх код эсвэл BPF угсралтаар бичих нь үр дүнг бүрэн хянах боломжийг олгодог боловч заримдаа зөөврийн болон/эсвэл уншигдах кодтой байхыг илүүд үздэг. Энэ талаар номын сан бидэнд туслах болно
Жишээ нь, өмнө нь системийн дуудлагын хар жагсаалтыг суулгасан хэрэглэгчийн сонгосон хоёртын файлыг ажиллуулдаг програм бичье.
#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]);
}
Эхлээд бид массивыг тодорхойлно sys_numbers
40 гаруй системийн дуудлагын дугаарыг хаах. Дараа нь контекстийг эхлүүлнэ үү ctx
номын санд юуг зөвшөөрөхийг хүсч байгаагаа хэлээрэй (SCMP_ACT_ALLOW
) бүх системийн дуудлага нь анхдагчаар (хар жагсаалт үүсгэхэд илүү хялбар байдаг). Дараа нь бид хар жагсаалтаас системийн бүх дуудлагыг нэг нэгээр нь нэмнэ. Жагсаалтаас системийн дуудлагын хариуд бид хүсэлт гаргаж байна SCMP_ACT_TRAP
, энэ тохиолдолд seccomp процесс руу дохио илгээх болно SIGSYS
ямар системийн дуудлага дүрэм зөрчсөн тухай тайлбартай. Эцэст нь бид програмыг ашиглан цөмд ачаална seccomp_load
, энэ нь програмыг эмхэтгэж, системийн дуудлагыг ашиглан процесст хавсаргах болно seccomp(2)
.
Амжилттай эмхэтгэхийн тулд програм нь номын сантай холбоотой байх ёстой libseccomp
Жишээ нь:
cc -std=c17 -Wall -Wextra -c -o seccomp_lib.o seccomp_lib.c
cc -o seccomp_lib seccomp_lib.o -lseccomp
Амжилттай хөөргөх жишээ:
$ ./seccomp_lib echo ok
ok
Хаагдсан системийн дуудлагын жишээ:
$ sudo ./seccomp_lib mount -t bpf bpf /tmp
Bad system call
Бидний хэрэглэдэг strace
дэлгэрэнгүй:
$ 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
хууль бус системийн дуудлагыг ашигласны улмаас програмыг зогсоосон гэдгийг бид яаж мэдэх вэ mount(2)
.
Тиймээс бид номын санг ашиглан шүүлтүүр бичсэн libseccomp
, энгийн бус кодыг дөрвөн мөрөнд багтаах. Дээрх жишээн дээр, хэрэв олон тооны системийн дуудлага байгаа бол шалгалт нь зөвхөн харьцуулалтын жагсаалт учраас гүйцэтгэлийн хугацаа мэдэгдэхүйц буурч болно. Оновчлолын хувьд libseccomp саяхан байсан SCMP_FLTATR_CTL_OPTIMIZE
. Энэ атрибутыг 2 болгож тохируулснаар шүүлтүүрийг хоёртын хайлтын програм болгон хувиргана.
Хэрэв та хоёртын хайлтын шүүлтүүр хэрхэн ажилладагийг харахыг хүсвэл эндээс харна уу
$ 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
BPF программууд доголын үсрэлт хийж чадахгүй тул илүү хурдан юу ч бичих боломжгүй (жишээ нь бид үүнийг хийж чадахгүй. jmp A
буюу jmp [label+X]
) тул бүх шилжилт хөдөлгөөнгүй байна.
seccomp болон strace
Хэрэглээг хүн бүр мэддэг strace
Линукс дээрх процессуудын зан төлөвийг судлах зайлшгүй хэрэгсэл юм. Гэсэн хэдий ч олон хүн энэ тухай сонссон strace
ашиглан хэрэгжүүлсэн ptrace(2)
, мөн энэ механизмд бид ямар системийн дуудлагын үед процессыг зогсоох шаардлагатайг зааж өгөх боломжгүй, жишээлбэл, тушаалууд.
$ 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
Ойролцоогоор ижил хугацаанд боловсруулагддаг, гэхдээ хоёр дахь тохиолдолд бид зөвхөн нэг системийн дуудлагыг хянахыг хүсч байна.
Шинэ сонголт --seccomp-bpf
, нэмэгдсэн strace
5.3 хувилбар нь үйл явцыг олон удаа хурдасгах боломжийг олгодог бөгөөд нэг системийн дуудлагын дагуу эхлүүлэх хугацаа нь ердийн эхлүүлэх хугацаатай харьцуулж болно.
$ 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
(Мэдээжийн хэрэг, бид энэ командын үндсэн системийн дуудлагыг мөрдөхгүй байгаа нь бага зэрэг хууран мэхлэлт байна. Хэрэв бид мөрдөж байсан бол жишээ нь, newfsstat
Дараа нь strace
үгүйтэй адил хүчтэй тоормослох болно --seccomp-bpf
.)
Энэ сонголт хэрхэн ажилладаг вэ? Түүнгүйгээр strace
процесстой холбогдож, ашиглаж эхэлнэ PTRACE_SYSCALL
. Удирдагдсан процесс нь (ямар ч) системийн дуудлагыг гаргах үед хяналтыг шилжүүлдэг strace
, энэ нь системийн дуудлагын аргументуудыг харж, түүнийг ашиглан ажиллуулдаг PTRACE_SYSCALL
. Хэсэг хугацааны дараа процесс нь системийн дуудлагыг дуусгаж, түүнээс гарах үед хяналтыг дахин шилжүүлнэ strace
, энэ нь буцах утгыг харж, ашиглан үйл явцыг эхлүүлнэ PTRACE_SYSCALL
, гэх мэт.
Гэхдээ seccomp-ийн тусламжтайгаар энэ процессыг яг бидний хүссэнээр оновчтой болгож болно. Тухайлбал, хэрэв бид зөвхөн системийн дуудлагыг харахыг хүсвэл X
, дараа нь бид BPF шүүлтүүр бичиж болно X
утгыг буцаана SECCOMP_RET_TRACE
, мөн бидний сонирхолгүй дуудлагад - SECCOMP_RET_ALLOW
:
ld [0]
jneq #X, ignore
trace: ret #0x7ff00000
ignore: ret #0x7fff0000
Энэ тохиолдолд strace
гэж эхлээд процессыг эхлүүлнэ PTRACE_CONT
, хэрэв системийн дуудлага байхгүй бол манай шүүлтүүрийг системийн дуудлага бүрт боловсруулдаг X
, дараа нь процесс үргэлжлүүлэн ажиллах боловч хэрэв энэ бол X
, дараа нь seccomp хяналтыг шилжүүлнэ strace
нь аргументуудыг харж, процессыг эхлүүлэх болно PTRACE_SYSCALL
(seccomp нь системийн дуудлагаас гарах үед програмыг ажиллуулах чадваргүй тул). Системийн дуудлага буцаж ирэхэд, strace
ашиглан процессыг дахин эхлүүлэх болно PTRACE_CONT
мөн seccomp-ээс шинэ мессежийг хүлээх болно.
Сонголтыг ашиглах үед --seccomp-bpf
хоёр хязгаарлалт байдаг. Нэгдүгээрт, аль хэдийн байгаа процесст нэгдэх боломжгүй болно (сонголт -p
хөтөлбөр strace
), учир нь үүнийг seccomp дэмждэггүй. Хоёрдугаарт, ямар ч боломж байхгүй үгүй seccomp шүүлтүүрүүд нь үүнийг идэвхгүй болгох чадваргүйгээр бүх хүүхэд процессуудад өвлөгддөг тул хүүхдийн процессуудыг хараарай.
Яг яаж байгаа талаар бага зэрэг дэлгэрэнгүй strace
хамтран ажилладаг seccomp
-аас олж болно
xt_bpf
Одоо сүлжээний ертөнц рүү буцаж орцгооё.
Сэдвийн мэдээлэл: эрт дээр үед 2007 онд гол нь байсан xt_u32
сүлжээ шүүлтүүрийн хувьд. Үүнийг илүү эртний замын хөдөлгөөний ангилагчтай зүйрлэж бичсэн cls_u32
Дараах энгийн үйлдлүүдийг ашиглан iptables-ийн дурын хоёртын дүрмийг бичих боломжийг танд олгоно: багцаас 32 бит ачаалж, тэдгээр дээр арифметик үйлдлийн багцыг гүйцэтгэх. Жишээлбэл,
sudo iptables -A INPUT -m u32 --u32 "6&0xFF=1" -j LOG --log-prefix "seen-by-xt_u32"
32-р дүүргэлтээс эхлэн IP толгойн 6 битийг ачаалж, тэдгээрт маск тавина. 0xFF
(бага байтыг аваарай). Энэ талбар protocol
IP толгой ба бид үүнийг 1 (ICMP) -тай харьцуулдаг. Нэг дүрмээр та олон шалгалтыг нэгтгэж болно, мөн та операторыг ажиллуулж болно @
— X байтыг баруун тийш шилжүүлнэ. Жишээлбэл, дүрэм
iptables -m u32 --u32 "6&0xFF=0x6 && 0>>22&0x3C@4=0x29"
TCP дарааллын дугаар тэнцүү биш эсэхийг шалгана 0x29
. Ийм дүрмийг гараар бичих нь тийм ч тохиромжтой биш гэдэг нь тодорхой болсон тул би цааш дэлгэрэнгүй ярихгүй. Нийтлэлд xt_u32
. Мөн энэ нийтлэлийн төгсгөлд байгаа холбоосыг үзнэ үү.
2013 оноос хойш модулийн оронд модуль xt_u32
Та BPF дээр суурилсан модулийг ашиглаж болно xt_bpf
. Үүнийг уншсан хэн бүхэн түүний үйл ажиллагааны зарчмыг аль хэдийн тодорхой мэдэж байх ёстой: BPF байт кодыг iptables дүрмээр ажиллуул. Та шинэ дүрэм үүсгэж болно, жишээ нь:
iptables -A INPUT -m bpf --bytecode <байткод> -j LOG
энд <байткод>
- энэ бол ассемблерийн гаралтын формат дахь код юм bpf_asm
анхдагчаар, жишээлбэл,
$ 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
Энэ жишээнд бид бүх UDP пакетуудыг шүүж байна. Модуль дахь BPF програмын контекст xt_bpf
, мэдээжийн хэрэг iptables-ийн хувьд IPv4 толгойн эхэнд багц өгөгдөл рүү чиглэнэ. BPF програмаас утгыг буцаана false
пакет таарахгүй байна гэсэн үг.
Энэ нь модуль нь тодорхой байна xt_bpf
дээрх жишээнээс илүү төвөгтэй шүүлтүүрүүдийг дэмждэг. Cloudfare-ийн бодит жишээнүүдийг харцгаая. Саяхныг хүртэл тэд модулийг ашиглаж байсан xt_bpf
DDoS халдлагаас хамгаалах. Нийтлэлд bpfgen
та нэрний DNS асуулгад тохирох BPF програмыг үүсгэж болно 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
Хөтөлбөрт бид эхлээд бүртгэлд ачаална X
мөрийн эхлэлийн хаяг x04habrx03comx00
UDP датаграм дотор ороод хүсэлтийг шалгана уу: 0x04686162 <-> "x04hab"
гэх мэт.
Хэсэг хугацааны дараа Cloudfare p0f -> 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,
...
Одоогоор Cloudfare ашиглахаа больсон xt_bpf
, тэд XDP руу шилжсэн тул BPF-ийн шинэ хувилбарыг ашиглах сонголтуудын нэгийг үзнэ үү.
cls_bpf
Цөмд сонгодог BPF ашиглах сүүлийн жишээ бол ангилагч юм cls_bpf
Линукс дээрх замын хөдөлгөөний удирдлагын дэд системд 2013 оны сүүлээр Линукс дээр нэмж, эртний системийг орлуулсан. cls_u32
.
Гэсэн хэдий ч бид одоо энэ ажлыг тайлбарлахгүй cls_bpf
, сонгодог BPF-ийн талаархи мэдлэгийн үүднээс энэ нь бидэнд юу ч өгөхгүй - бид бүх функцтэй аль хэдийн танилцсан. Нэмж дурдахад, Extended BPF-ийн тухай дараагийн нийтлэлүүдэд бид энэ ангилагчтай нэгээс олон удаа уулзах болно.
Сонгодог BPF ашиглах талаар ярихгүй байх бас нэг шалтгаан c cls_bpf
Асуудал нь Өргөтгөсөн BPF-тэй харьцуулахад энэ тохиолдолд хэрэглэх хүрээ эрс нарийссан: сонгодог програмууд нь багцын агуулгыг өөрчлөх боломжгүй бөгөөд дуудлага хоорондын төлөвийг хадгалах боломжгүй юм.
Тиймээс сонгодог BPF-тэй баяртай гэж хэлээд ирээдүйгээ харах цаг болжээ.
Сонгодог BPF-тэй баяртай
Бид ерээд оны эхээр бүтээгдсэн BPF технологи хэрхэн дөрөвний нэг зууны турш амжилттай амьдарч, эцсээ хүртэл шинэ хэрэглээг олж авсныг харлаа. Гэсэн хэдий ч сонгодог BPF-ийг хөгжүүлэхэд түлхэц болсон стек машинаас RISC руу шилжихтэй адил 32-аад онд 64 битийн машинаас XNUMX битийн машин руу шилжиж, сонгодог BPF хуучирч эхэлсэн. Нэмж дурдахад, сонгодог BPF-ийн боломжууд маш хязгаарлагдмал бөгөөд хуучирсан архитектураас гадна бид BPF програм руу залгасан дуудлагын хоорондох төлөвийг хадгалах чадваргүй, хэрэглэгчтэй шууд харилцах боломж байхгүй, харилцан үйлчлэх боломж байхгүй. цөөн тооны бүтцийн талбаруудыг уншихаас бусад тохиолдолд цөмтэй sk_buff
болон хамгийн энгийн туслах функцуудыг ажиллуулснаар та пакетуудын агуулгыг өөрчилж, дахин чиглүүлэх боломжгүй.
Үнэн хэрэгтээ одоогийн байдлаар Линукс дээрх сонгодог BPF-ээс үлдсэн бүх зүйл нь API интерфейс бөгөөд цөм дотор залгуур шүүлтүүр эсвэл seccomp шүүлтүүр гэх мэт бүх сонгодог програмууд автоматаар Өргөтгөсөн BPF формат руу хөрвүүлэгддэг. (Энэ нь яг яаж болдог талаар бид дараагийн өгүүллээр ярих болно.)
2013 онд Алексей Старовойтов BPF-ийн шинэчлэлийн схемийг санал болгосноор шинэ архитектурт шилжих ажил эхэлсэн. 2014 онд холбогдох засварууд
Энэ цувралын цаашдын нийтлэлүүд нь эхлээд дотоод BPF, дараа нь өргөтгөсөн BPF, одоо зүгээр л BPF гэгддэг шинэ технологийн архитектур, хэрэглээг хамарна.
лавлагаа
- Стивен МакКэнн, Ван Жэйкобсон, "BSD пакет шүүлтүүр: Хэрэглэгчийн түвшний пакет барих шинэ архитектур",
https://www.tcpdump.org/papers/bpf-usenix93.pdf
- Стивен МакКэнн, "libpcap: Пакет барихад зориулсан архитектур ба оновчлолын арга зүй",
https://sharkfestus.wireshark.org/sharkfest.11/presentations/McCanne-Sharkfest'11_Keynote_Address.pdf
tcpdump
,libpcap
:https://www.tcpdump.org/ IPtable U32 тоглолтын заавар .- BPF - мартагдсан байт код:
https://blog.cloudflare.com/bpf-the-forgotten-bytecode/
- BPF хэрэгслийг танилцуулж байна:
https://blog.cloudflare.com/introducing-the-bpf-tools/
bpf_cls
:http://man7.org/linux/man-pages/man8/tc-bpf.8.html
- Хэсэгчилсэн тойм:
https://lwn.net/Articles/656307/
https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
habr: Контейнер ба аюулгүй байдал: seccomp habr: Демонуудыг systemd-ээр тусгаарлах эсвэл "үүнд Docker хэрэггүй!" - Пол Чайнон, "strace --seccomp-bpf: юүдэн доорх харц",
https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
netsniff-ng
:http://netsniff-ng.org/
Эх сурвалж: www.habr.com