เบžเบงเบเป€เบฎเบปเบฒเบ‚เบฝเบ™เบเบฒเบ™เบ›เป‰เบญเบ‡เบเบฑเบ™เบเบฒเบ™เป‚เบˆเบกเบ•เบต DDoS เปƒเบ™ XDP. เบชเปˆเบงเบ™โ€‹เบ™เบดเบงโ€‹เป€เบ„เบผเบ

เป€เบ—เบเป‚เบ™เป‚เบฅเบเบต eXpress Data Path (XDP) เบŠเปˆเบงเบเปƒเบซเป‰เบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบเบฒเบ™เบˆเบฒเบฅเบฐเบˆเบญเบ™เปเบšเบšเบชเบธเปˆเบกเบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™เบเบฒเบ™เป‚เบ•เป‰เบ•เบญเบš Linux เบเปˆเบญเบ™เบ—เบตเปˆเปเบžเบฑเบเป€เบเบฑเบ”เบˆเบฐเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ stack เป€เบ„เบทเบญเบ‚เปˆเบฒเบ kernel. เบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบเบ‚เบญเบ‡ XDP - เบเบฒเบ™เบ›เป‰เบญเบ‡เบเบฑเบ™เบเบฒเบ™เป‚เบˆเบกเบ•เบต DDoS (CloudFlare), เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เบชเบฐเบฅเบฑเบšเบชเบฑเบšเบŠเป‰เบญเบ™, เบเบฒเบ™เป€เบเบฑเบšเบเปเบฒเบชเบฐเบ–เบดเบ•เบด (Netflix). เป‚เบ›เบฅเปเบเบฅเบก XDP เบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เป‚เบ”เบเป€เบ„เบทเปˆเบญเบ‡ virtual eBPF, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบžเบงเบเบกเบฑเบ™เบกเบตเบ‚เปเป‰เบˆเปเบฒเบเบฑเบ”เบ—เบฑเบ‡เบฅเบฐเบซเบฑเบ”เบ‚เบญเบ‡เบžเบงเบเป€เบ‚เบปเบฒเปเบฅเบฐเบซเบ™เป‰เบฒเบ—เบตเปˆ kernel เบ—เบตเปˆเบกเบตเบขเบนเปˆเบ‚เบถเป‰เบ™เบขเบนเปˆเบเบฑเบšเบ›เบฐเป€เบžเบ”เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡.

เบšเบปเบ”เบ„เบงเบฒเบกเบกเบตเบˆเบธเบ”เบ›เบฐเบชเบปเบ‡เป€เบžเบทเปˆเบญเบ•เบทเปˆเบกเบ‚เปเป‰เบšเบปเบเบœเปˆเบญเบ‡เบ‚เบญเบ‡เบงเบฑเบ”เบชเบฐเบ”เบธเบˆเปเบฒเบ™เบงเบ™เบซเบฅเบฒเบเปƒเบ™ XDP. เบเปˆเบญเบ™เบญเบทเปˆเบ™ เปเบปเบ”, เบžเบงเบเป€เบ‚เบปเบฒเปƒเบซเป‰เบฅเบฐเบซเบฑเบ”เบ—เบตเปˆเบžเป‰เบญเบกเบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เป‚เบ”เบเบ—เบฑเบ™เบ—เบตเบ—เบตเปˆเบ‚เป‰เบฒเบกเบฅเบฑเบเบชเบฐเบ™เบฐเบ‚เบญเบ‡ XDP: เบกเบฑเบ™เบ–เบทเบเบเบฐเบเบฝเบกเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบขเบฑเป‰เบ‡เบขเบทเบ™เบซเบผเบทเบ‡เปˆเบฒเบเบ”เบฒเบเป€เบเบตเบ™เป„เบ›เบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เปƒเบซเป‰เป€เบเบตเบ”เบšเบฑเบ™เบซเบฒ. เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบ—เปˆเบฒเบ™เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบžเบฐเบเบฒเบเบฒเบกเบ‚เบฝเบ™เบฅเบฐเบซเบฑเบ”เบ‚เบญเบ‡เบ—เปˆเบฒเบ™เบˆเบฒเบ scratch, เบ—เปˆเบฒเบ™เบšเปเปˆเบกเบตเบ„เบงเบฒเบกเบ„เบดเบ”เบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เปเบ™เบงเปƒเบ”เบเบฑเบšเบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”เบ›เบปเบเบเบฐเบ•เบด. เบญเบฑเบ™เบ—เบตเบชเบญเบ‡, เบงเบดเบ—เบตเบเบฒเบ™เบ—เบปเบ”เบชเบญเบš XDP เปƒเบ™เบ—เป‰เบญเบ‡เบ–เบดเปˆเบ™เป‚เบ”เบเบšเปเปˆเบกเบต VM เปเบฅเบฐเบฎเบฒเบ”เปเบงเบšเปเปˆเป„เบ”เป‰เบ–เบทเบเบ„เบธเป‰เบกเบ„เบญเบ‡, เป€เบ–เบดเบ‡เบงเปˆเบฒเบˆเบฐเบกเบตเบ„เบงเบฒเบกเบˆเบดเบ‡เบ—เบตเปˆเบงเปˆเบฒเบžเบงเบเป€เบ‚เบปเบฒเบกเบตเบ‚เบธเบกเบ‚เบญเบ‡เบ•เบปเบ™เป€เบญเบ‡. เบ‚เปเป‰เบ„เบงเบฒเบกเปเบกเปˆเบ™เบกเบตเบˆเบธเบ”เบ›เบฐเบชเบปเบ‡เบชเปเบฒเบฅเบฑเบšเบ™เบฑเบเบ‚เบฝเบ™เป‚เบ›เบฅเปเบเบฅเบกเบ—เบตเปˆเบ„เบธเป‰เบ™เป€เบ„เบตเบเบเบฑเบšเป€เบ„เบทเบญเบ‚เปˆเบฒเบเปเบฅเบฐ Linux เบ—เบตเปˆเบกเบตเบ„เบงเบฒเบกเบชเบปเบ™เปƒเบˆเปƒเบ™ XDP เปเบฅเบฐ eBPF.

เปƒเบ™เบชเปˆเบงเบ™เบ™เบตเป‰, เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเป€เบ‚เบปเป‰เบฒเปƒเบˆเบขเปˆเบฒเบ‡เบฅเบฐเบญเบฝเบ”เบงเปˆเบฒเบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡ XDP เบ–เบทเบเบ›เบฐเบเบญเบšเปเบฅเบฐเบงเบดเบ—เบตเบเบฒเบ™เบ—เบปเบ”เบชเบญเบšเบกเบฑเบ™, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ‚เบฝเบ™เปเบšเบšเบ‡เปˆเบฒเบเป†เบ‚เบญเบ‡เบเบปเบ™เป„เบเบเบฒเบ™เบ„เบธเบเบเบต SYN เบ—เบตเปˆเบกเบตเบŠเบทเปˆเบชเบฝเบ‡เปƒเบ™เบฅเบฐเบ”เบฑเบšเบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เปเบžเบฑเบเป€เบเบฑเบ”. เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบšเปเปˆเบชเป‰เบฒเบ‡ "เบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆเบชเบตเบ‚เบฒเบง" เป€เบ—เบทเปˆเบญ
เบฅเบนเบเบ„เป‰เบฒเบ—เบตเปˆเบ–เบทเบเบขเบทเบ™เบขเบฑเบ™, เบฎเบฑเบเบชเบฒเป€เบ„เบทเปˆเบญเบ‡เบ™เบฑเบšเปเบฅเบฐเบˆเบฑเบ”เบเบฒเบ™เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡ - เบšเบฑเบ™เบ—เบถเบเบžเบฝเบ‡เบžเป.

เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ‚เบฝเบ™เปƒเบ™ C - เบกเบฑเบ™เบšเปเปˆเปเบกเปˆเบ™เบ„เบปเบ™เบญเบฑเบšเป€เบ”เบ”:, เปเบ•เปˆเบกเบฑเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เป„เบ”เป‰. เบฅเบฐเบซเบฑเบ”เบ—เบฑเบ‡เบซเบกเบปเบ”เปเบกเปˆเบ™เบกเบตเบขเบนเปˆเปƒเบ™ GitHub เบœเปˆเบฒเบ™เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเปƒเบ™เบ•เบญเบ™เบ—เป‰เบฒเบเปเบฅเบฐเปเบšเปˆเบ‡เบญเบญเบเป€เบ›เบฑเบ™เบ„เปเบฒเบซเบกเบฑเป‰เบ™เบชเบฑเบ™เบเบฒเบ•เบฒเบกเบ‚เบฑเป‰เบ™เบ•เบญเบ™เบ—เบตเปˆเป„เบ”เป‰เบญเบฐเบ—เบดเบšเบฒเบเป„เบงเป‰เปƒเบ™เบšเบปเบ”เบ„เบงเบฒเบก.

เบเบฒเบ™เบ›เบฐเบ•เบดเป€เบชเบ”. เปƒเบ™เป„เบฅเบเบฐเบ‚เบญเบ‡เบšเบปเบ”เบ„เบงเบฒเบกเบ™เบตเป‰, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบˆเบฐเบžเบฑเบ”เบ—เบฐเบ™เบฒเบเบฒเบ™เปเบเป‰เป„เบ‚ mini เป€เบžเบทเปˆเบญเบ›เป‰เบญเบ‡เบเบฑเบ™เบเบฒเบ™เป‚เบˆเบกเบ•เบต DDoS, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเบ™เบตเป‰เปเบกเปˆเบ™เบงเบฝเบเบ‡เบฒเบ™เบ—เบตเปˆเปเบ—เป‰เบˆเบดเบ‡เบชเปเบฒเบฅเบฑเบš XDP เปเบฅเบฐเบžเบทเป‰เบ™เบ—เบตเปˆเบ„เบงเบฒเบกเบŠเปˆเบฝเบงเบŠเบฒเบ™เบ‚เบญเบ‡เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒ. เบขเปˆเบฒเบ‡เปƒเบ”เบเปเปˆเบ•เบฒเบก, เป€เบ›เบปเป‰เบฒเบซเบกเบฒเบเบ•เบปเป‰เบ™เบ•เปเปเบกเปˆเบ™เป€เบžเบทเปˆเบญเป€เบ‚เบปเป‰เบฒเปƒเบˆเป€เบ•เบฑเบเป‚เบ™เป‚เบฅเบขเบต; เบฅเบฐเบซเบฑเบ”เบเบฒเบ™เบชเบญเบ™เบšเปเปˆเป„เบ”เป‰เบ–เบทเบเบ›เบฑเบšเปƒเบซเป‰เป€เปเบฒเบฐเบชเบปเบก เปเบฅเบฐเบšเปเปˆเบกเบตเบšเบฒเบ‡เบญเบฑเบ™.

เบžเบฒเบšเบฅเบงเบกเบ‚เบญเบ‡ XDP

เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบˆเบฐเบญเบฐเบ—เบดเบšเบฒเบเบžเบฝเบ‡เปเบ•เปˆเบˆเบธเบ”เบชเปเบฒเบ„เบฑเบ™เป€เบžเบทเปˆเบญเบšเปเปˆเปƒเบซเป‰เบŠเป‰เปเบฒเบเบฑเบ™เป€เบญเบเบฐเบชเบฒเบ™เปเบฅเบฐเบšเบปเบ”เบ„เบงเบฒเบกเบ—เบตเปˆเบกเบตเบขเบนเปˆเปเบฅเป‰เบง.

เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™, เบฅเบฐเบซเบฑเบ”เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เบ–เบทเบเป‚เบซเบฅเบ”เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เปเบเปˆเบ™. เปเบžเบฑเบเป€เบเบฑเบ”เบ—เบตเปˆเป€เบ‚เบปเป‰เบฒเบกเบฒเปเบกเปˆเบ™เบ–เบทเบเบชเบปเปˆเบ‡เป„เบ›เบซเบฒเบ•เบปเบงเบเบญเบ‡. เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™, เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เบ•เป‰เบญเบ‡เป„เบ”เป‰เบ•เบฑเบ”เบชเบดเบ™เปƒเบˆ: เบœเปˆเบฒเบ™เปเบžเบฑเบเป€เบเบฑเบ”เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เปเบเปˆเบ™ (.XDP_PASS) เบงเบฒเบ‡โ€‹เบŠเบญเบ‡ (XDP_DROP) เบซเบผเบทโ€‹เบชเบปเปˆเบ‡โ€‹เบ„เบทเบ™ (XDP_TX). เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เบชเบฒเบกเบฒเบ”เบ›เปˆเบฝเบ™เบŠเบธเบ”, เบ™เบตเป‰เปเบกเปˆเบ™เบ„เบงเบฒเบกเบˆเบดเบ‡เป‚เบ”เบเบชเบฐเป€เบžเบฒเบฐเบชเปเบฒเบฅเบฑเบš XDP_TX. เบ™เบญเบเบ™เบฑเป‰เบ™เบ—เปˆเบฒเบ™เบเบฑเบ‡เบชเบฒเบกเบฒเบ”เบเบปเบเป€เบฅเบตเบเป‚เบ„เบ‡เบเบฒเบ™ (XDP_ABORTED) เปเบฅเบฐเบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบŠเบธเบ”เปƒเบซเบกเปˆ, เปเบ•เปˆเบ™เบตเป‰เปเบกเปˆเบ™เบ„เป‰เบฒเบเบ„เบทเบเบฑเบ™ assert(0) - เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™ debugging.

เป€เบ„เบทเปˆเบญเบ‡ virtual eBPF (extended Berkley Packet Filter) เปเบกเปˆเบ™เบ–เบทเบเบชเป‰เบฒเบ‡เปเบšเบšเบ‡เปˆเบฒเบเบ”เบฒเบเป‚เบ”เบเป€เบˆเบ”เบ•เบฐเบ™เบฒเป€เบžเบทเปˆเบญเปƒเบซเป‰ kernel เบชเบฒเบกเบฒเบ”เบเบงเบ”เป€เบšเบดเปˆเบ‡เบงเปˆเบฒเบฅเบฐเบซเบฑเบ”เบšเปเปˆ loop เปเบฅเบฐเบšเปเปˆเบ—เปเบฒเบฅเบฒเบเบ„เบงเบฒเบกเบŠเบปเบ‡เบˆเปเบฒเบ‚เบญเบ‡เบ„เบปเบ™เบญเบทเปˆเบ™. เบ‚เปเป‰โ€‹เบˆเปเบฒโ€‹เบเบฑเบ”โ€‹เบชเบฐโ€‹เบชเบปเบกโ€‹เปเบฅเบฐโ€‹เบเบฒเบ™โ€‹เบเบงเบ”โ€‹เบชเบญเบšโ€‹:

  • Loops (เบเบฑเบšโ€‹เบ„เบทเบ™โ€‹เป„เบ›โ€‹เบšเปˆเบญเบ™โ€‹) เปเบกเปˆเบ™โ€‹เบซเป‰เบฒเบกโ€‹.
  • เบกเบต stack เบชเปเบฒเบฅเบฑเบšเบ‚เปเป‰เบกเบนเบ™, เปเบ•เปˆเบšเปเปˆเบกเบตเบŸเบฑเบ‡เบŠเบฑเบ™ (เบŸเบฑเบ‡เบŠเบฑเบ™ C เบ—เบฑเบ‡เบซเบกเบปเบ”เบ•เป‰เบญเบ‡เบขเบนเปˆเปƒเบ™เปเบ–เบง).
  • เบเบฒเบ™เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบ„เบงเบฒเบกเบŠเบปเบ‡เบˆเปเบฒเบขเบนเปˆเบ™เบญเบ stack เปเบฅเบฐ packet buffer เปเบกเปˆเบ™เบ–เบทเบเบซเป‰เบฒเบก.
  • เบ‚เบฐเบซเบ™เบฒเบ”เบฅเบฐเบซเบฑเบ”เปเบกเปˆเบ™เบˆเปเบฒเบเบฑเบ”, เปเบ•เปˆเปƒเบ™เบ—เบฒเบ‡เบ›เบฐเบ•เบดเบšเบฑเบ”, เบ™เบตเป‰เบšเปเปˆเปเบกเปˆเบ™เบ„เบงเบฒเบกเบชเปเบฒเบ„เบฑเบ™เบซเบผเบฒเบ.
  • เบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เป‚เบ—เบซเบฒเบŸเบฑเบ‡เบŠเบฑเบ™ kernel เบžเบดเป€เบชเบ” (เบ•เบปเบงเบŠเปˆเบงเบ eBPF) เป€เบ—เบปเปˆเบฒเบ™เบฑเป‰เบ™.

เบเบฒเบ™เบญเบญเบเปเบšเบšเปเบฅเบฐเบ•เบดเบ”เบ•เบฑเป‰เบ‡เบ•เบปเบงเบเบญเบ‡เป€เบšเบดเปˆเบ‡เบ„เบทเบงเปˆเบฒเบ™เบตเป‰:

  1. เบฅเบฐเบซเบฑเบ”เปเบซเบผเปˆเบ‡ (เบ•เบปเบงเบขเปˆเบฒเบ‡ kernel.c) เบ–เบทเบเบฅเบงเบšเบฅเบงเบกเป€เบ›เบฑเบ™เบงเบฑเบ”เบ–เบธ (kernel.o) เบชเปเบฒเบฅเบฑเบšเบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒเป€เบ„เบทเปˆเบญเบ‡ virtual eBPF. เปƒเบ™เป€เบ”เบทเบญเบ™เบ•เบธเบฅเบฒ 2019, เบเบฒเบ™เบฅเบงเบšเบฅเบงเบกเบ‚เปเป‰เบกเบนเบ™เปƒเบชเปˆ eBPF เป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบชเบฐเบซเบ™เบฑเบšเบชเบฐเบซเบ™เบนเบ™เป‚เบ”เบ Clang เปเบฅเบฐเบชเบฑเบ™เบเบฒเป„เบงเป‰เปƒเบ™ GCC 10.1.
  2. เบ–เป‰เบฒเบฅเบฐเบซเบฑเบ”เบงเบฑเบ”เบ–เบธเบ™เบตเป‰เบกเบตเบเบฒเบ™เป‚เบ—เบซเบฒเป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ‚เบญเบ‡เปเบเปˆเบ™ (เบ•เบปเบงเบขเปˆเบฒเบ‡, เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เปเบฅเบฐเบ•เบปเบงเบ™เบฑเบš), ID เบ‚เบญเบ‡เบžเบงเบเบกเบฑเบ™เบ–เบทเบเปเบ—เบ™เบ—เบตเปˆเบ”เป‰เบงเบเบชเบนเบ™, เบŠเบถเปˆเบ‡เบซเบกเบฒเบเบ„เบงเบฒเบกเบงเปˆเบฒเบฅเบฐเบซเบฑเบ”เบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเบšเปเปˆเบชเบฒเบกเบฒเบ”เบ›เบฐเบ•เบดเบšเบฑเบ”เป„เบ”เป‰. เบเปˆเบญเบ™เบ—เบตเปˆเบˆเบฐเป‚เบซเบฅเบ”เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ kernel, เบ—เปˆเบฒเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป„เบ”เป‰เบ—เบปเบ”เปเบ—เบ™เบชเบนเบ™เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เบ”เป‰เบงเบ IDs เบ‚เบญเบ‡เบงเบฑเบ”เบ–เบธเบชเบฐเป€เบžเบฒเบฐเบ—เบตเปˆเบชเป‰เบฒเบ‡เบ‚เบถเป‰เบ™เป‚เบ”เบเบœเปˆเบฒเบ™เบเบฒเบ™เป‚เบ— kernel (เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบฅเบฐเบซเบฑเบ”). เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เบชเบดเปˆเบ‡เบ™เบตเป‰เบเบฑเบšเบญเบธเบ›เบฐเบเบญเบ™เบžเบฒเบเบ™เบญเบ, เบซเบผเบทเบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ‚เบฝเบ™เป‚เบ›เบผเปเบเบผเบกเบ—เบตเปˆเบˆเบฐเป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเปเบฅเบฐเป‚เบซเบฅเบ”เบ•เบปเบงเบเบญเบ‡เบชเบฐเป€เบžเบฒเบฐ.
  3. kernel เบเบงเบ”เบชเบญเบšเป‚เบ„เบ‡เบเบฒเบ™เบ—เบตเปˆเป‚เบซเบฅเบ”. เบเบฒเบ™เบ‚เบฒเบ”เบฎเบญเบšเบงเบฝเบ™เปเบฅเบฐเบ„เบงเบฒเบกเบฅเบปเป‰เบกเป€เบซเบผเบงเบ—เบตเปˆเบˆเบฐเป€เบเบตเบ™ packet เปเบฅเบฐ stack boundaries เปเบกเปˆเบ™เบเบฒเบ™เบเบงเบ”เบชเบญเบš. เบ–เป‰เบฒเบœเบนเป‰เบเบงเบ”เบชเบญเบšเบšเปเปˆเบชเบฒเบกเบฒเบ”เบžเบดเบชเบนเบ”เป„เบ”เป‰เบงเปˆเบฒเบฅเบฐเบซเบฑเบ”เบ–เบทเบเบ•เป‰เบญเบ‡, เป‚เบ„เบ‡เบเบฒเบ™เบ–เบทเบเบ›เบฐเบ•เบดเป€เบชเบ” - เบ—เปˆเบฒเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เปƒเบซเป‰เบฅเบฒเบงเบžเปเปƒเบˆ.
  4. เบซเบผเบฑเบ‡เบˆเบฒเบเบเบฒเบ™เบเบงเบ”เบชเบญเบšเบชเบปเบšเบœเบปเบ™เบชเปเบฒเป€เบฅเบฑเบ”, kernel เบฅเบงเบšเบฅเบงเบกเบฅเบฐเบซเบฑเบ”เบงเบฑเบ”เบ–เบธเบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒ eBPF เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบฅเบฐเบซเบฑเบ”เป€เบ„เบทเปˆเบญเบ‡เบˆเบฑเบเบชเปเบฒเบฅเบฑเบšเบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒเบฅเบฐเบšเบปเบš (เบžเบฝเบ‡เปเบ•เปˆเปƒเบ™เบ—เบตเปˆเปƒเบŠเป‰เป€เบงเบฅเบฒ).
  5. เป‚เบ„เบ‡โ€‹เบเบฒเบ™โ€‹เบ•เบดเบ”โ€‹เบเบฑเบšโ€‹เบเบฒเบ™โ€‹เป‚เบ•เป‰โ€‹เบ•เบญเบšโ€‹เปเบฅเบฐโ€‹เป€เบฅเบตเปˆเบกโ€‹เบ•เบปเป‰เบ™โ€‹เบเบฒเบ™โ€‹เบ›เบธเบ‡โ€‹เปเบ•เปˆเบ‡โ€‹เบŠเบญเบ‡โ€‹.

เบ™เบฑเบšเบ•เบฑเป‰เบ‡เปเบ•เปˆ XDP เปเบฅเปˆเบ™เบขเบนเปˆเปƒเบ™เปเบเปˆเบ™, เบเบฒเบ™เบ”เบตเบšเบฑเบเปเบกเปˆเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เป‚เบ”เบเปƒเบŠเป‰เบšเบฑเบ™เบ—เบถเบเบเบฒเบ™เบ•เบดเบ”เบ•เบฒเบกเปเบฅเบฐ, เปƒเบ™เบ„เบงเบฒเบกเป€เบ›เบฑเบ™เบˆเบดเบ‡, เบŠเบธเบ”เบ—เบตเปˆเป‚เบ„เบ‡เบเบฒเบ™เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เบซเบผเบทเบชเป‰เบฒเบ‡. เบขเปˆเบฒเบ‡เปƒเบ”เบเปเปˆเบ•เบฒเบก, eBPF เบฎเบฑเบšเบ›เบฐเบเบฑเบ™เบงเปˆเบฒเบฅเบฐเบซเบฑเบ”เบ—เบตเปˆเบ”เบฒเบงเป‚เบซเบฅเบ”เปเบกเปˆเบ™เบ›เบญเบ”เป„เบžเบชเปเบฒเบฅเบฑเบšเบฅเบฐเบšเบปเบš, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ—เบปเบ”เบฅเบญเบ‡เบเบฑเบš XDP เป‚เบ”เบเบเบปเบ‡เปƒเบ™ Linux เบ—เป‰เบญเบ‡เบ–เบดเปˆเบ™เบ‚เบญเบ‡เบ—เปˆเบฒเบ™.

เบเบฒเบ™เบเบฐเบเบฝเบกเบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบก

Assembly

Clang เบšเปเปˆเบชเบฒเบกเบฒเบ”เบœเบฐเบฅเบดเบ”เบฅเบฐเบซเบฑเบ”เบงเบฑเบ”เบ–เบธเป‚เบ”เบเบเบปเบ‡เบชเปเบฒเบฅเบฑเบšเบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒ eBPF, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ›เบฐเบเบญเบšเบ”เป‰เบงเบเบชเบญเบ‡เบ‚เบฑเป‰เบ™เบ•เบญเบ™:

  1. เบฅเบงเบšเบฅเบงเบกเบฅเบฐเบซเบฑเบ” C เป€เบ›เบฑเบ™ LLVM bytecode (clang -emit-llvm).
  2. เบ›เปˆเบฝเบ™ bytecode เป€เบ›เบฑเบ™เบฅเบฐเบซเบฑเบ”เบงเบฑเบ”เบ–เบธ eBPF (llc -march=bpf -filetype=obj).

เป€เบกเบทเปˆเบญเบ‚เบฝเบ™เบ•เบปเบงเบเบญเบ‡, เบชเบญเบ‡เป„เบŸเบฅเปŒเบ—เบตเปˆเบกเบตเบซเบ™เป‰เบฒเบ—เบตเปˆเบŠเปˆเบงเบเปเบฅเบฐ macros เบˆเบฐเป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ” เบˆเบฒเบโ€‹เบเบฒเบ™โ€‹เบ—เบปเบ”โ€‹เบชเบญเบš kernelโ€‹. เบกเบฑเบ™เป€เบ›เบฑเบ™เบชเบดเปˆเบ‡ เบชเบณ เบ„เบฑเบ™เบ—เบตเปˆเบžเบงเบเบกเบฑเบ™เบเบปเบ‡เบเบฑเบšเบฅเบธเป‰เบ™ kernel (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 (kernel 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 เบ›เบฐเบเบญเบšเบกเบตเป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡เป„เบ›เบซเบฒเบซเบปเบง kernel, ARCH - เบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบฅเบฐเบšเบปเบš. เป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡เปเบฅเบฐเป€เบ„เบทเปˆเบญเบ‡เบกเบทเบญเบฒเบ”เบˆเบฐเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™เป€เบฅเบฑเบเบ™เป‰เบญเบเบฅเบฐเบซเบงเปˆเบฒเบ‡เบเบฒเบ™เปเบˆเบเบขเบฒเบ.

เบ•เบปเบงเบขเปˆเบฒเบ‡เบ„เบงเบฒเบกเปเบ•เบเบ•เปˆเบฒเบ‡เบ‚เบญเบ‡ Debian 10 (kernel 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) headers เบ–เบทเบเบเปเบฒเบ™เบปเบ”เบชเปเบฒเบฅเบฑเบšเบฅเบฐเบซเบฑเบ” kernel, เบ™เบฑเบšเบ•เบฑเป‰เบ‡เปเบ•เปˆเบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เป„เบ”เป‰เบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™ kernel.

เบเบฒเบ™เบ›เป‰เบญเบ‡เบเบฑเบ™ stack เบชเบฒเบกเบฒเบ”เบ–เบทเบเบ›เบดเบ”เปƒเบŠเป‰เบ‡เบฒเบ™ (-fno-stack-protector), เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเบ•เบปเบงเบเบงเบ”เบชเบญเบšเบฅเบฐเบซเบฑเบ” eBPF เบเบฑเบ‡เบเบงเบ”เบชเบญเบšเบเบฒเบ™เบฅเปˆเบงเบ‡เบฅเบฐเป€เบกเบตเบ” stack out-of-bounds. เบกเบฑเบ™เบ„เบธเป‰เบกเบ„เปˆเบฒเบ—เบตเปˆเบˆเบฐเป€เบ›เบตเบ”เบเบฒเบ™เป€เบžเบตเปˆเบกเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบ—เบฑเบ™เบ—เบต, เป€เบžเบฒเบฐเบงเปˆเบฒเบ‚เบฐเบซเบ™เบฒเบ”เบ‚เบญเบ‡ bytecode 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) เปเบกเปˆเบ™เป€เบซเบกเบฒเบฐเบชเบปเบกเบชเปเบฒเบฅเบฑเบšเบžเบงเบเป€เบฎเบปเบฒ: เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เปเบกเปˆเบ™เบ„เบนเปˆเบ‚เบญเบ‡เบเบฒเบ™เป‚เบ•เป‰เบ•เบญเบšเป€เบ„เบทเบญเบ‚เปˆเบฒเบ virtual "เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ" เป‚เบ”เบเบเบปเบ‡เบเบฑเบšเบเบฑเบ™เปเบฅเบฐเบเบฑเบ™. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบชเป‰เบฒเบ‡เบžเบงเบเบกเบฑเบ™เป„เบ”เป‰เปเบšเบšเบ™เบตเป‰ (เปƒเบ™เบžเบฒเบเบ™เบตเป‰เบ„เปเบฒเบชเบฑเปˆเบ‡เบ—เบฑเบ‡เบซเบกเบปเบ” 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 เบˆเบฐเบšเปเปˆเบชเบปเปˆเบ‡เบเบฒเบ™เบˆเบฐเบฅเบฒเบˆเบญเบ™เป„เบ›เบซเบฒเบซเบ™เบถเปˆเบ‡เปƒเบ™เบ™เบฑเป‰เบ™เป‚เบ”เบเบœเปˆเบฒเบ™เป€เบ„เบทเปˆเบญเบ‡เบญเบทเปˆเบ™. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เปเบเป‰เป„เบ‚เบ™เบตเป‰เบ”เป‰เบงเบเบเบปเบ”เบฅเบฐเบšเบฝเบš tricky iptables, เปเบ•เปˆเบžเบงเบเป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒเบˆเบฐเบ•เป‰เบญเบ‡เบกเบตเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบเบฒเบ™เบซเบธเป‰เบกเบซเปเปˆ, เบŠเบถเปˆเบ‡เบšเปเปˆเบชเบฐเบ”เบงเบเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™ debugging. เบกเบฑเบ™เบ”เบตเบเบงเปˆเบฒเบ—เบตเปˆเบˆเบฐเปƒเบŠเป‰ namespaces เป€เบ„เบทเบญเบ‚เปˆเบฒเบ (เบ•เปเปˆเป„เบ›เบ™เบตเป‰เปเบกเปˆเบ™ netns).

namespace เป€เบ„เบทเบญเบ‚เปˆเบฒเบเบ›เบฐเบเบญเบšเบ”เป‰เบงเบเบŠเบธเบ”เบ‚เบญเบ‡เบชเปˆเบงเบ™เบ•เบดเบ”เบ•เปเปˆ, เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบเบฒเบ™เบเปเบฒเบ™เบปเบ”เป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡, เปเบฅเบฐเบเบปเบ”เบฅเบฐเบšเบฝเบš NetFilter เบ—เบตเปˆเป‚เบ”เบ”เบ”เปˆเบฝเบงเบˆเบฒเบเบงเบฑเบ”เบ–เบธเบ—เบตเปˆเบ„เป‰เบฒเบเบ„เบทเบเบฑเบ™เปƒเบ™ netns เบญเบทเปˆเบ™เป†. เปเบ•เปˆเบฅเบฐเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบขเบนเปˆเปƒเบ™ namespace เปเบฅเบฐเบกเบตเบžเบฝเบ‡เปเบ•เปˆเป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบงเบฑเบ”เบ–เบธเบ‚เบญเบ‡ netns เบ™เบฑเป‰เบ™. เป‚เบ”เบเบ„เปˆเบฒเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™, เบฅเบฐเบšเบปเบšเบกเบต namespace เป€เบ„เบทเบญเบ‚เปˆเบฒเบเบ”เบฝเบงเบชเปเบฒเบฅเบฑเบšเบงเบฑเบ”เบ–เบธเบ—เบฑเบ‡เบซเบกเบปเบ”, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เบงเบฝเบเบขเบนเปˆเปƒเบ™ Linux เปเบฅเบฐเบšเปเปˆเบฎเบนเป‰เบเปˆเบฝเบงเบเบฑเบš netns.

เบกเบฒเบชเป‰เบฒเบ‡ namespace เปƒเปเปˆ 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 ... เปƒเบ™ namespace เบ„เปเบฒเบชเบฑเปˆเบ‡เบ™เบตเป‰ 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 เปƒเบ™ namespace เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™:

    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. repository เบกเบต script เบ—เบตเปˆ automates เป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบš stand เป„เบ”เป‰, เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบเบปเบเบ•เบปเบงเบขเปˆเบฒเบ‡, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ” configure stand เบ”เป‰เบงเบเบ„เปเบฒเบชเบฑเปˆเบ‡ sudo ./stand up เปเบฅเบฐเบฅเบถเบšเบกเบฑเบ™ sudo ./stand down.

เบเบฒเบ™เบ•เบดเบ”เบ•เบฒเบก

เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เปเบกเปˆเบ™เบเปˆเบฝเบงเบ‚เป‰เบญเบ‡เบเบฑเบšเบญเบธเบ›เบฐเบเบญเบ™เป€เบŠเบฑเปˆเบ™เบ™เบตเป‰:

ip -force link set dev xdp-local xdp object xdp_filter.o verbose

Key -force เบ•เป‰เบญเบ‡เบเบฒเบ™เป€เบžเบทเปˆเบญเป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเป‚เบ„เบ‡เบเบฒเบ™เปƒเบซเบกเปˆเบ–เป‰เบฒเบญเบฑเบ™เบญเบทเปˆเบ™เบ–เบทเบเป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเปเบฅเป‰เบง. "เบšเปเปˆเบกเบตเบ‚เปˆเบฒเบงเป€เบ›เบฑเบ™เบ‚เปˆเบฒเบงเบ”เบต" เบšเปเปˆเปเบกเปˆเบ™เบเปˆเบฝเบงเบเบฑเบšเบ„เปเบฒเบชเบฑเปˆเบ‡เบ™เบตเป‰, เบเบฒเบ™เบชเบฐเบซเบฅเบธเบšเปเบกเปˆเบ™ voluminous เปƒเบ™เบเปเบฅเบฐเบ™เบตเปƒเบ”เบเปเปˆเบ•เบฒเบก. เบŠเบตเป‰เบšเบญเบ 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(), เปเบ•เปˆเบžเบฝเบ‡เปเบ•เปˆเบชเบฐเบซเบ™เบฑเบšเบชเบฐเบซเบ™เบนเบ™เป€เบ–เบดเบ‡เบชเบฒเบก arguments เบ™เบญเบเป€เบซเบ™เบทเบญเบˆเบฒเบเบฎเบนเบšเปเบšเบš, เปเบฅเบฐเบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆเบˆเปเบฒเบเบฑเบ”เบ‚เบญเบ‡ specifiers. เบกเบฐเบซเบฒเบžเบฒเบ bpf_printk() เป€เบฎเบฑเบ”เปƒเบซเป‰เบเบฒเบ™เป‚เบ—เบ‡เปˆเบฒเบเบ‚เบถเป‰เบ™.

   SEC("prog")
   int xdp_main(struct xdp_md* ctx) {
+      bpf_printk("got packet: %pn", ctx);
       return XDP_PASS;
   }

เบœเบปเบ™โ€‹เป„เบ”เป‰โ€‹เบฎเบฑเบšโ€‹เป„เบ›โ€‹เบซเบฒโ€‹เบŠเปˆเบญเบ‡โ€‹เบ—เบฒเบ‡โ€‹เบเบฒเบ™โ€‹เบ•เบดเบ”โ€‹เบ•เบฒเบก kernelโ€‹, เป€เบŠเบดเปˆเบ‡โ€‹เบˆเปเบฒโ€‹เป€เบ›เบฑเบ™โ€‹เบ•เป‰เบญเบ‡โ€‹เป„เบ”เป‰โ€‹เบฎเบฑเบšโ€‹เบเบฒเบ™โ€‹เป€เบ›เบตเบ”โ€‹เปƒเบŠเป‰โ€‹เบ‡เบฒเบ™โ€‹:

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 เบšเปเปˆเบกเบตเบชเปˆเบงเบ™เบ‚เปเป‰เบกเบนเบ™, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบงเบดเบ—เบตเบ”เบฝเบงเบ—เบตเปˆเบˆเบฐเป€เบ‚เบปเป‰เบฒเบฅเบฐเบซเบฑเบ”เบชเบฐเบ•เบฃเบดเบ‡เบฎเบนเบšเปเบšเบšเปเบกเปˆเบ™เบเบฒเบ™เป‚เบ•เป‰เบ–เบฝเบ‡เบ—เบฑเบ™เบ—เบตเบ‚เบญเบ‡เบ„เปเบฒเบชเบฑเปˆเบ‡ VM:

$ python -c "import binascii; print(bytes(reversed(binascii.unhexlify('0a7025203a74656b63617020746f67'))))"
b'got packet: %pn'

เบชเปเบฒเบฅเบฑเบšเป€เบซเบ”เบœเบปเบ™เบ™เบตเป‰, debug output เบขเปˆเบฒเบ‡เบซเบผเบงเบ‡เบซเบผเบฒเบ bloats เบฅเบฐเบซเบฑเบ”เบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบš.

เบเบณเบฅเบฑเบ‡เบชเบปเปˆเบ‡เปเบžเบฑเบเป€เบเบฑเบ” XDP

เบกเบฒเบ›เปˆเบฝเบ™เบ•เบปเบงเบเบญเบ‡เบเบฑเบ™: เปƒเบซเป‰เบกเบฑเบ™เบชเบปเปˆเบ‡เปเบžเบฑเบเป€เบเบฑเบ”เบ—เบตเปˆเป€เบ‚เบปเป‰เบฒเบกเบฒเบ—เบฑเบ‡เปเบปเบ”เบ„เบทเบ™. เบ™เบตเป‰เปเบกเปˆเบ™เบšเปเปˆเบ–เบทเบเบ•เป‰เบญเบ‡เบˆเบฒเบเบ—เบฑเบ”เบชเบฐเบ™เบฐเบ‚เบญเบ‡เป€เบ„เบทเบญเบ‚เปˆเบฒเบ, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเบกเบฑเบ™เป€เบ›เบฑเบ™เบชเบดเปˆเบ‡เบˆเปเบฒเป€เบ›เบฑเบ™เบ—เบตเปˆเบˆเบฐเบ›เปˆเบฝเบ™เบ—เบตเปˆเบขเบนเปˆเปƒเบ™เบชเปˆเบงเบ™เบซเบปเบง, เปเบ•เปˆเปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเปƒเบ™เบซเบผเบฑเบเบเบฒเบ™เปเบกเปˆเบ™เบชเปเบฒเบ„เบฑเบ™.

       bpf_printk("got packet: %pn", ctx);
-      return XDP_PASS;
+      return XDP_TX;
   }

เป€เบ›เบตเบ”เบ•เบปเบง tcpdump เบชเบธเบ” xdp-remote. เบกเบฑเบ™เบ„เบงเบ™เบˆเบฐเบชเบฐเปเบ”เบ‡เปƒเบซเป‰เป€เบซเบฑเบ™เบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เป ICMP Echo เบ‚เบฒเบญเบญเบเปเบฅเบฐเบ‚เบฒเป€เบ‚เบปเป‰เบฒเบ”เบฝเบงเบเบฑเบ™เปเบฅเบฐเบขเบธเบ”เบเบฒเบ™เบชเบฐเปเบ”เบ‡ ICMP Echo Reply. เปเบ•เปˆเบกเบฑเบ™เบšเปเปˆเป„เบ”เป‰เบชเบฐเปเบ”เบ‡เปƒเบซเป‰เป€เบซเบฑเบ™. เบกเบฑเบ™ turns เปƒเบซเป‰โ€‹เป€เบซเบฑเบ™โ€‹เบงเปˆเบฒโ€‹เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เป€เบฎเบฑเบ”โ€‹เบงเบฝเบโ€‹ XDP_TX เปƒเบ™โ€‹เป‚เบ„เบ‡โ€‹เบเบฒเบ™โ€‹เบเปˆเบฝเบงโ€‹เบเบฑเบšโ€‹เบเบฒเบ™โ€‹ xdp-local เปเบกเปˆเบ™เบกเบตเบ„เบงเบฒเบกเบˆเปเบฒเป€เบ›เบฑเบ™เบเบฑเบšเบเบฒเบ™เป‚เบ•เป‰เบ•เบญเบšเบ„เบนเปˆ xdp-remote เป‚เบ„เบ‡เบเบฒเบ™เป„เบ”เป‰เบ–เบทเบเบกเบญเบšเบซเบกเบฒเบ, เป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบกเบฑเบ™เบซเบงเปˆเบฒเบ‡เป€เบ›เบปเปˆเบฒ, เปเบฅเบฐเบฅเบฒเบงเป„เบ”เป‰เบ–เบทเบเบเบปเบเบ‚เบถเป‰เบ™เบกเบฒ.

เบ‚เป‰เบญเบเบฎเบนเป‰เป€เบฅเบทเปˆเบญเบ‡เบ™เบตเป‰เป„เบ”เป‰เปเบ™เบงเปƒเบ”?

เบ•เบดเบ”เบ•เบฒเบกเป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡เบ‚เบญเบ‡เบŠเบธเบ”เปƒเบ™เปเบเปˆเบ™ เบเบปเบ™เป„เบเป€เบซเบ”เบเบฒเบ™ perf เบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰, เป‚เบ”เบเบงเบดเบ—เบตเบ—เบฒเบ‡เบเบฒเบ™, เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เป€เบ„เบทเปˆเบญเบ‡ virtual เบ”เบฝเบงเบเบฑเบ™, เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, eBPF เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™ disassemblies เบเบฑเบš eBPF.

เป€เบˆเบปเป‰เบฒโ€‹เบ•เป‰เบญเบ‡โ€‹เป€เบฎเบฑเบ”โ€‹เบ„เบงเบฒเบกโ€‹เบ”เบตโ€‹เปƒเบซเป‰โ€‹เบžเบปเป‰เบ™โ€‹เบˆเบฒเบโ€‹เบ„เบงเบฒเบกโ€‹เบŠเบปเปˆเบง เป€เบžเบฒเบฐโ€‹เบšเปเปˆโ€‹เบกเบตโ€‹เบซเบเบฑเบ‡โ€‹เบญเบตเบโ€‹เบ—เบตเปˆโ€‹เบˆเบฐโ€‹เป€เบฎเบฑเบ”โ€‹เปƒเบซเป‰โ€‹เบกเบฑเบ™โ€‹เบญเบญเบโ€‹เป„เบ”เป‰.

$ 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

เบ–เป‰เบฒเบžเบฝเบ‡เปเบ•เปˆ ARPs เบ–เบทเบเบชเบฐเปเบ”เบ‡เปเบ—เบ™, เบ—เปˆเบฒเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป€เบญเบปเบฒเบ•เบปเบงเบเบญเบ‡เบญเบญเบ (เบญเบฑเบ™เบ™เบตเป‰ sudo ./stand detach), เปƒเบซเป‰เป„เบ› ping, เบˆเบฒเบเบ™เบฑเป‰เบ™เบ•เบฑเป‰เบ‡เบ•เบปเบงเบเบญเบ‡เปเบฅเป‰เบงเบฅเบญเบ‡เปƒเปเปˆเบญเบตเบเบ„เบฑเป‰เบ‡. เบšเบฑเบ™เบซเบฒเปเบกเปˆเบ™เบงเปˆเบฒเบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡ XDP_TX เบ–เบทเบเบ•เป‰เบญเบ‡เบ—เบฑเบ‡เปƒเบ™ ARP เปเบฅเบฐเบ–เป‰เบฒ stack
namespaces xdp-test เบˆเบฑเบ”เบเบฒเบ™ "เบฅเบทเบก" เบ—เบตเปˆเบขเบนเปˆ MAC 192.0.2.1, เบกเบฑเบ™เบˆเบฐเบšเปเปˆเบชเบฒเบกเบฒเบ”เปเบเป‰เป„เบ‚ IP เบ™เบตเป‰.

เบเบฒเบ™เบชเป‰เบฒเบ‡เบšเบฑเบ™เบซเบฒ

เปƒเบซเป‰เบเป‰เบฒเบงเป„เบ›เบชเบนเปˆเบงเบฝเบเบ‡เบฒเบ™เบ—เบตเปˆเบฅเบฐเบšเบธเป„เบงเป‰: เบ‚เบฝเบ™เบเบปเบ™เป„เบเบเบฒเบ™เบ„เบธเบเบเบต SYN เปƒเบ™ XDP.

เบ™เป‰เปเบฒเบ–เป‰เบงเบก SYN เบเบฑเบ‡เบ„เบปเบ‡เป€เบ›เบฑเบ™เบเบฒเบ™เป‚เบˆเบกเบ•เบต DDoS เบ—เบตเปˆเบ™เบดเบเบปเบก, เป‚เบ”เบเป€เบ™เบทเป‰เบญเปเบ—เป‰เปเบฅเป‰เบงเบ‚เบญเบ‡เบกเบฑเบ™เปเบกเปˆเบ™เบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰. เป€เบกเบทเปˆเบญเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบ–เบทเบเบชเป‰เบฒเบ‡เบ•เบฑเป‰เบ‡เบ‚เบถเป‰เบ™ (เบเบฒเบ™เบˆเบฑเบšเบกเบท TCP), เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเป„เบ”เป‰เบฎเบฑเบš SYN, เบˆเบฑเบ”เบชเบฑเบ™เบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเปƒเบ™เบญเบฐเบ™เบฒเบ„เบปเบ”, เบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบเบฑเบšเบŠเบธเบ” SYNACK เปเบฅเบฐเบฅเปเบ–เป‰เบฒ ACK. เบœเบนเป‰เป‚เบˆเบกเบ•เบตเบžเบฝเบ‡เปเบ•เปˆเบชเบปเปˆเบ‡เปเบžเบฑเบเป€เบเบฑเบ” SYN เบซเบผเบฒเบเบžเบฑเบ™เบŠเบธเบ”เบ•เปเปˆเบงเบดเบ™เบฒเบ—เบตเบˆเบฒเบเบ—เบตเปˆเบขเบนเปˆเบ›เบญเบกเบˆเบฒเบเปเบ•เปˆเบฅเบฐเป‚เบฎเบ”เปƒเบ™ botnet เบซเบผเบฒเบเบžเบฑเบ™เบญเบฑเบ™. เป€เบŠเบตเบšเป€เบงเบตเบ–เบทเบเบšเบฑเบ‡เบ„เบฑเบšเปƒเบซเป‰เบˆเบฑเบ”เบชเบฑเบ™เบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™เบ—เบฑเบ™เบ—เบตเป€เบกเบทเปˆเบญเบกเบฒเบฎเบญเบ”เบ‚เบญเบ‡เปเบžเบฑเบเป€เบเบฑเบ”, เปเบ•เปˆเบ›เปˆเบญเบเบžเบงเบเบกเบฑเบ™เบญเบญเบเบซเบผเบฑเบ‡เบˆเบฒเบเป€เบงเบฅเบฒเบญเบฑเบ™เปƒเบซเบเปˆเบซเบผเบงเบ‡, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™, เบซเบ™เปˆเบงเบเบ„เบงเบฒเบกเบˆเปเบฒเบซเบผเบทเบ‚เปเป‰เบˆเปเบฒเบเบฑเบ”เบˆเบฐเบซเบกเบปเบ”เป„เบ›, เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเปƒเบซเบกเปˆเบšเปเปˆเป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบเบญเบกเบฎเบฑเบš, เปเบฅเบฐเบเบฒเบ™เบšเปเบฅเบดเบเบฒเบ™เบšเปเปˆเบชเบฒเบกเบฒเบ”เปƒเบŠเป‰เป„เบ”เป‰.

เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบšเปเปˆเบˆเบฑเบ”เบชเบฑเบ™เบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™เป‚เบ”เบเบญเบตเบ‡เปƒเบชเปˆเปเบžเบฑเบเป€เบเบฑเบ” SYN, เปเบ•เปˆเบงเปˆเบฒเบžเบฝเบ‡เปเบ•เปˆเบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบเบฑเบšเปเบžเบฑเบเป€เบเบฑเบ” SYNACK, เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบˆเบฐเป€เบ‚เบปเป‰เบฒเปƒเบˆเป„เบ”เป‰เปเบ™เบงเปƒเบ”เบงเปˆเบฒเปเบžเบฑเบเป€เบเบฑเบ” ACK เบ—เบตเปˆเบกเบฒเบฎเบญเบ”เบ•เปเปˆเบกเบฒเบซเบกเบฒเบเป€เบ–เบดเบ‡เปเบžเบฑเบเป€เบเบฑเบ” SYN เบ—เบตเปˆเบšเปเปˆเบ–เบทเบเบšเบฑเบ™เบ—เบถเบเป„เบงเป‰? เบซเบผเบฑเบ‡เบˆเบฒเบเบ—เบตเปˆเบ—เบฑเบ‡เบซเบกเบปเบ”, เบœเบนเป‰เป‚เบˆเบกเบ•เบตเบเบฑเบ‡เบชเบฒเบกเบฒเบ”เบชเป‰เบฒเบ‡ ACKs เบ›เบญเบก. เบˆเบธเบ”เบ‚เบญเบ‡เบ„เบธเบเบเบต SYN เปเบกเปˆเบ™เป€เบžเบทเปˆเบญเป€เบ‚เบปเป‰เบฒเบฅเบฐเบซเบฑเบ”เบกเบฑเบ™ seqnum เบ•เบปเบงเบเปเบฒเบ™เบปเบ”เบเบฒเบ™เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเป€เบ›เบฑเบ™ hash เบ‚เบญเบ‡เบ—เบตเปˆเบขเบนเปˆ, เบžเบญเบ”เปเบฅเบฐเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เป€เบเบทเบญ. เบ–เป‰เบฒ ACK เบชเบฒเบกเบฒเบ”เบกเบฒเบฎเบญเบ”เบเปˆเบญเบ™เบ—เบตเปˆเป€เบเบทเบญเบˆเบฐเบกเบตเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ„เบดเบ”เป„เบฅเปˆ hash เบญเบตเบเป€เบ—เบทเปˆเบญเบซเบ™เบถเปˆเบ‡เปเบฅเบฐเบ›เบฝเบšเบ—เบฝเบšเบเบฑเบš acknum. เบŸเบญเบ acknum เบœเบนเป‰เป‚เบˆเบกเบ•เบตเบšเปเปˆเบชเบฒเบกเบฒเบ”, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเป€เบเบทเบญเบ›เบฐเบเบญเบšเบกเบตเบ„เบงเบฒเบกเบฅเบฑเบš, เปเบฅเบฐเบˆเบฐเบšเปเปˆเบกเบตเป€เบงเบฅเบฒเบ—เบตเปˆเบˆเบฐเบˆเบฑเบ”เบฅเบฝเบ‡เบกเบฑเบ™เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบŠเปˆเบญเบ‡เบ—เบฒเบ‡เบˆเปเบฒเบเบฑเบ”.

เบ„เบธเบเบเบต SYN เป„เบ”เป‰เบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เบกเบฒเบ”เบปเบ™เปเบฅเป‰เบงเปƒเบ™ Linux kernel เปเบฅเบฐเป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบชเบฒเบกเบฒเบ”เบ–เบทเบเป€เบ›เบตเบ”เปƒเบŠเป‰เป‚เบ”เบเบญเบฑเบ”เบ•เบฐเป‚เบ™เบกเบฑเบ”เบ–เป‰เบฒ SYNs เบกเบฒเบฎเบญเบ”เป„เบงเป€เบเบตเบ™เป„เบ›เปเบฅเบฐเบกเบตเบˆเปเบฒเบ™เบงเบ™เบซเบผเบงเบ‡เบซเบผเบฒเบ.

เป‚เบ„เบ‡เบเบฒเบ™เบเบฒเบ™เบชเบถเบเบชเบฒเบเปˆเบฝเบงเบเบฑเบšเบเบฒเบ™เบˆเบฑเบšเบกเบท TCP

TCP เบชเบฐเบซเบ™เบญเบ‡เบเบฒเบ™เบชเบปเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™เป€เบ›เบฑเบ™เบเบฐเปเบชเบ‚เบญเบ‡ bytes, เบ•เบปเบงเบขเปˆเบฒเบ‡, เบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เป HTTP เบ–เบทเบเบชเบปเปˆเบ‡เบœเปˆเบฒเบ™ TCP. เบเบฐเปเบชเบ–เบทเบเบ–เปˆเบฒเบเบ—เบญเบ”เป€เบ›เบฑเบ™เบ•เปˆเบญเบ™เป†เปƒเบ™เปเบžเบฑเบเป€เบเบฑเบ”. เปเบžเบฑเบเป€เบเบฑเบ” TCP เบ—เบฑเบ‡เปเบปเบ”เบกเบตเบ—เบธเบ‡เบ•เบฒเบกเป€เบซเบ”เบœเบปเบ™ เปเบฅเบฐเบ•เบปเบงเป€เบฅเบเบฅเบณเบ”เบฑเบš 32-เบšเบดเบ”:

  • เบเบฒเบ™เบ›เบฐเบชเบปเบกเบ›เบฐเบชเบฒเบ™เบ‚เบญเบ‡เบ—เบธเบ‡เบเปเบฒเบ™เบปเบ”เบšเบปเบ”เบšเบฒเบ”เบ‚เบญเบ‡เบŠเบธเบ”เบชเบฐเป€เบžเบฒเบฐ. เบ—เบธเบ‡ SYN เบŠเบตเป‰เปƒเบซเป‰เป€เบซเบฑเบ™เบงเปˆเบฒเบ™เบตเป‰เปเบกเปˆเบ™เปเบžเบฑเบเป€เบเบฑเบ”เบ—เปเบฒเบญเบดเบ”เบ‚เบญเบ‡เบœเบนเป‰เบชเบปเปˆเบ‡เปƒเบ™เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ. เบ—เบธเบ‡ ACK เบซเบกเบฒเบเบ„เบงเบฒเบกเบงเปˆเบฒเบœเบนเป‰เบชเบปเปˆเบ‡เป„เบ”เป‰เบฎเบฑเบšเบ‚เปเป‰เบกเบนเบ™เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบ—เบฑเบ‡เบซเบกเบปเบ”เป€เบ–เบดเบ‡เป„เบšเบ•เปŒ acknum. เปเบžเบฑเบเป€เบเบฑเบ”เบชเบฒเบกเบฒเบ”เบกเบตเบซเบผเบฒเบเบ—เบธเบ‡ เปเบฅเบฐเบ–เบทเบเป€เบญเบตเป‰เบ™เป‚เบ”เบเบเบฒเบ™เบฅเบงเบกเบเบฑเบ™เบ‚เบญเบ‡เบžเบงเบเบกเบฑเบ™, เบ•เบปเบงเบขเปˆเบฒเบ‡, เบŠเบธเบ” SYNACK.

  • เปเบฒเบเป€เบฅเบเบฅเบณเบ”เบฑเบš (seqnum) เบฅเบฐเบšเบธเบ„เปˆเบฒเบŠเบปเบ”เป€เบŠเบตเบเปƒเบ™เบเบฐเปเบชเบ‚เปเป‰เบกเบนเบ™เบชเบณเบฅเบฑเบšเป„เบšเบ•เปŒเบ—เบณเบญเบดเบ”เบ—เบตเปˆเบ–เบทเบเบชเบปเปˆเบ‡เปƒเบ™เปเบžเบฑเบเป€เบเบฑเบ”เบ™เบตเป‰. เบ•เบปเบงเบขเปˆเบฒเบ‡, เบ–เป‰เบฒเบขเบนเปˆเปƒเบ™เปเบžเบฑเบเป€เบเบฑเบ”เบ—เปเบฒเบญเบดเบ”เบ—เบตเปˆเบกเบต X bytes เบ‚เบญเบ‡เบ‚เปเป‰เบกเบนเบ™เบ•เบปเบงเป€เบฅเบเบ™เบตเป‰เปเบกเปˆเบ™ N, เปƒเบ™เบŠเบธเบ”เบ•เปเปˆเป„เบ›เบ—เบตเปˆเบกเบตเบ‚เปเป‰เบกเบนเบ™เปƒเบซเบกเปˆเบกเบฑเบ™เบˆเบฐเป€เบ›เบฑเบ™ N + X. เปƒเบ™เบ•เบญเบ™เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ‚เบญเบ‡เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ, เปเบ•เปˆเบฅเบฐเบเปˆเบฒเบเป€เบฅเบทเบญเบเบ•เบปเบงเป€เบฅเบเบ™เบตเป‰เปเบšเบšเบชเบธเปˆเบก.

  • เบˆเปเบฒเบ™เบงเบ™เบเบฒเบ™เบฎเบฑเบšเบฎเบนเป‰ (acknum) - เบŠเบปเบ”เป€เบŠเบตเบเบ”เบฝเบงเบเบฑเบ™เบเบฑเบš seqnum, เปเบ•เปˆเบกเบฑเบ™เบšเปเปˆเป„เบ”เป‰เบเปเบฒเบ™เบปเบ”เบˆเปเบฒเบ™เบงเบ™ byte เบ—เบตเปˆเบ–เบทเบเบชเบปเปˆเบ‡, เปเบ•เปˆเบˆเปเบฒเบ™เบงเบ™ byte เบ—เปเบฒเบญเบดเบ”เบˆเบฒเบเบœเบนเป‰เบฎเบฑเบš, เบ—เบตเปˆเบœเบนเป‰เบชเบปเปˆเบ‡เบšเปเปˆเป€เบซเบฑเบ™.

เปƒเบ™เบ•เบญเบ™เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ‚เบญเบ‡เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ, เบเปˆเบฒเบเบ•เปˆเบฒเบ‡เป†เบ•เป‰เบญเบ‡เบ•เบปเบเบฅเบปเบ‡ seqnum ะธ acknum. เบฅเบนเบเบ„เป‰เบฒเบชเบปเปˆเบ‡เบŠเบธเบ” SYN เบเบฑเบšเบกเบฑเบ™ seqnum = X. เป€เบŠเบตเบšเป€เบงเบตเบ•เบญเบšเบชเบฐเปœเบญเบ‡เบ”เป‰เบงเบเปเบžเบฑเบเป€เบเบฑเบ” SYNACK, เบšเปˆเบญเบ™เบ—เบตเปˆเบกเบฑเบ™เบšเบฑเบ™เบ—เบถเบเบ‚เปเป‰เบกเบนเบ™เบ‚เบญเบ‡เบกเบฑเบ™ seqnum = Y เปเบฅเบฐเป€เบ›เบตเบ”เป€เบœเบตเบ acknum = X + 1. เบฅเบนเบเบ„เป‰เบฒเบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบเบฑเบš SYNACK เบ”เป‰เบงเบเบŠเบธเบ” ACK, เบšเปˆเบญเบ™เบ—เบตเปˆ seqnum = X + 1, acknum = Y + 1. เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบตเป‰, เบเบฒเบ™เป‚เบญเบ™เบ‚เปเป‰เบกเบนเบ™เบ•เบปเบงเบˆเบดเบ‡เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™.

เบ–เป‰เบฒเบกเบดเบ”เบชเบฐเบซเบฒเบเบšเปเปˆเบฎเบฑเบšเบฎเบนเป‰เบเบฒเบ™เบฎเบฑเบšเบŠเบญเบ‡, TCP เบˆเบฐเบชเบปเปˆเบ‡เบกเบฑเบ™เบ„เบทเบ™เปƒเปเปˆเบซเบผเบฑเบ‡เบˆเบฒเบเปเบปเบ”เป€เบงเบฅเบฒ.

เป€เบ›เบฑเบ™เบซเบเบฑเบ‡เบ„เบธเบเบเบต SYN เบˆเบถเปˆเบ‡เบšเปเปˆเบ–เบทเบเปƒเบŠเป‰เบชเบฐเป€เปเบต?

เบ—เปเบฒเบญเบดเบ”, เบ–เป‰เบฒ SYNACK เบซเบผเบท ACK เบชเบนเบ™เป€เบชเบ, เบ—เปˆเบฒเบ™เบˆเบฐเบ•เป‰เบญเบ‡เบฅเปเบ–เป‰เบฒเบกเบฑเบ™เบ–เบทเบเบชเบปเปˆเบ‡เป„เบ›เบญเบตเบเป€เบ—เบทเปˆเบญเบซเบ™เบถเปˆเบ‡ - เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบˆเบฐเบŠเป‰เบฒเบฅเบปเบ‡. เบญเบฑเบ™เบ—เบตเบชเบญเบ‡, เปƒเบ™เบŠเบธเบ” SYN - เปเบฅเบฐเบžเบฝเบ‡เปเบ•เปˆเบขเบนเปˆเปƒเบ™เบกเบฑเบ™! โ€” เบˆเปเบฒโ€‹เบ™เบงเบ™โ€‹เบ‚เบญเบ‡โ€‹เบ—เบฒเบ‡โ€‹เป€เบฅเบทเบญเบโ€‹เบ—เบตเปˆโ€‹เบ–เบทเบโ€‹เบชเบปเปˆเบ‡โ€‹เบœเบปเบ™โ€‹เบเบฐโ€‹เบ—เบปเบšโ€‹เบ•เปเปˆโ€‹เบเบฒเบ™โ€‹เบ”เปเบฒโ€‹เป€เบ™เบตเบ™โ€‹เบ‡เบฒเบ™โ€‹เบ‚เบญเบ‡โ€‹เบเบฒเบ™โ€‹เป€เบŠเบทเปˆเบญเบกโ€‹เบ•เปเปˆโ€‹เบ•เปเปˆโ€‹เป„เบ›โ€‹. เป‚เบ”เบเบšเปเปˆเบˆเบทเปˆเปเบžเบฑเบเป€เบเบฑเบ” SYN เบ—เบตเปˆเป€เบ‚เบปเป‰เบฒเบกเบฒ, เป€เบŠเบตเบšเป€เบงเบตเบˆเบถเปˆเบ‡เบšเปเปˆเบชเบปเบ™เปƒเบˆเบ—เบฒเบ‡เป€เบฅเบทเบญเบเป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰, เบฅเบนเบเบ„เป‰เบฒเบˆเบฐเบšเปเปˆเบชเบปเปˆเบ‡เบžเบงเบเบกเบฑเบ™เปƒเบ™เปเบžเบฑเบเป€เบเบฑเบ”เบ•เปเปˆเป„เบ›. TCP เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เบงเบฝเบเปƒเบ™เบเปเบฅเบฐเบ™เบตเบ™เบตเป‰, เปเบ•เปˆเบขเปˆเบฒเบ‡เบซเบ™เป‰เบญเบเปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เป€เบšเบทเป‰เบญเบ‡เบ•เบปเป‰เบ™เบ„เบธเบ™เบ™เบฐเบžเบฒเบšเบ‚เบญเบ‡เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบˆเบฐเบซเบผเบธเบ”เบฅเบปเบ‡.

เบˆเบฒเบเบ—เบฑเบ”เบชเบฐเบ™เบฐเบ‚เบญเบ‡เปเบžเบฑเบเป€เบเบฑเบ”, เป‚เบ„เบ‡เบเบฒเบ™ XDP เบ•เป‰เบญเบ‡เป€เบฎเบฑเบ”เบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

  • เบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบเบฑเบš SYN เบเบฑเบš SYNACK เบเบฑเบšเบ„เบธเบเบเบต;
  • เบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบ•เปเปˆ ACK เบ”เป‰เบงเบ RST (เบ•เบฑเบ”เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ);
  • เบ–เบดเป‰เบกเปเบžเบฑเบเป€เบเบฑเบ”เบ—เบตเปˆเบเบฑเบ‡เป€เบซเบผเบทเบญ.

Pseudocode เบ‚เบญเบ‡ algorithm เบžเป‰เบญเบกเบเบฑเบšเบเบฒเบ™เปเบเบเปเบžเบฑเบเป€เบเบฑเบ”:

ะ•ัะปะธ ัั‚ะพ ะฝะต Ethernet,
    ะฟั€ะพะฟัƒัั‚ะธั‚ัŒ ะฟะฐะบะตั‚.
ะ•ัะปะธ ัั‚ะพ ะฝะต IPv4,
    ะฟั€ะพะฟัƒัั‚ะธั‚ัŒ ะฟะฐะบะตั‚.
ะ•ัะปะธ ะฐะดั€ะตั ะฒ ั‚ะฐะฑะปะธั†ะต ะฟั€ะพะฒะตั€ะตะฝะฝั‹ั…,               (*)
        ัƒะผะตะฝัŒัˆะธั‚ัŒ ัั‡ะตั‚ั‡ะธะบ ะพัั‚ะฐะฒัˆะธั…ัั ะฟั€ะพะฒะตั€ะพะบ,
        ะฟั€ะพะฟัƒัั‚ะธั‚ัŒ ะฟะฐะบะตั‚.
ะ•ัะปะธ ัั‚ะพ ะฝะต TCP,
    ัะฑั€ะพัะธั‚ัŒ ะฟะฐะบะตั‚.     (**)
ะ•ัะปะธ ัั‚ะพ SYN,
    ะพั‚ะฒะตั‚ะธั‚ัŒ SYN-ACK ั cookie.
ะ•ัะปะธ ัั‚ะพ ACK,
    ะตัะปะธ ะฒ acknum ะปะตะถะธั‚ ะฝะต cookie,
        ัะฑั€ะพัะธั‚ัŒ ะฟะฐะบะตั‚.
    ะ—ะฐะฝะตัั‚ะธ ะฒ ั‚ะฐะฑะปะธั†ัƒ ะฐะดั€ะตั ั N ะพัั‚ะฐะฒัˆะธั…ัั ะฟั€ะพะฒะตั€ะพะบ.    (*)
    ะžั‚ะฒะตั‚ะธั‚ัŒ RST.   (**)
ะ’ ะพัั‚ะฐะปัŒะฝั‹ั… ัะปัƒั‡ะฐัั… ัะฑั€ะพัะธั‚ัŒ ะฟะฐะบะตั‚.

เบซเบ™เบถเปˆเบ‡ (*) เบˆเบธเบ”เบ—เบตเปˆเบ—เปˆเบฒเบ™เบ•เป‰เบญเบ‡เบเบฒเบ™เบˆเบฑเบ”เบเบฒเบ™เบชเบฐเบ–เบฒเบ™เบฐเบ‚เบญเบ‡เบฅเบฐเบšเบปเบšเป„เบ”เป‰เบ–เบทเบเบซเบกเบฒเบ - เปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบ—เปเบฒเบญเบดเบ”เบ—เบตเปˆเบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เป„เบ”เป‰เป‚เบ”เบเบšเปเปˆเบกเบตเบžเบงเบเบกเบฑเบ™เป‚เบ”เบเบžเบฝเบ‡เปเบ•เปˆเบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบˆเบฑเบšเบกเบท TCP เบเบฑเบšเบเบฒเบ™เบœเบฐเบฅเบดเบ”เบ„เบธเบเบเบต SYN เป€เบ›เบฑเบ™ seqnum.

เบขเบนเปˆเบˆเบธเบ” (**), เปƒเบ™เบ‚เบฐเบ™เบฐเบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบšเปเปˆเบกเบตเบ•เบฒเบ•เบฐเบฅเบฒเบ‡, เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ‚เป‰เบฒเบกเบŠเบญเบ‡.

เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบˆเบฑเบšเบกเบท TCP

เบเบฒเบ™เปเบเบเปเบžเบฑเบเป€เบเบฑเบ” เปเบฅเบฐเบเบงเบ”เบชเบญเบšเบฅเบฐเบซเบฑเบ”

เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ•เป‰เบญเบ‡เบเบฒเบ™เป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบซเบปเบงเป€เบ„เบทเบญเบ‚เปˆเบฒเบ: Ethernet (uapi/linux/if_ether.h), IPv4 (uapi/linux/ip.h) เปเบฅเบฐ TCP (uapi/linux/tcp.h). เบ‚เป‰เบญเบเบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบญเบฑเบ™เบชเบธเบ”เบ—เป‰เบฒเบเป„เบ”เป‰เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”เบ—เบตเปˆเบเปˆเบฝเบงเบ‚เป‰เบญเบ‡เบเบฑเบš atomic64_t, เบ‚เป‰เบญเบเบ•เป‰เบญเบ‡เบ„เบฑเบ”เบฅเบญเบเบ„เปเบฒเบ™เบดเบเบฒเบกเบ—เบตเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบฅเบฐเบซเบฑเบ”.

เบŸเบฑเบ‡เบŠเบฑเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”เบ—เบตเปˆเป€เบ™เบฑเป‰เบ™เปƒเบชเปˆเปƒเบ™ C เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบญเปˆเบฒเบ™เบ•เป‰เบญเบ‡เบ–เบทเบ inlined เบขเบนเปˆเบˆเบธเบ”เบ‚เบญเบ‡เบเบฒเบ™เป‚เบ—, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒ eBPF verifier เปƒเบ™ kernel เบซเป‰เบฒเบก backtracking, เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, เปƒเบ™เบ„เบงเบฒเบกเป€เบ›เบฑเบ™เบˆเบดเบ‡, loops เปเบฅเบฐ function calls.

#define INTERNAL static __attribute__((always_inline))

Macro LOG() เบ›เบดเบ”เปƒเบŠเป‰เบ‡เบฒเบ™เบเบฒเบ™เบžเบดเบกเปƒเบ™เบเบฒเบ™เบ›เปˆเบญเบเบ•เบปเบง.

เป‚เบ„เบ‡เบเบฒเบ™เปเบกเปˆเบ™ conveyor เบ‚เบญเบ‡เบซเบ™เป‰เบฒเบ—เบตเปˆ. เปเบ•เปˆเบฅเบฐเบ„เบปเบ™เป„เบ”เป‰เบฎเบฑเบšเบŠเบธเบ”เบ—เบตเปˆเบชเปˆเบงเบ™เบซเบปเบงเบฅเบฐเบ”เบฑเบšเบ—เบตเปˆเบชเบญเบ”เบ„เป‰เบญเบ‡เบเบฑเบ™เบ–เบทเบเป€เบ™เบฑเป‰เบ™เปƒเบชเปˆ, เบ•เบปเบงเบขเปˆเบฒเบ‡, 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): เบกเบตเป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡เบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบชเบดเบšเบชเบฒเบก byte เบˆเบฒเบเบˆเบธเบ”เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ‚เบญเบ‡ buffer เบขเบนเปˆเบ™เบญเบเปเบžเบฑเบเป€เบเบฑเบ”. เบกเบฑเบ™เป€เบ›เบฑเบ™เบเบฒเบ™เบเบฒเบเบ—เบตเปˆเบˆเบฐเป€เบ‚เบปเป‰เบฒเปƒเบˆเบˆเบฒเบเบฅเบฒเบเบเบฒเบ™เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบเปเบฒเบฅเบฑเบ‡เป€เบงเบปเป‰เบฒเป€เบ–เบดเบ‡, เปเบ•เปˆเบกเบตเบ„เปเบฒเปเบ™เบฐเบ™เปเบฒ (12) เปเบฅเบฐ disassembler เบชเบฐเปเบ”เบ‡เป€เบชเบฑเป‰เบ™เบ‚เบญเบ‡เบฅเบฐเบซเบฑเบ”เปเบซเบผเปˆเบ‡:

