EXpress рдбреЗрдЯрд╛ рдкрд╛рде (XDP) рддрдХрдиреАрдХ рдХрд░реНрдиреЗрд▓ рдиреЗрдЯрд╡рд░реНрдХ рд╕реНрдЯреИрдХ рдкрд░ рдкреИрдХреЗрдЯ рдЖрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд▓рд┐рдирдХреНрд╕ рдЗрдВрдЯрд░рдлреЗрд╕ рдкрд░ рдпрд╛рддрд╛рдпрд╛рдд рдХреА рдордирдорд╛рдиреА рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред XDP рдХрд╛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ - DDoS рд╣рдорд▓реЛрдВ (CloudFlare), рдкрд░рд┐рд╖реНрдХреГрдд рдлрд╝рд┐рд▓реНрдЯрд░, рд╕рд╛рдВрдЦреНрдпрд┐рдХреА рд╕рдВрдЧреНрд░рд╣ (Netflix) рдХреЗ рд╡рд┐рд░реБрджреНрдз рд╕реБрд░рдХреНрд╖рд╛ред XDP рдкреНрд░реЛрдЧреНрд░рд╛рдореНрд╕ рдХреЛ EBPF рд╡рд░реНрдЪреБрдЕрд▓ рдорд╢реАрди рджреНрд╡рд╛рд░рд╛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП, рдЙрдирдХреЗ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдЙрдирдХреЗ рдХреЛрдб рдФрд░ рдЙрдкрд▓рдмреНрдз рдХрд░реНрдиреЗрд▓ рдлрд╝рдВрдХреНрд╢рди рджреЛрдиреЛрдВ рдкрд░ рдкреНрд░рддрд┐рдмрдВрдз рд╣реИред
рд▓реЗрдЦ рдореЗрдВ рдХрдИ рдПрдХреНрд╕рдбреАрдкреА рд╕рд╛рдордЧреНрд░реА рдХреА рдХрдорд┐рдпреЛрдВ рдХреЛ рднрд░рдиреЗ рдХрд╛ рдЗрд░рд╛рджрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╡реЗ рддреИрдпрд╛рд░ рдХрд┐рдП рдЧрдП рдХреЛрдб рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рддреБрд░рдВрдд XDP рдХреА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░ рджреЗрддреЗ рд╣реИрдВ: рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдпрд╛ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рдХрд╛рд░рдг рдмрдирдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд░рд▓ред рдЬрдм рдЖрдк рдЕрдкрдиреЗ рдХреЛрдб рдХреЛ рд╕реНрдХреНрд░реИрдЪ рд╕реЗ рд╕реНрдХреНрд░реИрдЪ рд╕реЗ рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рд╕рдордЭ рдореЗрдВ рдирд╣реАрдВ рдЖрддрд╛ рд╣реИ рдХрд┐ рд╡рд┐рд╢рд┐рд╖реНрдЯ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИред рджреВрд╕рд░реЗ, рд╡реАрдПрдо рдФрд░ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рдХреЗ рдмрд┐рдирд╛ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ XDP рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рддрд░реАрдХреЗ рдХреЛ рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд╡рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдЙрдирдХреЗ рдЕрдкрдиреЗ рдиреБрдХрд╕рд╛рди рд╣реИрдВред рдкрд╛рда рдиреЗрдЯрд╡рд░реНрдХрд┐рдВрдЧ рдФрд░ рд▓рд┐рдирдХреНрд╕ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЗ рд▓рд┐рдП рдЕрднрд┐рдкреНрд░реЗрдд рд╣реИ рдЬреЛ рдПрдХреНрд╕рдбреАрдкреА рдФрд░ рдИрдПрдХреНрд╕рдкреАрдПрдл рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВред
рдЗрд╕ рднрд╛рдЧ рдореЗрдВ, рд╣рдо рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдЬрд╛рдВрдЪ рдХрд░реЗрдВрдЧреЗ рдХрд┐ XDP рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЛ рдХреИрд╕реЗ рдЗрдХрдЯреНрдард╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдкреИрдХреЗрдЯ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рд╕реНрддрд░ рдкрд░ рдкреНрд░рд╕рд┐рджреНрдз SYN рдХреБрдХреА рддрдВрддреНрд░ рдХрд╛ рдПрдХ рд╕рд░рд▓ рд╕рдВрд╕реНрдХрд░рдг рд▓рд┐рдЦреЗрдВрдЧреЗред рдЬрдмрдХрд┐ рд╣рдо "рд╢реНрд╡реЗрдд рд╕реВрдЪреА" рдирд╣реАрдВ рдмрдирд╛рдПрдВрдЧреЗ
рд╕рддреНрдпрд╛рдкрд┐рдд рдЧреНрд░рд╛рд╣рдХ, рдХрд╛рдЙрдВрдЯрд░ рд░рдЦреЗрдВ рдФрд░ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░реЗрдВ - рдкрд░реНрдпрд╛рдкреНрдд рд▓реЙрдЧред
рд╣рдо рд╕реА рдореЗрдВ рд▓рд┐рдЦреЗрдВрдЧреЗ - рдпрд╣ рдлреИрд╢рдиреЗрдмрд▓ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд╣реИред рд╕рднреА рдХреЛрдб рдЕрдВрдд рдореЗрдВ рд▓рд┐рдВрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЧрд┐рдЯрд╣рдм рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИ рдФрд░ рд▓реЗрдЦ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдЪрд░рдгреЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрдорд┐рдЯ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рд╣реИред
рдЕрд╕реНрд╡реАрдХрд░рдгред рд▓реЗрдЦ рдХреЗ рджреМрд░рд╛рди, DDoS рд╣рдорд▓реЛрдВ рд╕реЗ repelling рдХреЗ рд▓рд┐рдП рдПрдХ рдорд┐рдиреА-рд╕рдорд╛рдзрд╛рди рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ XDP рдФрд░ рдореЗрд░реЗ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдпрдерд╛рд░реНрдерд╡рд╛рджреА рдХрд╛рд░реНрдп рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореБрдЦреНрдп рд▓рдХреНрд╖реНрдп рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХреА рд╕реЗ рдирд┐рдкрдЯрдирд╛ рд╣реИ, рдпрд╣ рдПрдХ рддреИрдпрд╛рд░-рдирд┐рд░реНрдорд┐рдд рд╕реБрд░рдХреНрд╖рд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧрд╛рдЗрдб рдирд╣реАрдВ рд╣реИред рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдХреЛрдб рдЕрдиреБрдХреВрд▓рд┐рдд рдирд╣реАрдВ рд╣реИ рдФрд░ рдХреБрдЫ рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИред
рдПрдХ рдирдЬрд╝рд░ рдореЗрдВ XDP
рдореИрдВ рдХреЗрд╡рд▓ рдореБрдЦреНрдп рдмрд┐рдВрджреБрдУрдВ рдХреЛ рд░реЗрдЦрд╛рдВрдХрд┐рдд рдХрд░реВрдВрдЧрд╛ рддрд╛рдХрд┐ рдбреЙрдХреНрдпреВрдореЗрдВрдЯреЗрд╢рди рдФрд░ рдореМрдЬреВрджрд╛ рд▓реЗрдЦреЛрдВ рдХреА рдирдХрд▓ рди рдХреА рдЬрд╛ рд╕рдХреЗред
рддреЛ, рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЛрдб рдХреЛ рдХрд░реНрдиреЗрд▓ рдореЗрдВ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрдирдмрд╛рдЙрдВрдб рдкреИрдХреЗрдЯ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЗ рд▓рд┐рдП рднреЗрдЬреЗ рдЬрд╛рддреЗ рд╣реИрдВред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЛ рдПрдХ рдирд┐рд░реНрдгрдп рд▓реЗрдирд╛ рдЪрд╛рд╣рд┐рдП: рдкреИрдХреЗрдЯ рдХреЛ рдХрд░реНрдиреЗрд▓ ( XDP_PASS
) рдкрд░ рдЫреЛрдбрд╝реЗрдВ, рдкреИрдХреЗрдЯ рдХреЛ рдЫреЛрдбрд╝реЗрдВ ( XDP_DROP
) рдпрд╛ рдЗрд╕реЗ рд╡рд╛рдкрд╕ рднреЗрдЬреЗрдВ ( XDP_TX
)ред рдлрд╝рд┐рд▓реНрдЯрд░ рдкреИрдХреЗрдЬ рдХреЛ рдмрджрд▓ рд╕рдХрддрд╛ рд╣реИ, рдпрд╣ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ XDP_TX
рд▓рд┐рдП XDP_TX
ред рдЖрдк рдкреНрд░реЛрдЧреНрд░рд╛рдо ( XDP_ABORTED
) рдХреЛ рднреА рдХреНрд░реИрд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкреИрдХреЗрдЬ рдХреЛ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдбреАрдмрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП XDP_ABORTED
assert(0)
рдХрд╛ рдПрдХ рдПрдирд╛рд▓реЙрдЧ рд╣реИред
EBPF рд╡рд░реНрдЪреБрдЕрд▓ рдорд╢реАрди (рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдмрд░реНрдХрд▓реЗ рдкреИрдХреЗрдЯ рдлрд╝рд┐рд▓реНрдЯрд░) рдХреЛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕рд░рд▓ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рддрд╛рдХрд┐ рдХрд░реНрдиреЗрд▓ рдпрд╣ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░ рд╕рдХреЗ рдХрд┐ рдХреЛрдб рд▓реВрдк рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдХрд┐рд╕реА рдФрд░ рдХреА рдореЗрдореЛрд░реА рдХреЛ рдиреБрдХрд╕рд╛рди рдирд╣реАрдВ рдкрд╣реБрдВрдЪрд╛рддрд╛ рд╣реИред рдкреНрд░рддрд┐рдмрдВрдзреЛрдВ рдФрд░ рдЬрд╛рдБрдЪреЛрдВ рдХреЛ рдЕрд▓рдЧ рдХрд░реЗрдВ:
- рдирд┐рд╖рд┐рджреНрдз рдЪрдХреНрд░ (рд╡рд╛рдкрд╕ рдХреВрджреЛ)ред
- рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдЯреИрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЛрдИ рдлрд╝рдВрдХреНрд╢рдВрд╕ (рд╕рднреА рд╕реА рдлрд╝рдВрдХреНрд╢рди рдЗрдирд▓рд╛рдЗрди рдирд╣реАрдВ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП)ред
- рд╕реНрдЯреИрдХ рдФрд░ рдкреИрдХреЗрдЯ рдмрдлрд╝рд░ рдХреЗ рдмрд╛рд╣рд░ рдореЗрдореЛрд░реА рддрдХ рдкрд╣реБрдБрдЪ рдирд┐рд╖рд┐рджреНрдз рд╣реИред
- рдХреЛрдб рдХрд╛ рдЖрдХрд╛рд░ рд╕реАрдорд┐рдд рд╣реИ, рд▓реЗрдХрд┐рди рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ рдпрд╣ рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИред
- рдХреЙрд▓ рдХреЗрд╡рд▓ рд╡рд┐рд╢реЗрд╖ рдХрд░реНрдиреЗрд▓ рдлрд╝рдВрдХреНрд╢рдВрд╕ (eBPF рд╕рд╣рд╛рдпрдХреЛрдВ) рдХреЛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рд╣реИред
рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд╛ рдбрд┐рдЬрд╝рд╛рдЗрди рдФрд░ рд╕реНрдерд╛рдкрдирд╛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
- рд╕реНрд░реЛрдд рдХреЛрдб (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
kernel.c
) рдХреЛ EBPP рд╡рд░реНрдЪреБрдЕрд▓ рдорд╢реАрди рдХреЗ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рддрд╣рдд рдСрдмреНрдЬреЗрдХреНрдЯ ( kernel.o
) рдореЗрдВ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЕрдХреНрдЯреВрдмрд░ 2019 рддрдХ, EBPF рдореЗрдВ рд╕рдВрдХрд▓рди рдХреНрд▓реИрдВрдЧ рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рд╣реИ рдФрд░ рдЬреАрд╕реАрд╕реА 10.1 рдореЗрдВ рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред - рдпрджрд┐ рдЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛрдб рдореЗрдВ рдХрд░реНрдиреЗрд▓ рд╕реНрдЯреНрд░рдХреНрдЪрд░реНрд╕ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЯреЗрдмрд▓ рдФрд░ рдХрд╛рдЙрдВрдЯрд░) рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рдЖрддреЗ рд╣реИрдВ, рддреЛ рдЙрдирдХреЗ рдЖрдИрдбреА рдХреЗ рдмрдЬрд╛рдп рд╢реВрдиреНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рдд рдРрд╕реЗ рдХреЛрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдХрд░реНрдиреЗрд▓ рдореЗрдВ рд▓реЛрдб рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рдХрд░реНрдиреЗрд▓ рдХреЙрд▓ (рд▓рд┐рдВрдХ рдХреЛрдб) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрдирд╛рдИ рдЧрдИ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╡рд╕реНрддреБрдУрдВ рдХреА рдЖрдИрдбреА рдХреЗ рд╕рд╛рде рдЗрди рд╢реВрдиреНрдп рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЖрдк рдмрд╛рд╣рд░реА рдЙрдкрдпреЛрдЧрд┐рддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдЖрдк рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдлрд┐рд▓реНрдЯрд░ рдХреЛ рд▓рд┐рдВрдХ рдФрд░ рд▓реЛрдб рдХрд░реЗрдЧрд╛ред
- рдХрд░реНрдиреЗрд▓ рд▓реЛрдб рдХрд┐рдП рдЧрдП рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рддрд╛ рд╣реИред рдкреИрдХреЗрдЯ рдФрд░ рд╕реНрдЯреИрдХ рдХреА рд╕реАрдорд╛рдУрдВ рд╕реЗ рдкрд░реЗ рдЫреЛрд░реЛрдВ рдФрд░ рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХреА рдЬрд╛рддреА рд╣реИред рдпрджрд┐ рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛ рдпрд╣ рд╕рд╛рдмрд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдХреЛрдб рд╕рд╣реА рд╣реИ, рддреЛ рдХрд╛рд░реНрдпрдХреНрд░рдо рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ - рдЖрдкрдХреЛ рдЗрд╕реЗ рдЦреБрд╢ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
- рд╕рдлрд▓ рд╕рддреНрдпрд╛рдкрди рдХреЗ рдмрд╛рдж, рдХрд░реНрдиреЗрд▓ eBPF рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛрдб рдХреЛ рд╕рд┐рд╕реНрдЯрдо рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдорд╢реАрди рдХреЛрдб (рдмрд╕-рдЗрди-рдЯрд╛рдЗрдо) рдореЗрдВ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддрд╛ рд╣реИред
- рдХрд╛рд░реНрдпрдХреНрд░рдо рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕реЗ рдЬреБрдбрд╝рддрд╛ рд╣реИ рдФрд░ рдкреИрдХреЗрдЯ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИред
рдЪреВрдВрдХрд┐ XDP рдХрд░реНрдиреЗрд▓ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЯреНрд░реЗрд╕рд┐рдВрдЧ рд▓реЙрдЧреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдкреИрдХреЗрдЯ рджреНрд╡рд╛рд░рд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдлрд╝рд┐рд▓реНрдЯрд░ рдпрд╛ рдЬреЗрдирд░реЗрдЯ рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, eBPF рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП рд▓реЛрдб рдХрд┐рдП рдЧрдП рдХреЛрдб рдХреЗ рд▓рд┐рдП рд╕реБрд░рдХреНрд╖рд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдк XDP рдХреЗ рд╕рд╛рде рд╕реАрдзреЗ рд╕реНрдерд╛рдиреАрдп рд▓рд┐рдирдХреНрд╕ рдкрд░ рдкреНрд░рдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдкрд░реНрдпрд╛рд╡рд░рдг рдХреА рддреИрдпрд╛рд░реА
рд╕рднрд╛
Clang рд╕реАрдзреЗ eBPF рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рд▓рд┐рдП рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛрдб рдЬрд╛рд░реА рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рджреЛ рдЪрд░рдг рд╣реЛрддреЗ рд╣реИрдВ:
- LLVM bytecode (
clang -emit-llvm
) рдореЗрдВ C рдХреЛрдб рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдВред - рдмрд╛рдЗрдЯрдХреЛрдб рдХреЛ eBPF рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛрдб (
llc -march=bpf -filetype=obj
) рдореЗрдВ llc -march=bpf -filetype=obj
ред
рдлрд╝рд┐рд▓реНрдЯрд░ рд▓рд┐рдЦрддреЗ рд╕рдордп, рдХрд░реНрдиреЗрд▓ рдкрд░реАрдХреНрд╖рдгреЛрдВ рд╕реЗ рд╕рд╣рд╛рдпрдХ рдХрд╛рд░реНрдпреЛрдВ рдФрд░ рдореИрдХреНрд░реЛ рдХреЗ рд╕рд╛рде рдХреБрдЫ рдлрд╛рдЗрд▓реЗрдВ рдХрд╛рдо рдореЗрдВ рдЖрддреА рд╣реИрдВред рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рд╡реЗ рдХрд░реНрдиреЗрд▓ рд╕рдВрд╕реНрдХрд░рдг ( KVER
) рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реЛрдВред рдЙрдиреНрд╣реЗрдВ helpers/
рдореЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ 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
рдореЗрдХрд╛рдЗрд▓ рдлрд╝реЙрд░ рдЖрд░реНрдХ рд▓рд┐рдирдХреНрд╕ (рдХрд░реНрдиреЗрд▓ 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
рдореЗрдВ рдХрд░реНрдиреЗрд▓ рд╣реЗрдбрд░, KDIR
- рд╕рд┐рд╕реНрдЯрдо рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рд╢рд╛рдорд┐рд▓ рд╣реИред рд╡рд┐рддрд░рдг рдХреЗ рдмреАрдЪ рдкрде рдФрд░ рдЙрдкрдХрд░рдг рдереЛрдбрд╝рд╛ рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред
рдбреЗрдмрд┐рдпрди 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 рд╣реЗрдбрд░ (рдпреВрдЬрд░рд╕реНрдкреЗрд╕ 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
ред рдЕрдм рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд╣рд╛рдБ рдХрд░рдирд╛ рд╣реИ?
рдЯреЗрд╕реНрдЯ рд╕реНрдЯреИрдВрдб
рд╕реНрдЯреИрдВрдб рдореЗрдВ рджреЛ рдЗрдВрдЯрд░рдлреЗрд╕ рд╢рд╛рдорд┐рд▓ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП: рдЬрд┐рд╕ рдкрд░ рдПрдХ рдлрд┐рд▓реНрдЯрд░ рд╣реЛрдЧрд╛ рдФрд░ рдЬрд┐рд╕рдореЗрдВ рд╕реЗ рдкреИрдХреЗрдЯ рднреЗрдЬреЗ рдЬрд╛рдПрдВрдЧреЗред рд╣рдорд╛рд░реЗ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЗ рд╕рд╛рде рдирд┐рдпрдорд┐рдд рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣ рдЬрд╛рдБрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдирдХреЗ IP рдХреЗ рд╕рд╛рде рдкреВрд░реНрдг рд▓рд┐рдирдХреНрд╕ рдбрд┐рд╡рд╛рдЗрд╕ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рд╡реЗрде (рд╡рд░реНрдЪреБрдЕрд▓ рдИрдерд░рдиреЗрдЯ) рдЬреИрд╕реЗ рдбрд┐рд╡рд╛рдЗрд╕ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╣реИрдВ: рд╡реЗ рдПрдХ рдЬреЛрдбрд╝реА рд╡рд░реНрдЪреБрдЕрд▓ рдиреЗрдЯрд╡рд░реНрдХ рдЗрдВрдЯрд░рдлреЗрд╕ рд╣реИрдВ рдЬреЛ рд╕реАрдзреЗ рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ "рдХрдиреЗрдХреНрдЯ" рд╣реЛрддреЗ рд╣реИрдВред рдЖрдк рдЙрдиреНрд╣реЗрдВ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ (рдЗрд╕ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ, рд╕рднреА ip
рдХрдорд╛рдВрдб рдХреЛ root
рд░реВрдк рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ 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) рд╕реЗ рднреЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ: рдЗрдВрдЯрд░рдлреЗрд╕ рдПрдХ рд╣реА рдорд╢реАрди рдкрд░ рд╣реИрдВ, рдФрд░ рд▓рд┐рдирдХреНрд╕ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдХреЛ рджреВрд╕рд░реЗ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЯреНрд░реИрдлрд╝рд┐рдХ рдирд╣реАрдВ рднреЗрдЬреЗрдЧрд╛ред рдЖрдк рдЗрд╕реЗ рдореБрд╢реНрдХрд┐рд▓ iptables
рдирд┐рдпрдореЛрдВ рдХреЗ рд╕рд╛рде рд╣рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрдиреНрд╣реЗрдВ рдкреИрдХреЗрдЬ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛, рдЬреЛ рдбреАрдмрдЧрд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдиреЗрдЯрд╡рд░реНрдХ рдиреЗрдорд╕реНрдкреЗрд╕ (рдиреЗрдЯрд╡рд░реНрдХ рдиреЗрдорд╕реНрдкреЗрд╕, рдЗрд╕рдХреЗ рдмрд╛рдж рдиреЗрдЯреНрд╕) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред
рдиреЗрдЯрд╡рд░реНрдХ рдиреЗрдорд╕реНрдкреЗрд╕ рдореЗрдВ рдЗрдВрдЯрд░рдлреЗрд╕, рд░рд╛рдЙрдЯрд┐рдВрдЧ рдЯреЗрдмрд▓, рдФрд░ рдиреЗрдЯрдлрд┐рд▓реНрдЯрд░ рдирд┐рдпрдореЛрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдЕрдиреНрдп рдиреЗрдЯрд╡рд░реНрдХреЛрдВ рдореЗрдВ рд╕рдорд╛рди рд╡рд╕реНрддреБрдУрдВ рд╕реЗ рдЕрд▓рдЧ рд╣реЛрддрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдПрдХ рдирд╛рдорд╕реНрдерд╛рди рдореЗрдВ рдЪрд▓рддреА рд╣реИ, рдФрд░ рдХреЗрд╡рд▓ рдЗрд╕ рдЬрд╛рд▓ рдХреА рд╡рд╕реНрддреБрдПрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕реБрд▓рдн рд╣реИрдВред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╕рднреА рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдХрд▓ рдиреЗрдЯрд╡рд░реНрдХ рдирд╛рдорд╕реНрдерд╛рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдк рд▓рд┐рдирдХреНрд╕ рдкрд░ рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдиреЗрдЯреНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВред
рдПрдХ рдирдпрд╛ xdp-test
рдирд╛рдо рд╕реНрдерд╛рди рдмрдирд╛рдПрдБ рдФрд░ xdp-remote
рд▓реЗ xdp-remote
ред
ip netns add xdp-test ip link set dev xdp-remote netns xdp-test
рдлрд┐рд░ xdp-test
рдореЗрдВ рдЪрд▓рдиреЗ рд╡рд╛рд▓реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ xdp-test
рдХреЛ рдирд╣реАрдВ xdp-local
(рдпрд╣ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдиреЗрдЯрд╡рдиреНрд╕ рдореЗрдВ рд░рд╣реЗрдЧреА) рдФрд░ 192.0.2.1 рдХреЛ рдХреЗрд╡рд▓ рдПрдХ рдкреИрдХреЗрдЯ рднреЗрдЬрддреЗ рд╕рдордп рдЗрд╕реЗ xdp-remote
рдорд╛рдзреНрдпрдо рд╕реЗ xdp-remote
, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ 192.0.2.0/ рдореЗрдВ рдПрдХрдорд╛рддреНрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣реИ 24 рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реИред рдпрд╣ рд╡рд┐рдкрд░реАрдд рджрд┐рд╢рд╛ рдореЗрдВ рднреА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рдиреЗрдЯрдиреНрд╕ рдХреЗ рдмреАрдЪ рдЬрд╛рдиреЗ рдкрд░, рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдбреНрд░реЙрдк рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкрддрд╛ рдЦреЛ рджреЗрддрд╛ рд╣реИред Netns рдореЗрдВ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ ip ...
рдЪрд▓рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ ip ...
рдЗрд╕ ip netns exec
рдХрдорд╛рдВрдб рдиреЗрдорд╕реНрдкреЗрд╕ 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 up
рдФрд░ рдЗрд╕реЗ sudo ./stand down
рдХрдорд╛рдВрдб рд╕реЗ рд╣рдЯрд╛ рджреЗрдВред
рдЕрдиреБрд░реЗрдЦрдг
рдлрд╝рд┐рд▓реНрдЯрд░ рдбрд┐рд╡рд╛рдЗрд╕ рдХреЗ рд╕рд╛рде рд╕рдВрд▓рдЧреНрди рд╣реИ:
ip -force link set dev xdp-local xdp object xdp_filter.o verbose
рдпрджрд┐ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреЛрдИ рдЕрдиреНрдп рдмрд╛рдзреНрдп рд╣реИ, рддреЛ рдирдП рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ рдмрд╛рдЗрдВрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП -force
рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред "рдХреЛрдИ рднреА рдЦрдмрд░ рдЕрдЪреНрдЫреА рдЦрдмрд░ рдирд╣реАрдВ рд╣реИ" рдЗрд╕ рдЖрджреЗрд╢ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рдирд┐рд╖реНрдХрд░реНрд╖ рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ рд╕реНрд╡реИрдЪреНрдЫрд┐рдХ рд╣реИред 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()
рдлрд╝рдВрдХреНрд╢рди bpf_trace_printk()
рд╕рдорд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рддреАрди рддрд░реНрдХреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдЫреЛрдбрд╝рдХрд░, рдФрд░ рдХреНрд╡рд╛рд▓реАрдлрд╛рдпрд░ рдХреА рдПрдХ рд╕реАрдорд┐рдд рд╕реВрдЪреАред bpf_printk()
рдореИрдХреНрд░реЛ рдХреЙрд▓ рдХреЛ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИред
SEC("prog") int xdp_main(struct xdp_md* ctx) { + bpf_printk("got packet: %p\n", 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
рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВред
рдкрд┐рдВрдЧ рдЕрдм рдЗрд╕рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрджреЗрд╢ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:
<...>-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 <...>
рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдИрдПрдХреНрд╕рдкреАрдПрдл рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдореЗрдВ рдбреЗрдЯрд╛ рдЦрдВрдб рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкреНрд░рд╛рд░реВрдк рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдПрдиреНрдХреЛрдб рдХрд░рдиреЗ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рддрд░реАрдХрд╛ рд╡реАрдПрдо рдХрдорд╛рдВрдбреЛрдВ рдХреЗ рддрддреНрдХрд╛рд▓ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рд╣реИ:
$ python -c "import binascii; print(bytes(reversed(binascii.unhexlify('0a7025203a74656b63617020746f67'))))" b'got packet: %p\n'
рдЗрд╕ рдХрд╛рд░рдг рд╕реЗ, рдбрд┐рдмрдЧ рдЖрдЙрдЯрдкреБрдЯ рдкрд░рд┐рдгрд╛рдореА рдХреЛрдб рдХреЛ рдмрд╣реБрдд рдмрдврд╝рд╛рддрд╛ рд╣реИред
XDP рдкреИрдХреЗрдЬ рднреЗрдЬрдирд╛
рдЪрд▓реЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЛ рдмрджрд▓рддреЗ рд╣реИрдВ: рдЗрд╕реЗ рд╕рднреА рдЖрдиреЗ рд╡рд╛рд▓реЗ рдкреИрдХреЗрдЯ рд╡рд╛рдкрд╕ рднреЗрдЬрдиреЗ рджреЗрдВред рдпрд╣ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рдЧрд▓рдд рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣реЗрдбрд░ рдореЗрдВ рдкрддреЛрдВ рдХреЛ рдмрджрд▓рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрдм рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ рдХрд╛рдо рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред
bpf_printk("got packet: %p\n", ctx); - return XDP_PASS; + return XDP_TX; }
xdp-remote
рдкрд░ tcpdump
рдЪрд▓рд╛рдПрдБред рдпрд╣ рд╕рдорд╛рди рдЖрдЙрдЯрдЧреЛрдЗрдВрдЧ рдФрд░ рдЗрдирдХрдорд┐рдВрдЧ ICMP рдЗрдХреЛ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ ICMP рдЗрдХреЛ рд░рд┐рдкреНрд▓рд╛рдИ рджрд┐рдЦрд╛рдирд╛ рдмрдВрдж рдХрд░ рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рджрд┐рдЦрд╛ рдирд╣реАрдВред рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ XDP_TX
рд▓рд┐рдП xdp-local
рдкрд░ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдореЗрдВ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП xdp-local
рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ xdp-remote
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ xdp-remote
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ xdp-remote
, рднрд▓реЗ рд╣реА рд╡рд╣ рдЦрд╛рд▓реА рд╣реЛ, рдФрд░ рдЙрд╕реЗ рдЙрдард╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдореБрдЭреЗ рдХреИрд╕реЗ рдкрддрд╛ рдЪрд▓рд╛?рд╕рдВрдкреВрд░реНрдг рдИрд╡реЗрдВрдЯ рддрдВрддреНрд░, рд╡реИрд╕реЗ, рдПрдХ рд╣реА рд╡рд░реНрдЪреБрдЕрд▓ рдорд╢реАрди рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рдХрд░реНрдиреЗрд▓ рдореЗрдВ рдкреИрдХреЗрдЬ рдкрде рдХреЛ рдЯреНрд░реЗрд╕ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдорд┐рд▓рддреА рд╣реИ, рдЕрд░реНрдерд╛рдд, 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_flush_bq()
рд╕реЗ рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЛрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рд╣рдо ENXIO
рджреНрд╡рд╛рд░рд╛ ENXIO
рдФрд░ рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдкрд╛рддреЗ рд╣реИрдВред
xdp_dummy.c
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдиреНрдпреВрдирддрдо рдлрд╝рд┐рд▓реНрдЯрд░ ( XDP_PASS
) рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ, рдЗрд╕реЗ 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
рдиреЗрдорд╕реНрдкреЗрд╕ рдореИрдХ рдПрдбреНрд░реЗрд╕ 192.0.2.1 рдХреЛ "рднреВрд▓" рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛, рдпрд╣ рдЗрд╕ рдЖрдИрдкреА рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдмрдпрд╛рди
рдЖрдЗрдП рдмрддрд╛рдП рдЧрдП рдХрд╛рд░реНрдп рдкрд░ рдЖрдЧреЗ рдмрдврд╝реЗрдВ: XDP рдкрд░ SYN рдХреБрдХреАрдЬрд╝ рддрдВрддреНрд░ рд▓рд┐рдЦреЗрдВред
рдЕрдм рддрдХ, SYN рдмрд╛рдврд╝ рдПрдХ рд▓реЛрдХрдкреНрд░рд┐рдп DDoS рд╣рдорд▓рд╛ рдмрдирд╛ рд╣реБрдЖ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рд╕рд╛рд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИред рдХрдиреЗрдХреНрд╢рди (рдЯреАрд╕реАрдкреА рд╣реИрдВрдбрд╢реЗрдХ) рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╕рдордп, рд╕рд░реНрд╡рд░ рдПрдХ SYN рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ, рднрд╡рд┐рд╖реНрдп рдХреЗ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд╕рдВрд╕рд╛рдзрди рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдПрдХ SYNACK рдкреИрдХреЗрдЯ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИ, рдФрд░ ACK рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИред рд╣рдорд▓рд╛рд╡рд░ рдмрд╕ рдорд▓реНрдЯреА-рд╣рдЬрд╛рд░ рдмреЙрдЯрдиреЗрдЯ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдореЗрдЬрдмрд╛рди рд╕реЗ рд╣рдЬрд╛рд░реЛрдВ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдХреА рдорд╛рддреНрд░рд╛ рдореЗрдВ рдирдХрд▓реА рдкрддреЗ рд╕реЗ SYN рдкреИрдХреЗрдЯ рднреЗрдЬрддрд╛ рд╣реИред рд╕рд░реНрд╡рд░ рдХреЛ рдкреИрдХреЗрдЯ рдХреЗ рдЖрдЧрдорди рдкрд░ рддреБрд░рдВрдд рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдПрдХ рдмрдбрд╝реЗ рд╕рдордп рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдореЗрдореЛрд░реА рдпрд╛ рд╕реАрдорд╛ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддреА рд╣реИ, рдирдП рдХрдиреЗрдХреНрд╢рди рд╕реНрд╡реАрдХрд╛рд░ рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рд╕реЗрд╡рд╛ рдЕрдиреБрдкрд▓рдмреНрдз рд╣реИред
рдпрджрд┐ рдЖрдк SYN рдкреИрдХреЗрдЯ рдХреЗ рд▓рд┐рдП рд╕рдВрд╕рд╛рдзрди рдЖрд╡рдВрдЯрд┐рдд рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ SYNACK рдкреИрдХреЗрдЯ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╕рд░реНрд╡рд░ рдХреИрд╕реЗ рд╕рдордЭ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдмрд╛рдж рдореЗрдВ рдЖрдпрд╛ ACK рдкреИрдХреЗрдЯ SYN рдкреИрдХреЗрдЯ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╕рд╣реЗрдЬрд╛ рдирд╣реАрдВ рдЧрдпрд╛ рдерд╛? рдЖрдЦрд┐рд░рдХрд╛рд░, рдПрдХ рд╣рдорд▓рд╛рд╡рд░ рдирдХрд▓реА рдПрд╕реАрдХреЗ рднреА рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддрд╛ рд╣реИред SYN рдХреБрдХреА рдХрд╛ рд╕рд╛рд░ рдкрддреЗ, рдмрдВрджрд░рдЧрд╛рд╣реЛрдВ рдФрд░ рдмрджрд▓рддреЗ рдирдордХ рд╕реЗ рдПрдХ рд╣реИрд╢ рдХреЗ рд░реВрдк рдореЗрдВ seqnum
рдореЗрдВ seqnum
рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдПрдирдХреЛрдб рдХрд░рдирд╛ рд╣реИред рдпрджрд┐ ACK рдирдордХ рдкрд░рд┐рд╡рд░реНрддрди рд╕реЗ рдкрд╣рд▓реЗ рдкрд╣реБрдВрдЪрдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛, рддреЛ рдЖрдк рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рд╕реЗ рд╣реИрд╢ рдХреА рдЧрдгрдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рдХреА рддреБрд▓рдирд╛ рдПрдХ acknum
ред рд╣рдорд▓рд╛рд╡рд░ рдирдХрд▓реА acknum
рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдирдордХ рдореЗрдВ рдПрдХ рд░рд╣рд╕реНрдп рд╢рд╛рдорд┐рд▓ рд╣реИ, рдФрд░ рд╕реАрдорд┐рдд рдЪреИрдирд▓ рдХреЗ рдХрд╛рд░рдг рдЗрд╕реЗ рд╕реБрд▓рдЭрд╛рдиреЗ рдХрд╛ рд╕рдордп рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
SYN рдХреБрдХреА рдХреЛ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЕрдЧрд░ SYN рдмрд╣реБрдд рдЬрд▓реНрджреА рдФрд░ рдереЛрдХ рдореЗрдВ рдЖ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдпрд╣ рд╕реНрд╡рддрдГ рд╣реА рдЪрд╛рд▓реВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рдЯреАрд╕реАрдкреА рд╣реИрдВрдбрд╢реЗрдХ рдкрд░ рд╢реИрдХреНрд╖рд┐рдХ рдХрд╛рд░реНрдпрдХреНрд░рдордЯреАрд╕реАрдкреА рдмрд╛рдЗрдЯреНрд╕ рдХреА рдПрдХ рдзрд╛рд░рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдбреЗрдЯрд╛ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, HTTP рдЕрдиреБрд░реЛрдз рдЯреАрд╕реАрдкреА рдкрд░ рднреЗрдЬреЗ рдЬрд╛рддреЗ рд╣реИрдВред рдкреИрдХреЗрдЯ рдореЗрдВ рдЯреБрдХрдбрд╝реЛрдВ рдореЗрдВ рдзрд╛рд░рд╛ рдХрд╛ рд╕рдВрдЪрд╛рд░ рд╣реЛрддрд╛ рд╣реИред рд╕рднреА рдЯреАрд╕реАрдкреА рдкреИрдХреЗрдЯ рдореЗрдВ рддрд╛рд░реНрдХрд┐рдХ рдЭрдВрдбреЗ рдФрд░ 32-рдмрд┐рдЯ рдЕрдиреБрдХреНрд░рдо рд╕рдВрдЦреНрдпрд╛ рд╣реЛрддреА рд╣реИ:
рдЭрдВрдбреЗ рдХрд╛ рд╕рдВрдпреЛрдЬрди рдПрдХ рд╡рд┐рд╢реЗрд╖ рдкреИрдХреЗрдЬ рдХреА рднреВрдорд┐рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИред SYN рдзреНрд╡рдЬ рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╣ рдХрдиреЗрдХреНрд╢рди рдХрд╛ рдкрд╣рд▓рд╛ рдкреНрд░реЗрд╖рдХ рдкреИрдХреЗрдЯ рд╣реИред ACK рдзреНрд╡рдЬ рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдкреНрд░реЗрд╖рдХ рдХреЛ рдПрдХ рдХрдиреЗрдХреНрд╢рди рдмрд╛рдЗрдЯ рд╕реЗ рдкрд╣рд▓реЗ рд╕рднреА рдХрдиреЗрдХреНрд╢рди рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рд╣реБрдП рдереЗред рдПрдХ рдкреИрдХреЗрдЯ рдореЗрдВ рдХрдИ рдЭрдВрдбреЗ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдЙрдирдХреЗ рд╕рдВрдпреЛрдЬрди рджреНрд╡рд╛рд░рд╛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ SYNACK рдкреИрдХреЗрдЯред
рдЕрдиреБрдХреНрд░рдо рд╕рдВрдЦреНрдпрд╛ (seqnum) рдЗрд╕ рдкреИрдХреЗрдЯ рдореЗрдВ рдкреНрд░рд╕рд╛рд░рд┐рдд рд╣реЛрдиреЗ рд╡рд╛рд▓реА рдкрд╣рд▓реА рдмрд╛рдЗрдЯ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдСрдлрд╕реЗрдЯ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдбреЗрдЯрд╛ рдХреЗ X рдмрд╛рдЗрдЯреНрд╕ рд╡рд╛рд▓реЗ рдкрд╣рд▓реЗ рдкреИрдХреЗрдЯ рдореЗрдВ рдпрд╣ рд╕рдВрдЦреНрдпрд╛ N рдереА, рддреЛ рдЕрдЧрд▓реЗ рдкреИрдХреЗрдЯ рдореЗрдВ рдирдП рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдпрд╣ N + X рд╣реЛрдЧрд╛ред рдХрдиреЗрдХреНрд╢рди рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рдкрдХреНрд╖ рдЗрд╕ рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рдЪрдпрди рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдХрд░рддрд╛ рд╣реИред
рдкрд╛рд╡рддреА рд╕рдВрдЦреНрдпрд╛ (acknum) - seqnum рдХреЗ рд╕рдорд╛рди рдСрдлрд╕реЗрдЯ, рд▓реЗрдХрд┐рди рдкреНрд░реЗрд╖рд┐рдд рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдмрд╛рдЗрдЯреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдкреНрд░рд╛рдкреНрддрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдкрд╣рд▓реЗ рдмрд╛рдЗрдЯ рдХреА рд╕рдВрдЦреНрдпрд╛ рдЬреЛ рдкреНрд░реЗрд╖рдХ рдиреЗ рдирд╣реАрдВ рджреЗрдЦреА рдереАред
рдХрдиреЗрдХреНрд╢рди рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ, рдкрд╛рд░реНрдЯрд┐рдпреЛрдВ рдХреЛ seqnum
рдФрд░ acknum
рдкрд░ рд╕рд╣рдордд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЧреНрд░рд╛рд╣рдХ рдЕрдкрдиреЗ seqnum = X
рд╕рд╛рде рдПрдХ SYN рдкреИрдХреЗрдЯ рднреЗрдЬрддрд╛ рд╣реИред рд╕рд░реНрд╡рд░ рдПрдХ SYNACK рдкреИрдХреЗрдЯ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рд╡рд╣ рдЕрдкрдирд╛ seqnum = Y
рд▓рд┐рдЦрддрд╛ рд╣реИ рдФрд░ acknum = X + 1
рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИред рдЧреНрд░рд╛рд╣рдХ рдПрдХ рдПрд╕реАрдХреЗ рдкреИрдХреЗрдЯ рдХреЗ рд╕рд╛рде SYNACK рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ seqnum = X + 1
, acknum = Y + 1
ред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреЗрдЯрд╛ рд╕реНрдерд╛рдирд╛рдВрддрд░рдг рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред
рдпрджрд┐ рд╡рд╛рд░реНрддрд╛рдХрд╛рд░ рдкреИрдХреЗрдЯ рдХреА рдкреНрд░рд╛рдкреНрддрд┐ рдХреА рдкреБрд╖реНрдЯрд┐ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдЯреАрд╕реАрдкреА рдЯрд╛рдЗрдордЖрдЙрдЯ рджреНрд╡рд╛рд░рд╛ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рднреЗрдЬрддрд╛ рд╣реИред
SYN рдХреБрдХреАрдЬрд╝ рд╣рдореЗрд╢рд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХреА рдЬрд╛рддреА рд╣реИрдВ?рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдпрджрд┐ SYNACK рдпрд╛ ACK рдЦреЛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдлрд┐рд░ рд╕реЗ рднреЗрдЬрдиреЗ рдХрд╛ рдЗрдВрддрдЬрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ - рдХрдиреЗрдХреНрд╢рди рдзреАрдорд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИред рджреВрд╕рд░реЗ, SYN рдкреИрдХреЗрдЬ рдореЗрдВ - рдФрд░ рдХреЗрд╡рд▓ рдЗрд╕рдореЗрдВ! - рдХрдИ рд╡рд┐рдХрд▓реНрдк рдкреНрд░реЗрд╖рд┐рдд рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рдХрдиреЗрдХреНрд╢рди рдХреЗ рдЖрдЧреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдЖрдиреЗ рд╡рд╛рд▓реЗ SYN рдкреИрдХреЗрдЯ рдХреЛ рдпрд╛рдж рдХрд┐рдП рдмрд┐рдирд╛, рд╕рд░реНрд╡рд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЗрди рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░ рджреЗрддрд╛ рд╣реИ, рдЕрдЧрд▓реЗ рдкреИрдХреЗрдЯ рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдЙрдиреНрд╣реЗрдВ рдЕрдм рдирд╣реАрдВ рднреЗрдЬреЗрдЧрд╛ред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЯреАрд╕реАрдкреА рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЪрд░рдг рдореЗрдВ, рдХрдиреЗрдХреНрд╢рди рдХреА рдЧреБрдгрд╡рддреНрддрд╛ рдХрдо рд╣реЛ рдЬрд╛рдПрдЧреАред
рдкреИрдХреЗрдЬ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ, рдПрдХ XDP рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ рдирд┐рдореНрди рдХрд╛рд░реНрдп рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:
- SYN рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдХреА рдХреЗ рд╕рд╛рде SYNACK;
- ACK RST (рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ) рдХрд╛ рдЬрд╡рд╛рдм;
- рдЕрдиреНрдп рдкреИрдХреЗрдЯ рддреНрдпрд╛рдЧреЗрдВред
рдкреИрдХреЗрдЬ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдЫрджреНрдордХреЛрдб:
Ethernet, . IPv4, . , (*) , . TCP, . (**) SYN, SYN-ACK cookie. ACK, acknum cookie, . N . (*) RST. (**) .
рдПрдХ (*)
рдЙрди рдмрд┐рдВрджреБрдУрдВ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╕рд┐рд╕реНрдЯрдо рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП - рдкрд╣рд▓реЗ рдЪрд░рдг рдореЗрдВ, рдЖрдк рдЙрдирдХреЗ рдмрд┐рдирд╛ рдмрд╕ рдПрдХ рдЯреАрд╕реАрдкреА рд╣реИрдВрдбрд╢реЗрдХ рдХреЛ SYN рдХреБрдХреА рдХреА рдкреАрдврд╝реА рдХреЗ рд╕рд╛рде seqnum рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рдХреЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЬрдЧрд╣ (**)
, рдЬрдмрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдореЗрдЬ рдирд╣реАрдВ рд╣реИ, рд╣рдо рдкреИрдХреЗрдЯ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВрдЧреЗред
рдЯреАрд╕реАрдкреА рд╣рд╛рде рдорд┐рд▓рд╛рдирд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
рдкреИрдХреЗрдЬ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░реЗрдВ рдФрд░ рдХреЛрдб рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░реЗрдВ
рд╣рдореЗрдВ рдиреЗрдЯрд╡рд░реНрдХ рд╣реЗрдбрд░ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: рдИрдерд░рдиреЗрдЯ ( uapi/linux/if_ether.h
), IPv4 ( uapi/linux/ip.h
) рдФрд░ TCP ( uapi/linux/tcp.h
)ред рдкрд┐рдЫрд▓реЗ рдПрдХ рдореИрдВ atomic64_t
рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдХрд╛рд░рдг рдХрдиреЗрдХреНрдЯ рдирд╣реАрдВ рдХрд░ рд╕рдХрд╛, рдореБрдЭреЗ рдЖрд╡рд╢реНрдпрдХ рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреЛ рдХреЛрдб рдореЗрдВ рдХреЙрдкреА рдХрд░рдирд╛ рдкрдбрд╝рд╛ред
рдкрдардиреАрдпрддрд╛ рдХреЗ рд▓рд┐рдП рд╕реА рдореЗрдВ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдП рдЧрдП рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХреЙрд▓ рдХреЗ рд╕реНрдерд╛рди рдкрд░ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдХрд░реНрдиреЗрд▓ рдореЗрдВ рдИрдмреАрдкреАрдПрдл рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛ рд╕рдВрдХреНрд░рдордг рдХреЛ рд╡рд╛рдкрд╕ рд░реЛрдХ рджреЗрддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рдд, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд▓реВрдк рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ред
#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); }
рдореИрдВ рдП рдФрд░ рдмреА рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдЪреЗрдХреЛрдВ рдкрд░ рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рддрд╛ рд╣реВрдВред рдпрджрд┐ рдЖрдк рдП рдХреА рдЯрд┐рдкреНрдкрдгреА рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдХрд╛рд░реНрдпрдХреНрд░рдо рдЗрдХрдЯреНрдард╛ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдирд┐рдореНрди рдХреЗ рджреМрд░рд╛рди рд╕рддреНрдпрд╛рдкрди рддреНрд░реБрдЯрд┐ рд╣реЛрдЧреА:
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 рдХреЛ рдЙрддреНрддрд░ рджреЗрдВ
рдЗрд╕ рд╕реНрддрд░ рдкрд░ рд▓рдХреНрд╖реНрдп рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд seqnum
рд╕рд╛рде рдПрдХ рд╕рд╣реА SYNACK рдкреИрдХреЗрдЯ seqnum
, рдЬрд┐рд╕реЗ рднрд╡рд┐рд╖реНрдп рдореЗрдВ SYN рдХреБрдХреА рд╕реЗ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрди 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 рдХрд░реНрдиреЗрд▓ рдХреЛ рдРрд╕реА рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рдереАред рд╢рд╛рдпрдж рд╕рдВрдХрд▓рдХ рдиреЗ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЛ рдХреНрд╖реЗрддреНрд░ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд┐рдпрд╛ред Moral - рд╕рд░рд▓реАрдХреГрдд рдХреЛрдб рдмрд╣реБрдд рд╕рд╛рд░реЗ рдШреЛрдВрд╕рд▓реЗ рдХреЗ рд╢рд┐рдХрд╛рд░ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИред
рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛ рдХреЗ рд╕рдореНрдорд╛рди рдореЗрдВ рд▓рдВрдмрд╛рдИ рдХреА рдЖрдЧреЗ рдХреА рдирд┐рдпрдорд┐рдд рдЬрд╛рдБрдЪ; рдиреАрдЪреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ 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;
рдЯреАрд╕реАрдкреА рдкреЛрд░реНрдЯ, рдЖрдИрдкреА рдПрдбреНрд░реЗрд╕ рдФрд░ рдореИрдХ рдПрдбреНрд░реЗрд╕ рд╕реНрд╡реИрдк рдХрд░реЗрдВред рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп XDP рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╕реЗ рд╕реБрд▓рдн рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП memcpy()
рдПрдХ рдореИрдХреНрд░реЛ рд╣реИ рдЬреЛ рдХреНрд▓реИрдВрдЧ рдЖрдВрддрд░рд┐рдХ рдХреЛ рдЫреБрдкрд╛рддрд╛ рд╣реИред
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);
рдЪреЗрдХрд╕рдо рдкреБрдирд░реНрдЧрдгрдирд╛
рдЖрдИрдкреАрд╡реА 4 рдФрд░ рдЯреАрд╕реАрдкреА рдЪреЗрдХрд╕рдо рдХреЛ рд╣реЗрдбрд░ рдореЗрдВ рд╕рднреА 16-рдмрд┐рдЯ рд╢рдмреНрджреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рд╣реЗрдбрд░ рдХрд╛ рдЖрдХрд╛рд░ рдЙрди рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рдд рд╕рдВрдХрд▓рди рдХреЗ рд╕рдордп рдпрд╣ рдЕрдЬреНрдЮрд╛рдд рд╣реИред рдпрд╣ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛ рдПрдХ рдирд┐рдпрдорд┐рдд рд╕реАрдорд╛ рдХреЛ рдПрдХ рдЪрд░ рд╕реАрдорд╛ рдкрд░ рдирд╣реАрдВ рдЫреЛрдбрд╝реЗрдВрдЧреЗред рд▓реЗрдХрд┐рди рд╣реЗрдбрд░ рдХрд╛ рдЖрдХрд╛рд░ рд╕реАрдорд┐рдд рд╣реИ: рдкреНрд░рддреНрдпреЗрдХ рдХреЛ 64 рдмрд╛рдЗрдЯреНрд╕ рддрдХред рдЖрдк рдирд┐рд╢реНрдЪрд┐рдд рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд▓реВрдк рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рд╕рдордп рд╕реЗ рдкрд╣рд▓реЗ рд╕рдорд╛рдкреНрдд рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рдореИрдВ рдиреЛрдЯ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ RFC 1624 рд╣реИ рдХрд┐ рдХреИрд╕реЗ рдЪреЗрдХрд╕рдо рдХреЛ рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдкреБрдирд░реНрдЧрдгрдирд╛ рдХрд┐рдпрд╛ рдЬрд╛рдП рдЕрдЧрд░ рдХреЗрд╡рд▓ рдирд┐рд╢реНрдЪрд┐рдд рдкреИрдХреЗрдЯ рд╢рдмреНрдж рдмрджрд▓реЗ рдЬрд╛рдПрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд┐рдзрд┐ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдмрдирд╛рдП рд░рдЦрдирд╛ рдЕрдзрд┐рдХ рдХрдард┐рди рд╣реЛрдЧрд╛ред
рдЪреЗрдХрд╕рдо рдЧрдгрдирд╛ рд╕рдорд╛рд░реЛрд╣:
#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, :
:
$ 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- .
рд╕рдВрджрд░реНрдн: