කුඩා ළමුන් සඳහා BPF, ශුන්‍ය කොටස: සම්භාව්‍ය BPF

Berkeley Packet Filters (BPF) යනු ලිනක්ස් කර්නල් තාක්‍ෂණයක් වන අතර එය වසර කිහිපයක් තිස්සේ ඉංග්‍රීසි භාෂා තාක්‍ෂණ ප්‍රකාශනවල මුල් පිටුවල පවතී. BPF භාවිතය සහ සංවර්ධනය පිළිබඳ වාර්තා වලින් සම්මන්ත්‍රණ පිරී ඇත. ඩේවිඩ් මිලර්, ලිනක්ස් ජාල උප පද්ධති නඩත්තු කරන්නා, ලිනක්ස් ප්ලම්බර්ස් 2018 හි ඔහුගේ කතාව කැඳවයි "මේ කතාව XDP ගැන නොවේ" (XDP යනු BPF සඳහා එක් භාවිත අවස්ථාවකි). බ්‍රෙන්ඩන් ග්‍රෙග් විසින් දේශන පවත්වයි Linux BPF Superpowers. Toke Høiland-Jørgensen හිනා වෙනවාකර්නලය දැන් ක්ෂුද්‍ර කර්නලයක් බව. තෝමස් ග්‍රාෆ් එම අදහස ප්‍රවර්ධනය කරයි BPF යනු කර්නලය සඳහා javascript වේ.

Habré හි තවමත් BPF පිළිබඳ ක්‍රමානුකූල විස්තරයක් නොමැත, එබැවින් ලිපි මාලාවකින් මම තාක්‍ෂණයේ ඉතිහාසය ගැන කතා කිරීමට උත්සාහ කරමි, ගෘහ නිර්මාණ ශිල්පය සහ සංවර්ධන මෙවලම් විස්තර කරන්න, සහ BPF භාවිතා කිරීමේ යෙදුම් සහ භාවිතයේ ක්ෂේත්‍ර ගෙනහැර දක්වන්නෙමි. මෙම ලිපිය, ශුන්‍යය, මාලාවේ, සම්භාව්‍ය BPF හි ඉතිහාසය සහ ගෘහ නිර්මාණ ශිල්පය පවසන අතර එහි මෙහෙයුම් මූලධර්මවල රහස් ද හෙළි කරයි. tcpdump, seccomp, strace, සහ තවත් බොහෝ දේ.

BPF සංවර්ධනය Linux ජාලකරණ ප්‍රජාව විසින් පාලනය කරනු ලැබේ, BPF හි පවතින ප්‍රධාන යෙදුම් ජාල වලට සම්බන්ධ වන අතර එබැවින් අවසරය ඇතුව @eucariot, මම කතා මාලාව හැඳින්වූයේ "කුඩා ළමයින් සඳහා 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 ප්‍රොසෙසරය මත පදනම්ව නිර්මාණය කරන ලද අතථ්‍ය යන්ත්‍ර ගෘහ නිර්මාණ ශිල්පය - වැනි ප්‍රසිද්ධ නිෂ්පාදනවල වැඩ අශ්වයා ඇපල් II හෝ NES. නව අතථ්‍ය යන්ත්‍රය දැනට පවතින විසඳුම් හා සසඳන විට දස ගුණයකින් පෙරහන් කාර්ය සාධනය වැඩි කළේය.

BPF යන්ත්‍ර ගෘහ නිර්මාණ ශිල්පය

උදාහරණ විශ්ලේෂණය කරමින් අපි ගෘහ නිර්මාණ ශිල්පය වැඩ කරන ආකාරයෙන් දැන හඳුනා ගනිමු. කෙසේ වෙතත්, ආරම්භ කිරීම සඳහා, යන්ත්‍රයේ පරිශීලකයාට ප්‍රවේශ විය හැකි 32-බිට් රෙජිස්ටර් දෙකක් තිබූ බව කියමු, සමුච්චකය A සහ දර්ශක ලේඛනය X, බයිට් 64 ක මතකයක් (වචන 16), ලිවීමට සහ පසුව කියවීම සඳහා ලබා ගත හැකි අතර, මෙම වස්තූන් සමඟ වැඩ කිරීම සඳහා කුඩා විධාන පද්ධතියක්. කොන්දේසි සහිත ප්‍රකාශන ක්‍රියාත්මක කිරීම සඳහා පැනීමේ උපදෙස් වැඩසටහන් වල ද ලබා ගත හැකි නමුත්, වැඩසටහන කාලෝචිත ලෙස නිම කිරීම සහතික කිරීම සඳහා, ඉදිරියට පැනීම පමණක් කළ හැකි විය, එනම්, විශේෂයෙන්, ලූප නිර්මාණය කිරීම තහනම් විය.