llvm-objdump -S xdp_filter.o | less

เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ™เบตเป‰, เบกเบฑเบ™เบŠเบตเป‰เปƒเบซเป‰เป€เบซเบฑเบ™เป€เบ–เบดเบ‡เป€เบชเบฑเป‰เบ™

LOG("Ether(proto=0x%x)", bpf_ntohs(ether->h_proto));

เป€เบŠเบดเปˆเบ‡เป€เบฎเบฑเบ”เปƒเบซเป‰เบกเบฑเบ™เบŠเบฑเบ”เป€เบˆเบ™เบงเปˆเบฒเบšเบฑเบ™เบซเบฒเปเบกเปˆเบ™ ether. เบกเบฑเบ™เบˆเบฐเป€เบ›เบฑเบ™เปเบšเบšเบ™เบตเป‰เบชเบฐเป€เปเบต.

เบ•เบญเบšเบเบฑเบš SYN

เป€เบ›เบปเป‰เบฒเบซเบกเบฒเบเปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบ™เบตเป‰เปเบกเปˆเบ™เป€เบžเบทเปˆเบญเบชเป‰เบฒเบ‡เปเบžเบฑเบเป€เบเบฑเบ” SYNACK เบ—เบตเปˆเบ–เบทเบเบ•เป‰เบญเบ‡เบ”เป‰เบงเบเบเบฒเบ™เบชเป‰เบญเบกเปเบŠเบก seqnum, เป€เบŠเบดเปˆเบ‡เบˆเบฐเบ–เบทเบเปเบ—เบ™เบ—เบตเปˆเปƒเบ™เบญเบฐเบ™เบฒเบ„เบปเบ”เป‚เบ”เบเบ„เบธเบเบเบต SYN. เบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบ—เบฑเบ‡เบซเบกเบปเบ”เป€เบเบตเบ”เบ‚เบถเป‰เบ™เปƒเบ™ process_tcp_syn() เปเบฅเบฐเป€เบ‚เบ”เบญเป‰เบญเบกเบ‚เป‰เบฒเบ‡.

