Berkeley Packet Filters (BPF) ã¯ãæ°å¹Žåããè±èªã®æè¡åºçç©ã®è¡šçŽã食ã£ãŠãã Linux ã«ãŒãã« ãã¯ãããžã§ãã ã«ã³ãã¡ã¬ã³ã¹ã§ã¯ãBPF ã®äœ¿çšãšéçºã«é¢ããå ±åãæ°å€ãè¡ãããŸãã Linux ãããã¯ãŒã¯ ãµãã·ã¹ãã ã¡ã³ããã® David Miller æ°ã Linux Plumbers 2018 ã§è¬æŒ
Habré ã«é¢ãã BPF ã®äœç³»çãªèª¬æã¯ãŸã ãããŸããããã®ãããäžé£ã®èšäºã§ããã®ãã¯ãããžãŒã®æŽå²ã«ã€ããŠèª¬æããã¢ãŒããã¯ãã£ãšéçºããŒã«ã«ã€ããŠèª¬æããBPF ã®äœ¿çšã®å¿çšåéãšå®è·µã®æŠèŠã説æããããšæããŸãã ã·ãªãŒãºã®ãã®èšäºãŒãã§ã¯ãå€å
žç㪠BPF ã®æŽå²ãšã¢ãŒããã¯ãã£ã説æãããã®åäœåçã®ç§å¯ãæããã«ããŸãã tcpdump
, seccomp
, strace
ãОЌМПгПеЎÑÑгПеã
BPF ã®éçºã¯ Linux ãããã¯ãŒã¯ ã³ãã¥ããã£ã«ãã£ãŠç®¡çãããŠãããBPF ã®æ¢åã®äž»ãªã¢ããªã±ãŒã·ã§ã³ã¯ãããã¯ãŒã¯ã«é¢é£ããŠãããããèš±å¯ãåŸãŠããŸãã
BPF ã®æŽå²ã®çãã³ãŒã¹(c)
ææ°ã® BPF ãã¯ãããžã¯ãåãååã®å€ããã¯ãããžãæ¹è¯ããã³æ¡åŒµããããŒãžã§ã³ã§ãããçŸåšã¯æ··ä¹±ãé¿ããããã«ã¯ã©ã·ã㯠BPF ãšåŒã°ããŠããŸãã æåãªãŠãŒãã£ãªãã£ã¯å€å
žç㪠BPF ã«åºã¥ããŠäœæãããŸãã tcpdump
ãã¡ã«ããºã seccomp
ãããŸãç¥ãããŠããªãã¢ãžã¥ãŒã«ã xt_bpf
ã®ããã« iptables
ãšåé¡å cls_bpf
ã ææ°ã® Linux ã§ã¯ãã¯ã©ã·ã㯠BPF ããã°ã©ã ã¯èªåçã«æ°ãã圢åŒã«å€æãããŸããããŠãŒã¶ãŒã®èŠ³ç¹ããèŠããšãAPI ã¯ãã®ãŸãŸæ®ãããŠããããã®èšäºã§èª¬æããããã«ãã¯ã©ã·ã㯠BPF ã®æ°ããçšéããŸã èŠã€ãã£ãŠããŸãã ãã®çç±ããããŸããLinux ã§ã®å€å
žç㪠BPF ã®éçºã®æŽå²ããã©ããšããããã©ã®ããã«ããããŠãªãçŸä»£ã®åœ¢ã«é²åããã®ããããæ確ã«ãªããããç§ã¯å€å
žç㪠BPF ã«é¢ããèšäºããå§ããããšã«ããŸããã
åäžçŽã® XNUMX 幎代ã®çµããã«ãæåãªããŒã¬ã³ã¹ ããŒã¯ã¬ãŒç 究æã®ãšã³ãžãã¢ã¯ãåäžçŽã® XNUMX 幎代åŸåã«ã¯ææ°ã ã£ãããŒããŠã§ã¢äžã§ãããã¯ãŒã¯ ãã±ãããé©åã«ãã£ã«ã¿ãªã³ã°ããæ¹æ³ã®åé¡ã«èå³ãæã¡ãŸããã ããšããš CSPF (CMU/Stanford Packet Filter) ãã¯ãããžãŒã§å®è£ ããããã£ã«ã¿ãªã³ã°ã®åºæ¬çãªèãæ¹ã¯ãäžèŠãªãã±ãããã§ããã ãæ©ããã£ã«ã¿ãªã³ã°ããããšã§ããã ããã«ãããäžèŠãªããŒã¿ããŠãŒã¶ãŒç©ºéã«ã³ããŒãããããšãåé¿ãããããã§ãã ã«ãŒãã«ç©ºéã§ãŠãŒã¶ãŒ ã³ãŒããå®è¡ããããã®ã©ã³ã¿ã€ã ã»ãã¥ãªãã£ãæäŸããããã«ããµã³ãããã¯ã¹ä»®æ³ãã·ã³ã䜿çšãããŸããã
ãã ããæ¢åã®ãã£ã«ã¿ãŒã®ä»®æ³ãã·ã³ã¯ã¹ã¿ãã¯ããŒã¹ã®ãã·ã³ã§å®è¡ãããããã«èšèšãããŠãããæ°ãã RISC ãã·ã³ã§ã¯ããã»ã©å¹ççã«å®è¡ãããŸããã§ããã ãã®çµæãããŒã¯ã¬ãŒç 究æã®ãšã³ãžãã¢ã®åªåã«ãããæ°ãã BPF (ããŒã¯ã¬ãŒ ãã±ãã ãã£ã«ã¿ãŒ) ãã¯ãããžãŒãéçºãããŸããããã®ä»®æ³ãã·ã³ ã¢ãŒããã¯ãã£ã¯ã以äžã®ãããªããç¥ããã補åã®äž»åã§ãã Motorola 6502 ããã»ããµã«åºã¥ããŠèšèšãããŸããã
BPF ãã·ã³ã®ã¢ãŒããã¯ãã£
äºäŸãåæããªãããå®è·µçãªæ¹æ³ã§å»ºç¯ã«ã€ããŠåŠã³ãŸãã ãã ãããŸãããã·ã³ã«ãŠãŒã¶ãŒãã¢ã¯ã»ã¹ã§ãã 32 ã€ã® XNUMX ããã ã¬ãžã¹ã¿ãã€ãŸãã¢ãã¥ã ã¬ãŒã¿ããã£ããšããŸãã A
ãšã€ã³ããã¯ã¹ã¬ãžã¹ã¿ X
ãæžã蟌ã¿ãšãã®åŸã®èªã¿åãã«äœ¿çšã§ãã 64 ãã€ãã®ã¡ã¢ãª (16 ã¯ãŒã)ãããã³ãããã®ãªããžã§ã¯ããæäœããããã®å°èŠæš¡ãªã³ãã³ã ã·ã¹ãã ã æ¡ä»¶åŒãå®è£
ããããã®ãžã£ã³ãåœä»€ãããã°ã©ã å
ã§äœ¿çšã§ããŸããããããã°ã©ã ã®ã¿ã€ã ãªãŒãªå®äºãä¿èšŒããããã«ããžã£ã³ãã¯åæ¹ã«ã®ã¿è¡ãããšãã§ããç¹ã«ã«ãŒããäœæããããšã¯çŠæ¢ãããŠããŸããã
ãã·ã³ãèµ·åããããã®äžè¬çãªã¹ããŒã ã¯æ¬¡ã®ãšããã§ãã ãŠãŒã¶ãŒã¯ãBPF ã¢ãŒããã¯ãã£çšã®ããã°ã©ã ãäœæãã ããã€ã ã«ãŒãã«ã¡ã«ããºã (ã·ã¹ãã ã³ãŒã«ãªã©)ãããã°ã©ã ãããŒãããŠæ¥ç¶ããŸãã äžéšã®äººã« ã«ãŒãã«å ã®ã€ãã³ã ãžã§ãã¬ãŒã¿ãŒã«éä¿¡ãããŸã (ããšãã°ãã€ãã³ãã¯ãããã¯ãŒã¯ ã«ãŒãäžã®æ¬¡ã®ãã±ããã®å°çã§ã)ã ã€ãã³ããçºçãããšãã«ãŒãã«ã¯ããã°ã©ã ãå®è¡ãïŒããšãã°ã€ã³ã¿ãŒããªã¿å ã§ïŒããã·ã³ã®ã¡ã¢ãªã¯ äžéšã®äººã« ã«ãŒãã« ã¡ã¢ãªé å (åä¿¡ãã±ããã®ããŒã¿ãªã©)ã
äŸãèŠãŠå§ããã«ã¯äžèšã§ååã§ããå¿
èŠã«å¿ããŠã·ã¹ãã ãšã³ãã³ãã®åœ¢åŒã«ã€ããŠç解ããŠãããŸãã ä»®æ³ãã·ã³ã®ã³ãã³ã ã·ã¹ãã ãããã«èª¿ã¹ãŠããã®ãã¹ãŠã®æ©èœã«ã€ããŠç¥ãããå Žåã¯ãå
ã®èšäºãèªãããšãã§ããŸãã libpcap
: ãã±ãã ãã£ããã£ã®ã¢ãŒããã¯ãã£ãšæé©åææ³libpcap
.
次ã«ãLinux ã§ã®ã¯ã©ã·ã㯠BPF ã®äœ¿çšã«é¢ããéèŠãªäŸããã¹ãŠæ€èšããŠãããŸãã tcpdump
(libpcap
)ãã»ã³ã³ãã xt_bpf
, cls_bpf
.
tcpdump
BPF ã®éçºã¯ãããç¥ããããŠãŒãã£ãªãã£ã§ãããã±ãã ãã£ã«ã¿ãªã³ã°ã®ããã³ããšã³ãã®éçºãšäžŠè¡ããŠè¡ãããŸããã tcpdump
ã ããã¯ãå€ãã®ãªãã¬ãŒãã£ã³ã° ã·ã¹ãã ã§å©çšã§ããã¯ã©ã·ã㯠BPF ã䜿çšããæãå€ããæãæåãªäŸã§ãããããããã䜿çšããŠãã¯ãããžã®ç 究ãéå§ããŸãã
(ãã®èšäºã®ãã¹ãŠã®äŸã¯ Linux äžã§å®è¡ããŸãã 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
XNUMXè¡ç®ã§ã³ãã³ããå®è¡ããŸã ldh [12]
ãããã¯ãã¬ãžã¹ã¿ãžã®ããŒãããè¡šããŸãã A
ã¢ãã¬ã¹ 16 ã«ããåã¯ãŒã (12 ããã) ã§ãããå¯äžã®åé¡ã¯ãã©ã®ãããªçš®é¡ã®ã¡ã¢ãªãã¢ãã¬ã¹æå®ããŠããã®ããšããããšã§ãã çãã¯ã x
å§ãŸã (x+1)
åæããããããã¯ãŒã¯ãã±ããã®ç¬¬ XNUMX ãã€ãã ã€ãŒãµãããã€ã³ã¿ãŒãã§ã€ã¹ãããã±ãããèªã¿åããŸã eth0
ãããŠãã
6 6 2
|Destination MAC|Source MAC|Ether Type|...|
ãããã£ãŠãã³ãã³ããå®è¡ããåŸã ldh [12]
ã¬ãžã¹ã¿ãŒã«ãã A
ãã£ãŒã«ããããã§ããã Ether Type
â ãã®ã€ãŒãµããã ãã¬ãŒã ã§éä¿¡ããããã±ããã®ã¿ã€ãã 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
XNUMX ã€ã®ãã¡ã® XNUMX ã€ãèšå®ãããŠãããã©ããã確èªããŸã jset
æäžäœ XNUMX ãããã¯ã¯ãªã¢ãããŸãã XNUMX ãããã®ãã¡ XNUMX ãããã¯ããã±ããããã©ã°ã¡ã³ãåããã IP ãã±ããã®äžéšã§ãããã©ããããŸãããã©ã°ã¡ã³ãåãããŠããå Žåã¯æåŸã®ãã©ã°ã¡ã³ãã§ãããã©ããã瀺ããŸãã XNUMX çªç®ã®ãããã¯äºçŽãããŠããããŒãã«ããå¿
èŠããããŸãã æŽæ°ãã±ãããå£ãããã±ããããã§ãã¯ããããªãã®ã§ãXNUMX ããããã¹ãŠããã§ãã¯ããŸãã
ãã®ãªã¹ãã®äžã§æãèå³æ·±ãã®ã¯è¡ 6 ã§ãã è¡šçŸ ldxb 4*([14]&0xf)
ã¬ãžã¹ã¿ã«ããŒãããããšãæå³ããŸã X
ãã±ããã® 4 çªç®ã®ãã€ãã®äžäœ XNUMX ãããã XNUMX ã§ä¹ç®ãããã®ãXNUMX çªç®ã®ãã€ãã®äžäœ XNUMX ãããã¯ãã£ãŒã«ãã§ãã 4*([14]&0xf)
ã¯ããã®åœ¢åŒã§ã®ã¿ããŸãã¬ãžã¹ã¿ã«å¯ŸããŠã®ã¿äœ¿çšã§ããç¹å¥ãªã¢ãã¬ã¹æå®ã¹ããŒã ã®æå®ã§ãã X
ãã€ãŸãç§ãã¡ã«ãèšããŸãã 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 è¡ç®ã§ãã±ãããã³ããŒãããã©ããã®çµæãè¿ããŸãã
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
...
åºåã®æåã® XNUMX è¡ã§äœæããŸãã eth0
ã ãã ip
㯠XNUMX ã€ã® BPF åœä»€ã§æ§æãããXNUMX è¡ç®ã§ã¯ãªãã·ã§ã³ã®äœ¿çšæ¹æ³ã瀺ãããŠããŸãã 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
.
èå³æ·±ãããšã«ããã£ã«ã¿ãŒã¯çã ãã§ãªãããããããœã±ããã«æ¥ç¶ã§ããŸãã ãã
ãå©çšã«ã€ããŠè©³ããã¯ãã¡ã setsockopt
ãã£ã«ã¿ãŒã®æ¥ç¶ã«ã€ããŠã¯ããåç
§ããŠãã ããã struct sock_fprog
å©ããªã㧠tcpdump
ã»ã¯ã·ã§ã³ã§è©±ããŸã
å€å žç㪠BPF ãš XNUMX äžçŽ
BPF 㯠1997 幎㫠Linux ã«çµã¿èŸŒãŸããé·ãéäž»åã§ããç¶ããŸããã libpcap
ç¹å¥ãªå€æŽã¯ãããŸãã (ãã¡ãã Linux åºæã®å€æŽã¯ãããŸã) x86_64
ã³ãŒãã
JIT ã³ã³ãã€ã©ãŒã¯äžé£ã®å€æŽã®æåã®ãã®ã§ãã: 2012 幎 xt_bpf
ãããã«ããã次ã®ã«ãŒã«ãäœæã§ããŸãã iptables
BPF ã®ååãåŸãŠã2013 幎 XNUMX æã« cls_bpf
ããã«ãããBPF ã䜿çšããŠãã©ãã£ãã¯åé¡åãäœæã§ããããã«ãªããŸãã
ããããã¹ãŠã®äŸã«ã€ããŠã¯åŸã»ã©è©³ããèŠãŠãããŸããããã®åã«ãBPF çšã®ä»»æã®ããã°ã©ã ãäœæããŠã³ã³ãã€ã«ããæ¹æ³ãåŠç¿ããã®ã圹ç«ã¡ãŸããã©ã€ãã©ãªã«ãã£ãŠæäŸãããæ©èœãããããã§ãã libpcap
å¶éä»ã (ç°¡åãªäŸ: ãã£ã«ã¿ãŒãçæããã) libpcap
0 ã€ã®å€ - 0 ãŸã㯠40000xXNUMX ã®ã¿ãè¿ãããšãã§ããŸãïŒããŸã㯠seccomp ã®å Žåã®ããã«ãäžè¬çã«ã¯é©çšãããŸããã
èªåã®æã§BPFãããã°ã©ãã³ã°ãã
BPF åœä»€ã®ãã€ããªåœ¢åŒãç解ããŸããããããã¯éåžžã«ç°¡åã§ãã
16 8 8 32
| code | jt | jf | k |
ååœä»€ã¯ 64 ããããå ããæåã® 16 ããããåœä»€ã³ãŒãã§ããã®åŸã« XNUMX ãããã®ã€ã³ãã³ãã XNUMX ã€ãããŸãã 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),
}
ãã ãããã®ãªãã·ã§ã³ã¯ããŸã䟿å©ã§ã¯ãããŸããã ããã¯ãLinux ã«ãŒãã« ããã°ã©ããæšè«ãããã®ã§ããããããã£ãŠã 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,
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 ã䜿çšãããã£ã«ã¿ãªã³ã°ã«å ããŠãå¹æçãªãã©ãã£ã㯠ãžã§ãã¬ãŒã¿ãŒãå«ãŸããŠãããBPF ãããé«åºŠã§ãã tools/bpf/bpf_asm
ãšåŒã°ãã BPF ã¢ã»ã³ãã© bpfc
ã ããã±ãŒãžã«ã¯éåžžã«è©³çŽ°ãªããã¥ã¡ã³ããå«ãŸããŠããŸããèšäºã®æåŸã«ãããªã³ã¯ãåç
§ããŠãã ããã
ã»ã³ã³ã
ãããã£ãŠãä»»æã®è€éãã® BPF ããã°ã©ã ãäœæããæ¹æ³ã¯ãã§ã«ç¥ã£ãŠãããæ°ããäŸãæ€èšããæºåãã§ããŠããŸãããã®æåã®äŸã¯ seccomp ãã¯ãããžãŒã§ããããã«ãããBPF ãã£ã«ã¿ãŒã䜿çšããŠãBPF ããã°ã©ã ã§å©çšå¯èœãªäžé£ã®ã·ã¹ãã ã³ãŒã«åŒæ°ã管çã§ããŸããç¹å®ã®ããã»ã¹ãšãã®åå«ã
seccomp ã®æåã®ããŒãžã§ã³ã¯ 2005 幎ã«ã«ãŒãã«ã«è¿œå ãããŸããããããã»ã¹ã§äœ¿çšã§ããã·ã¹ãã ã³ãŒã«ã®ã»ããã次ã®ãã®ã«å¶éãããšãã XNUMX ã€ã®ãªãã·ã§ã³ããæäŸããŠããªãã£ããããããŸã人æ°ããããŸããã§ããã read
, write
, exit
О sigreturn
ãã«ãŒã«ã«éåããããã»ã¹ã¯æ¬¡ã®æ¹æ³ã§åŒ·å¶çµäºãããŸããã SIGKILL
ã ãã ãã2012 幎㫠seccomp ã« BPF ãã£ã«ã¿ãŒã䜿çšããæ©èœãè¿œå ãããèš±å¯ãããã·ã¹ãã ã³ãŒã«ã®ã»ãããå®çŸ©ãããããã®åŒæ°ã®ãã§ãã¯ãå®è¡ãããã§ããããã«ãªããŸããã (èå³æ·±ãããšã«ãChrome ã¯ãã®æ©èœã®æåã®ãŠãŒã¶ãŒã® XNUMX ã€ã§ãããChrome æ
åœè
ã¯çŸåšãBPF ã®æ°ããããŒãžã§ã³ã«åºã¥ã㊠KRSI ã¡ã«ããºã ãéçºããLinux ã»ãã¥ãªã㣠ã¢ãžã¥ãŒã«ã®ã«ã¹ã¿ãã€ãºãå¯èœã«ããŠããŸãã) è¿œå ã®ããã¥ã¡ã³ããžã®ãªã³ã¯ã¯æåŸã«ãããŸããèšäºã®ã
ããã«ã¯ 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
- æ倧 XNUMX ã€ã®ã·ã¹ãã ã³ãŒã«åŒæ°ãããã³ 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 ãšããçªå·ãä»ãã XNUMX ã€ã®ã·ã¹ãã ã³ãŒã«ã®ãã©ãã¯ãªã¹ãããã§ãã¯ããŸãããããã®ã·ã¹ãã ã³ãŒã«ã¯äœã§ãã? ããã°ã©ã ãã©ã®ã¢ãŒããã¯ãã£åãã«æžãããã®ããããããªãããã確ããªããšã¯èšããŸããã ãããã£ãŠã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
) ããã©ã«ãã§ãã¹ãŠã®ã·ã¹ãã ã³ãŒã« (ãã©ãã¯ãªã¹ããäœæããæ¹ãç°¡åã§ã)ã 次ã«ããã¹ãŠã®ã·ã¹ãã ã³ãŒã«ããã©ãã¯ãªã¹ãã« XNUMX ã€ãã€è¿œå ããŸãã ãªã¹ãããã®ã·ã¹ãã ã³ãŒã«ã«å¿çããŠã 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
ãèªæã§ã¯ãªãã³ãŒãã XNUMX è¡ã«åããŸãã äžèšã®äŸã§ã¯ãå€æ°ã®ã·ã¹ãã ã³ãŒã«ãããå Žåããã§ãã¯ã¯åãªãæ¯èŒã®ãªã¹ãã§ãããããå®è¡æéã倧å¹
ã«ççž®ã§ããŸãã æé©åã®ããã«ã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
Linux äžã®ããã»ã¹ã®åäœãç 究ããããã«äžå¯æ¬ ãªããŒã«ã§ãã ããããå€ãã®äººãèããããšãããã®ã¯ã 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
ã¯ã»ãŒåæã«åŠçãããŸãããXNUMX çªç®ã®ã±ãŒã¹ã§ã¯ XNUMX ã€ã®ã·ã¹ãã ã³ãŒã«ã®ã¿ããã¬ãŒã¹ããããšèããŠããŸãã
æ°ãããªãã·ã§ã³ --seccomp-bpf
ã«è¿œå strace
ããŒãžã§ã³ 5.3 ã§ã¯ãããã»ã¹ãäœåã«ãé«éåã§ããXNUMX ã€ã®ã·ã¹ãã ã³ãŒã«ã®ãã¬ãŒã¹ã§ã®èµ·åæéã¯ãã§ã«éåžžã®èµ·åæéãšåçã«ãªã£ãŠããŸãã
$ 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
å¶éã XNUMX ã€ãããŸãã ãŸããæ¢åã®ããã»ã¹ã«åå ããããšã¯ã§ããŸãã (ãªãã·ã§ã³) -p
ããã°ã©ã strace
)ããã㯠seccomp ã§ãµããŒããããŠããªãããã§ãã 第äºã«ãå¯èœæ§ã¯ãããŸãã ã㌠åããã»ã¹ã«æ³šç®ããŠãã ãããããã¯ãseccomp ãã£ã«ã¿ããã¹ãŠã®åããã»ã¹ã«ç¶æ¿ããããããç¡å¹ã«ããæ©èœããªãããã§ãã
æ£ç¢ºãªæ¹æ³ã«ã€ããŠããå°ã詳ãã説æãããšã strace
ã§åäœããŸã seccomp
ããèŠã€ããããšãã§ããŸã
xt_bpf
ããŠããããã¯ãŒã¯ã®äžçã«æ»ããŸãããã
èæ¯: ãã£ãšåã® 2007 幎ãã³ã¢ã¯ xt_u32
ããããã£ã«ã¿ãŒçšã ããã¯ãããã«å€ããã©ãã£ãã¯åé¡åãšã®é¡æšã«ãã£ãŠäœæãããŸããã cls_u32
ãŸããããã±ãŒãžãã 32 ããããããŒããããããã«å¯ŸããŠäžé£ã®ç®è¡æŒç®ãå®è¡ãããšããåçŽãªæäœã䜿çšããŠãiptables ã®ä»»æã®ãã€ã㪠ã«ãŒã«ãäœæã§ããããã«ãªããŸããã äŸãã°ã
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) ãšæ¯èŒããŸãã XNUMX ã€ã®ã«ãŒã«ã«å€ãã®ãã§ãã¯ãçµåã§ããæŒç®åãå®è¡ããããšãã§ããŸãã @
â 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,
...
çŸåšã¯ã¯ã©ãŠããã§ã¢ã䜿çšããŠããŸãã xt_bpf
ãæ°ããããŒãžã§ã³ã® BPF ã䜿çšããããã®ãªãã·ã§ã³ã® XNUMX ã€ã§ãã XDP ã«ç§»è¡ããããããåç
§ããŠãã ããã
cls_bpf
ã«ãŒãã«å
ã§ã¯ã©ã·ã㯠BPF ã䜿çšããæåŸã®äŸã¯ãåé¡åã§ãã cls_bpf
Linux ã®ãã©ãã£ãã¯å¶åŸ¡ãµãã·ã¹ãã çšã2013 幎æ«ã« Linux ã«è¿œå ãããæŠå¿µçã«å€ä»£ã®ãµãã·ã¹ãã ã眮ãæããŸãã cls_u32
.
ãã ãããã®äœåã«ã€ããŠã¯ããã§ã¯èª¬æããŸãã cls_bpf
ãªããªããå€å
žç㪠BPF ã«é¢ããç¥èã®èŠ³ç¹ããã¯ãããã¯ç§ãã¡ã«äœãåŸãããªãããã§ããç§ãã¡ã¯ãã§ã«ãã¹ãŠã®æ©èœã«ç²ŸéããŠããŸãã ããã«ãæ¡åŒµ BPF ã«ã€ããŠèª¬æããåŸç¶ã®èšäºã§ã¯ããã®åé¡åãè€æ°ååãäžããŸãã
å€å
žç㪠BPF c ã®äœ¿çšã«ã€ããŠè©±ããªããã XNUMX ã€ã®çç± cls_bpf
åé¡ã¯ãæ¡åŒµ BPF ãšæ¯èŒããŠããã®å Žåã®é©çšç¯å²ã倧å¹
ã«çãŸã£ãŠããããšã§ããåŸæ¥ã®ããã°ã©ã ã¯ããã±ãŒãžã®å
容ãå€æŽã§ãããåŒã³åºãéã®ç¶æ
ãä¿åã§ããŸããã
ãããã£ãŠãå€å žç㪠BPF ã«å¥ããåããæªæ¥ã«ç®ãåããæãæ¥ãŸããã
å€å žç㪠BPF ã«å¥ããåãã
ç§ãã¡ã¯ã32 幎代åé ã«éçºããã BPF ãã¯ãããžãŒãååäžçŽã«ããã£ãŠã©ã®ããã«çãç¶ããæåŸãŸã§æ°ããªçšéãèŠã€ããã®ãã調ã¹ãŸããã ããããã¯ã©ã·ã㯠BPF éçºã®ãã£ãããšãªã£ãã¹ã¿ã㯠ãã·ã³ãã RISC ãžã®ç§»è¡ãšåæ§ã«ã64 幎代ã«ã¯ XNUMX ããã ãã·ã³ãã XNUMX ããã ãã·ã³ãžã®ç§»è¡ããããã¯ã©ã·ã㯠BPF ã¯æ代é
ãã«ãªãå§ããŸããã ããã«ãã¯ã©ã·ã㯠BPF ã®æ©èœã¯éåžžã«éãããŠãããã¢ãŒããã¯ãã£ãå€ãããšã«å ããŠãBPF ããã°ã©ã ã®åŒã³åºãã®éã«ç¶æ
ãä¿åããæ©èœããªãããŠãŒã¶ãŒãšã®çŽæ¥å¯Ÿè©±ã®å¯èœæ§ããªããçžäºäœçšããå¯èœæ§ããããŸãããéãããæ°ã®æ§é äœãã£ãŒã«ãã®èªã¿åããé€ããã«ãŒãã«ãäœ¿çš sk_buff
æãåçŽãªãã«ããŒé¢æ°ãèµ·åããå Žåããã±ããã®å
容ãå€æŽãããããã±ããããªãã€ã¬ã¯ããããããããšã¯ã§ããŸããã
å®éãçŸåšãLinux ã®ã¯ã©ã·ã㯠BPF ã«æ®ã£ãŠããã®ã¯ API ã€ã³ã¿ãŒãã§ã€ã¹ã ãã§ãããã«ãŒãã«å ã§ã¯ããœã±ãã ãã£ã«ã¿ãŒã§ãã£ãŠã seccomp ãã£ã«ã¿ãŒã§ãã£ãŠãããã¹ãŠã®ã¯ã©ã·ã㯠ããã°ã©ã ã¯æ°ãã圢åŒã§ããæ¡åŒµ BPF ã«èªåçã«å€æãããŸãã (ãããã©ã®ããã«èµ·ããã®ãã«ã€ããŠã¯ã次ã®èšäºã§è©³ãã説æããŸãã)
æ°ããã¢ãŒããã¯ãã£ãžã®ç§»è¡ã¯ãAlexey Starovoitov ã BPF æŽæ°ã¹ããŒã ãææ¡ãã 2013 幎ã«å§ãŸããŸããã 2014 幎ã«å¯Ÿå¿ããããã
ãã®ã·ãªãŒãºã®ä»åŸã®èšäºã§ã¯ãåœåã¯å éš BPFããã®åŸæ¡åŒµ BPFããããŠçŸåšã¯åã« BPF ãšããŠç¥ãããŠããæ°ãããã¯ãããžãŒã®ã¢ãŒããã¯ãã£ãšã¢ããªã±ãŒã·ã§ã³ã«ã€ããŠèª¬æããŸãã
ãªãã¡ã¬ã³ã¹
- Steven McCanne ããã³ Van JacobsonããBSD ãã±ãã ãã£ã«ã¿ãŒ: ãŠãŒã¶ãŒã¬ãã«ã®ãã±ãã ãã£ããã£ã®ããã®æ°ããã¢ãŒããã¯ãã£ãã
https://www.tcpdump.org/papers/bpf-usenix93.pdf
- Steven McCanneãã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
- seccomp ã®æŠèŠ:
https://lwn.net/Articles/656307/
https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
habr: ã³ã³ãããšã»ãã¥ãªãã£: seccomp habr: systemd ã§ããŒã¢ã³ãåé¢ããããŸãã¯ãããã«ã¯ Docker ã¯å¿ èŠãããŸãã!ã - Paul Chaignonããstrace --seccomp-bpf: å
éšã®æ§åãã
https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
netsniff-ng
:http://netsniff-ng.org/
åºæïŒ habr.com