යන්ත්රය ආරම්භ කිරීම සඳහා සාමාන්ය යෝජනා ක්රමය පහත පරිදි වේ. පරිශීලකයා BPF ගෘහ නිර්මාණ ශිල්පය සහ භාවිතා කිරීම සඳහා වැඩසටහනක් නිර්මාණය කරයි සමහරක් කර්නල් යාන්ත්‍රණය (පද්ධති ඇමතුමක් වැනි), වැඩසටහන පූරණය කර සම්බන්ධ කරයි ඇතැම් කර්නලයේ සිදුවීම් උත්පාදක යන්ත්රය වෙත (උදාහරණයක් ලෙස, සිදුවීමක් යනු ජාල කාඩ්පතෙහි ඊළඟ පැකට්ටුව පැමිණීමයි). සිදුවීමක් සිදු වූ විට, කර්නලය වැඩසටහන ක්‍රියාත්මක කරයි (උදාහරණයක් ලෙස, පරිවර්තකයක), සහ යන්ත්‍ර මතකය අනුරූප වේ ඇතැම් කර්නල් මතක කලාපය (උදාහරණයක් ලෙස, එන පැකට්ටුවක දත්ත).

උදාහරණ දෙස බැලීම ආරම්භ කිරීමට ඉහත සඳහන් දේ ප්රමාණවත් වනු ඇත: අපි අවශ්ය පරිදි පද්ධතිය සහ විධාන ආකෘතිය සමඟ දැන හඳුනා ගන්නෙමු. ඔබට අථත්‍ය යන්ත්‍රයක විධාන පද්ධතිය වහාම අධ්‍යයනය කර එහි සියලු හැකියාවන් ගැන ඉගෙන ගැනීමට අවශ්‍ය නම්, ඔබට මුල් ලිපිය කියවිය හැකිය. BSD පැකට් පෙරහන සහ/හෝ ගොනුවේ පළමු භාගය ලේඛනගත කිරීම/ජාලකරණය/filter.txt කර්නල් ලේඛනයෙන්. ඊට අමතරව, ඔබට ඉදිරිපත් කිරීම අධ්යයනය කළ හැකිය libpcap: පැකට් ග්‍රහණය සඳහා ගෘහ නිර්මාණ ශිල්පය සහ ප්‍රශස්තකරණ ක්‍රමවේදයක්, BPF හි කතුවරුන්ගෙන් කෙනෙකු වන McCanne, නිර්මාණයේ ඉතිහාසය ගැන කතා කරයි 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 architecture bytecode තුළට ගොස් කර්නලය වෙත යවන්න (කොටසේ විස්තර බලන්න Tcpdump: පැටවීම) අතුරු මුහුණත හරහා ගමන් කරන සෑම පැකට්ටුවක් සඳහාම පටවන ලද පෙරහන ක්‍රියාත්මක වේ eth0. පෙරහන ශුන්‍ය නොවන අගයක් ලබා දෙන්නේ නම් n, පසුව දක්වා n පැකට්ටුවේ බයිට් පරිශීලක අවකාශයට පිටපත් කරනු ලබන අතර අපට එය ප්‍රතිදානයේදී පෙනෙනු ඇත tcpdump.

කුඩා ළමුන් සඳහා BPF, ශුන්‍ය කොටස: සම්භාව්‍ය BPF

කර්නලය වෙත යවන ලද බයිට්කේතය අපට පහසුවෙන් සොයාගත හැකි බව පෙනේ 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සහ මෙය අදහස් කරයිපැකට්ටුව මේ ආකාරයෙන් පෙනේ (සරල බව සඳහා, පැකට්ටුවේ VLAN ටැග් නොමැති බව අපි උපකල්පනය කරමු):

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

එබැවින් විධානය ක්රියාත්මක කිරීමෙන් පසුව ldh [12] ලේඛනයේ A ක්ෂේත්රයක් වනු ඇත Ether Type - මෙම ඊතර්නෙට් රාමුව තුළ සම්ප්‍රේෂණය කරන ලද පැකට් වර්ගය. 1 වන පේළියේ අපි ලේඛනයේ අන්තර්ගතය සංසන්දනය කරමු A (පැකේජ වර්ගය) c 0x86ddසහ මෙය සහ එහි ඇත අප උනන්දු වන වර්ගය IPv6 වේ. 1 පේළියේ, සංසන්දනාත්මක විධානයට අමතරව, තවත් තීරු දෙකක් ඇත - 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 පැකට්ටුවක් බව පරීක්ෂා කර ඇත (ඊතර් වර්ගය = 0x800) සහ එය ලේඛනයට පටවන්න A පැකට්ටුවේ 24 වන බයිටය. අපේ පැකේජය මේ වගේ

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