เบเบฒเบ™เบขเบฑเป‰เบ‡เบขเบทเบ™เบŠเบธเบ”

Oddly เบžเบฝเบ‡เบžเป, เบ™เบตเป‰เปเบกเปˆเบ™เป€เบชเบฑเป‰เบ™เบ—เบตเปˆเป‚เบ”เบ”เป€เบ”เบฑเปˆเบ™เบ—เบตเปˆเบชเบธเบ”, เบซเบผเบทเปเบ—เบ™เบ—เบตเปˆเบˆเบฐ, เบ„เปเบฒเป€เบซเบฑเบ™เบเปˆเบฝเบงเบเบฑเบšเบกเบฑเบ™:

/* Required to verify checksum calculation */
const void* data_end = (const void*)ctx->data_end;

เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบ‚เบฝเบ™เบฅเบฐเบซเบฑเบ”เบชเบฐเบšเบฑเบšเบ—เปเบฒเบญเบดเบ”เบ‚เบญเบ‡, kernel 5.1 เป„เบ”เป‰เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰, เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบเบงเบ”เบชเบญเบšเบงเปˆเบฒเบกเบตเบ„เบงเบฒเบกเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™เบฅเบฐเบซเบงเปˆเบฒเบ‡. data_end ะธ (const void*)ctx->data_end. เปƒเบ™เป€เบงเบฅเบฒเบ‚เบฝเบ™, kernel 5.3.1 เบšเปเปˆเบกเบตเบšเบฑเบ™เบซเบฒเบ™เบตเป‰. เบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เบงเปˆเบฒ compiler เป„เบ”เป‰เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบ•เบปเบงเปเบ›เบ—เป‰เบญเบ‡เบ–เบดเปˆเบ™เบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบˆเบฒเบเบžเบฒเบเบชเบฐเบซเบ™เบฒเบก. เบˆเบฑเบ™เบเบฒเบšเบฑเบ™เบ‚เบญเบ‡เป€เบฅเบทเปˆเบญเบ‡: เบ„เบงเบฒเบกเบ‡เปˆเบฒเบเบ”เบฒเบเบ‚เบญเบ‡เบฅเบฐเบซเบฑเบ”เบชเบฒเบกเบฒเบ”เบŠเปˆเบงเบเป„เบ”เป‰เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบกเบตเบฎเบฑเบ‡เบซเบผเบฒเบ.

