Technologia eXpress Data Path (XDP) arbitrariam negotiationis tractationem in interfaciebus permittit. Linux Antequam fasciculi acervum retiaculi nuclei ingrediuntur, applicationes XDP includunt protectionem DDoS (CloudFlare), filtra complexa, et collectionem statisticarum (Netflix). Programmata XDP a machina virtuali eBPF exsequuntur et ideo limitationes habent et in codice suo et in functionibus nuclei praesto, secundum genus filtri.
Hic articulus intendit vitia multarum materiarum de XDP corrigere. Primo, codicem iam paratum praebent qui statim functiones XDP praetermittit: vel ad verificationem paratus est vel nimis simplex est ut problemata creet. Cum conaris codicem tuum ex nihilo scribere, difficile est intellegere quomodo errores typicos tractare. Secundo, methodos ad XDP localiter probandum sine machina virtuali vel apparatu non tractat, quamvis hae methodi suas insidias habeant. Hic textus destinatur programmatoribus qui retibus et... Linux, qui XDP et eBPF student.
In hac parte, singillatim intelligemus quomodo XDP colum collectum sit et quomodo eum experiatur, tunc scribemus simplicem versionem notae SYN crustulorum mechanismum in gradu processus fasciculi. Nos non creare "album album" sed
verificatur clientes, custodi calculis et colum - satis tigna administrare.
Scribemus in C - non est similis, sed practicus est. Totum codicem in GitHub per nexum in fine praesto est et dividitur in committit secundum gradus in articulo descriptos.
Renuntiationem. Per decursum huius articuli, minimam solutionem explicabimus ad repellendos DDoS impetus, quia hoc munus reale est pro XDP et peritia mea area. Praecipuum tamen propositum est technologiam intelligere, hoc non est dux ad tutelam paratam efficiendam. In codice consequat non optimized et nonnullas nuances omittit.
XDP Brevis Overview
Tantum puncta cardinis effingam ut documenta et articulos exsistentes non duplicent.
Ita, colum code in nucleum oneratur. Reditus fasciculi ad colum transmittuntur. Quam ob rem colum statuere debet: fasciculum in nucleum transi.XDP_PASS) Gutta packet (XDP_DROP) Vel mitte (XDP_TX). Colamentum sarcinam mutare potest, hoc praesertim verum est XDP_TX. Etiam programmata abortum facere potes (XDP_ABORTED) et sarcinam retexere, sed hoc analogum est assert(0) — ad debugging.
eBPF (extenta Berkley Packet Filter) machina virtualis consulto simplex facta est ut nucleus inspicere possit codicem non ansam et aliorum memoriam non laedat. Cumulativo constrictas et compescit;
- Ansae (retro) prohibentur.
- BIBLIOTHECA data est, sed munera nulla (omnia C functiones inlineari debent).
- Memoria accessuum extra ACERVUM et quiddam conleci prohibentur.
- Magnitudo codicis circumscripta est, sed in usu hoc non est valde significatum.
- Tantum vocat ad munera specialia nuclei (eBPF adiutores) permissa.
Expansis et insertis filtrum hoc spectat:
- Source codice (eg *
kernel.c) Obiectum compilata (kernel.o) pro architectura machinae virtualis eBPF. Compilatio ad eBPF, sicut Octobre MMXIX, adiuvatur Clang et promittitur in GCC 2019. - Si hoc obiectum codice continet structuras nucleos (exempli gratia tabulae et calculi), eorum IDs substituuntur a cyphras, quod significat talem codicem exsecutioni mandari non posse. Priusquam in nucleum oneraveris, necesse est has cyphras reponere cum IDs objectorum specificorum per nucleos vocatos creatos (coniunge codicem). Hoc cum exterioribus utilitatibus facere potes, vel programmata scribere potes quae speciale colum ligant et cumulat.
- Programma onustum nucleus certificat. Absentia cyclorum et defectus super fasciculum et limites acervos coercetur. Si uerificans probare non potest codicem esse verum, propositum reicitur — necesse est ut ei placere possit.
- Post prospere verificationem, nucleus fabricae obiecti architecturae eBPF compingit in codice machinae pro architecturae systematis (mox-in tempore).
- Progressio ad interface adiungitur et incipit processus facis.
Cum XDP in nucleo currat, debugging per vestigia diurna et fasciculos quos programma filtrat vel generat perficitur. Attamen, eBPF securitatem codicis onusti pro systemate praestat, ut cum XDP directe in machina tua locali experiri possis. Linux.
Praeparans Opera
conventus
Clang non potest directe producere codicem objectum ad architecturam eBPF, ergo processus duobus gradibus consistit:
- Compile C code ad LLVM bytecode (
clang -emit-llvm). - Convertere bytecode ad eBPF rem codice (
llc -march=bpf -filetype=obj).
Cum colum scribebat, duo fasciculi cum functionibus auxiliaribus et macros utiles erunt . Aliquam sit amet quam acinum versionem aequare (KVER). Download eos 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 BASEFasciculus Makefile pro Arch Linux (nucleus 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 ./*.oKDIR iter ad acinum caput continet; ARCH — architecturae systematis. Viae et instrumenta distributiones leviter variari possunt.
Exemplum differentiarum pro Debian 10 (nucleus 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 directorium cum capitis auxiliis et pluribus directoriis cum nucleo capitis connectere. Symbolum __KERNEL__ significat UAPI (usoris API) capitis capita pro codice kernel definiri, cum colum in nucleo supplicium sit.
Stack praesidium potest erret (-fno-stack-protector), quia eBPF codicis uerificatiuum adhuc pro ACERVUS violationes limitum coercet. In optimizations statim vertere valet, quia magnitudo eBPF bytecode limitatur.
Incipiamus filtrum quod omnia facis et nihil agit;
#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";bigas make orationes xdp_filter.o. Ubi nunc ea conaris?
Test scamnum
Duas interfacies instructa est apparatio: unam pro filtro et alteram unde fasciculi mittentur. Hae machinae plene functionales esse debent. Linux cum inscriptionibus IP tuis ad inspiciendum quomodo applicationes regulares cum filtro nostro operantur.
Devices Veth (Aethernet virtualis) nobis aptae sunt: haec sunt bina interfaces virtualis retis "connexa" directe inter se. Eos sic creare potes (in hac sectione omnia mandata ip peraguntur e root):
ip link add xdp-remote type veth peer name xdp-localest xdp-remote и xdp-local - fabrica nomina. On xdp-local (192.0.2.1/24) filtrum apponetur, with xdp-remote (192.0.2.2/24) commeatum advenientem transmittet. Sed problema est: interfacies in eadem machina sunt, et Linux Non per alterum commeatum ad unum eorum mittet. Hoc callidis regulis solvi potest. iptablessed sarcinas mutare, quod debugging incommodum est. Praestat spatiis retis uti (infra netns).
Spatium nominum retiale continet seriem interfacierum, tabularum itinerum, et regularum NetFilter, ab obiectis similibus in aliis nominibus retialibus separatas. Quisque processus in spatio nominum specifico operatur et solum ad obiecta intra illud spatium nominum retiale accedere potest. Systema, per default, unum spatium nominum retiale pro omnibus obiectis habet, ita ut in eo laborare possis. Linux et de retibus nescio.
Novo spatio nominali faciamus xdp-test ac movere ibi xdp-remote.
ip netns add xdp-test
ip link set dev xdp-remote netns xdp-testTum processus currit in xdp-testnon "videbit" xdp-local remanebit in netns per defaltam et cum missum fasciculum ad 192.0.2.1 transibit xdp-remotequia sola interface in 192.0.2.0/24 huic processui pervia est. Hoc etiam in oppositum operatur.
Cum inter netns moveatur, interface descendit et electronica amittit. Configurare interface in rete, currere debes ip ... in hoc imperio spatio nominali 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 upUt vides, hoc non est diversum ab occasu xdp-local per default spatio nominali:
ip address add 192.0.2.1/24 dev xdp-local
ip link set xdp-local upSi curris tcpdump -tnevi xdp-local, videre potes e xdp-testtraduntur huic instrumenti;
ip netns exec xdp-test ping 192.0.2.1Convenit mittere concham xdp-test. Repositorium habet scriptum quod automates cum stante operantur, exempli gratia, possis stare cum mandato sudo ./stand up ac delere sudo ./stand down.
Tracing
Filtrum cum fabrica sic coniungitur:
ip -force link set dev xdp-local xdp object xdp_filter.o verboseclavem -force opus est ut novam programma coniungat si alius iam coniunctus est. "Nihil evangelium est bonum nuntium" non est de hoc mandato, conclusio est in omni casu voluminosa. indicant verbose ad libitum, sed cum eo apparet relatio in opere codicis verificantis cum indice conventus:
Verifier analysis:
0: (b7) r0 = 2
1: (95) exitProgressio ab interface reserare:
ip link set dev xdp-local xdp offIn scripto haec sunt mandata sudo ./stand attach и sudo ./stand detach.
Colamentum apponendo, efficere potes ut ping currere pergit, sed opus facit propositum? Addamus omnia. Officium similis printf()sed tantum sustinet ad tria argumenta praeter exemplar et limi- tium elenchum. Macro bpf_printk() simpliciorem vocationem.
SEC("prog")
int xdp_main(struct xdp_md* ctx) {
+ bpf_printk("got packet: %pn", ctx);
return XDP_PASS;
}Output accedit ad vestigium nuclei canalis, quod fieri debet;
echo -n 1 | sudo tee /sys/kernel/debug/tracing/options/trace_printkVidere nuntium filum:
cat /sys/kernel/debug/tracing/trace_pipeUtrumque praeceptum vocant sudo ./stand log.
Ping nunc felis nunc ut hoc nuntios:
<...>-110930 [004] ..s1 78803.244967: 0: got packet: 00000000ac510377Si verificantis output inspicias, miras calculos animadvertes;
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
<...>Ita est, quod programmata eBPF non habent sectionem datam, ergo unicus modus chordae formatae immediatae rationes mandatorum VM encode est;
$ python -c "import binascii; print(bytes(reversed(binascii.unhexlify('0a7025203a74656b63617020746f67'))))"
b'got packet: %pn'Quam ob rem, debug output valde bloats codicem consequens.
Mittens XDP Packets
Filtrum mutemus: omnes fasciculos ineuntes remittat. Haec falsa ex parte retis, cum inscriptiones in capite mutare necesse esset, nunc opus in principio magni momenti est.
bpf_printk("got packet: %pn", ctx);
- return XDP_PASS;
+ return XDP_TX;
}Launch tcpdump on xdp-remote. Ostendere idem exitus et ineuntes ICMP Echo Request et desinere ostendens ICMP Echo Respondere. Sed non ostendit. Evenit ut opus XDP_TX in progressio on xdp-local ad par interface xdp-remote programma etiam adsignatum, etsi vacuum, et elevatum.
Unde hoc noui?
Mechanismus perf eventus permittit obiter, eadem machina virtuali utens, hoc est, eBPF, pro discontionibus cum eBPF.
Debes ex malo facere, quia nihil est aliud facere ex malo.
$ 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])
<...>Quid est signum 6?
$ errno 6
ENXIO 6 No such device or addressmunus veth_xdp_flush_bq() accipit errorem codice e veth_xdp_xmit(), ubi quaerere per ENXIO et commentarium reperies.
Reddamus minimum filter (XDP_PASS) In file xdp_dummy.c, fac cum fac , liga eam cum xdp-remote:
ip netns exec remote
ip link set dev int xdp object dummy.oautem tcpdump ostendit quid sit expectandum;
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 64Si modo ARPs loco ostenduntur, Filtra tollere debes (hoc facit sudo ./stand detach) Dimitte pingtunc filtra pone et iterum conare. Quaestio est quod colum XDP_TX valet tam in ARP et si ACERVUS
spatiis nominalibus xdp-test curo "obliviscere" MAC inscriptionem 192.0.2.1, hanc IP solvere non poterit.
DE PECCATO quaestio
Ad certum negotium transeamus: scribe machina crustula SYN in XDP.
SYN Diluvium remanet impetus popularis DDoS, cujus essentia talis est. Cum nexus constituitur (TCP handshake), minister syn accipit, facultates allocet ad futuram connexionem, respondet cum fasciculo SYNACK et ACK exspectat. Percussor tantum millia SYN packets secundas mittit ex inscriptionibus spoofed ab unoquoque exercitu in botnet multi-mille-strong. Servus in adventu fasciculi statim facultates collocare cogitur, sed eas post tempus magnum dimittit: proinde, memoria vel limites defatigati sunt, novi nexus non recipiuntur, et servitium perpendat.
Si facultates in SYN fasciculo non collocant, sed tantum cum fasciculo SYNACK respondes, quomodo tunc ministra potest intelligere fasciculum ACK qui postea venit ad syn fasciculum qui non servatus est? Post omnes, oppugnator etiam fictus ACKs generare potest. Syn crustulum punctum encode est in . seqnum nexum parametri ut detraheret inscriptiones portuum et mutans salem. Si ACK curo venerit antequam sal mutatum sit, iterum computare potes et cum eo compara acknum. Forge acknum oppugnator non potest, cum sal secretum includit, nec tempus erit per illud ex limitata canali.
Crustulum SYN iam diu in nucleo implementatum est. Linux et etiam automatice activari potest si SYNs nimis celeriter et magno numero advenerint.
Educational programmata TCP handshake
TCP transmissio data praebet ut rivus bytes, exempli gratia, petitiones HTTP super TCP transmittuntur. rivus in frusta dilabitur. Omnes TCP packets habent vexilla logica et numeri seriei 32-bit;
Compositio vexillorum munus particularis sarcinae determinat. SYN Vexillum indicat hunc esse primum fasciculum in nexu mittentis. Vexillum ACK significat Mittens accepit omnem nexum data usque ad byte
acknum. Fasciculus plura vexilla habere potest et ab eorum compositione dicitur, verbi gratia synacki fasciculus.Sequentia numerus (seqnum) designat offsets in notitia fluminis primi byte qui in hac fasciculo transmittitur. Exempli gratia, si in primo fasciculo cum X bytes notitiarum hic numerus fuerit N, in altera fasciculus cum novis data N+X erit. In nexu principio, passim uterque numerus hunc eligit.
Agnitio numeri - idem cinguli ac seqnum, sed non determinat numerum byte transmissi, sed numerum primi byte a recipiente, quem mittens non vidit.
In principio nexu, partes consentire debent seqnum и acknum. Cliens mittit syn fasciculum cum suis seqnum = X. Servus cum fasciculo SYNACK respondet, ubi suum commemorat seqnum = Y et exponit acknum = X + 1. Cliens synack respondet cum fasciculo ACK, ubi seqnum = X + 1, acknum = Y + 1. Post haec ipsa translationis notitia incipit.
Si par acceptum fasciculum non agnoscit, TCP post tempus resilit.
Cur SYN crustula non semper adhibentur?
Uno modo, si SYNACK vel ACK perierit, exspectandum erit ut iterum mittendus - nexus quae retardabit. Secundo in sarcina SYN - et in ea tantum! — nonnullae optiones transmittuntur quae ulteriorem nexum operationis afficiunt. Sine memoria advenientis SYN packets, ministra sic optiones has negligit, cliens eas in proximas fasciculos non mittet. TCP operari in hoc casu potest, sed saltem in initio, qualitas connexionis decrescet.
Ex perspectiva fasciculis, progressio XDP sequentia facere debet:
- respondere SYN with synack with crustulum ;
- respondent ACK cum RST (disconnect);
- abiicias reliquas facis.
Pseudocode algorithmus una cum sarcina parsing :
Если это не Ethernet,
пропустить пакет.
Если это не IPv4,
пропустить пакет.
Если адрес в таблице проверенных, (*)
уменьшить счетчик оставшихся проверок,
пропустить пакет.
Если это не TCP,
сбросить пакет. (**)
Если это SYN,
ответить SYN-ACK с cookie.
Если это ACK,
если в acknum лежит не cookie,
сбросить пакет.
Занести в таблицу адрес с N оставшихся проверок. (*)
Ответить RST. (**)
В остальных случаях сбросить пакет.Unus (*) puncta ubi debes statum systematis administrare - in primo stadio sine illis facere potes, solum exsequendo handshake TCP cum generatione syn crustulum ut seqnum.
In macula (**)dum mensam non habemus, fasciculum omittemus.
Exsequens TCP handshake
Parsing in sarcina et probari in codice
Non opus est structurarum network header: Aer (uapi/linux/if_ether.h), IPv4 (uapi/linux/ip.h) Et TCP (uapi/linux/tcp.h). Hoc coniungere potui propter errores relatos atomic64_tDebebam imitari definitiones necessarias in codice.
Munera omnia quae in C in luce sunt ad promptitudinem inclinari debent in puncto vocationis, cum eBPF verificantis in nucleo vetat regressionem, id est, re vera, ansas et functiones vocat.
#define INTERNAL static __attribute__((always_inline))Macro LOG() disables excudendi in emissione constructum.
Propositum est TRADUCTOR officiorum. Quisque accipit fasciculum in quo vari um caput extulit, v.gr. process_ether() Expectat ut impleatur ether. Fundatur in eventus analysis campi, munus fasciculum ad altiorem gradum transire potest. Effectus functionis actio est XDP. Nunc, SYN and ACK tracto omnes facis.
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);
}Animum duco ad reprimenda A et B. Si commentabis A, propositum aedificabis, sed error verificationis erit cum oneratione:
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!Clavis filum invalid access to packet, off=13 size=1, R7(id=0,off=0,r=0): Sunt viae executionis quando tertiae decimae byte ab initio quiddam est extra conleci. Difficile est intelligere ex enumeratione quam de linea loquimur, sed est numerus instructus (12) et disassembler ostendens lineas fontium codicem;
llvm-objdump -S xdp_filter.o | lessHic demonstrat lineam
LOG("Ether(proto=0x%x)", bpf_ntohs(ether->h_proto));Ex quo patet quod quaestio est ether. Etiam id semper velit.
Ad primum ergo syn
Propositum in hac statu est rectam synacam generare cum certo seqnumquae in posterum a SYN crustulum restituetur. Omnes mutationes fieri in process_tcp_syn() et locis circumiacentibus.
Sarcina verificationis
Incommode hic versus est notissimus, vel potius commentarius;
/* Required to verify checksum calculation */
const void* data_end = (const void*)ctx->data_end;Cum primam versionem codicis scriberet, 5.1 nucleus adhibitus est, cuius differentia pro uerificante erat. data_end и (const void*)ctx->data_end. In tempore scribendi nucleus hoc problema 5.3.1 non habuit. Fieri potest ut compilator accederet variabilis localis aliter quam campus. Fabulae moralis: Simplicius signum adiuvare potest cum multum nidificans est.
Proxima sunt exercitatione longitudo coercens ad gloriam uerificantis; O* MAX_CSUM_BYTES inferius.
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 */
}Explicans sarcina
Implemus seqnum и acknumpone ACK (SYN iam positum);
const u32 cookie = 42;
tcp->ack_seq = bpf_htonl(bpf_ntohl(tcp->seq) + 1);
tcp->seq = bpf_htonl(cookie);
tcp->ack = 1;Swap TCP portus, IP oratio et MAC inscriptiones. Vexillum bibliothecae XDP a programmatis XDP adiri non est memcpy() — a tortor quae intus Clang abscondit.
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);Recalculum checksums
IPv4 et TCP checksums additamenta omnium verborum 16-parum in capite requirunt, et capitum magnitudo in illis inscripta est, id est tempore compilationis incognita. Hoc problema est quia uerificans normalem ansam ad terminum variabilis non praetermittet. Magnitudo autem capitis finitur: usque ad 64 bytes singulas. Ansam facere potes cum certo numero iterationum, quae mane finire possunt.
Quod est " quomodo ad checksum ex parte recalculare, si modo certa verba fasciculorum mutantur. Sed modus non est universalis, et difficilius exsecutionem ponere.
Checksum munus calculi:
#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;
}Etsi size verificatur in vocatione Codicis, condicio secundae exitus necessaria est ut uerificans perfectionem ansa probare possit.
Pro 32-bis verbis, versio simplicior impletur;
INTERNAL u32
sum16_32(u32 v) {
return (v >> 16) + (v & 0xffff);
}Actu recalculing checksums and mittendis packet back:
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;munus carry() facit checksum ex summa 32-bitrum verborum 16 bis, secundum RFC 791'.
TCP handshake verificationem
Colum recte constituit nexum cum netcat, omittendo ultimo ACK, cui Linux respondit fasciculo RST quia acervus retiarius SYN non accepit — in SYNACK conversus et remissus est — et ex prospectu systematis operandi, fasciculus advenit qui ad conexiones apertas non pertinebat.
$ sudo ip netns exec xdp-test nc -nv 192.0.2.1 6666
192.0.2.1 6666: Connection reset by peerAliquam sit amet applicationes flexas plenas inhibere et observare tcpdump on xdp-remote quia, e.g. hping3 non respondet falsa checksums.
SYN crustulum
Ex prospectu XDP, ipsa verificatio est trivialis. Algorithmus calculi est primitivus et verisimiliter vulnerabilis aggressori callido. Nucleus... Linux, exempli gratia, cryptographicum SipHash utitur, sed eius implementatio pro XDP manifeste extra fines huius articuli est.
Introducti ad novos TODOs ad communicationem externum pertinentes:
XDP progressio potest abscondere
cookie_seed(partem secreti salis) in variabili globali repositione opus est in nucleo cuius valor periodice renovabitur a certo generante.Si SYN crustulum par in ACK conleci, nuntium imprimere non debes, sed IP clientis verificati memento ut pergas transitum ex eo.
Legitima clientis verificationem:
$ sudoip netns exec xdp-test nc -nv 192.0.2.1 6666
192.0.2.1 6666: Connection reset by peerHaec omnia monstrant quod reprehendo Transierunt (flags=0x2 — Hoc est, SYN; flags=0x10 est 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 20200c0Dum nullus est index IPS verificatorum, nullum praesidium erit ab ipso diluvio SYN, sed hic est reactionem ad diluvium ACK ab hoc mandato immissum;
sudo ip netns exec xdp-test hping3 --flood -A -s 1111 -p 2222 192.0.2.1Log entries:
Ether(proto=0x800)
IP(src=0x15bd11a dst=0x15bd11e proto=6)
TCP(sport=3236 dport=2222 flags=0x10)
cookie mismatchconclusio,
Interdum eBPF in genere et XDP in particulari magis exhibentur instrumentum administratoris provectum quam ut suggestum evolutionis. Re quidem, XDP instrumentum est ut processus nuclei fasciculorum impediat, et non alterutrum cum acervo nucleo, sicut DPDK et aliae nuclei praetermittant bene. Ex altera parte, XDP permittit te ad logicam satis complexam efficiendam, quae praeterea facile est sine intermissione in negocii processui renovare. Verificans magnas difficultates non creat, personaliter, non recuso hoc pro partibus usoris usoris.
In altera parte, si locus iucundus est, mensam de clientibus et disiunctis verificatis complebimus, calculis deducendi et utilitatem usoris scribemus ad colum administrandum.
references:
Source: www.habr.com