ඒ කියන්නේ අපි රෙජිස්ටර් එකට ලෝඩ් වෙනවා A IP ශීර්ෂයේ ප්‍රොටෝකෝල ක්ෂේත්‍රය, එය තාර්කික ය, මන්ද අපට පිටපත් කිරීමට අවශ්‍ය වන්නේ TCP පැකට් පමණි. අපි Protocol සමඟ සංසන්දනය කරමු 0x6 (IPPROTO_TCP) 3 පේළියේ.

4 සහ 5 පේළිවල අපි ලිපිනය 20 හි පිහිටා ඇති අර්ධ වචන පටවා විධානය භාවිතා කරමු jset තුනෙන් එකක් සෙට් වෙලාද කියලා බලන්න කොඩි - නිකුත් කරන ලද වෙස්මුහුණ පැළඳීම jset වඩාත්ම වැදගත් බිටු තුන ඉවත් කර ඇත. බිටු තුනෙන් දෙකක් අපට පවසන්නේ පැකට්ටුව ඛණ්ඩනය වූ IP පැකට්ටුවක කොටසක්ද, එසේ නම්, එය අවසාන කොටසද යන්නයි. තෙවන බිට් එක වෙන් කර ඇති අතර ශුන්‍ය විය යුතුය. අපට අසම්පූර්ණ හෝ කැඩුණු පැකට් පරීක්ෂා කිරීමට අවශ්‍ය නැත, එබැවින් අපි බිටු තුනම පරීක්ෂා කරමු.

මෙම ලැයිස්තුවේ 6 වන පේළිය වඩාත් සිත්ගන්නා සුළුය. ප්රකාශනය ldxb 4*([14]&0xf) එයින් අදහස් වන්නේ අපි ලේඛනයට පටවන බවයි X පැකට්ටුවේ පහළොස්වන බයිටයේ අවම සැලකිය යුතු බිටු හතර 4 න් ගුණ කළ යුතුය. පහළොස්වන බයිටයේ අවම සැලකිය යුතු බිටු හතර වන්නේ ක්ෂේත්‍රයයි අන්තර්ජාල ශීර්ෂයේ දිග IPv4 ශීර්ෂකය, ශීර්ෂයේ දිග වචන වලින් ගබඩා කරයි, එබැවින් ඔබ 4 න් ගුණ කළ යුතුය. සිත්ගන්නා කරුණ නම්, ප්‍රකාශනය 4*([14]&0xf) මෙම පෝරමයේ පමණක් භාවිතා කළ හැකි සහ ලේඛනයක් සඳහා පමණක් භාවිතා කළ හැකි විශේෂ ලිපින යෝජනා ක්රමයක් සඳහා නම් කිරීමකි X, i.e. අපිටත් කියන්න බෑ ldb 4*([14]&0xf) නැත ldxb 5*([14]&0xf) (අපට සඳහන් කළ හැක්කේ වෙනත් ඕෆ්සෙට් එකක් පමණි, උදාහරණයක් ලෙස, ldxb 4*([16]&0xf)) මෙම ආමන්ත්‍රණ ක්‍රමය BPF වෙත එක් කර ඇත්තේ නිශ්චිතවම ලැබීම සඳහා බව පැහැදිලිය X (දර්ශක ලේඛනය) IPv4 ශීර්ෂයේ දිග.

එබැවින් 7 වන පේළියේ අපි වචනයෙන් අඩක් පැටවීමට උත්සාහ කරමු (X+16). ඊතර්නෙට් ශීර්ෂය මගින් බයිට් 14 ක් අල්ලාගෙන ඇති බව මතක තබා ගැනීම සහ X IPv4 ශීර්ෂයේ දිග අඩංගු වේ, අපි එය තේරුම් ගනිමු A TCP ගමනාන්ත වරාය පූරණය කර ඇත:

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

අවසාන වශයෙන්, 8 වන පේළියේ අපි අපේක්ෂිත අගය සමඟ ගමනාන්ත වරාය සංසන්දනය කර 9 හෝ 10 පේළිවල අපි ප්‍රති result ලය ලබා දෙමු - පැකට්ටුව පිටපත් කළ යුතුද නැද්ද යන්න.

Tcpdump: පැටවීම