เบ•เปเปˆเป„เบ›เปเบกเปˆเบ™เบเบฒเบ™เบเบงเบ”เบชเบญเบšเบ„เบงเบฒเบกเบเบฒเบงเบ›เบปเบเบเบฐเบ•เบดเบชเปเบฒเบฅเบฑเบšเบฅเบฑเบ”เบชเบฐเบซเบกเบตเบžเบฒเบšเบ‚เบญเบ‡เบ•เบปเบงเบเบงเบ”เบชเบญเบš; เบญ 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);

เบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆเบ„เบทเบ™เบ‚เบญเบ‡ checksums

IPv4 เปเบฅเบฐ TCP checksums เบฎเบฝเบเบฎเป‰เบญเบ‡เปƒเบซเป‰เบกเบตเบเบฒเบ™เป€เบžเบตเปˆเบกเบ„เปเบฒเบชเบฑเบš 16-bit เบ—เบฑเบ‡เบซเบกเบปเบ”เปƒเบ™ headers, เปเบฅเบฐเบ‚เบฐเบซเบ™เบฒเบ”เบ‚เบญเบ‡ headers เป„เบ”เป‰เบ–เบทเบเบ‚เบฝเบ™เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบžเบงเบเบกเบฑเบ™, เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, เบšเปเปˆเบฎเบนเป‰เปƒเบ™เป€เบงเบฅเบฒเบฅเบงเบšเบฅเบงเบก. เบ™เบตเป‰เปเบกเปˆเบ™เบšเบฑเบ™เบซเบฒเป€เบžเบฒเบฐเบงเปˆเบฒเบ•เบปเบงเบเบงเบ”เบชเบญเบšเบˆเบฐเบšเปเปˆเบ‚เป‰เบฒเบก loop เบ›เบปเบเบเบฐเบ•เบดเป„เบ›เบซเบฒเบ•เบปเบงเปเบ›เบ‚เบญเบšเป€เบ‚เบ”. เปเบ•เปˆเบ‚เบฐเบซเบ™เบฒเบ”เบ‚เบญเบ‡เบซเบปเบงเปเบกเปˆเบ™เบˆเปเบฒเบเบฑเบ”: เบชเบนเบ‡เป€เบ–เบดเบ‡ 64 bytes เปเบ•เปˆเบฅเบฐเบ„เบปเบ™. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ” loop เบ—เบตเปˆเบกเบตเบˆเปเบฒเบ™เบงเบ™เบ„เบปเบ‡เบ—เบตเปˆเบ‚เบญเบ‡ iterations, เป€เบŠเบดเปˆเบ‡เบชเบฒเบกเบฒเบ”เบชเบดเป‰เบ™เบชเบธเบ”เป„เบง.

เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบชเบฑเบ‡เป€เบเบ”เบงเปˆเบฒเบกเบต RFC 1624 เบเปˆเบฝเบงเบเบฑเบšเบงเบดเบ—เบตเบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆเบšเบฒเบ‡เบชเปˆเบงเบ™เบ‚เบญเบ‡ checksum เบ–เป‰เบฒเบžเบฝเบ‡เปเบ•เปˆเบ„เปเบฒเบ„เบปเบ‡เบ—เบตเปˆเบ‚เบญเบ‡เปเบžเบฑเบเป€เบเบฑเบ”เบ–เบทเบเบ›เปˆเบฝเบ™เปเบ›เบ‡. เบขเปˆเบฒเบ‡เปƒเบ”เบเปเบ•เบฒเบก, เบงเบดเบ—เบตเบเบฒเบ™เบšเปเปˆเปเบกเปˆเบ™เบ—เบปเปˆเบงเป„เบ›, เปเบฅเบฐเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบˆเบฐเบกเบตเบ„เบงเบฒเบกเบซเบเบธเป‰เบ‡เบเบฒเบเบซเบผเบฒเบเบ—เบตเปˆเบˆเบฐเบฎเบฑเบเบชเบฒ.

เบŸเบฑเบ‡เบŠเบฑเบ™เบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆ Checksum:

#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 เบเบฒเบ™เบเบงเบ”เบชเบญเบšเป‚เบ”เบเบฅเบฐเบซเบฑเบ”เบเบฒเบ™เป‚เบ—, เป€เบ‡เบทเปˆเบญเบ™เป„เบ‚เบเบฒเบ™เบญเบญเบเบ—เบตเบชเบญเบ‡เปเบกเปˆเบ™เบกเบตเบ„เบงเบฒเบกเบˆเปเบฒเป€เบ›เบฑเบ™เป€เบžเบทเปˆเบญเปƒเบซเป‰เบœเบนเป‰เบเบงเบ”เบชเบญเบšเบชเบฒเบกเบฒเบ”เบžเบดเบชเบนเบ”เบเบฒเบ™เบชเปเบฒเป€เบฅเบฑเบ”เบ‚เบญเบ‡ loop เป„เบ”เป‰.

เบชเปเบฒเบฅเบฑเบšเบ„เปเบฒเบชเบฑเบš 32-bit, เบชเบฐเบšเบฑเบšเบ—เบตเปˆเบ‡เปˆเบฒเบเบ”เบฒเบเปเบกเปˆเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”:

INTERNAL u32
sum16_32(u32 v) {
    return (v >> 16) + (v & 0xffff);
}

เบ•เบปเบงเบˆเบดเบ‡เปเบฅเป‰เบงเบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆ checksums เปเบฅเบฐเบเบฒเบ™เบชเบปเปˆเบ‡เบŠเบญเบ‡เบ„เบทเบ™:

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() เป€เบฎเบฑเบ”เปƒเบซเป‰ checksum เบˆเบฒเบเบœเบปเบ™เบฅเบงเบก 32-bit เบ‚เบญเบ‡เบ„เปเบฒเบชเบฑเบš 16-bit, เบญเบตเบ‡เบ•เบฒเบก RFC 791.

เบเบฒเบ™เบขเบฑเป‰เบ‡เบขเบทเบ™เบเบฒเบ™เบˆเบฑเบšเบกเบท TCP

เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เบขเปˆเบฒเบ‡เบ–เบทเบเบ•เป‰เบญเบ‡เบชเป‰เบฒเบ‡เบ•เบฑเป‰เบ‡เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบเบฑเบš netcat, เบ‚เบฒเบ” ACK เบชเบธเบ”เบ—เป‰เบฒเบ, เบ—เบตเปˆ Linux เบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบเบฑเบšเปเบžเบฑเบเป€เบเบฑเบ” RST, เบ™เบฑเบšเบ•เบฑเป‰เบ‡เปเบ•เปˆ stack เป€เบ„เบทเบญเบ‚เปˆเบฒเบเบšเปเปˆเป„เบ”เป‰เบฎเบฑเบš SYN - เบกเบฑเบ™เบ–เบทเบเบ›เปˆเบฝเบ™เป€เบ›เบฑเบ™ SYNACK เปเบฅเบฐเบชเบปเปˆเบ‡เบ„เบทเบ™ - เปเบฅเบฐเบˆเบฒเบเบˆเบธเบ”เบ‚เบญเบ‡ OS, packet เบกเบฒเบฎเบญเบ”เบ—เบตเปˆเบšเปเปˆเบเปˆเบฝเบงเบ‚เป‰เบญเบ‡เบเบฑเบšเบเบฒเบ™เป€เบ›เบตเบ”. เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ.

$ 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 เบšเปเปˆเบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบเบฑเบš checksums เบ—เบตเปˆเบšเปเปˆเบ–เบทเบเบ•เป‰เบญเบ‡.

เบˆเบฒเบเบ—เบฑเบ”เบชเบฐเบ™เบฐเบ‚เบญเบ‡ XDP, เบเบฒเบ™เบเบงเบ”เบชเบญเบšเบ•เบปเบงเบกเบฑเบ™เป€เบญเบ‡เปเบกเปˆเบ™เป€เบ›เบฑเบ™เป€เบฅเบทเปˆเบญเบ‡เป€เบฅเบฑเบเป†เบ™เป‰เบญเบเป†. เบชเบนเบ”เบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆเปเบกเปˆเบ™เป€เบšเบทเป‰เบญเบ‡เบ•เบปเป‰เบ™ เปเบฅเบฐเบญเบฒเบ”เบˆเบฐเบกเบตเบ„เบงเบฒเบกเบชเปˆเบฝเบ‡เบ•เปเปˆเบเบฑเบšเบœเบนเป‰เป‚เบˆเบกเบ•เบตเบ—เบตเปˆเบŠเบฑเบšเบŠเป‰เบญเบ™. เบ•เบปเบงเบขเปˆเบฒเบ‡เป€เบŠเบฑเปˆเบ™ Linux kernel เปƒเบŠเป‰ SipHash cryptographic, เปเบ•เปˆเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ‚เบญเบ‡เบกเบฑเบ™เบชเปเบฒเบฅเบฑเบš XDP เปเบกเปˆเบ™เป€เบซเบฑเบ™เป„เบ”เป‰เบŠเบฑเบ”เป€เบˆเบ™เป€เบเบตเบ™เบ‚เบญเบšเป€เบ‚เบ”เบ‚เบญเบ‡เบšเบปเบ”เบ„เบงเบฒเบกเบ™เบตเป‰.

เปเบ™เบฐเบ™เปเบฒเบชเปเบฒเบฅเบฑเบš TODOs เปƒเบซเบกเปˆเบ—เบตเปˆเบเปˆเบฝเบงเบ‚เป‰เบญเบ‡เบเบฑเบšเบเบฒเบ™เบชเบทเปˆเบชเบฒเบ™เบžเบฒเบเบ™เบญเบ:

  • เป‚เบ„เบ‡เบเบฒเบ™ XDP เบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบเบฑเบšเบฎเบฑเบเบชเบฒเป„เบ”เป‰ cookie_seed (เบชเปˆเบงเบ™เบฅเบฑเบšเบ‚เบญเบ‡เป€เบเบทเบญ) เบขเบนเปˆเปƒเบ™เบ•เบปเบงเปเบ›เบ—เบปเปˆเบงเป‚เบฅเบ, เบ—เปˆเบฒเบ™เบ•เป‰เบญเบ‡เบเบฒเบ™เป€เบเบฑเบšเบฎเบฑเบเบชเบฒเปƒเบ™เปเบเปˆเบ™, เบกเบนเบ™เบ„เปˆเบฒเบ—เบตเปˆเบˆเบฐเป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบ›เบฑเบšเบ›เบธเบ‡เปเบ•เปˆเบฅเบฐเป„เบฅเบเบฐเบˆเบฒเบเป€เบ„เบทเปˆเบญเบ‡เบเปเบฒเป€เบ™เบตเบ”เบ—เบตเปˆเป€เบŠเบทเปˆเบญเบ–เบทเป„เบ”เป‰.

  • เบ–เป‰เบฒเบ„เบธเบเบเบต SYN เบเบปเบ‡เบเบฑเบ™เบขเบนเปˆเปƒเบ™เปเบžเบฑเบเป€เบเบฑเบ” 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

เปƒเบ™เบ‚เบฐเบ™เบฐเบ—เบตเปˆเบšเปเปˆเบกเบตเบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆเบ‚เบญเบ‡ IPs เบ—เบตเปˆเบ–เบทเบเบขเบทเบ™เบขเบฑเบ™, เบกเบฑเบ™เบˆเบฐเบšเปเปˆเบกเบตเบเบฒเบ™เบ›เป‰เบญเบ‡เบเบฑเบ™เบˆเบฒเบเบ™เป‰เปเบฒเบ–เป‰เบงเบก SYN เบ•เบปเบงเบ‚เบญเบ‡เบกเบฑเบ™เป€เบญเบ‡, เปเบ•เปˆเบ™เบตเป‰เปเบกเปˆเบ™เบ›เบฐเบ•เบดเบเบดเบฅเบดเบเบฒเบ•เปเปˆเบเบฑเบšเบ™เป‰เปเบฒเบ–เป‰เบงเบก ACK เบ—เบตเปˆเป€เบ›เบตเบ”เบ•เบปเบงเป‚เบ”เบเบ„เปเบฒเบชเบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

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 เปเบกเปˆเบ™เป€เบ„เบทเปˆเบญเบ‡เบกเบทเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เปเบŠเบเปเบŠเบ‡เบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบ‚เบญเบ‡เปเบžเบฑเบเป€เบเบฑเบ”เป‚เบ”เบเปเบเปˆเบ™, เปเบฅเบฐเบšเปเปˆเปเบกเปˆเบ™เบ—เบฒเบ‡เป€เบฅเบทเบญเบเบชเปเบฒเบฅเบฑเบš stack kernel, เป€เบŠเบฑเปˆเบ™ DPDK เปเบฅเบฐเบ—เบฒเบ‡เป€เบฅเบทเบญเบ bypass kernel เบญเบทเปˆเบ™เป†. เปƒเบ™เบ—เบฒเบ‡เบเบปเบ‡เบเบฑเบ™เบ‚เป‰เบฒเบก, XDP เบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ›เบฐเบ•เบดเบšเบฑเบ”เป€เบซเบ”เบœเบปเบ™เบ—เบตเปˆเบ‚เป‰เบญเบ™เบ‚เป‰เบฒเบ‡เบชเบฑเบšเบชเบปเบ™, เป€เบŠเบดเปˆเบ‡, เบ™เบญเบเบˆเบฒเบเบ™เบฑเป‰เบ™, เบ‡เปˆเบฒเบเบ•เปเปˆเบเบฒเบ™เบ›เบฑเบšเบ›เบธเบ‡เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เบ‚เบฑเบ”เบ‚เบงเบฒเบ‡เบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบเบฒเบ™เบˆเบฐเบฅเบฒเบˆเบญเบ™. เบ•เบปเบงเบเบงเบ”เบชเบญเบšเบšเปเปˆเป„เบ”เป‰เบชเป‰เบฒเบ‡เบšเบฑเบ™เบซเบฒเปƒเบซเบเปˆเป‚เบ”เบเบชเปˆเบงเบ™เบ•เบปเบง, เบ‚เป‰เบญเบเบˆเบฐเบšเปเปˆเบ›เบฐเบ•เบดเป€เบชเบ”เบ™เบตเป‰เบชเปเบฒเบฅเบฑเบšเบชเปˆเบงเบ™เบ‚เบญเบ‡เบฅเบฐเบซเบฑเบ” userspace.

เปƒเบ™เบชเปˆเบงเบ™เบ—เบตเบชเบญเบ‡, เบ–เป‰เบฒเบซเบปเบงเบ‚เปเป‰เปเบกเปˆเบ™เบซเบ™เป‰เบฒเบชเบปเบ™เปƒเบˆ, เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเป€เบฎเบฑเบ”เบชเปเบฒเป€เบฅเบฑเบ”เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ‚เบญเบ‡เบฅเบนเบเบ„เป‰เบฒเบ—เบตเปˆเบ–เบทเบเบขเบทเบ™เบขเบฑเบ™เปเบฅเบฐเบเบฒเบ™เบ‚เบฑเบ”เบ‚เบงเบฒเบ‡, เบ›เบฐเบ•เบดเบšเบฑเบ”เบ•เบปเบงเบ™เบฑเบšเปเบฅเบฐเบ‚เบฝเบ™ userspace utility เป€เบžเบทเปˆเบญเบˆเบฑเบ”เบเบฒเบ™เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡.

เป€เบญเบเบฐเบชเบฒเบ™เบญเป‰เบฒเบ‡เบญเบตเบ‡:

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™