Π’Π΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΡ eXpress Data Path (XDP) ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ ΡΡΠ°ΡΠΈΠΊΠ° Π½Π° ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°Ρ Linux Π΄ΠΎ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΏΠ°ΠΊΠ΅ΡΡ ΠΏΠΎΡΡΡΠΏΡΡ Π² ΡΠ΅ΡΠ΅Π²ΠΎΠΉ ΡΡΠ΅ΠΊ ΡΠ΄ΡΠ°. ΠΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ XDP β Π·Π°ΡΠΈΡΠ° ΠΎΡ DDoS-Π°ΡΠ°ΠΊ (CloudFlare), ΡΠ»ΠΎΠΆΠ½ΡΠ΅ ΡΠΈΠ»ΡΡΡΡ, ΡΠ±ΠΎΡ ΡΡΠ°ΡΠΈΡΡΠΈΠΊΠΈ (Netflix). ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΡ XDP ΠΈΡΠΏΠΎΠ»Π½ΡΡΡΡΡ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΠΎΠΉ ΠΌΠ°ΡΠΈΠ½ΠΎΠΉ eBPF, ΠΏΠΎΡΡΠΎΠΌΡ ΠΈΠΌΠ΅ΡΡ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΡ ΠΊΠ°ΠΊ Π½Π° ΡΠ²ΠΎΠΉ ΠΊΠΎΠ΄, ΡΠ°ΠΊ ΠΈ Π½Π° Π΄ΠΎΡΡΡΠΏΠ½ΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ ΡΠ΄ΡΠ° Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΈΠΏΠ° ΡΠΈΠ»ΡΡΡΠ°.
Π‘ΡΠ°ΡΡΡ ΠΏΡΠΈΠ·Π²Π°Π½Π° Π²ΠΎΡΠΏΠΎΠ»Π½ΠΈΡΡ Π½Π΅Π΄ΠΎΡΡΠ°ΡΠΊΠΈ ΠΌΠ½ΠΎΠ³ΠΎΡΠΈΡΠ»Π΅Π½Π½ΡΡ ΠΌΠ°ΡΠ΅ΡΠΈΠ°Π»ΠΎΠ² ΠΏΠΎ XDP. ΠΠΎ-ΠΏΠ΅ΡΠ²ΡΡ , Π² Π½ΠΈΡ Π΄Π°Π΅ΡΡΡ Π³ΠΎΡΠΎΠ²ΡΠΉ ΠΊΠΎΠ΄, ΠΊΠΎΡΠΎΡΡΠΉ ΡΡΠ°Π·Ρ ΠΎΠ±Ρ ΠΎΠ΄ΠΈΡ ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡΠΈ XDP: ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²Π»Π΅Π½ Π΄Π»Ρ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ ΠΈΠ»ΠΈ ΡΠ»ΠΈΡΠΊΠΎΠΌ ΠΏΡΠΎΡΡ, ΡΡΠΎΠ±Ρ Π²ΡΠ·Π²Π°ΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ. ΠΡΠΈ ΠΏΠΎΠΏΡΡΠΊΠ΅ ΠΏΠΎΡΠΎΠΌ Π½Π°ΠΏΠΈΡΠ°ΡΡ ΡΠ²ΠΎΠΉ ΠΊΠΎΠ΄ Ρ Π½ΡΠ»Ρ Π½Π΅Ρ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΡ, ΡΡΠΎ Π΄Π΅Π»Π°ΡΡ ΡΒ Ρ Π°ΡΠ°ΠΊΡΠ΅ΡΠ½ΡΠΌΠΈ ΠΎΡΠΈΠ±ΠΊΠ°ΠΌΠΈ. ΠΠΎ-Π²ΡΠΎΡΡΡ , Π½Π΅Β ΠΎΡΠ²Π΅ΡΠ°ΡΡΡΡ ΡΠΏΠΎΡΠΎΠ±Ρ Π»ΠΎΠΊΠ°Π»ΡΠ½ΠΎ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ XDP Π±Π΅Π· ΠΠ ΠΈ Β«ΠΆΠ΅Π»Π΅Π·Π°Β», ΠΏΡΠΈ ΡΠΎΠΌ, ΡΡΠΎΒ ΡΒ Π½ΠΈΡ ΡΠ²ΠΎΠΈ Β«ΠΏΠΎΠ΄Π²ΠΎΠ΄Π½ΡΠ΅ ΠΊΠ°ΠΌΠ½ΠΈΒ». Π’Π΅ΠΊΡΡ ΡΠ°ΡΡΡΠΈΡΠ°Π½ Π½Π°Β ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΡΠΎΠ², Π·Π½Π°ΠΊΠΎΠΌΡΡ ΡΒ ΡΠ΅ΡΡΠΌΠΈ ΠΈΒ Linux, ΠΊΠΎΡΠΎΡΡΠΌ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ΅Π½ XDP ΠΈΒ eBPF.
ΠΒ ΡΡΠΎΠΉ ΡΠ°ΡΡΠΈ Π΄Π΅ΡΠ°Π»ΡΠ½ΠΎ ΡΠ°Π·Π±Π΅ΡΠ΅ΠΌΡΡ, ΠΊΠ°ΠΊ ΡΠΎΠ±ΠΈΡΠ°Π΅ΡΡΡ XDP-ΡΠΈΠ»ΡΡΡ ΠΈ ΠΊΠ°ΠΊ Π΅Π³ΠΎ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ, Π·Π°ΡΠ΅ΠΌ Π½Π°ΠΏΠΈΡΠ΅ΠΌ ΠΏΡΠΎΡΡΠΎΠΉ Π²Π°ΡΠΈΠ°Π½Ρ ΠΈΠ·Π²Π΅ΡΡΠ½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ
Π°Π½ΠΈΠ·ΠΌΠ° SYN cookies Π½Π°Β ΡΡΠΎΠ²Π½Π΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ². ΠΠΎΠΊΠ° Π½Π΅Β Π±ΡΠ΄Π΅ΠΌ ΡΠΎΡΠΌΠΈΡΠΎΠ²Π°ΡΡ Β«Π±Π΅Π»ΡΠΉ ΡΠΏΠΈΡΠΎΠΊΒ»
ΠΏΡΠΎΠ²Π΅ΡΠ΅Π½Π½ΡΡ
ΠΊΠ»ΠΈΠ΅Π½ΡΠΎΠ², Π²Π΅ΡΡΠΈ ΡΡΠ΅ΡΡΠΈΠΊΠΈ ΠΈΒ ΡΠΏΡΠ°Π²Π»ΡΡΡ ΡΠΈΠ»ΡΡΡΠΎΠΌΒ β Ρ
Π²Π°ΡΠΈΡ Π»ΠΎΠ³ΠΎΠ².
ΠΠΈΡΠ°ΡΡ Π±ΡΠ΄Π΅ΠΌ Π½Π°Β CΒ β ΡΡΠΎ Π½Π΅Β ΠΌΠΎΠ΄Π½ΠΎ, Π·Π°ΡΠΎ ΠΏΡΠ°ΠΊΡΠΈΡΠ½ΠΎ. ΠΠ΅ΡΡ ΠΊΠΎΠ΄ Π΄ΠΎΡΡΡΠΏΠ΅Π½ Π½Π°Β GitHub ΠΏΠΎΒ ΡΡΡΠ»ΠΊΠ΅ Π²Β ΠΊΠΎΠ½ΡΠ΅ ΠΈΒ ΡΠ°Π·Π±ΠΈΡ Π½Π°Β ΠΊΠΎΠΌΠΌΠΈΡΡ ΠΏΠΎΒ ΡΡΠ°ΠΏΠ°ΠΌ, ΠΎΠΏΠΈΡΠ°Π½Π½ΡΠΌ Π²Β ΡΡΠ°ΡΡΠ΅.
Disclaimer. ΠΒ Ρ ΠΎΠ΄Π΅ ΡΡΠ°ΡΡΠΈ Π±ΡΠ΄Π΅Ρ ΡΠ°Π·ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ ΠΌΠΈΠ½ΠΈ-ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π΄Π»ΡΒ ΠΎΡΡΠ°ΠΆΠ΅Π½ΠΈΡ ΠΎΡΒ DDoS-Π°ΡΠ°ΠΊ, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ ΡΡΠΎ ΡΠ΅Π°Π»ΠΈΡΡΠΈΡΠ½Π°Ρ Π·Π°Π΄Π°ΡΠ° Π΄Π»ΡΒ XDP ΠΈΒ ΠΌΠΎΡ ΠΎΠ±Π»Π°ΡΡΡ. ΠΠ΄Π½Π°ΠΊΠΎ Π³Π»Π°Π²Π½Π°Ρ ΡΠ΅Π»ΡΒ β ΡΠ°Π·ΠΎΠ±ΡΠ°ΡΡΡΡ ΡΒ ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠ΅ΠΉ, ΡΡΠΎ Π½Π΅Β ΡΡΠΊΠΎΠ²ΠΎΠ΄ΡΡΠ²ΠΎ ΠΏΠΎΒ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ Π³ΠΎΡΠΎΠ²ΠΎΠΉ Π·Π°ΡΠΈΡΡ. Π£ΡΠ΅Π±Π½ΡΠΉ ΠΊΠΎΠ΄ Π½Π΅Β ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠΎΠ²Π°Π½ ΠΈΒ ΠΎΠΏΡΡΠΊΠ°Π΅Ρ Π½Π΅ΠΊΠΎΡΠΎΡΡΠ΅ Π½ΡΠ°Π½ΡΡ.
ΠΡΠ°ΡΠΊΠΈΠΉ ΠΎΠ±Π·ΠΎΡ XDP
ΠΠ·Π»ΠΎΠΆΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΊΠ»ΡΡΠ΅Π²ΡΠ΅ ΠΌΠΎΠΌΠ΅Π½ΡΡ, ΡΡΠΎΠ±Ρ Π½Π΅ Π΄ΡΠ±Π»ΠΈΡΠΎΠ²Π°ΡΡ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ ΠΈΒ ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠΈΠ΅ ΡΡΠ°ΡΡΠΈ.
ΠΡΠ°ΠΊ, Π² ΡΠ΄ΡΠΎ Π·Π°Π³ΡΡΠΆΠ°Π΅ΡΡΡ ΠΊΠΎΠ΄ ΡΠΈΠ»ΡΡΡΠ°. Π€ΠΈΠ»ΡΡΡΡ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΡΡ Π²Ρ
ΠΎΠ΄ΡΡΠΈΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ. ΠΒ ΠΈΡΠΎΠ³Π΅ ΡΠΈΠ»ΡΡΡ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΡΠΈΠ½ΡΡΡ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅: ΠΏΡΠΎΠΏΡΡΡΠΈΡΡ ΠΏΠ°ΠΊΠ΅Ρ Π²Β ΡΠ΄ΡΠΎ (XDP_PASS
), ΡΠ±ΡΠΎΡΠΈΡΡ ΠΏΠ°ΠΊΠ΅Ρ (XDP_DROP
) ΠΈΠ»ΠΈΒ ΠΎΡΠΏΡΠ°Π²ΠΈΡΡ Π΅Π³ΠΎΒ ΠΎΠ±ΡΠ°ΡΠ½ΠΎ (XDP_TX
). Π€ΠΈΠ»ΡΡΡ ΠΌΠΎΠΆΠ΅Ρ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡΡ ΠΏΠ°ΠΊΠ΅Ρ, ΡΡΠΎ ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎ Π°ΠΊΡΡΠ°Π»ΡΠ½ΠΎ Π΄Π»ΡΒ XDP_TX
. Π’Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ½ΠΎ Π°Π²Π°ΡΠΈΠΉΠ½ΠΎ ΠΏΡΠ΅ΡΠ²Π°ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ (XDP_ABORTED
) ΠΈΒ ΡΠ±ΡΠΎΡΠΈΡΡ ΠΏΠ°ΠΊΠ΅Ρ, Π½ΠΎΒ ΡΡΠΎ Π°Π½Π°Π»ΠΎΠ³ assert(0)
Β β Π΄Π»ΡΒ ΠΎΡΠ»Π°Π΄ΠΊΠΈ.
ΠΠΈΡΡΡΠ°Π»ΡΠ½Π°Ρ ΠΌΠ°ΡΠΈΠ½Π° eBPF (extended Berkley Packet Filter) ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΠΎ ΡΠ΄Π΅Π»Π°Π½Π° ΠΏΡΠΎΡΡΠΎΠΉ, Π΄Π°Π±Ρ ΡΠ΄ΡΠΎ ΠΌΠΎΠ³Π»ΠΎ ΠΏΡΠΎΠ²Π΅ΡΠΈΡΡ, ΡΡΠΎ ΠΊΠΎΠ΄ Π½Π΅Β Π·Π°ΡΠΈΠΊΠ»ΠΈΠ²Π°Π΅ΡΡΡ ΠΈΒ Π½Π΅Β ΠΏΠΎΠ²ΡΠ΅ΠΆΠ΄Π°Π΅Ρ ΡΡΠΆΡΡ ΠΏΠ°ΠΌΡΡΡ. Π‘ΠΎΠ²ΠΎΠΊΡΠΏΠ½ΡΠ΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΡ ΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ:
- ΠΠ°ΠΏΡΠ΅ΡΠ΅Π½Ρ ΡΠΈΠΊΠ»Ρ (ΠΏΠ΅ΡΠ΅Ρ ΠΎΠ΄Ρ Π½Π°Π·Π°Π΄).
- ΠΡΡΡ ΡΡΠ΅ΠΊ Π΄Π»Ρ Π΄Π°Π½Π½ΡΡ , Π½ΠΎ Π½Π΅Ρ ΡΡΠ½ΠΊΡΠΈΠΉ (Π²ΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ C Π΄ΠΎΠ»ΠΆΠ½Ρ Π²ΡΡΡΠ°ΠΈΠ²Π°ΡΡΡΡ).
- ΠΠ°ΠΏΡΠ΅ΡΠ΅Π½Ρ ΠΎΠ±ΡΠ°ΡΠ΅Π½ΠΈΡ ΠΊ ΠΏΠ°ΠΌΡΡΠΈ Π·Π° ΠΏΡΠ΅Π΄Π΅Π»Π°ΠΌΠΈ ΡΡΠ΅ΠΊΠ° ΠΈ Π±ΡΡΠ΅ΡΠ° ΠΏΠ°ΠΊΠ΅ΡΠ°.
- Π Π°Π·ΠΌΠ΅Ρ ΠΊΠΎΠ΄Π° ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½, Π½ΠΎ Π½Π°Β ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅ ΡΡΠΎ Π½Π΅Β ΠΎΡΠ΅Π½Ρ ΡΡΡΠ΅ΡΡΠ²Π΅Π½Π½ΠΎ.
- Π Π°Π·ΡΠ΅ΡΠ΅Π½Ρ Π²ΡΠ·ΠΎΠ²Ρ ΡΠΎΠ»ΡΠΊΠΎ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΡ ΡΡΠ½ΠΊΡΠΈΠΉ ΡΠ΄ΡΠ° (eBPF helpers).
Π Π°Π·ΡΠ°Π±ΠΎΡΠΊΠ° ΠΈ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΡΠΈΠ»ΡΡΡΠ° Π²ΡΠ³Π»ΡΠ΄ΡΡ ΡΠ°ΠΊ:
- ΠΡΡ
ΠΎΠ΄Π½ΡΠΉ ΠΊΠΎΠ΄ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ,
kernel.c
) ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡΡΠ΅ΡΡΡ Π² ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΡΠΉ (kernel.o
) ΠΏΠΎΠ΄Β Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΠΎΠΉ ΠΌΠ°ΡΠΈΠ½Ρ eBPF. ΠΠ°Β ΠΎΠΊΡΡΠ±ΡΡ 2019 ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΡ Π²Β eBPF ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΡΡΡ Clang ΠΈΒ ΠΎΠ±Π΅ΡΠ°Π½Π° Π²Β GCCΒ 10.1. - ΠΡΠ»ΠΈ Π²Β ΡΡΠΎΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΠΎΠΌ ΠΊΠΎΠ΄Π΅ Π΅ΡΡΡ ΠΎΠ±ΡΠ°ΡΠ΅Π½ΠΈΡ ΠΊΒ ΡΡΡΡΠΊΡΡΡΠ°ΠΌ ΡΠ΄ΡΠ° (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΊ ΡΠ°Π±Π»ΠΈΡΠ°ΠΌ ΠΈ ΡΡΠ΅ΡΡΠΈΠΊΠ°ΠΌ), Π²ΠΌΠ΅ΡΡΠΎ ΠΈΡ ID ΡΡΠΎΡΡ Π½ΡΠ»ΠΈ, ΡΠΎΒ Π΅ΡΡΡ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ ΡΠ°ΠΊΠΎΠΉ ΠΊΠΎΠ΄ Π½Π΅Π»ΡΠ·Ρ. ΠΠ΅ΡΠ΅Π΄ Π·Π°Π³ΡΡΠ·ΠΊΠΎΠΉ Π²Β ΡΠ΄ΡΠΎ Π½ΡΠΆΠ½ΠΎ ΡΡΠΈ Π½ΡΠ»ΠΈ Π·Π°ΠΌΠ΅Π½ΠΈΡΡ Π½Π°Β ID ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ², ΡΠΎΠ·Π΄Π°Π½Π½ΡΡ ΡΠ΅ΡΠ΅Π· Π²ΡΠ·ΠΎΠ²Ρ ΡΠ΄ΡΠ° (ΡΠ»ΠΈΠ½ΠΊΠΎΠ²Π°ΡΡ ΠΊΠΎΠ΄). ΠΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ ΡΡΠΎ Π²Π½Π΅ΡΠ½ΠΈΠΌΠΈ ΡΡΠΈΠ»ΠΈΡΠ°ΠΌΠΈ, Π°Β ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΏΠΈΡΠ°ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, ΠΊΠΎΡΠΎΡΠ°Ρ Π±ΡΠ΄Π΅Ρ Π»ΠΈΠ½ΠΊΠΎΠ²Π°ΡΡ ΠΈΒ Π·Π°Π³ΡΡΠΆΠ°ΡΡ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠΉ ΡΠΈΠ»ΡΡΡ.
- Π―Π΄ΡΠΎ Π²Π΅ΡΠΈΡΠΈΡΠΈΡΡΠ΅Ρ Π·Π°Π³ΡΡΠΆΠ°Π΅ΠΌΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ. ΠΡΠΎΠ²Π΅ΡΡΠ΅ΡΡΡ ΠΎΡΡΡΡΡΡΠ²ΠΈΠ΅ ΡΠΈΠΊΠ»ΠΎΠ² ΠΈΒ Π½Π΅Π²ΡΡ ΠΎΠ΄ Π·Π°Β Π³ΡΠ°Π½ΠΈΡΡ ΠΏΠ°ΠΊΠ΅ΡΠ° ΠΈΒ ΡΡΠ΅ΠΊΠ°. ΠΡΠ»ΠΈ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ Π½Π΅Β ΠΌΠΎΠΆΠ΅Ρ Π΄ΠΎΠΊΠ°Π·Π°ΡΡ, ΡΡΠΎΒ ΠΊΠΎΠ΄ ΠΊΠΎΡΡΠ΅ΠΊΡΠ΅Π½, ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° ΠΎΡΠ²Π΅ΡΠ³Π°Π΅ΡΡΡ,Β β Π½Π°Π΄ΠΎ ΡΠΌΠ΅ΡΡ ΡΠ±Π»Π°ΠΆΠ°ΡΡ Π΅Π³ΠΎ.
- ΠΠΎΡΠ»Π΅ ΡΡΠΏΠ΅ΡΠ½ΠΎΠΉ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ ΡΠ΄ΡΠΎ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡΡΠ΅Ρ ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΡΠΉ ΠΊΠΎΠ΄ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ eBPF Π²Β ΠΌΠ°ΡΠΈΠ½Π½ΡΠΉ ΠΊΠΎΠ΄ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠΉ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ (just-in-time).
- ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° ΠΏΡΠΈΠΊΡΠ΅ΠΏΠ»ΡΠ΅ΡΡΡ ΠΊΒ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ ΠΈΒ Π½Π°ΡΠΈΠ½Π°Π΅Ρ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ ΠΏΠ°ΠΊΠ΅ΡΡ.
ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ XDP ΡΠ°Π±ΠΎΡΠ°Π΅Ρ Π²Β ΡΠ΄ΡΠ΅, ΠΎΡΠ»Π°Π΄ΠΊΠ° Π²Π΅Π΄Π΅ΡΡΡ ΠΏΠΎΒ Π»ΠΎΠ³Π°ΠΌ ΡΡΠ°ΡΡΠΈΡΠΎΠ²ΠΊΠΈ ΠΈ,Β ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ, ΠΏΠΎΒ ΠΏΠ°ΠΊΠ΅ΡΠ°ΠΌ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° ΡΠΈΠ»ΡΡΡΡΠ΅Ρ ΠΈΠ»ΠΈΒ Π³Π΅Π½Π΅ΡΠΈΡΡΠ΅Ρ. Π’Π΅ΠΌ Π½Π΅Β ΠΌΠ΅Π½Π΅Π΅, eBPF ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°Π΅Ρ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΡ Π·Π°Π³ΡΡΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π° Π΄Π»ΡΒ ΡΠΈΡΡΠ΅ΠΌΡ, ΠΏΠΎΡΡΠΎΠΌΡ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΠΈΡΠΎΠ²Π°ΡΡ ΡΒ XDP ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡΡΠΌΠΎ Π½Π°Β Π»ΠΎΠΊΠ°Π»ΡΠ½ΠΎΠΌ Linux.
ΠΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠ° ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ
Π‘Π±ΠΎΡΠΊΠ°
Clang Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π½Π°ΠΏΡΡΠΌΡΡ Π²ΡΠ΄Π°Π²Π°ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΡΠΉ ΠΊΠΎΠ΄ Π΄Π»ΡΒ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ eBPF, ΠΏΠΎΡΡΠΎΠΌΡ ΠΏΡΠΎΡΠ΅ΡΡ ΡΠΎΡΡΠΎΠΈΡ ΠΈΠ·Β Π΄Π²ΡΡ ΡΠ°Π³ΠΎΠ²:
- Π‘ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡΠΎΠ²Π°ΡΡ ΠΊΠΎΠ΄ Π½Π°Β C Π²Β Π±Π°ΠΉΡ-ΠΊΠΎΠ΄ LLVM (
clang -emit-llvm
). - ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°ΡΡ Π±Π°ΠΉΡ-ΠΊΠΎΠ΄ Π²Β ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΡΠΉ ΠΊΠΎΠ΄ eBPF (
llc -march=bpf -filetype=obj
).
ΠΡΠΈΒ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΠΈ ΡΠΈΠ»ΡΡΡΠ° ΠΏΡΠΈΠ³ΠΎΠ΄ΠΈΡΡΡ ΠΏΠ°ΡΠ° ΡΠ°ΠΉΠ»ΠΎΠ² ΡΠΎΒ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°ΡΠ΅Π»ΡΠ½ΡΠΌΠΈ ΡΡΠ½ΠΊΡΠΈΡΠΌΠΈ ΠΈΒ ΠΌΠ°ΠΊΡΠΎΡΠ°ΠΌΠΈ KVER
). ΠΠ°ΡΠ°Π΅ΠΌ ΠΈΡ
Π²Β helpers/
:
export KVER=v5.3.7
export BASE=https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/plain/tools/testing/selftests/bpf
wget -P helpers --content-disposition "${BASE}/bpf_helpers.h?h=${KVER}" "${BASE}/bpf_endian.h?h=${KVER}"
unset KVER BASE
Makefile Π΄Π»ΡΒ Arch Linux (ΡΠ΄ΡΠΎ 5.3.7):
CLANG ?= clang
LLC ?= llc
KDIR ?= /lib/modules/$(shell uname -r)/build
ARCH ?= $(subst x86_64,x86,$(shell uname -m))
CFLAGS =
-Ihelpers
-I$(KDIR)/include
-I$(KDIR)/include/uapi
-I$(KDIR)/include/generated/uapi
-I$(KDIR)/arch/$(ARCH)/include
-I$(KDIR)/arch/$(ARCH)/include/generated
-I$(KDIR)/arch/$(ARCH)/include/uapi
-I$(KDIR)/arch/$(ARCH)/include/generated/uapi
-D__KERNEL__
-fno-stack-protector -O2 -g
xdp_%.o: xdp_%.c Makefile
$(CLANG) -c -emit-llvm $(CFLAGS) $< -o - |
$(LLC) -march=bpf -filetype=obj -o $@
.PHONY: all clean
all: xdp_filter.o
clean:
rm -f ./*.o
KDIR
ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΏΡΡΡ ΠΊΒ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°ΠΌ ΡΠ΄ΡΠ°, ARCH
Β β Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΡ ΡΠΈΡΡΠ΅ΠΌΡ. ΠΡΡΠΈ ΠΈΒ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ ΠΌΠΎΠ³ΡΡ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΡΠ»ΠΈΡΠ°ΡΡΡΡ ΠΌΠ΅ΠΆΠ΄Ρ Π΄ΠΈΡΡΡΠΈΠ±ΡΡΠΈΠ²Π°ΠΌΠΈ.
ΠΡΠΈΠΌΠ΅Ρ ΠΎΡΠ»ΠΈΡΠΈΠΉ Π΄Π»Ρ Debian 10 (ΡΠ΄ΡΠΎ 4.19.67)
# Π΄ΡΡΠ³Π°Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π°
CLANG ?= clang
LLC ?= llc-7
# Π΄ΡΡΠ³ΠΎΠΉ ΠΊΠ°ΡΠ°Π»ΠΎΠ³
KDIR ?= /usr/src/linux-headers-$(shell uname -r)
ARCH ?= $(subst x86_64,x86,$(shell uname -m))
# Π΄Π²Π° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΡ
ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π° -I
CFLAGS =
-Ihelpers
-I/usr/src/linux-headers-4.19.0-6-common/include
-I/usr/src/linux-headers-4.19.0-6-common/arch/$(ARCH)/include
# Π΄Π°Π»Π΅Π΅ Π±Π΅Π· ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ
CFLAGS
ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ°ΡΡ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡ ΡΠΎΒ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°ΡΠ΅Π»ΡΠ½ΡΠΌΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°ΠΌΠΈ ΠΈΒ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΠΉ ΡΒ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°ΠΌΠΈ ΡΠ΄ΡΠ°. Π‘ΠΈΠΌΠ²ΠΎΠ» __KERNEL__
ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ, ΡΡΠΎΒ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ UAPI (userspace API) ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡΡΡΡ Π΄Π»ΡΒ ΠΊΠΎΠ΄Π° ΡΠ΄ΡΠ°, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΡΠΈΠ»ΡΡΡ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ Π²Β ΡΠ΄ΡΠ΅.
ΠΠ°ΡΠΈΡΡ ΡΡΠ΅ΠΊΠ° ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡΠΊΠ»ΡΡΠΈΡΡ (-fno-stack-protector
), ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΊΠΎΠ΄Π° eBPF Π²ΡΠ΅ ΡΠ°Π²Π½ΠΎ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅Ρ Π½Π΅Π²ΡΡ
ΠΎΠ΄ Π·Π° Π³ΡΠ°Π½ΠΈΡΡ ΡΡΠ΅ΠΊΠ°. Π‘ΡΠ°Π·Ρ ΡΡΠΎΠΈΡ Π²ΠΊΠ»ΡΡΠΈΡΡ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ ΡΠ°Π·ΠΌΠ΅Ρ Π±Π°ΠΉΡ-ΠΊΠΎΠ΄Π° eBPF ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½.
ΠΠ°ΡΠ½Π΅ΠΌ Ρ ΡΠΈΠ»ΡΡΡΠ°, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΡΠΎΠΏΡΡΠΊΠ°Π΅Ρ Π²ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ ΠΈ Π½ΠΈΡΠ΅Π³ΠΎ Π½Π΅Β Π΄Π΅Π»Π°Π΅Ρ:
#include <uapi/linux/bpf.h>
#include <bpf_helpers.h>
SEC("prog")
int xdp_main(struct xdp_md* ctx) {
return XDP_PASS;
}
char _license[] SEC("license") = "GPL";
ΠΠΎΠΌΠ°Π½Π΄Π° make
ΡΠΎΠ±ΠΈΡΠ°Π΅Ρ xdp_filter.o
. ΠΠ΄Π΅ Π΅Π³ΠΎ ΡΠ΅ΠΏΠ΅ΡΡ ΠΈΡΠΏΡΡΠ°ΡΡ?
Π’Π΅ΡΡΠΎΠ²ΡΠΉ ΡΡΠ΅Π½Π΄
Π‘ΡΠ΅Π½Π΄ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²ΠΊΠ»ΡΡΠ°ΡΡ Π΄Π²Π° ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°: Π½Π°Β ΠΊΠΎΡΠΎΡΠΎΠΌ Π±ΡΠ΄Π΅Ρ ΡΠΈΠ»ΡΡΡ ΠΈΒ ΡΒ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ Π±ΡΠ΄ΡΡ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ ΠΏΠ°ΠΊΠ΅ΡΡ. ΠΡΠΎ Π΄ΠΎΠ»ΠΆΠ½Ρ Π±ΡΡΡ ΠΏΠΎΠ»Π½ΠΎΡΠ΅Π½Π½ΡΠ΅ ΡΡΡΡΠΎΠΉΡΡΠ²Π° Linux ΡΠΎΒ ΡΠ²ΠΎΠΈΠΌΠΈ IP, ΡΡΠΎΠ±Ρ ΠΏΡΠΎΠ²Π΅ΡΡΡΡ, ΠΊΠ°ΠΊΒ ΠΎΠ±ΡΡΠ½ΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΡΒ Π½Π°ΡΠΈΠΌ ΡΠΈΠ»ΡΡΡΠΎΠΌ.
Π£ΡΡΡΠΎΠΉΡΡΠ²Π° ΡΠΈΠΏΠ° veth (virtual Ethernet) Π½Π°ΠΌ ΠΏΠΎΠ΄Ρ
ΠΎΠ΄ΡΡ: ΡΡΠΎ ΠΏΠ°ΡΠ° Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΡΡ
ΡΠ΅ΡΠ΅Π²ΡΡ
ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ², Β«ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½Π½ΡΡ
Β» ΠΌΠ΅ΠΆΠ΄Ρ ΡΠΎΠ±ΠΎΠΉ Π½Π°ΠΏΡΡΠΌΡΡ. Π‘ΠΎΠ·Π΄Π°ΡΡ ΠΈΡ
ΠΌΠΎΠΆΠ½ΠΎ ΡΠ°ΠΊ (Π²Β ΡΡΠΎΠΌ ΡΠ°Π·Π΄Π΅Π»Π΅ Π²ΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ ip
Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ ΠΎΡΒ root
):
ip link add xdp-remote type veth peer name xdp-local
ΠΠ΄Π΅ΡΡ xdp-remote
ΠΈΒ xdp-local
Β β ΠΈΠΌΠ΅Π½Π° ΡΡΡΡΠΎΠΉΡΡΠ². ΠΠ°Β xdp-local
(192.0.2.1/24) Π±ΡΠ΄Π΅Ρ ΠΏΡΠΈΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ ΡΠΈΠ»ΡΡΡ, ΡΒ xdp-remote
(192.0.2.2/24) Π±ΡΠ΄Π΅Ρ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ Π²Ρ
ΠΎΠ΄ΡΡΠΈΠΉ ΡΡΠ°ΡΠΈΠΊ. ΠΠ΄Π½Π°ΠΊΠΎ Π΅ΡΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°: ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ Π½Π°Ρ
ΠΎΠ΄ΡΡΡΡ Π½Π°Β ΠΎΠ΄Π½ΠΎΠΉ ΠΌΠ°ΡΠΈΠ½Π΅, ΠΈΒ Linux Π½Π΅Β Π±ΡΠ΄Π΅Ρ ΡΠ»Π°ΡΡ ΡΡΠ°ΡΠΈΠΊ Π½Π°Β ΠΎΠ΄ΠΈΠ½ ΠΈΠ·Β Π½ΠΈΡ
ΡΠ΅ΡΠ΅Π· Π΄ΡΡΠ³ΠΎΠΉ. ΠΠΎΠΆΠ½ΠΎ ΡΠ΅ΡΠ°ΡΡ ΡΡΠΎ Ρ
ΠΈΡΡΡΠΌΠΈ ΠΏΡΠ°Π²ΠΈΠ»Π°ΠΌΠΈ iptables
, Π½ΠΎΒ ΠΈΠΌ ΠΏΡΠΈΠ΄Π΅ΡΡΡ ΠΌΠ΅Π½ΡΡΡ ΠΏΠ°ΠΊΠ΅ΡΡ, ΡΡΠΎΒ Π½Π΅ΡΠ΄ΠΎΠ±Π½ΠΎ ΠΏΡΠΈΒ ΠΎΡΠ»Π°Π΄ΠΊΠ΅. ΠΡΡΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠ΅ΡΠ΅Π²ΡΠ΅ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π° ΠΈΠΌΠ΅Π½ (network namespaces, Π΄Π°Π»Π΅Π΅ netns).
Π‘Π΅ΡΠ΅Π²ΠΎΠ΅ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²ΠΎ ΠΈΠΌΠ΅Π½ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ Π½Π°Π±ΠΎΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ², ΡΠ°Π±Π»ΠΈΡ ΠΌΠ°ΡΡΡΡΡΠΈΠ·Π°ΡΠΈΠΈ ΠΈΒ ΠΏΡΠ°Π²ΠΈΠ» NetFilter, ΠΈΠ·ΠΎΠ»ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΠΎΡΒ Π°Π½Π°Π»ΠΎΠ³ΠΈΡΠ½ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Π²Β Π΄ΡΡΠ³ΠΈΡ netns. ΠΠ°ΠΆΠ΄ΡΠΉ ΠΏΡΠΎΡΠ΅ΡΡ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ Π²Β ΠΊΠ°ΠΊΠΎΠΌ-ΡΠΎ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅ ΠΈΠΌΠ΅Π½, ΠΈΒ Π΅ΠΌΡ Π΄ΠΎΡΡΡΠΏΠ½Ρ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΡ ΡΡΠΎΠ³ΠΎ netns. ΠΠΎΒ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ Π²Β ΡΠΈΡΡΠ΅ΠΌΠ΅ Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΠΎΠ΅ ΡΠ΅ΡΠ΅Π²ΠΎΠ΅ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²ΠΎ ΠΈΠΌΠ΅Π½ Π΄Π»Ρ Π²ΡΠ΅Ρ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ², ΠΏΠΎΡΡΠΎΠΌΡ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π²Β Linux ΠΈΒ Π½Π΅Β Π·Π½Π°ΡΡ ΠΏΡΠΎΒ netns.
Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ Π½ΠΎΠ²ΠΎΠ΅ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²ΠΎ ΠΈΠΌΠ΅Π½ xdp-test
ΠΈΒ ΠΏΠ΅ΡΠ΅ΠΌΠ΅ΡΡΠΈΠΌ ΡΡΠ΄Π° xdp-remote
.
ip netns add xdp-test
ip link set dev xdp-remote netns xdp-test
Π’ΠΎΠ³Π΄Π° ΠΏΡΠΎΡΠ΅ΡΡ, Π²ΡΠΏΠΎΠ»Π½ΡΡΡΠΈΠΉΡΡ Π²Β xdp-test
, Π½Π΅Β Π±ΡΠ΄Π΅Ρ Β«Π²ΠΈΠ΄Π΅ΡΡΒ» xdp-local
(ΠΎΠ½ ΠΎΡΡΠ°Π½Π΅ΡΡΡ Π²Β netns ΠΏΠΎΒ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ) ΠΈΒ ΠΏΡΠΈΒ ΠΎΡΠΏΡΠ°Π²ΠΊΠ΅ ΠΏΠ°ΠΊΠ΅ΡΠ° Π½Π°Β 192.0.2.1 ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ Π΅Π³ΠΎ ΡΠ΅ΡΠ΅Π·Β xdp-remote
, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ ΡΡΠΎ Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΡΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π²Β 192.0.2.0/24, Π΄ΠΎΡΡΡΠΏΠ½ΡΠΉ ΡΡΠΎΠΌΡ ΠΏΡΠΎΡΠ΅ΡΡΡ. ΠΡΠΎ Π΄Π΅ΠΉΡΡΠ²ΡΠ΅Ρ ΠΈΒ Π²Β ΠΎΠ±ΡΠ°ΡΠ½ΡΡ ΡΡΡΠΎΠ½Ρ.
ΠΡΠΈΒ ΠΏΠ΅ΡΠ΅ΠΌΠ΅ΡΠ΅Π½ΠΈΠΈ ΠΌΠ΅ΠΆΠ΄Ρ netns ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ΠΎΠΏΡΡΠΊΠ°Π΅ΡΡΡ ΠΈΒ ΡΠ΅ΡΡΠ΅Ρ Π°Π΄ΡΠ΅Ρ. Π§ΡΠΎΠ±Ρ Π½Π°ΡΡΡΠΎΠΈΡΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π²Β netns, Π½ΡΠΆΠ½ΠΎ Π·Π°ΠΏΡΡΡΠΈΡΡ ip ...
Π²Β ΡΡΠΎΠΌ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅ ΠΈΠΌΠ΅Π½ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ ip netns exec
:
ip netns exec xdp-test
ip address add 192.0.2.2/24 dev xdp-remote
ip netns exec xdp-test
ip link set xdp-remote up
ΠΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΈΠ΄Π΅ΡΡ, ΡΡΠΎ Π½Π΅Β ΠΎΡΠ»ΠΈΡΠ°Π΅ΡΡΡ ΠΎΡΒ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ xdp-local
Π²Β ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅ ΠΈΠΌΠ΅Π½ ΠΏΠΎΒ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ:
ip address add 192.0.2.1/24 dev xdp-local
ip link set xdp-local up
ΠΡΠ»ΠΈ Π·Π°ΠΏΡΡΡΠΈΡΡ tcpdump -tnevi xdp-local
, ΠΌΠΎΠΆΠ½ΠΎ ΡΠ²ΠΈΠ΄Π΅ΡΡ, ΡΡΠΎΒ ΠΏΠ°ΠΊΠ΅ΡΡ, ΠΎΡΠΏΡΠ°Π²Π»Π΅Π½Π½ΡΠ΅ ΠΈΠ·Β xdp-test
, Π΄ΠΎΡΡΠ°Π²Π»ΡΡΡΡΡ Π½Π°Β ΡΡΠΎΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ:
ip netns exec xdp-test ping 192.0.2.1
Π£Π΄ΠΎΠ±Π½ΠΎ Π·Π°ΠΏΡΡΡΠΈΡΡ ΡΠ΅Π»Π» Π²Β xdp-test
. ΠΒ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠ°ΡΠΈΠΈ Π΅ΡΡΡ ΡΠΊΡΠΈΠΏΡ, Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΡΡΡΠΈΠΉ ΡΠ°Π±ΠΎΡΡ ΡΠΎΒ ΡΡΠ΅Π½Π΄ΠΎΠΌ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΡΡΡΠΎΠΈΡΡ ΡΡΠ΅Π½Π΄ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ sudo ./stand up
ΠΈΒ ΡΠ΄Π°Π»ΠΈΡΡ Π΅Π³ΠΎ sudo ./stand down
.
Π’ΡΠ°ΡΡΠΈΡΠΎΠ²ΠΊΠ°
Π€ΠΈΠ»ΡΡΡ ΠΏΡΠΈΠ²ΡΠ·ΡΠ²Π°Π΅ΡΡΡ ΠΊΒ ΡΡΡΡΠΎΠΉΡΡΠ²Ρ ΡΠ°ΠΊ:
ip -force link set dev xdp-local xdp object xdp_filter.o verbose
ΠΠ»ΡΡ -force
Π½ΡΠΆΠ΅Π½, ΡΡΠΎΠ±Ρ ΠΏΡΠΈΠ²ΡΠ·Π°ΡΡ Π½ΠΎΠ²ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, Π΅ΡΠ»ΠΈ Π΄ΡΡΠ³Π°Ρ ΡΠΆΠ΅ ΠΏΡΠΈΠ²ΡΠ·Π°Π½Π°. Β«No news is good newsΒ» Π½Π΅Β ΠΏΡΠΎΒ ΡΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Ρ, Π²ΡΠ²ΠΎΠ΄ Π²Β Π»ΡΠ±ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ ΠΎΠ±ΡΠ΅ΠΌΠ½ΡΠΉ. Π£ΠΊΠ°Π·ΡΠ²Π°ΡΡ verbose
Π½Π΅ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ, Π½ΠΎΒ ΡΒ Π½ΠΈΠΌ ΠΏΠΎΡΠ²Π»ΡΠ΅ΡΡΡ ΠΎΡΡΠ΅Ρ ΠΎΒ ΡΠ°Π±ΠΎΡΠ΅ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠ° ΠΊΠΎΠ΄Π° ΡΒ Π»ΠΈΡΡΠΈΠ½Π³ΠΎΠΌ Π°ΡΡΠ΅ΠΌΠ±Π»Π΅ΡΠ°:
Verifier analysis:
0: (b7) r0 = 2
1: (95) exit
ΠΡΠ²ΡΠ·Π°ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΠΎΡΒ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°:
ip link set dev xdp-local xdp off
ΠΒ ΡΠΊΡΠΈΠΏΡΠ΅ ΡΡΠΎ ΠΊΠΎΠΌΠ°Π½Π΄Ρ sudo ./stand attach
ΠΈΒ sudo ./stand detach
.
ΠΡΠΈΠ²ΡΠ·Π°Π² ΡΠΈΠ»ΡΡΡ, ΠΌΠΎΠΆΠ½ΠΎ ΡΠ±Π΅Π΄ΠΈΡΡΡΡ, ΡΡΠΎΒ ping
ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡ, Π½ΠΎΒ ΡΠ°Π±ΠΎΡΠ°Π΅ΡΒ Π»ΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°? ΠΠΎΠ±Π°Π²ΠΈΠΌ Π»ΠΎΠ³ΠΈ. Π€ΡΠ½ΠΊΡΠΈΡ bpf_trace_printk()
printf()
, Π½ΠΎΒ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ Π²ΡΠ΅Π³ΠΎ Π΄ΠΎΒ ΡΡΠ΅Ρ
Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠΎΠ², ΠΊΡΠΎΠΌΠ΅ ΡΠ°Π±Π»ΠΎΠ½Π°, ΠΈΒ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½Π½ΡΠΉ ΡΠΏΠΈΡΠΎΠΊ ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΎΠ². ΠΠ°ΠΊΡΠΎΡ bpf_printk()
ΡΠΏΡΠΎΡΠ°Π΅Ρ Π²ΡΠ·ΠΎΠ².
SEC("prog")
int xdp_main(struct xdp_md* ctx) {
+ bpf_printk("got packet: %pn", ctx);
return XDP_PASS;
}
ΠΡΠ²ΠΎΠ΄ ΠΈΠ΄Π΅Ρ Π²Β ΠΊΠ°Π½Π°Π» ΡΡΠ°ΡΡΠΈΡΠΎΠ²ΠΊΠΈ ΡΠ΄ΡΠ°, ΠΊΠΎΡΠΎΡΡΠΉ Π½ΡΠΆΠ½ΠΎ Π²ΠΊΠ»ΡΡΠΈΡΡ:
echo -n 1 | sudo tee /sys/kernel/debug/tracing/options/trace_printk
ΠΡΠΎΡΠΌΠΎΡΡ ΠΏΠΎΡΠΎΠΊΠ° ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ:
cat /sys/kernel/debug/tracing/trace_pipe
ΠΠ±Π΅ ΡΡΠΈΡ
ΠΊΠΎΠΌΠ°Π½Π΄Ρ Π΄Π΅Π»Π°Π΅Ρ Π²ΡΠ·ΠΎΠ² sudo ./stand log
.
Ping ΡΠ΅ΠΏΠ΅ΡΡ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²ΡΠ·ΡΠ²Π°ΡΡ Π²Β Π½Π΅ΠΌ ΡΠ°ΠΊΠΈΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ:
<...>-110930 [004] ..s1 78803.244967: 0: got packet: 00000000ac510377
ΠΡΠ»ΠΈ ΠΏΡΠΈΡΠΌΠΎΡΡΠ΅ΡΡΡΡ ΠΊΒ Π²ΡΠ²ΠΎΠ΄Ρ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠ°, ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΌΠ΅ΡΠΈΡΡ ΡΡΡΠ°Π½Π½ΡΠ΅ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ:
0: (bf) r3 = r1
1: (18) r1 = 0xa7025203a7465
3: (7b) *(u64 *)(r10 -8) = r1
4: (18) r1 = 0x6b63617020746f67
6: (7b) *(u64 *)(r10 -16) = r1
7: (bf) r1 = r10
8: (07) r1 += -16
9: (b7) r2 = 16
10: (85) call bpf_trace_printk#6
<...>
ΠΠ΅Π»ΠΎ Π²Β ΡΠΎΠΌ, ΡΡΠΎΒ ΡΒ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ Π½Π°Β eBPF Π½Π΅Ρ ΡΠ΅ΠΊΡΠΈΠΈ Π΄Π°Π½Π½ΡΡ , ΠΏΠΎΡΡΠΎΠΌΡ Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΡΠΉ ΡΠΏΠΎΡΠΎΠ± Π·Π°ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°ΡΡ ΡΠΎΡΠΌΠ°ΡΠ½ΡΡ ΡΡΡΠΎΠΊΡΒ β immediate-Π°ΡΠ³ΡΠΌΠ΅Π½ΡΡ ΠΊΠΎΠΌΠ°Π½Π΄ ΠΠ:
$ python -c "import binascii; print(bytes(reversed(binascii.unhexlify('0a7025203a74656b63617020746f67'))))"
b'got packet: %pn'
ΠΠΎΒ ΡΡΠΎΠΉ ΠΏΡΠΈΡΠΈΠ½Π΅ ΠΎΡΠ»Π°Π΄ΠΎΡΠ½ΡΠΉ Π²ΡΠ²ΠΎΠ΄ ΡΠΈΠ»ΡΠ½ΠΎ ΡΠ°Π·Π΄ΡΠ²Π°Π΅Ρ ΠΈΡΠΎΠ³ΠΎΠ²ΡΠΉ ΠΊΠΎΠ΄.
ΠΡΠΏΡΠ°Π²ΠΊΠ° ΠΏΠ°ΠΊΠ΅ΡΠΎΠ² XDP
ΠΠ·ΠΌΠ΅Π½ΠΈΠΌ ΡΠΈΠ»ΡΡΡ: ΠΏΡΡΡΡ ΠΎΠ½ Π²ΡΠ΅ Π²Ρ ΠΎΠ΄ΡΡΠΈΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅Ρ ΠΎΠ±ΡΠ°ΡΠ½ΠΎ. ΠΡΠΎ Π½Π΅ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎ ΡΒ ΡΠ΅ΡΠ΅Π²ΠΎΠΉ ΡΠΎΡΠΊΠΈ Π·ΡΠ΅Π½ΠΈΡ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ Π½ΡΠΆΠ½ΠΎ Π±ΡΠ»ΠΎΒ Π±Ρ ΠΌΠ΅Π½ΡΡΡ Π°Π΄ΡΠ΅ΡΠ° Π²Β Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°Ρ , Π½ΠΎΒ ΡΠ΅ΠΉΡΠ°Ρ Π²Π°ΠΆΠ½Π° ΡΠ°Π±ΠΎΡΠ° Π²Β ΠΏΡΠΈΠ½ΡΠΈΠΏΠ΅.
bpf_printk("got packet: %pn", ctx);
- return XDP_PASS;
+ return XDP_TX;
}
ΠΠ°ΠΏΡΡΠΊΠ°Π΅ΠΌ tcpdump
Π½Π°Β xdp-remote
. ΠΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠΊΠ°Π·Π°ΡΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠ½ΡΠ΅ ΠΈΡΡ
ΠΎΠ΄ΡΡΠΈΠ΅ ΠΈΒ Π²Ρ
ΠΎΠ΄ΡΡΠΈΠ΅ ICMP Echo Request ΠΈΒ ΠΏΠ΅ΡΠ΅ΡΡΠ°ΡΡ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡ ICMP Echo Reply. ΠΠΎΒ Π½Π΅Β ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ. ΠΠΊΠ°Π·ΡΠ²Π°Π΅ΡΡΡ, Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ XDP_TX
Π² ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ΅ Π½Π° xdp-local
xdp-remote
ΡΠΎΠΆΠ΅ Π±ΡΠ»Π° Π½Π°Π·Π½Π°ΡΠ΅Π½Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°, Ρ
ΠΎΡΡ Π±Ρ ΠΏΡΡΡΠ°Ρ, ΠΈΒ ΠΎΠ½ Π±ΡΠ» ΠΏΠΎΠ΄Π½ΡΡ.
ΠΠ°ΠΊ Ρ ΡΡΠΎ ΡΠ·Π½Π°Π»?
Π’Ρ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠ΄Π΅Π»Π°ΡΡ Π΄ΠΎΠ±ΡΠΎ ΠΈΠ· Π·Π»Π°, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ Π΅Π³ΠΎ Π±ΠΎΠ»ΡΡΠ΅ Π½Π΅ ΠΈΠ· ΡΠ΅Π³ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ.
$ sudo perf trace --call-graph dwarf -e 'xdp:*'
0.000 ping/123455 xdp:xdp_bulk_tx:ifindex=19 action=TX sent=0 drops=1 err=-6
veth_xdp_flush_bq ([veth])
veth_xdp_flush_bq ([veth])
veth_poll ([veth])
<...>
Π§ΡΠΎ ΡΠ°ΠΊΠΎΠ΅ ΠΊΠΎΠ΄ 6?
$ errno 6
ENXIO 6 No such device or address
Π€ΡΠ½ΠΊΡΠΈΡ veth_xdp_flush_bq()
ΠΏΠΎΠ»ΡΡΠ°Π΅Ρ ΠΊΠΎΠ΄ ΠΎΡΠΈΠ±ΠΊΠΈ ΠΎΡΒ veth_xdp_xmit()
, Π³Π΄Π΅Β ΠΏΠΎΠΈΡΠΊΠΎΠΌ ΠΏΠΎΒ ENXIO
ΠΈΒ Π½Π°Ρ
ΠΎΠ΄ΠΈΠΌ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ.
ΠΠΎΡΡΡΠ°Π½ΠΎΠ²ΠΈΠΌ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΡΠΉ ΡΠΈΠ»ΡΡΡ (XDP_PASS
) Π²Β ΡΠ°ΠΉΠ»Π΅ xdp_dummy.c
, Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π΅Π³ΠΎ Π²Β Makefile, ΠΏΡΠΈΠ²ΡΠΆΠ΅ΠΌ ΠΊΒ xdp-remote
:
ip netns exec remote
ip link set dev int xdp object dummy.o
Π’Π΅ΠΏΠ΅ΡΡ tcpdump
ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ ΡΠΎ, ΡΡΠΎΒ ΠΎΠΆΠΈΠ΄Π°Π΅ΡΡΡ:
62:57:8e:70:44:64 > 26:0e:25:37:8f:96, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 13762, offset 0, flags [DF], proto ICMP (1), length 84)
192.0.2.2 > 192.0.2.1: ICMP echo request, id 46966, seq 1, length 64
62:57:8e:70:44:64 > 26:0e:25:37:8f:96, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 13762, offset 0, flags [DF], proto ICMP (1), length 84)
192.0.2.2 > 192.0.2.1: ICMP echo request, id 46966, seq 1, length 64
ΠΡΠ»ΠΈ Π²ΠΌΠ΅ΡΡΠΎ ΡΡΠΎΠ³ΠΎ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ARP, Π½ΡΠΆΠ½ΠΎ ΡΠ±ΡΠ°ΡΡ ΡΠΈΠ»ΡΡΡΡ (ΡΡΠΎ Π΄Π΅Π»Π°Π΅Ρ sudo ./stand detach
), ΠΏΡΡΡΠΈΡΡ ping
, Π·Π°ΡΠ΅ΠΌ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ ΡΠΈΠ»ΡΡΡΡ ΠΈΒ ΠΏΠΎΠΏΡΠΎΠ±ΠΎΠ²Π°ΡΡ ΡΠ½ΠΎΠ²Π°. ΠΡΠΎΠ±Π»Π΅ΠΌΠ° Π²Β ΡΠΎΠΌ, ΡΡΠΎΒ ΡΠΈΠ»ΡΡΡ XDP_TX
Π΄Π΅ΠΉΡΡΠ²ΡΠ΅Ρ ΠΈΒ Π½Π°Β ARP, ΠΈΒ Π΅ΡΠ»ΠΈ ΡΡΠ΅ΠΊ
ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π° ΠΈΠΌΠ΅Π½ xdp-test
ΡΡΠΏΠ΅Π» Β«Π·Π°Π±ΡΡΡΒ» MAC-Π°Π΄ΡΠ΅Ρ 192.0.2.1, ΠΎΠ½ Π½Π΅Β ΡΠΌΠΎΠΆΠ΅Ρ ΡΠ°Π·ΡΠ΅ΡΠΈΡΡ ΡΡΠΎΡ IP.
ΠΠΎΡΡΠ°Π½ΠΎΠ²ΠΊΠ° Π·Π°Π΄Π°ΡΠΈ
ΠΠ΅ΡΠ΅ΠΉΠ΄Π΅ΠΌ ΠΊΒ Π·Π°ΡΠ²Π»Π΅Π½Π½ΠΎΠΉ Π·Π°Π΄Π°ΡΠΈ: Π½Π°ΠΏΠΈΡΠ°ΡΡ Π½Π°Β XDP ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌ SYN cookies.
ΠΠΎΒ ΡΠΈΡ ΠΏΠΎΡ ΠΏΠΎΠΏΡΠ»ΡΡΠ½ΠΎΠΉ DDoS-Π°ΡΠ°ΠΊΠΎΠΉ ΠΎΡΡΠ°Π΅ΡΡΡ SYN flood, ΡΡΡΡ ΠΊΠΎΡΠΎΡΠΎΠΉ Π²Β ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌ. ΠΡΠΈΒ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ (TCP handshake) ΡΠ΅ΡΠ²Π΅Ρ ΠΏΠΎΠ»ΡΡΠ°Π΅Ρ SYN, Π²ΡΠ΄Π΅Π»ΡΠ΅Ρ ΡΠ΅ΡΡΡΡΡ ΠΏΠΎΠ΄Β Π±ΡΠ΄ΡΡΠ΅Π΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅, ΠΎΡΠ²Π΅ΡΠ°Π΅Ρ SYNACK-ΠΏΠ°ΠΊΠ΅ΡΠΎΠΌ ΠΈΒ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ ACK. ΠΡΠ°ΠΊΡΡΡΠΈΠΉ ΠΏΡΠΎΡΡΠΎ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅Ρ SYN-ΠΏΠ°ΠΊΠ΅ΡΡ ΡΒ ΠΏΠΎΠ΄Π΄Π΅Π»ΡΠ½ΡΡ Π°Π΄ΡΠ΅ΡΠΎΠ² Π²Β ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π΅ ΡΡΡΡΡ Π²Β ΡΠ΅ΠΊΡΠ½Π΄Ρ ΡΒ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Ρ ΠΎΡΡΠ° ΠΈΠ·Β ΠΌΠ½ΠΎΠ³ΠΎΡΡΡΡΡΠ½ΠΎΠ³ΠΎ Π±ΠΎΡΠ½Π΅ΡΠ°. Π‘Π΅ΡΠ²Π΅Ρ Π²ΡΠ½ΡΠΆΠ΄Π΅Π½ Π²ΡΠ΄Π΅Π»ΡΡΡ ΡΠ΅ΡΡΡΡΡ ΡΡΠ°Π·Ρ ΠΏΠΎΒ ΠΏΡΠΈΠ±ΡΡΠΈΠΈ ΠΏΠ°ΠΊΠ΅ΡΠ°, Π°Β ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅Ρ ΠΏΠΎΒ Π±ΠΎΠ»ΡΡΠΎΠΌΡ ΡΠ°ΠΉΠΌΠ°ΡΡΡ, Π²Β ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ΅ ΠΈΡΡΠ΅ΡΠΏΡΠ²Π°Π΅ΡΡΡ ΠΏΠ°ΠΌΡΡΡ ΠΈΠ»ΠΈΒ Π»ΠΈΠΌΠΈΡΡ, Π½ΠΎΠ²ΡΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Π½Π΅Β ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡΡΡ, ΡΠ΅ΡΠ²ΠΈΡ Π½Π΅Π΄ΠΎΡΡΡΠΏΠ΅Π½.
ΠΡΠ»ΠΈ Π½Π΅Β Π²ΡΠ΄Π΅Π»ΡΡΡ ΠΏΠΎΒ SYN-ΠΏΠ°ΠΊΠ΅ΡΡ ΡΠ΅ΡΡΡΡΡ, Π°Β ΡΠΎΠ»ΡΠΊΠΎ ΠΎΡΠ²Π΅ΡΠ°ΡΡ SYNACK-ΠΏΠ°ΠΊΠ΅ΡΠΎΠΌ, ΠΊΠ°ΠΊ ΡΠΎΠ³Π΄Π° ΡΠ΅ΡΠ²Π΅ΡΡ ΠΏΠΎΠ½ΡΡΡ, ΡΡΠΎΒ ACK-ΠΏΠ°ΠΊΠ΅Ρ, ΠΏΡΠΈΡΠ΅Π΄ΡΠΈΠΉ ΠΏΠΎΠ·ΠΆΠ΅, ΠΎΡΠ½ΠΎΡΠΈΡΡΡ ΠΊΒ SYN-ΠΏΠ°ΠΊΠ΅ΡΡ, ΠΊΠΎΡΠΎΡΡΠΉ Π½Π΅Β ΡΠΎΡ
ΡΠ°Π½ΡΠ»ΠΈ? ΠΠ΅Π΄Ρ Π°ΡΠ°ΠΊΡΡΡΠΈΠΉ ΠΌΠΎΠΆΠ΅Ρ Π³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°ΡΡ ΠΈΒ ΡΠ°Π»ΡΡΠΈΠ²ΡΠ΅ ACK. Π‘ΡΡΡ SYN cookie Π² ΡΠΎΠΌ, ΡΡΠΎΠ±Ρ ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°ΡΡ Π²Β seqnum
ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΠΊΠ°ΠΊΒ Ρ
ΡΡ ΠΎΡΒ Π°Π΄ΡΠ΅ΡΠΎΠ², ΠΏΠΎΡΡΠΎΠ² ΠΈΒ ΠΌΠ΅Π½ΡΡΡΠ΅ΠΉΡΡ ΡΠΎΠ»ΠΈ. ΠΡΠ»ΠΈ ACK ΡΡΠΏΠ΅Π» ΠΏΡΠΈΠΉΡΠΈ Π΄ΠΎΒ ΡΠΌΠ΅Π½Ρ ΡΠΎΠ»ΠΈ, ΠΌΠΎΠΆΠ½ΠΎ Π΅ΡΠ΅ ΡΠ°Π· ΠΏΠΎΡΡΠΈΡΠ°ΡΡ Ρ
ΡΡ ΠΈΒ ΡΡΠ°Π²Π½ΠΈΡΡ ΡΒ acknum
. ΠΠΎΠ΄Π΄Π΅Π»Π°ΡΡ acknum
Π°ΡΠ°ΠΊΡΡΡΠΈΠΉ Π½Π΅Β ΠΌΠΎΠΆΠ΅Ρ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΡΠΎΠ»Ρ Π²ΠΊΠ»ΡΡΠ°Π΅Ρ ΡΠ΅ΠΊΡΠ΅Ρ, Π°Β ΠΏΠ΅ΡΠ΅Π±ΡΠ°ΡΡ Π½Π΅Β ΡΡΠΏΠ΅Π΅Ρ ΠΈΠ·-Π·Π°Β ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠ°Π½Π°Π»Π°.
SYN cookie Π΄Π°Π²Π½ΠΎ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ Π²Β ΡΠ΄ΡΠ΅ Linux ΠΈΒ Π΄Π°ΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ Π²ΠΊΠ»ΡΡΠ°ΡΡΡΡ, Π΅ΡΠ»ΠΈΒ SYN ΠΏΡΠΈΡ ΠΎΠ΄ΡΡ ΡΠ»ΠΈΡΠΊΠΎΠΌ Π±ΡΡΡΡΠΎ ΠΈΒ ΠΌΠ°ΡΡΠΎΠ²ΠΎ.
ΠΠΈΠΊΠ±Π΅Π· ΠΏΠΎ TCP handshake
TCP ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°Π΅Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ Π΄Π°Π½Π½ΡΡ ΠΊΠ°ΠΊ ΠΏΠΎΡΠΎΠΊΠ° Π±Π°ΠΉΡΠΎΠ², Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΠΎΠ²Π΅ΡΡ TCP ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΡΡ HTTP-Π·Π°ΠΏΡΠΎΡΡ. ΠΠΎΡΠΎΠΊ ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΡΡΡ ΠΏΠΎΒ ΠΊΡΡΠΎΡΠΊΠ°ΠΌ Π²Β ΠΏΠ°ΠΊΠ΅ΡΠ°Ρ . Π£Β Π²ΡΠ΅Ρ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ² TCP Π΅ΡΡΡ Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΡΠ»Π°Π³ΠΈ ΠΈΒ 32-Π±ΠΈΡΠ½ΡΠ΅ Π½ΠΎΠΌΠ΅ΡΠ° ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΠ΅ΠΉ:
-
ΠΠΎΠΌΠ±ΠΈΠ½Π°ΡΠΈΡ ΡΠ»Π°Π³ΠΎΠ² ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ ΡΠΎΠ»Ρ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅ΡΠ°. Π€Π»Π°Π³Β SYN ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ, ΡΡΠΎΒ ΡΡΠΎ ΠΏΠ΅ΡΠ²ΡΠΉ ΠΏΠ°ΠΊΠ΅Ρ ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ Π²Β ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΈ. Π€Π»Π°Π³ ACK ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ, ΡΡΠΎΒ ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ ΠΏΠΎΠ»ΡΡΠΈΠ» Π²ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Π΄ΠΎΒ Π±Π°ΠΉΡΠ°
acknum
. ΠΠ°ΠΊΠ΅Ρ ΠΌΠΎΠΆΠ΅Ρ ΠΈΠΌΠ΅ΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ»Π°Π³ΠΎΠ² ΠΈΒ Π½Π°Π·ΡΠ²Π°Π΅ΡΡΡ ΠΏΠΎΒ ΠΈΡ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°ΡΠΈΠΈ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, SYNACK-ΠΏΠ°ΠΊΠ΅Ρ. -
Sequence number (seqnum) ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ ΡΠΌΠ΅ΡΠ΅Π½ΠΈΠ΅ Π²Β ΠΏΠΎΡΠΎΠΊΠ΅ Π΄Π°Π½Π½ΡΡ Π΄Π»ΡΒ ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ Π±Π°ΠΉΡΠ°, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΡΡΡ Π²Β ΡΡΠΎΠΌ ΠΏΠ°ΠΊΠ΅ΡΠ΅. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π΅ΡΠ»ΠΈ Π²Β ΠΏΠ΅ΡΠ²ΠΎΠΌ ΠΏΠ°ΠΊΠ΅ΡΠ΅ ΡΒ XΒ Π±Π°ΠΉΡΠ°ΠΌΠΈ Π΄Π°Π½Π½ΡΡ ΡΡΠΎΡ Π½ΠΎΠΌΠ΅Ρ Π±ΡΠ»Β N, Π²Β ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌ ΠΏΠ°ΠΊΠ΅ΡΠ΅ ΡΒ Π½ΠΎΠ²ΡΠΌΠΈ Π΄Π°Π½Π½ΡΠΌΠΈ ΠΎΠ½ Π±ΡΠ΄Π΅Ρ N+X. ΠΒ Π½Π°ΡΠ°Π»Π΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΠΊΠ°ΠΆΠ΄Π°Ρ ΡΡΠΎΡΠΎΠ½Π° Π²ΡΠ±ΠΈΡΠ°Π΅Ρ ΡΡΠΎΡ Π½ΠΎΠΌΠ΅Ρ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ.
-
Acknowledgement number (acknum)Β β ΡΠ°ΠΊΠΎΠ΅Β ΠΆΠ΅ ΡΠΌΠ΅ΡΠ΅Π½ΠΈΠ΅, ΠΊΠ°ΠΊΒ seqnum, Π½ΠΎΒ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ Π½Π΅Β Π½ΠΎΠΌΠ΅Ρ ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°Π΅ΠΌΠΎΠ³ΠΎ Π±Π°ΠΉΡΠ°, Π°Β Π½ΠΎΠΌΠ΅Ρ ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ Π±Π°ΠΉΡΠ° ΠΎΡΒ ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ, ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ Π½Π΅Β Π²ΠΈΠ΄Π΅Π».
ΠΒ Π½Π°ΡΠ°Π»Π΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΡΡΠΎΡΠΎΠ½Ρ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠΎΠ³Π»Π°ΡΠΎΠ²Π°ΡΡ seqnum
ΠΈΒ acknum
. ΠΠ»ΠΈΠ΅Π½Ρ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅Ρ SYN-ΠΏΠ°ΠΊΠ΅Ρ ΡΠΎΒ ΡΠ²ΠΎΠΈΠΌ seqnum = X
. Π‘Π΅ΡΠ²Π΅Ρ ΠΎΡΠ²Π΅ΡΠ°Π΅Ρ SYNACK-ΠΏΠ°ΠΊΠ΅ΡΠΎΠΌ, ΠΊΡΠ΄Π° Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅Ρ ΡΠ²ΠΎΠΉ seqnum = Y
ΠΈΒ Π²ΡΡΡΠ°Π²Π»ΡΠ΅Ρ acknum = X + 1
. ΠΠ»ΠΈΠ΅Π½Ρ Π½Π°Β SYNACK ΠΎΡΠ²Π΅ΡΠ°Π΅Ρ ACK-ΠΏΠ°ΠΊΠ΅ΡΠΎΠΌ, Π³Π΄Π΅Β seqnum = X + 1
, acknum = Y + 1
. ΠΠΎΡΠ»Π΅ ΡΡΠΎΠ³ΠΎ Π½Π°ΡΠΈΠ½Π°Π΅ΡΡΡ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠ° Π΄Π°Π½Π½ΡΡ
.
ΠΡΠ»ΠΈ ΡΠΎΠ±Π΅ΡΠ΅Π΄Π½ΠΈΠΊ Π½Π΅Β ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π°Π΅Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΏΠ°ΠΊΠ΅ΡΠ°, TCP ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅Ρ Π΅Π³ΠΎ ΠΏΠΎΠ²ΡΠΎΡΠ½ΠΎ ΠΏΠΎΒ ΡΠ°ΠΉΠΌΠ°ΡΡΡ.
ΠΠΎΡΠ΅ΠΌΡ SYN cookies Π½Π΅Β ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ Π²ΡΠ΅Π³Π΄Π°?
ΠΠΎ-ΠΏΠ΅ΡΠ²ΡΡ , Π΅ΡΠ»ΠΈ ΠΏΠΎΡΠ΅ΡΡΠ΅ΡΡΡ SYNACK ΠΈΠ»ΠΈΒ ACK, ΠΏΡΠΈΠ΄Π΅ΡΡΡ ΠΆΠ΄Π°ΡΡ ΠΏΠΎΠ²ΡΠΎΡΠ½ΠΎΠΉ ΠΎΡΠΏΡΠ°Π²ΠΊΠΈΒ β Π·Π°ΠΌΠ΅Π΄Π»ΡΠ΅ΡΡΡ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ. ΠΠΎ-Π²ΡΠΎΡΡΡ , Π²Β SYN-ΠΏΠ°ΠΊΠ΅ΡΠ΅Β β ΠΈΒ ΡΠΎΠ»ΡΠΊΠΎ Π²Β Π½Π΅ΠΌ!Β β ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΡΡΡ ΡΡΠ΄ ΠΎΠΏΡΠΈΠΉ, Π²Π»ΠΈΡΡΡΠΈΡ Π½Π°Β Π΄Π°Π»ΡΠ½Π΅ΠΉΡΡΡ ΡΠ°Π±ΠΎΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ. ΠΠ΅Β Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Ρ Π²Ρ ΠΎΠ΄ΡΡΠΈΠ΅ SYN-ΠΏΠ°ΠΊΠ΅ΡΡ, ΡΠ΅ΡΠ²Π΅Ρ ΡΠ°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ ΠΈΠ³Π½ΠΎΡΠΈΡΡΠ΅Ρ ΡΡΠΈ ΠΎΠΏΡΠΈΠΈ, Π²Β ΡΠ»Π΅Π΄ΡΡΡΠΈΡ ΠΏΠ°ΠΊΠ΅ΡΠ°Ρ ΠΊΠ»ΠΈΠ΅Π½Ρ ΡΠΆΠ΅ Π½Π΅Β ΠΏΡΠΈΡΠ»Π΅Ρ ΠΈΡ . Π Π°Π±ΠΎΡΠ°ΡΡ TCP ΠΏΡΠΈΒ ΡΡΠΎΠΌ ΠΌΠΎΠΆΠ΅Ρ, Π½ΠΎΒ ΠΊΠ°ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡΠΌ Π½Π°Β Π½Π°ΡΠ°Π»ΡΠ½ΠΎΠΌ ΡΡΠ°ΠΏΠ΅ ΠΊΠ°ΡΠ΅ΡΡΠ²ΠΎ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΡΠ½ΠΈΠ·ΠΈΡΡΡ.
Π‘Β ΡΠΎΡΠΊΠΈ Π·ΡΠ΅Π½ΠΈΡ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ², XDP-ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° Π΄ΠΎΠ»ΠΆΠ½Π° Π΄Π΅Π»Π°ΡΡ ΡΠ»Π΅Π΄ΡΡΡΠ΅Π΅:
- Π½Π° SYN ΠΎΡΠ²Π΅ΡΠ°ΡΡ SYNACK ΡΒ cookie;
- Π½Π°Β ACK ΠΎΡΠ²Π΅ΡΠ°ΡΡ RST (ΡΠ°Π·ΡΡΠ²Π°ΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅);
- ΠΎΡΡΠ°Π»ΡΠ½ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ ΡΠ±ΡΠ°ΡΡΠ²Π°ΡΡ.
ΠΡΠ΅Π²Π΄ΠΎΠΊΠΎΠ΄ Π°Π»Π³ΠΎΡΠΈΡΠΌΠ° Π²ΠΌΠ΅ΡΡΠ΅ ΡΒ ΡΠ°Π·Π±ΠΎΡΠΎΠΌ ΠΏΠ°ΠΊΠ΅ΡΠ°:
ΠΡΠ»ΠΈ ΡΡΠΎ Π½Π΅ Ethernet,
ΠΏΡΠΎΠΏΡΡΡΠΈΡΡ ΠΏΠ°ΠΊΠ΅Ρ.
ΠΡΠ»ΠΈ ΡΡΠΎ Π½Π΅ IPv4,
ΠΏΡΠΎΠΏΡΡΡΠΈΡΡ ΠΏΠ°ΠΊΠ΅Ρ.
ΠΡΠ»ΠΈ Π°Π΄ΡΠ΅Ρ Π² ΡΠ°Π±Π»ΠΈΡΠ΅ ΠΏΡΠΎΠ²Π΅ΡΠ΅Π½Π½ΡΡ
, (*)
ΡΠΌΠ΅Π½ΡΡΠΈΡΡ ΡΡΠ΅ΡΡΠΈΠΊ ΠΎΡΡΠ°Π²ΡΠΈΡ
ΡΡ ΠΏΡΠΎΠ²Π΅ΡΠΎΠΊ,
ΠΏΡΠΎΠΏΡΡΡΠΈΡΡ ΠΏΠ°ΠΊΠ΅Ρ.
ΠΡΠ»ΠΈ ΡΡΠΎ Π½Π΅ TCP,
ΡΠ±ΡΠΎΡΠΈΡΡ ΠΏΠ°ΠΊΠ΅Ρ. (**)
ΠΡΠ»ΠΈ ΡΡΠΎ SYN,
ΠΎΡΠ²Π΅ΡΠΈΡΡ SYN-ACK Ρ cookie.
ΠΡΠ»ΠΈ ΡΡΠΎ ACK,
Π΅ΡΠ»ΠΈ Π² acknum Π»Π΅ΠΆΠΈΡ Π½Π΅ cookie,
ΡΠ±ΡΠΎΡΠΈΡΡ ΠΏΠ°ΠΊΠ΅Ρ.
ΠΠ°Π½Π΅ΡΡΠΈ Π² ΡΠ°Π±Π»ΠΈΡΡ Π°Π΄ΡΠ΅Ρ Ρ N ΠΎΡΡΠ°Π²ΡΠΈΡ
ΡΡ ΠΏΡΠΎΠ²Π΅ΡΠΎΠΊ. (*)
ΠΡΠ²Π΅ΡΠΈΡΡ RST. (**)
Π ΠΎΡΡΠ°Π»ΡΠ½ΡΡ
ΡΠ»ΡΡΠ°ΡΡ
ΡΠ±ΡΠΎΡΠΈΡΡ ΠΏΠ°ΠΊΠ΅Ρ.
ΠΠ΄Π½ΠΎΠΉ (*)
ΠΎΡΠΌΠ΅ΡΠ΅Π½Ρ ΠΏΡΠ½ΠΊΡΡ, Π²Β ΠΊΠΎΡΠΎΡΡΡ
Π½ΡΠΆΠ½ΠΎ ΡΠΏΡΠ°Π²Π»ΡΡΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ΠΌ ΡΠΈΡΡΠ΅ΠΌΡΒ β Π½Π°Β ΠΏΠ΅ΡΠ²ΠΎΠΌ ΡΡΠ°ΠΏΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±ΠΎΠΉΡΠΈΡΡ Π±Π΅Π·Β Π½ΠΈΡ
, ΠΏΡΠΎΡΡΠΎ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π² TCP handshake ΡΒ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠ΅ΠΉ SYN cookie Π²Β ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ seqnum.
ΠΠ°Β ΠΌΠ΅ΡΡΠ΅ (**)
, ΠΏΠΎΠΊΠ° ΡΒ Π½Π°Ρ Π½Π΅Ρ ΡΠ°Π±Π»ΠΈΡΡ, Π±ΡΠ΄Π΅ΠΌ ΠΏΡΠΎΠΏΡΡΠΊΠ°ΡΡ ΠΏΠ°ΠΊΠ΅Ρ.
Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ TCP handshake
Π Π°Π·Π±ΠΎΡ ΠΏΠ°ΠΊΠ΅ΡΠ° ΠΈ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ ΠΊΠΎΠ΄Π°
ΠΠ°ΠΌ ΠΏΠΎΠ½Π°Π΄ΠΎΠ±ΡΡΡΡ ΡΡΡΡΠΊΡΡΡΡ ΡΠ΅ΡΠ΅Π²ΡΡ
Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ²: Ethernet (uapi/linux/if_ether.h
), IPv4 (uapi/linux/ip.h
) ΠΈΒ TCP (uapi/linux/tcp.h
). ΠΠΎΡΠ»Π΅Π΄Π½ΠΈΠΉ ΡΒ ΠΌΠ΅Π½Ρ ΡΠ°ΠΊ ΠΈΒ Π½Π΅Β ΠΏΠΎΠ»ΡΡΠΈΠ»ΠΎΡΡ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡ ΠΈΠ·-Π·Π°Β ΠΎΡΠΈΠ±ΠΎΠΊ, ΡΠ²ΡΠ·Π°Π½Π½ΡΡ
ΡΒ atomic64_t
, ΠΏΡΠΈΡΠ»ΠΎΡΡ ΡΠΊΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ Π½ΡΠΆΠ½ΡΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ Π²Β ΠΊΠΎΠ΄.
ΠΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ Π²Β C Π²ΡΠ΄Π΅Π»ΡΡΡΡΡ Π΄Π»ΡΒ ΡΠ΄ΠΎΠ±ΡΡΠ²Π° ΡΡΠ΅Π½ΠΈΡ, Π΄ΠΎΠ»ΠΆΠ½Ρ Π±ΡΡΡ Π²ΡΡΡΠΎΠ΅Π½Ρ ΠΏΠΎΒ ΠΌΠ΅ΡΡΡ Π²ΡΠ·ΠΎΠ²Π°, ΡΠ°ΠΊ ΠΊΠ°ΠΊ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ eBPF Π²Β ΡΠ΄ΡΠ΅ Π·Π°ΠΏΡΠ΅ΡΠ°Π΅Ρ ΠΏΠ΅ΡΠ΅Ρ ΠΎΠ΄Ρ Π½Π°Π·Π°Π΄, ΡΠΎΒ Π΅ΡΡΡ, ΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ, ΡΠΈΠΊΠ»Ρ ΠΈΒ Π²ΡΠ·ΠΎΠ²Ρ ΡΡΠ½ΠΊΡΠΈΠΉ.
#define INTERNAL static __attribute__((always_inline))
ΠΠ°ΠΊΡΠΎΡ LOG()
ΠΎΡΠΊΠ»ΡΡΠ°Π΅Ρ ΠΏΠ΅ΡΠ°ΡΡ Π²Β ΡΠ΅Π»ΠΈΠ·Π½ΠΎΠΉ ΡΠ±ΠΎΡΠΊΠ΅.
ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅Ρ ΡΠΎΠ±ΠΎΠΉ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ ΠΈΠ·Β ΡΡΠ½ΠΊΡΠΈΠΉ. ΠΠ°ΠΆΠ΄Π°Ρ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ ΠΏΠ°ΠΊΠ΅Ρ, Π²Β ΠΊΠΎΡΠΎΡΠΎΠΌ Π²ΡΠ΄Π΅Π»Π΅Π½ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠ΅Π³ΠΎ ΡΡΠΎΠ²Π½Ρ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, process_ether()
ΠΎΠΆΠΈΠ΄Π°Π΅Ρ, ΡΡΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ether
. ΠΠΎΒ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ°ΠΌ Π°Π½Π°Π»ΠΈΠ·Π° ΠΏΠΎΠ»Π΅ΠΉ ΡΡΠ½ΠΊΡΠΈΡ ΠΌΠΎΠΆΠ΅Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΠΏΠ°ΠΊΠ΅Ρ Π½Π°Β ΡΡΠΎΠ²Π΅Π½Ρ Π²ΡΡΠ΅. Π Π΅Π·ΡΠ»ΡΡΠ°Ρ ΡΠ°Π±ΠΎΡΡ ΡΡΠ½ΠΊΡΠΈΠΈΒ β Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ XDP. ΠΠΎΠΊΠ° ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ SYN ΠΈΒ ACK ΠΏΡΠΎΠΏΡΡΠΊΠ°ΡΡ Π²ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ.
struct Packet {
struct xdp_md* ctx;
struct ethhdr* ether;
struct iphdr* ip;
struct tcphdr* tcp;
};
INTERNAL int process_tcp_syn(struct Packet* packet) { return XDP_PASS; }
INTERNAL int process_tcp_ack(struct Packet* packet) { return XDP_PASS; }
INTERNAL int process_tcp(struct Packet* packet) { ... }
INTERNAL int process_ip(struct Packet* packet) { ... }
INTERNAL int
process_ether(struct Packet* packet) {
struct ethhdr* ether = packet->ether;
LOG("Ether(proto=0x%x)", bpf_ntohs(ether->h_proto));
if (ether->h_proto != bpf_ntohs(ETH_P_IP)) {
return XDP_PASS;
}
// B
struct iphdr* ip = (struct iphdr*)(ether + 1);
if ((void*)(ip + 1) > (void*)packet->ctx->data_end) {
return XDP_DROP; /* malformed packet */
}
packet->ip = ip;
return process_ip(packet);
}
SEC("prog")
int xdp_main(struct xdp_md* ctx) {
struct Packet packet;
packet.ctx = ctx;
// A
struct ethhdr* ether = (struct ethhdr*)(void*)ctx->data;
if ((void*)(ether + 1) > (void*)ctx->data_end) {
return XDP_PASS;
}
packet.ether = ether;
return process_ether(&packet);
}
ΠΠ±ΡΠ°ΡΠ°Ρ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π°Β ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ, ΠΎΡΠΌΠ΅ΡΠ΅Π½Π½ΡΠ΅ A ΠΈΒ B. ΠΡΠ»ΠΈ Π·Π°ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠΈΡΠΎΠ²Π°ΡΡΒ A, ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° ΡΠΎΠ±Π΅ΡΠ΅ΡΡΡ, Π½ΠΎΒ ΠΏΡΠΈΒ Π·Π°Π³ΡΡΠ·ΠΊΠ΅ Π±ΡΠ΄Π΅Ρ ΠΎΡΠΈΠ±ΠΊΠ° Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ:
Verifier analysis:
<...>
11: (7b) *(u64 *)(r10 -48) = r1
12: (71) r3 = *(u8 *)(r7 +13)
invalid access to packet, off=13 size=1, R7(id=0,off=0,r=0)
R7 offset is outside of the packet
processed 11 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
Error fetching program/map!
ΠΠ»ΡΡΠ΅Π²Π°Ρ ΡΡΡΠΎΠΊΠ° invalid access to packet, off=13 size=1, R7(id=0,off=0,r=0)
: Π΅ΡΡΡ ΠΏΡΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ, ΠΊΠΎΠ³Π΄Π° ΡΡΠΈΠ½Π°Π΄ΡΠ°ΡΡΠΉ Π±Π°ΠΉΡ ΠΎΡΒ Π½Π°ΡΠ°Π»Π° Π±ΡΡΠ΅ΡΠ° Π½Π°Ρ
ΠΎΠ΄ΠΈΡΡΡ Π²Π½Π΅Β ΠΏΠ°ΠΊΠ΅ΡΠ°. ΠΠΎΒ Π»ΠΈΡΡΠΈΠ½Π³Ρ ΡΠ»ΠΎΠΆΠ½ΠΎΠ²Π°ΡΠΎ ΠΏΠΎΠ½ΡΡΡ, ΠΎΒ ΠΊΠ°ΠΊΠΎΠΉ ΡΡΡΠΎΠΊΠ΅ ΠΈΠ΄Π΅Ρ ΡΠ΅ΡΡ, Π·Π°ΡΠΎ Π΅ΡΡΡ Π½ΠΎΠΌΠ΅Ρ ΠΈΠ½ΡΡΡΡΠΊΡΠΈΠΈ (12) ΠΈΒ Π΄ΠΈΠ·Π°ΡΡΠ΅ΠΌΠ±Π»Π΅Ρ, ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡΠΈΠΉ ΡΡΡΠΎΠΊΠΈ ΠΈΡΡ
ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°:
llvm-objdump -S xdp_filter.o | less
ΠΒ Π΄Π°Π½Π½ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ ΠΎΠ½ ΡΠΊΠ°Π·ΡΠ²Π°Π΅Ρ Π½Π°Β ΡΡΡΠΎΠΊΡ
LOG("Ether(proto=0x%x)", bpf_ntohs(ether->h_proto));
ΠΏΠΎΒ ΠΊΠΎΡΠΎΡΠΎΠΉ ΠΏΠΎΠ½ΡΡΠ½ΠΎ, ΡΡΠΎΒ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Π²Β ether
. ΠΡΠ΅Π³Π΄Π°Β Π±Ρ ΡΠ°ΠΊ.
ΠΡΠ²Π΅Ρ Π½Π° SYN
Π¦Π΅Π»Ρ Π½Π°Β ΡΡΠΎΠΌ ΡΡΠ°ΠΏΠ΅Β β ΡΠΎΡΠΌΠΈΡΠΎΠ²Π°ΡΡ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΡΠΉ SYNACK-ΠΏΠ°ΠΊΠ΅Ρ ΡΒ ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΌ seqnum
, ΠΊΠΎΡΠΎΡΡΠΉ Π²Β Π±ΡΠ΄ΡΡΠ΅ΠΌ Π·Π°ΠΌΠ΅Π½ΠΈΡΡΡ Π½Π°Β SYN cookie. ΠΡΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΡΡ Π²Β process_tcp_syn()
ΠΈΒ ΠΎΠΊΡΠ΅ΡΡΠ½ΠΎΡΡΡΡ
.
ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΠΏΠ°ΠΊΠ΅ΡΠ°
ΠΠ°ΠΊ Π½ΠΈ ΡΡΡΠ°Π½Π½ΠΎ, Π²ΠΎΡ ΡΠ°ΠΌΠ°Ρ ΠΏΡΠΈΠΌΠ΅ΡΠ°ΡΠ΅Π»ΡΠ½Π°Ρ ΡΡΡΠΎΠΊΠ°, ΡΠΎΡΠ½Π΅Π΅, ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ ΠΊΒ Π½Π΅ΠΉ:
/* Required to verify checksum calculation */
const void* data_end = (const void*)ctx->data_end;
ΠΡΠΈΒ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΠΈ ΠΏΠ΅ΡΠ²ΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ ΠΊΠΎΠ΄Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΎΡΡ ΡΠ΄ΡΠΎ 5.1, Π΄Π»ΡΒ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠ° ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ Π±ΡΠ»Π° ΡΠ°Π·Π½ΠΈΡΠ° ΠΌΠ΅ΠΆΠ΄Ρ data_end
ΠΈΒ (const void*)ctx->data_end
. ΠΡΠΈΒ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΠΈ ΡΡΠ°ΡΡΠΈ ΡΠ΄ΡΠΎ 5.3.1 Π½Π΅Β ΠΈΠΌΠ΅Π»ΠΎ ΡΠ°ΠΊΠΎΠΉ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ. ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡ ΠΎΠ±ΡΠ°ΡΠ°Π»ΡΡ ΠΊΒ Π»ΠΎΠΊΠ°Π»ΡΠ½ΠΎΠΉ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΠΈΠ½Π°ΡΠ΅, ΡΠ΅ΠΌΒ ΠΊΒ ΠΏΠΎΠ»Ρ. ΠΠΎΡΠ°Π»ΡΒ β Π½Π°Β Π±ΠΎΠ»ΡΡΠΎΠΉ Π²Π»ΠΎΠΆΠ΅Π½Π½ΠΎΡΡΠΈ ΡΠΏΡΠΎΡΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π° ΠΌΠΎΠΆΠ΅Ρ ΠΏΠΎΠΌΠΎΡΡ.
ΠΠ°Π»Π΅Π΅ ΡΡΡΠΈΠ½Π½ΡΠ΅ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ Π΄Π»ΠΈΠ½ Π²ΠΎ ΡΠ»Π°Π²Ρ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠ°; ΠΎΒ MAX_CSUM_BYTES
Π½ΠΈΠΆΠ΅.
const u32 ip_len = ip->ihl * 4;
if ((void*)ip + ip_len > data_end) {
return XDP_DROP; /* malformed packet */
}
if (ip_len > MAX_CSUM_BYTES) {
return XDP_ABORTED; /* implementation limitation */
}
const u32 tcp_len = tcp->doff * 4;
if ((void*)tcp + tcp_len > (void*)ctx->data_end) {
return XDP_DROP; /* malformed packet */
}
if (tcp_len > MAX_CSUM_BYTES) {
return XDP_ABORTED; /* implementation limitation */
}
Π Π°Π·Π²ΠΎΡΠΎΡ ΠΏΠ°ΠΊΠ΅ΡΠ°
ΠΠ°ΠΏΠΎΠ»Π½ΡΠ΅ΠΌ seqnum
ΠΈ acknum
, Π²ΡΡΡΠ°Π²Π»ΡΠ΅ΠΌ ACK (SYN ΡΠΆΠ΅ Π²ΡΡΡΠ°Π²Π»Π΅Π½):
const u32 cookie = 42;
tcp->ack_seq = bpf_htonl(bpf_ntohl(tcp->seq) + 1);
tcp->seq = bpf_htonl(cookie);
tcp->ack = 1;
ΠΠ΅Π½ΡΠ΅ΠΌ ΠΌΠ΅ΡΡΠ°ΠΌΠΈ ΠΏΠΎΡΡΡ TCP, Π°Π΄ΡΠ΅Ρ IP ΠΈΒ MAC-Π°Π΄ΡΠ΅ΡΠ°. Π‘ΡΠ°Π½Π΄Π°ΡΡΠ½Π°Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π½Π΅Π΄ΠΎΡΡΡΠΏΠ½Π° ΠΈΠ·Β XDP-ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, ΠΏΠΎΡΡΠΎΠΌΡ memcpy()
Β β ΠΌΠ°ΠΊΡΠΎΡ, ΡΠΊΡΡΠ²Π°ΡΡΠΈΠΉ ΠΈΠ½ΡΡΠΈΠ½ΡΠΈΠΊ Clang.
const u16 temp_port = tcp->source;
tcp->source = tcp->dest;
tcp->dest = temp_port;
const u32 temp_ip = ip->saddr;
ip->saddr = ip->daddr;
ip->daddr = temp_ip;
struct ethhdr temp_ether = *ether;
memcpy(ether->h_dest, temp_ether.h_source, ETH_ALEN);
memcpy(ether->h_source, temp_ether.h_dest, ETH_ALEN);
ΠΠ΅ΡΠ΅ΡΡΠ΅Ρ ΠΊΠΎΠ½ΡΡΠΎΠ»ΡΠ½ΡΡ ΡΡΠΌΠΌ
ΠΠΎΠ½ΡΡΠΎΠ»ΡΠ½ΡΠ΅ ΡΡΠΌΠΌΡ IPv4 ΠΈΒ TCP ΡΡΠ΅Π±ΡΡΡ ΡΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π²ΡΠ΅Ρ 16-Π±ΠΈΡΠ½ΡΡ ΡΠ»ΠΎΠ² Π²Β Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°Ρ , Π°Β ΡΠ°Π·ΠΌΠ΅Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² Π·Π°ΠΏΠΈΡΠ°Π½ Π²Β Π½ΠΈΡ , ΡΠΎΒ Π΅ΡΡΡ Π½Π°Β ΠΌΠΎΠΌΠ΅Π½Ρ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ Π½Π΅ΠΈΠ·Π²Π΅ΡΡΠ΅Π½. ΠΡΠΎ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ Π½Π΅Β ΠΏΡΠΎΠΏΡΡΡΠΈΡ ΠΎΠ±ΡΡΠ½ΡΠΉ ΡΠΈΠΊΠ» Π΄ΠΎΒ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π³ΡΠ°Π½ΠΈΡΡ. ΠΠ°ΡΠΎ ΡΠ°Π·ΠΌΠ΅Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½: Π΄ΠΎΒ 64 Π±Π°ΠΉΡΠΎΠ² ΠΊΠ°ΠΆΠ΄ΡΠΉ. ΠΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ ΡΠΈΠΊΠ» ΡΒ ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΌ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎΠΌ ΠΈΡΠ΅ΡΠ°ΡΠΈΠΉ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΌΠΎΠΆΠ΅Ρ Π·Π°ΠΊΠΎΠ½ΡΠΈΡΡΡΡ Π΄ΠΎΡΡΠΎΡΠ½ΠΎ.
ΠΠ°ΠΌΠ΅ΡΡ, ΡΡΠΎ Π΅ΡΡΡ
Π€ΡΠ½ΠΊΡΠΈΡ ΡΠ°ΡΡΠ΅ΡΠ° ΠΊΠΎΠ½ΡΡΠΎΠ»ΡΠ½ΠΎΠΉ ΡΡΠΌΠΌΡ:
#define MAX_CSUM_WORDS 32
#define MAX_CSUM_BYTES (MAX_CSUM_WORDS * 2)
INTERNAL u32
sum16(const void* data, u32 size, const void* data_end) {
u32 s = 0;
#pragma unroll
for (u32 i = 0; i < MAX_CSUM_WORDS; i++) {
if (2*i >= size) {
return s; /* normal exit */
}
if (data + 2*i + 1 + 1 > data_end) {
return 0; /* should be unreachable */
}
s += ((const u16*)data)[i];
}
return s;
}
ΠΠ΅ΡΠΌΠΎΡΡΡ Π½Π°Β ΡΠΎ, ΡΡΠΎΒ size
ΠΏΡΠΎΠ²Π΅ΡΠ΅Π½ΠΎ Π²ΡΠ·ΡΠ²Π°ΡΡΠΈΠΌ ΠΊΠΎΠ΄ΠΎΠΌ, Π²ΡΠΎΡΠΎΠ΅ ΡΡΠ»ΠΎΠ²ΠΈΠ΅ Π²ΡΡ
ΠΎΠ΄Π° Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ, ΡΡΠΎΠ±Ρ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΌΠΎΠ³ Π΄ΠΎΠΊΠ°Π·Π°ΡΡ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΠ΅ ΡΠΈΠΊΠ»Π°.
ΠΠ»ΡΒ 32-Π±ΠΈΡΠ½ΡΡ ΡΠ»ΠΎΠ² ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° Π±ΠΎΠ»Π΅Π΅ ΠΏΡΠΎΡΡΠ°Ρ Π²Π΅ΡΡΠΈΡ:
INTERNAL u32
sum16_32(u32 v) {
return (v >> 16) + (v & 0xffff);
}
Π‘ΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ ΠΏΠ΅ΡΠ΅ΡΡΠ΅Ρ ΠΊΠΎΠ½ΡΡΠΎΠ»ΡΠ½ΡΡ ΡΡΠΌΠΌ ΠΈΒ ΠΎΡΠΏΡΠ°Π²ΠΊΠ° ΠΏΠ°ΠΊΠ΅ΡΠ° ΠΎΠ±ΡΠ°ΡΠ½ΠΎ:
ip->check = 0;
ip->check = carry(sum16(ip, ip_len, data_end));
u32 tcp_csum = 0;
tcp_csum += sum16_32(ip->saddr);
tcp_csum += sum16_32(ip->daddr);
tcp_csum += 0x0600;
tcp_csum += tcp_len << 8;
tcp->check = 0;
tcp_csum += sum16(tcp, tcp_len, data_end);
tcp->check = carry(tcp_csum);
return XDP_TX;
Π€ΡΠ½ΠΊΡΠΈΡ carry()
Π΄Π΅Π»Π°Π΅Ρ ΠΈΠ·Β 32-Π±ΠΈΡΠ½ΠΎΠΉ ΡΡΠΌΠΌΡ 16-Π±ΠΈΡΠ½ΡΡ
ΡΠ»ΠΎΠ² ΠΊΠΎΠ½ΡΡΠΎΠ»ΡΠ½ΡΡ ΡΡΠΌΠΌΡ, ΡΠΎΠ³Π»Π°ΡΠ½ΠΎ RFCΒ 791.
ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΡΡΠΊΠΎΠΏΠΎΠΆΠ°ΡΠΈΡ TCP
Π€ΠΈΠ»ΡΡΡ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΡΒ netcat
, ΠΏΡΠΎΠΏΡΡΠΊΠ°Ρ ΡΠΈΠ½Π°Π»ΡΠ½ΡΠΉ ACK, Π½Π°Β ΠΊΠΎΡΠΎΡΡΠΉ Linux ΠΎΡΠ²Π΅ΡΠ°Π» RST-ΠΏΠ°ΠΊΠ΅ΡΠΎΠΌ, ΡΠ°ΠΊΒ ΠΊΠ°ΠΊ ΡΠ΅ΡΠ΅Π²ΠΎΠΉ ΡΡΠ΅ΠΊ Π½Π΅Β ΠΏΠΎΠ»ΡΡΠ°Π» SYNΒ β ΠΎΠ½ Π±ΡΠ» ΠΏΠ΅ΡΠ΅Π΄Π΅Π»Π°Π½ Π²Β SYNACK ΠΈΒ ΠΎΡΠΏΡΠ°Π²Π»Π΅Π½ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΒ — ΠΈΒ ΡΒ ΡΠΎΡΠΊΠΈ Π·ΡΠ΅Π½ΠΈΡ ΠΠ‘ ΠΏΡΠΈΠ±ΡΠ» ΠΏΠ°ΠΊΠ΅Ρ, Π½Π΅Β ΠΎΡΠ½ΠΎΡΡΡΠΈΠΉΡΡ ΠΊΒ ΠΎΡΠΊΡΡΡΡΠΌ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡΠΌ.
$ sudo ip netns exec xdp-test nc -nv 192.0.2.1 6666
192.0.2.1 6666: Connection reset by peer
ΠΠ°ΠΆΠ½ΠΎ ΠΏΡΠΎΠ²Π΅ΡΡΡΡ ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΏΠΎΠ»Π½ΠΎΡΠ΅Π½Π½ΡΠΌΠΈ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡΠΌΠΈ ΠΈΒ Π½Π°Π±Π»ΡΠ΄Π°ΡΡ tcpdump
Π½Π°Β xdp-remote
ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, hping3
Π½Π΅Β ΡΠ΅Π°Π³ΠΈΡΡΠ΅Ρ Π½Π°Β Π½Π΅ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΡΠ΅ ΠΊΠΎΠ½ΡΡΠΎΠ»ΡΠ½ΡΠ΅ ΡΡΠΌΠΌΡ.
SYN cookie
Π‘Β ΡΠΎΡΠΊΠΈ Π·ΡΠ΅Π½ΠΈΡ XDP ΡΠ°ΠΌΠ° ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° ΡΡΠΈΠ²ΠΈΠ°Π»ΡΠ½Π°. ΠΠ»Π³ΠΎΡΠΈΡΠΌ ΡΠ°ΡΡΠ΅ΡΠ° ΠΏΡΠΈΠΌΠΈΡΠΈΠ²Π½ΡΠΉ ΠΈ, Π²Π΅ΡΠΎΡΡΠ½ΠΎ, ΡΡΠ·Π²ΠΈΠΌΡΠΉ Π΄Π»ΡΒ ΠΈΠ·ΠΎΡΡΠ΅Π½Π½ΠΎΠ³ΠΎ Π·Π»ΠΎΡΠΌΡΡΠ»Π΅Π½Π½ΠΈΠΊΠ°. Π―Π΄ΡΠΎ Linux, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΠΊΡΠΈΠΏΡΠΎΠ³ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ SipHash, Π½ΠΎΒ Π΅Π³ΠΎ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π΄Π»ΡΒ XDP ΡΠ²Π½ΠΎ Π²ΡΡ ΠΎΠ΄ΠΈΡ Π·Π°Β ΡΠ°ΠΌΠΊΠΈ ΡΡΠ°ΡΡΠΈ.
ΠΠΎΡΠ²ΠΈΠ»ΠΎΡΡ Π΄Π»Ρ Π½ΠΎΠ²ΡΡ TODO, ΡΠ²ΡΠ·Π°Π½Π½ΡΡ ΡΠΎΒ Π²Π½Π΅ΡΠ½ΠΈΠΌ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ΠΌ:
-
XDP-ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° Π½Π΅Β ΠΌΠΎΠΆΠ΅Ρ Ρ ΡΠ°Π½ΠΈΡΡ
cookie_seed
(ΡΠ΅ΠΊΡΠ΅ΡΠ½ΡΡ ΡΠ°ΡΡΡ ΡΠΎΠ»ΠΈ) Π²Β Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΠΎΠΉ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ, Π½ΡΠΆΠ½ΠΎ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ Π²Β ΡΠ΄ΡΠ΅, Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π²Β ΠΊΠΎΡΠΎΡΠΎΠΌ Π±ΡΠ΄Π΅Ρ ΠΏΠ΅ΡΠΈΠΎΠ΄ΠΈΡΠ΅ΡΠΊΠΈ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡΡΡΡ ΠΈΠ·Β Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠ³ΠΎ Π³Π΅Π½Π΅ΡΠ°ΡΠΎΡΠ°. -
ΠΡΠΈ ΡΠΎΠ²ΠΏΠ°Π΄Π΅Π½ΠΈΠΈ SYN cookie Π²Β ACK-ΠΏΠ°ΠΊΠ΅ΡΠ΅ Π½ΡΠΆΠ½ΠΎ Π½Π΅Β ΠΏΠ΅ΡΠ°ΡΠ°ΡΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅, Π°Β Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°ΡΡ IP ΠΏΡΠΎΠ²Π΅ΡΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°, ΡΡΠΎΠ±Ρ Π΄Π°Π»Π΅Π΅ ΠΏΡΠΎΠΏΡΡΠΊΠ°ΡΡ ΠΏΠ°ΠΊΠ΅ΡΡΠΎΡΒ Π½Π΅Π³ΠΎ.
ΠΡΠΎΠ²Π΅ΡΠΊΠ° Π»Π΅Π³ΠΈΡΠΈΠΌΠ½ΡΠΌ ΠΊΠ»ΠΈΠ΅Π½ΡΠΎΠΌ:
$ sudoip netns exec xdp-test nc -nv 192.0.2.1 6666
192.0.2.1 6666: Connection reset by peer
ΠΒ Π»ΠΎΠ³Π°Ρ
Π·Π°ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°Π½ΠΎ ΠΏΡΠΎΡ
ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ (flags=0x2
Β β ΡΡΠΎ SYN, flags=0x10
Β β ΡΡΠΎ ACK):
Ether(proto=0x800)
IP(src=0x20e6e11a dst=0x20e6e11e proto=6)
TCP(sport=50836 dport=6666 flags=0x2)
Ether(proto=0x800)
IP(src=0xfe2cb11a dst=0xfe2cb11e proto=6)
TCP(sport=50836 dport=6666 flags=0x10)
cookie matches for client 20200c0
ΠΠΎΠΊΠ° Π½Π΅Ρ ΡΠΏΠΈΡΠΊΠ° ΠΏΡΠΎΠ²Π΅ΡΠ΅Π½Π½ΡΡ IP, Π·Π°ΡΠΈΡΡ ΠΎΡΒ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ SYN flood Π½Π΅Β Π±ΡΠ΄Π΅Ρ, Π½ΠΎΒ Π²ΠΎΡ ΡΠ΅Π°ΠΊΡΠΈΡ Π½Π°Β ACK flood, Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌΡΠΉ ΡΠ°ΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ:
sudo ip netns exec xdp-test hping3 --flood -A -s 1111 -p 2222 192.0.2.1
ΠΠ°ΠΏΠΈΡΠΈ Π²Β Π»ΠΎΠ³Π΅:
Ether(proto=0x800)
IP(src=0x15bd11a dst=0x15bd11e proto=6)
TCP(sport=3236 dport=2222 flags=0x10)
cookie mismatch
ΠΠ°ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅
ΠΠ½ΠΎΠ³Π΄Π° eBPF Π²ΠΎΠΎΠ±ΡΠ΅ ΠΈ XDP Π² ΡΠ°ΡΡΠ½ΠΎΡΡΠΈ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ ΡΠΊΠΎΡΠ΅Π΅ ΠΊΠ°ΠΊΒ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½Ρ ΠΏΡΠΎΠ΄Π²ΠΈΠ½ΡΡΠΎΠ³ΠΎ Π°Π΄ΠΌΠΈΠ½ΠΈΡΡΡΠ°ΡΠΎΡΠ°, Π½Π΅ΠΆΠ΅Π»ΠΈΒ ΠΊΠ°ΠΊΒ ΠΏΠ»Π°ΡΡΠΎΡΠΌΠ° Π΄Π»ΡΒ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ. ΠΠ΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ, XDPΒ β ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½Ρ Π²ΠΌΠ΅ΡΠ°ΡΠ΅Π»ΡΡΡΠ²Π° Π²Β ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ² ΡΠ΄ΡΠΎΠΌ, Π°Β Π½Π΅Β Π°Π»ΡΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π° ΡΠ΄Π΅ΡΠ½ΠΎΠΌΡ ΡΡΠ΅ΠΊΡ, ΠΊΠ°ΠΊΒ DPDK ΠΈΒ ΠΏΡΠΎΡΠΈΠ΅ Π²Π°ΡΠΈΠ°Π½ΡΡ kernel bypass. Π‘Β Π΄ΡΡΠ³ΠΎΠΉ ΡΡΠΎΡΠΎΠ½Ρ, XDP ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΡΠ»ΠΎΠΆΠ½ΡΡ Π»ΠΎΠ³ΠΈΠΊΡ, ΠΊΠΎΡΠΎΡΡΡ, ΠΊΒ ΡΠΎΠΌΡΒ ΠΆΠ΅, Π»Π΅Π³ΠΊΠΎ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡΡ Π±Π΅Π·Β ΠΏΠ°ΡΠ·Ρ Π²Β ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ΅ ΡΡΠ°ΡΠΈΠΊΠ°. ΠΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ Π½Π΅Β ΡΠΎΠ·Π΄Π°Π΅Ρ Π±ΠΎΠ»ΡΡΠΈΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌ, Π»ΠΈΡΠ½ΠΎ Ρ Π½Π΅Β ΠΎΡΠΊΠ°Π·Π°Π»ΡΡΒ Π±Ρ ΠΎΡΒ ΡΠ°ΠΊΠΎΠ³ΠΎ Π΄Π»ΡΒ ΡΠ°ΡΡΠ΅ΠΉ userspace-ΠΊΠΎΠ΄Π°.
ΠΠΎ Π²ΡΠΎΡΠΎΠΉ ΡΠ°ΡΡΠΈ, Π΅ΡΠ»ΠΈ ΡΠ΅ΠΌΠ° ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½Π°, Π΄ΠΎΠ΄Π΅Π»Π°Π΅ΠΌ ΡΠ°Π±Π»ΠΈΡΡ ΠΏΡΠΎΠ²Π΅ΡΠ΅Π½Π½ΡΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠΎΠ² ΠΈ ΡΠ°Π·ΡΡΠ² ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ, Π²Π½Π΅Π΄ΡΠΈΠΌ ΡΡΠ΅ΡΡΠΈΠΊΠΈ ΠΈ Π½Π°ΠΏΠΈΡΠ΅ΠΌ userspace-ΡΡΠΈΠ»ΠΈΡΡ Π΄Π»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΡΠΈΠ»ΡΡΡΠΎΠΌ.
Π‘ΡΡΠ»ΠΊΠΈ:
ΠΠΎΠ»Π½ΡΠΉ ΠΊΠΎΠ΄ Π½Π°Β GitHub bpftrace Cheat Sheet BPF and XDP Reference Guide XDP Tutorial PoC: compiling to eBPF from Rust
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com