පෙර උදාහරණවලදී, පැකට් පෙරීම සඳහා කර්නලයට BPF බයිට්කේතය පූරණය කරන්නේ කෙසේද යන්න පිළිබඳව අපි විශේෂයෙන් විස්තරාත්මකව වාසය නොකළෙමු. පොදුවේ ගත් කල, tcpdump බොහෝ පද්ධති වෙත සහ පෙරහන් සමඟ වැඩ කිරීම සඳහා ගෙනයනු ලැබේ tcpdump පුස්තකාලය භාවිතා කරයි libpcap. කෙටියෙන්, භාවිතා කරමින් අතුරු මුහුණතක් මත පෙරනයක් තැබීමට libpcap, ඔබ පහත සඳහන් දෑ කළ යුතුය:

  • ආකාරයේ විස්තරයක් සාදන්න pcap_t අතුරු මුහුණත නාමයෙන්: pcap_create,
  • අතුරු මුහුණත සක්රිය කරන්න: pcap_activate,
  • සම්පාදන පෙරහන: pcap_compile,
  • සම්බන්ධක පෙරහන: pcap_setfilter.

කාර්යය කෙසේ දැයි බැලීමට pcap_setfilter Linux හි ක්රියාත්මක, අපි භාවිතා කරමු 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 භාවිතයෙන් Linux හි පැකේජ පෙරීමට, ඔබට එවැනි ව්‍යුහයක ස්වරූපයෙන් පෙරනයක් තිබිය යුතුය. struct sock_fprog සහ විවෘත සොකට් එකක්, ඉන් පසු පෙරහන පද්ධති ඇමතුමක් භාවිතයෙන් සොකට් එකට සම්බන්ධ කළ හැක setsockopt.

සිත්ගන්නා කරුණ නම්, පෙරණය අමු පමණක් නොව ඕනෑම සොකට් එකකට ඇමිණිය හැකිය. මෙතන උදාහරණයකි එන සියලුම UDP ඩේටාග්‍රෑම් වලින් පළමු බයිට් දෙක හැර අන් සියල්ල කපා හරින වැඩසටහනකි. (ලිපිය අවුල් නොවන පරිදි මම කේතයේ අදහස් එක් කළෙමි.)

භාවිතය පිළිබඳ වැඩි විස්තර setsockopt පෙරහන් සම්බන්ධ කිරීම සඳහා, බලන්න සොකට් (7), නමුත් කැමති ඔබේම පෙරහන් ලිවීම ගැන struct sock_fprog උදව් නොමැතිව tcpdump අපි කොටසේ කතා කරමු අපගේම දෑතින් BPF වැඩසටහන්කරණය.

Classic BPF සහ XNUMX වැනි සියවස

BPF 1997 දී Linux හි ඇතුළත් කරන ලද අතර එය දිගු කලක් වැඩකාරයෙක් ලෙස පවතී libpcap විශේෂ වෙනස්කම් නොමැතිව (ලිනක්ස්-විශේෂිත වෙනස්කම්, ඇත්ත වශයෙන්ම, එය, නමුත් ඔවුන් ගෝලීය පින්තූරය වෙනස් කළේ නැත). BPF පරිණාමය වන බවට පළමු බරපතල සංඥා පැමිණියේ 2011 දී Eric Dumazet යෝජනා කළ විටය. පැච්, එය කර්නලයට Just In Time Compiler එක් කරයි - BPF බයිට්කේත ස්වදේශික බවට පරිවර්තනය කිරීම සඳහා පරිවර්තකයකි x86_64 කේතය.

JIT සම්පාදකය වෙනස් කිරීමේ දාමයේ පළමුවැන්නයි: 2012 දී පෙනී සිටියේය සඳහා පෙරහන් ලිවීමේ හැකියාව seccomp, BPF භාවිතා කරමින්, 2013 ජනවාරි මාසයේදී තිබුණා එකතු කළා මොඩියුලය xt_bpf, සඳහා නීති ලිවීමට ඔබට ඉඩ සලසයි iptables BPF ආධාරයෙන්, සහ 2013 ඔක්තෝම්බර් මාසයේදී විය එකතු කළා මොඩියුලයක් ද 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;
}

මේ අනුව, අපට දැනටමත් වැඩසටහන් ලිවිය හැකිය (උදාහරණයක් ලෙස, අපි උපදෙස් කේත දනිමු [1]) ෆිල්ටරය පෙනෙන්නේ මෙයයි 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))

යන්ත්‍ර කේත ස්වරූපයෙන් වැඩසටහන් ලිවීම එතරම් පහසු නැත, නමුත් සමහර විට එය අවශ්‍ය වේ (නිදසුනක් ලෙස, නිදොස් කිරීම, ඒකක පරීක්ෂණ නිර්මාණය කිරීම, හබ්‍රේ පිළිබඳ ලිපි ලිවීම යනාදිය). පහසුව සඳහා, ගොනුවේ <linux/filter.h> helper macros නිර්වචනය කර ඇත - ඉහත උදාහරණය නැවත ලිවිය හැක

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 සම්භාව්‍ය 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,

C ක්‍රමලේඛකයන්ගේ පහසුව සඳහා, වෙනස් ප්‍රතිදාන ආකෘතියක් භාවිතා කළ හැක:

$ 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 වලට අමතරව, Linux සහ 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. පැකේජයේ තරමක් සවිස්තරාත්මක ලියකියවිලි අඩංගු වේ, ලිපියේ අවසානයේ ඇති සබැඳි ද බලන්න.

seccomp

එබැවින්, අත්තනෝමතික සංකීර්ණතාවයකින් යුත් BPF වැඩසටහන් ලියන්නේ කෙසේදැයි අපි දැනටමත් දන්නා අතර නව උදාහරණ දෙස බැලීමට සූදානම්ව සිටිමු, ඉන් පළමුවැන්න seccomp තාක්‍ෂණය වන අතර එය BPF පෙරහන් භාවිතා කරමින් ලබා ගත හැකි පද්ධති ඇමතුම් තර්ක කට්ටලය සහ කට්ටලය කළමනාකරණය කිරීමට ඉඩ සලසයි. දෙන ලද ක්‍රියාවලියක් සහ එහි පැවත එන්නන්.

seccomp හි පළමු අනුවාදය 2005 දී කර්නලයට එක් කරන ලද අතර එය එතරම් ජනප්‍රිය නොවීය, මන්ද එය තනි විකල්පයක් පමණක් ලබා දී ඇත - ක්‍රියාවලියකට ලබා ගත හැකි පද්ධති ඇමතුම් කට්ටලය පහත දක්වා සීමා කිරීමට: read, write, exit и sigreturn, සහ නීති උල්ලංඝනය කරන ලද ක්රියාවලිය භාවිතා කර මරා දමන ලදී SIGKILL. කෙසේ වෙතත්, 2012 දී, seccomp විසින් BPF ෆිල්ටර භාවිතා කිරීමේ හැකියාව එක් කරන ලද අතර, ඔබට අවසර ලත් පද්ධති ඇමතුම් කට්ටලයක් නිර්වචනය කිරීමට සහ ඒවායේ තර්ක මත චෙක්පත් පවා සිදු කිරීමට ඉඩ සලසයි. (සිත්ගන්නා කරුණක් නම්, ක්‍රෝම් මෙම ක්‍රියාකාරීත්වයේ පළමු පරිශීලකයින්ගෙන් කෙනෙකි, සහ ක්‍රෝම් පුද්ගලයින් දැනට BPF හි නව අනුවාදයක් මත පදනම්ව KRSI යාන්ත්‍රණයක් සංවර්ධනය කරමින් සිටින අතර Linux ආරක්ෂක මොඩියුල අභිරුචිකරණය කිරීමට ඉඩ සලසයි.) අමතර ලියකියවිලි සඳහා සබැඳි අවසානයේ සොයාගත හැකිය. ලිපියේ.

seccomp භාවිතා කිරීම පිළිබඳ ලිපි දැනටමත් කේන්ද්‍රයේ ඇති බව සලකන්න, සමහර විට යමෙකුට පහත උපවගන්ති කියවීමට පෙර (හෝ ඒ වෙනුවට) ඒවා කියවීමට අවශ්‍ය වනු ඇත. ලිපියේ බහාලුම් සහ ආරක්ෂාව: seccomp 2007 අනුවාදය සහ BPF භාවිතා කරන අනුවාදය (libseccomp භාවිතයෙන් පෙරහන් ජනනය කරනු ලැබේ), ඩොකර් සමඟ seccomp සම්බන්ධ කිරීම ගැන කතා කරයි, සහ බොහෝ ප්‍රයෝජනවත් සබැඳි ද සපයයි. ලිපියේ systemd සමඟ ඩීමන් හුදකලා කිරීම හෝ "ඔබට මේ සඳහා ඩොකර් අවශ්‍ය නොවේ!" එය විශේෂයෙන්, ඩීමන් ධාවනය වන systemd සඳහා පද්ධති ඇමතුම් වල අසාදු ලේඛන හෝ සුදු ලැයිස්තු එකතු කරන ආකාරය ආවරණය කරයි.

මීළඟට අපි බලමු ෆිල්ටර් ලියන ආකාරය සහ පූරණය කරන ආකාරය seccomp හිස් C හි සහ පුස්තකාලය භාවිතා කරයි libseccomp සහ එක් එක් විකල්පයේ වාසි සහ අවාසි මොනවාද, අවසාන වශයෙන්, වැඩසටහන මඟින් seccomp භාවිතා කරන්නේ කෙසේදැයි බලමු strace.

seccomp සඳහා පෙරහන් ලිවීම සහ පැටවීම

අපි දැනටමත් BPF වැඩසටහන් ලියන්නේ කෙසේදැයි දනිමු, එබැවින් අපි මුලින්ම බලමු seccomp ක්‍රමලේඛන අතුරුමුහුණත. ඔබට ක්‍රියාවලි මට්ටමින් පෙරහනක් සැකසිය හැකි අතර, සියලුම ළමා ක්‍රියාවලීන් සීමා කිරීම් උරුම කර ගනී. මෙය පද්ධති ඇමතුමක් භාවිතයෙන් සිදු කෙරේ seccomp(2):

seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)

එහිදී &filter - මෙය දැනටමත් අපට හුරුපුරුදු ව්‍යුහයකට දර්ශකයකි struct sock_fprog, i.e. BPF වැඩසටහන.

seccomp සඳහා වැඩසටහන් සොකට් සඳහා වැඩසටහන් වලින් වෙනස් වන්නේ කෙසේද? සම්ප්රේෂිත සන්දර්භය. සොකට් වලදී, අපට පැකට් එක අඩංගු මතක ප්‍රදේශයක් ලබා දී ඇති අතර, සෙකොම්ප් නම්, අපට එවැනි ව්‍යුහයක් ලබා දී ඇත.

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

එය nr දියත් කිරීමට නියමිත පද්ධති ඇමතුමේ අංකය වේ, arch - වත්මන් ගෘහ නිර්මාණ ශිල්පය (මේ පිළිබඳ වැඩි විස්තර පහතින්), args - පද්ධති ඇමතුම් තර්ක හයක් දක්වා, සහ instruction_pointer යනු පද්ධති ඇමතුම සිදු කළ පරිශීලක අවකාශ උපදෙස් වෙත දර්ශකයකි. මේ අනුව, උදාහරණයක් ලෙස, පද්ධති ඇමතුම් අංකය ලේඛනයට පැටවීමට A අපි කියන්න ඕන

ldw [0]

seccomp වැඩසටහන් සඳහා වෙනත් විශේෂාංග ඇත, උදාහරණයක් ලෙස, සන්දර්භයට ප්‍රවේශ විය හැක්කේ 32-bit alignment මගින් පමණක් වන අතර ඔබට වචනයෙන් අඩක් හෝ බයිටයක් පූරණය කළ නොහැක - පෙරහනක් පූරණය කිරීමට උත්සාහ කරන විට ldh [0] පද්ධති ඇමතුම seccomp නැවත පැමිණෙනු ඇත EINVAL. ශ්‍රිතය මඟින් පටවන ලද පෙරහන් පරීක්ෂා කරයි seccomp_check_filter() කර්නල්. (විහිලු සහගත දෙය නම්, seccomp ක්‍රියාකාරිත්වය එක් කළ මුල් කැපවීමේදී, මෙම කාර්යයට උපදෙස් භාවිතා කිරීමට අවසරය එක් කිරීමට ඔවුන්ට අමතක විය. mod (කොට්ඨාශ ඉතිරි) සහ එය එකතු කළ දා සිට seccomp BPF වැඩසටහන් සඳහා දැන් නොමැත බිඳී යනු ඇත ABI.)

මූලික වශයෙන්, අපි දැනටමත් 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 එකලස් කිරීමේදී පෙරහන් ලිවීම ඔබට ප්‍රතිඵලය පිළිබඳ පූර්ණ පාලනයක් ලබා ගැනීමට ඉඩ සලසයි, නමුත් ඒ සමඟම, අතේ ගෙන යා හැකි සහ/හෝ කියවිය හැකි කේතයක් තිබීම වඩාත් සුදුසුය. පුස්තකාලය මේ සඳහා අපට උපකාර කරනු ඇත libseccomp, කළු හෝ සුදු පෙරහන් ලිවීම සඳහා සම්මත අතුරු මුහුණතක් සපයයි.

උදාහරණයක් ලෙස, පරිශීලකයා විසින් තෝරා ගන්නා ලද ද්විමය ගොනුවක් ධාවනය කරන වැඩසටහනක් ලියමු, කලින් පද්ධති ඇමතුම් අසාදු ලේඛනයක් ස්ථාපනය කර ඇත. ඉහත ලිපිය (වැඩිදුර කියවීමේ හැකියාව සඳහා වැඩසටහන සරල කර ඇත, සම්පූර්ණ අනුවාදය සොයාගත හැකිය මෙහි):

#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 ලෙස සැකසීමෙන් පෙරණය ද්විමය සෙවුම් වැඩසටහනක් බවට පරිවර්තනය වේ.

ද්විමය සෙවුම් පෙරහන් ක්‍රියා කරන ආකාරය බැලීමට ඔබට අවශ්‍ය නම්, බලන්න සරල පිටපත, පද්ධති ඇමතුම් අංක ඇමතීමෙන් BPF එකලස් කරන්නා තුළ එවැනි වැඩසටහන් උත්පාදනය කරයි, උදාහරණයක් ලෙස:

$ 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, සහ යනාදි.

කුඩා ළමුන් සඳහා BPF, ශුන්‍ය කොටස: සම්භාව්‍ය BPF

කෙසේ වෙතත්, 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 වෙතින් නව පණිවිඩ සඳහා රැඳී සිටිනු ඇත.

කුඩා ළමුන් සඳහා BPF, ශුන්‍ය කොටස: සම්භාව්‍ය BPF

විකල්පය භාවිතා කරන විට --seccomp-bpf සීමාවන් දෙකක් තිබේ. පළමුව, දැනටමත් පවතින ක්‍රියාවලියකට සම්බන්ධ වීමට නොහැකි වනු ඇත (විකල්පය -p වැඩසටහන් strace), මෙය seccomp විසින් සහාය නොදක්වන බැවින්. දෙවනුව, හැකියාවක් නැත නෑ මෙය අක්‍රිය කිරීමේ හැකියාවකින් තොරව සියලුම ළමා ක්‍රියාවලීන් මගින් seccomp පෙරහන් උරුම වන බැවින් ළමා ක්‍රියාවලි දෙස බලන්න.

හරියටම කොහොමද කියලා තව ටිකක් විස්තර strace සමඟ වැඩ කරන්න seccomp වෙතින් සොයා ගත හැක මෑත වාර්තාව. අප සඳහා, වඩාත්ම සිත්ගන්නා කරුණ නම්, seccomp විසින් නියෝජනය කරන ලද සම්භාව්‍ය BPF අදටත් භාවිතා වේ.

xt_bpf

දැන් අපි නැවතත් ජාල ලෝකයට යමු.

පසුබිම: බොහෝ කලකට පෙර, 2007 දී, හරය විය එකතු කළා මොඩියුලය xt_u32 netfilter සඳහා. එය ලියා ඇත්තේ ඊටත් වඩා පැරණි රථවාහන වර්ගීකරණයක් සමඟ සාදෘශ්‍යයකිනි cls_u32 සහ පහත සරල මෙහෙයුම් භාවිතා කරමින් iptables සඳහා අත්තනෝමතික ද්විමය රීති ලිවීමට ඔබට ඉඩ සලසයි: පැකේජයකින් බිටු 32 ක් පැටවීම සහ ඒවා මත අංක ගණිත මෙහෙයුම් මාලාවක් සිදු කිරීම. උදාහරණ වශයෙන්,

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

IP ශීර්ෂයේ බිටු 32 පූරණය කරයි, පැඩින් 6 සිට ආරම්භ කර, ඒවාට වෙස් මුහුණක් යොදයි 0xFF (අඩු බයිටය ගන්න). මෙම ක්ෂේත්රය protocol IP ශීර්ෂකය සහ අපි එය 1 (ICMP) සමඟ සංසන්දනය කරමු. ඔබට එක් රීතියක් තුළ බොහෝ චෙක්පත් ඒකාබද්ධ කළ හැකි අතර, ඔබට ක්රියාකරු ක්රියාත්මක කළ හැකිය @ — X බයිට් දකුණට ගෙන යන්න. උදාහරණයක් ලෙස, රීතිය

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

TCP අනුක්‍රමික අංකය සමාන නොවේදැයි පරීක්ෂා කරයි 0x29. එවැනි නීති රීති අතින් ලිවීම එතරම් පහසු නොවන බව දැනටමත් පැහැදිලි බැවින් මම වැඩිදුර විස්තර වෙත නොයමි. ලිපියේ BPF - අමතක වූ බයිට් කේතය, භාවිතය සහ රීති උත්පාදනය පිළිබඳ උදාහරණ සහිත සබැඳි කිහිපයක් තිබේ xt_u32. මෙම ලිපියේ අවසානයේ ඇති සබැඳි ද බලන්න.

මොඩියුලය වෙනුවට 2013 සිට මොඩියුලය xt_u32 ඔබට BPF පදනම් වූ මොඩියුලයක් භාවිතා කළ හැකිය xt_bpf. මෙතෙක් කියවා ඇති ඕනෑම කෙනෙකුට එහි ක්‍රියාකාරිත්වයේ මූලධර්මය පිළිබඳව දැනටමත් පැහැදිලි විය යුතුය: BPF bytecode 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 ප්‍රහාර වලින් ආරක්ෂා වීමට. ලිපියේ BPF මෙවලම් හඳුන්වා දීම ඔවුන් BPF ෆිල්ටර උත්පාදනය කරන්නේ කෙසේද (සහ ඇයි) සහ එවැනි පෙරහන් නිර්මාණය කිරීම සඳහා උපයෝගිතා කට්ටලයකට සබැඳි ප්‍රකාශයට පත් කරන්නේ කෙසේද යන්න පැහැදිලි කරයි. උදාහරණයක් ලෙස, උපයෝගීතාව භාවිතා කිරීම 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 සම්පාදක කේතය ප්‍රකාශයට පත් කළේය. ලිපියේ p0f BPF සම්පාදකය හඳුන්වා දීම ඔවුන් p0f යනු කුමක්ද සහ 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 හි නව අනුවාදය භාවිතා කිරීමේ විකල්පයන්ගෙන් එකක්, බලන්න. L4Drop: XDP DDoS අවම කිරීම්.

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-bit සිට XNUMX-bit යන්ත්‍ර දක්වා සංක්‍රමණයක් සිදු වූ අතර සම්භාව්‍ය BPF යල් පැන යාමට පටන් ගත්තේය. මීට අමතරව, සම්භාව්‍ය BPF හි හැකියාවන් ඉතා සීමිත වන අතර යල් පැන ගිය ගෘහ නිර්මාණ ශිල්පයට අමතරව - BPF වැඩසටහන් වෙත ඇමතුම් අතර තත්වය සුරැකීමට අපට හැකියාවක් නැත, සෘජු පරිශීලක අන්තර්ක්‍රියා කිරීමේ හැකියාවක් නොමැත, අන්තර්ක්‍රියා කිරීමේ හැකියාවක් නොමැත. සීමිත ව්‍යුහ ක්ෂේත්‍ර සංඛ්‍යාවක් කියවීම හැර, කර්නලය සමඟ sk_buff සහ සරලම උපකාරක කාර්යයන් දියත් කිරීම, ඔබට පැකට් වල අන්තර්ගතය වෙනස් කර ඒවා හරවා යැවිය නොහැක.

ඇත්ත වශයෙන්ම, දැනට Linux හි සම්භාව්‍ය BPF හි ඉතිරිව ඇත්තේ API අතුරුමුහුණත වන අතර, කර්නලය තුළ සියලුම සම්භාව්‍ය වැඩසටහන්, සොකට් පෙරහන් හෝ seccomp පෙරහන් වේවා, ස්වයංක්‍රීයව නව ආකෘතියක් වන Extended BPF වෙත පරිවර්තනය වේ. (මෙය හරියටම සිදුවන්නේ කෙසේද යන්න අපි ඊළඟ ලිපියෙන් කතා කරමු.)

නව ගෘහ නිර්මාණ ශිල්පයකට සංක්‍රමණය ආරම්භ වූයේ 2013 දී ඇලෙක්සි ස්ටාරොවොයිටොව් විසින් BPF යාවත්කාලීන යෝජනා ක්‍රමයක් යෝජනා කළ විටය. 2014 දී අනුරූප පැච් පෙනෙන්නට පටන් ගත්තේය හරය තුළ. මා තේරුම් ගත් පරිදි, මූලික සැලැස්ම වූයේ 64-bit යන්ත්‍රවල වඩාත් කාර්යක්ෂමව ක්‍රියාත්මක වන පරිදි ගෘහ නිර්මාණ ශිල්පය සහ JIT සම්පාදකය ප්‍රශස්ත කිරීම පමණි, නමුත් ඒ වෙනුවට මෙම ප්‍රශස්තිකරණය ලිනක්ස් සංවර්ධනයේ නව පරිච්ඡේදයක ආරම්භය සනිටුහන් කළේය.

මෙම ලිපි මාලාවේ වැඩිදුර ලිපි නව තාක්‍ෂණයේ ගෘහ නිර්මාණ ශිල්පය සහ යෙදුම් ආවරණය කරනු ඇත, මුලින් අභ්‍යන්තර BPF ලෙසත්, පසුව දීර්ඝ BPF ලෙසත්, දැන් සරලව BPF ලෙසත් හැඳින්වේ.

යොමු

  1. Steven McCanne සහ Van Jacobson, "The BSD Packet Filter: A New Architecture for User-level Packet Capture", https://www.tcpdump.org/papers/bpf-usenix93.pdf
  2. Steven McCanne, "libpcap: An Architecture and Optimization Methodology for Packet Capture", 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 - අමතක වූ බයිට් කේතය: https://blog.cloudflare.com/bpf-the-forgotten-bytecode/
  6. BPF මෙවලම හඳුන්වා දීම: https://blog.cloudflare.com/introducing-the-bpf-tools/
  7. bpf_cls: http://man7.org/linux/man-pages/man8/tc-bpf.8.html
  8. seccomp දළ විශ්ලේෂණයක්: https://lwn.net/Articles/656307/
  9. https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
  10. habr: බහාලුම් සහ ආරක්ෂාව: seccomp
  11. habr: systemd සමඟ ඩීමන් හුදකලා කිරීම හෝ "ඔබට මේ සඳහා ඩොකර් අවශ්‍ය නොවේ!"
  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/

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න