La conception de passerelles VPN modernes capables de soutenir des débits de plusieurs gigabits par seconde requiert un contrôle programmable précis sur les flux de paquets entrants et sortants. Bien qu'eXpress Data Path (XDP) se soit imposé pour le filtrage brut au niveau du pilote réseau, il présente une limite structurelle : il intervient uniquement en entrée (ingress) avant l'allocation de la structure de métadonnées du noyau (struct sk_buff), ce qui l'empêche d'inspecter les paquets sortants, de gérer les files d'attente d'émission ou d'appliquer des modifications protocolaires complexes après le traitement par la couche socket.
Pour une manipulation bidirectionnelle exhaustive, les architectes d'infrastructure Linux s'appuient sur le sous-système Traffic Control (TC) et ses programmes de classification eBPF (BPF_PROG_TYPE_SCHED_CLS). Rattachés via la discipline de file d'attente moderne clsact (qdisc), les programmes eBPF TC s'exécutent au cœur de la pile réseau avec un accès complet à l'abstraction sk_buff. Cela autorise l'aiguillage dynamique de couche 4 et 7, la redirection inter-interfaces sans copie mémoire et la régulation d'émission temporelle (EDT) sans aucun basculement de contexte vers l'espace utilisateur.
Dualité architecturale : eBPF TC et XDP au sein de la pile réseau
Pour situer le rôle d'eBPF TC dans les tunnels chiffrés, il convient d'observer son positionnement par rapport à XDP.
Paquet entrant (Ingress)
│
▼
┌──────────────┐
│ Point XDP │ <--- Traitement brut sur xdp_md avant allocation de skb
└──────┬───────┘ (Rejet ou redirection rapide, entrée seule, aucun point en sortie)
│
▼
alloc_skb()
│
▼
┌──────────────────┐
│ eBPF TC Ingress │ <--- Opère sur struct __sk_buff (qdisc clsact)
└──────┬───────────┘ (Analyse L3/L4 intégrale, tables BPF, redirection vers tunnel)
│
▼
Pile protocolaire (IP/TCP/UDP) ── Couche Socket
│
▼ (Trafic chiffré sortant Egress)
┌──────────────────┐
│ eBPF TC Egress │ <--- Opère sur struct __sk_buff avant l'anneau de la carte
└──────┬───────────┘ (Horodatage EDT, marquage DSCP, régulation sans verrou)
│
▼
File d'émission du pilote matériel (NIC)
L'intervention au niveau de la couche TC procure des avantages déterminants :
- Couverture bidirectionnelle : les points d'ancrage TC s'attachent simultanément sur les flux d'entrée et de sortie des interfaces physiques (ex.
eth0) et des interfaces de tunnel virtuel (ex.wg0). - Accès intégral à sk_buff : le code BPF peut inspecter et réécrire les en-têtes réseau, recalculer les sommes de contrôle, modifier les horodatages de sortie (
skb->tstamp) et appliquer des marques de pare-feu (skb->mark). - Exécution d'action directe : grâce au commutateur
direct-action(da), le classificateur BPF renvoie directement son verdict (TC_ACT_OK,TC_ACT_SHOT,TC_ACT_REDIRECT), éliminant l'empilement complexe de filtres successifs.
Redirection de paquets sans copie via bpf_redirect
Dans les déploiements mutualisés à haute densité, l'acheminement des flux entre adaptateurs Ethernet physiques et tunnels virtuels impose classiquement deux traversées complètes de la pile de routage IP du noyau. Ce cheminement sollicite les tables de routage, la table de suivi des connexions (conntrack) et les chaînes Netfilter, surchargeant les caches mémoire du processeur.
Avec eBPF TC, l'administrateur programme un transfert direct d'interface à interface dans l'espace noyau à l'aide de la fonction d'assistance bpf_redirect() :
#include <linux/bpf.h>
#include <linux/pkt_cls.h>
#include <bpf/bpf_helpers.h>
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 65536);
__type(key, __u32); /* Adresse IPv4 virtuelle du client */
__type(value, __u32); /* Index d'interface cible (ifindex) */
} route_map SEC(".maps");
SEC("tc")
int tc_ingress_router(struct __sk_buff *skb)
{
void *data = (void *)(long)skb->data;
void *data_end = (void *)(long)skb->data_end;
/* Verification des limites : en-tetes Ethernet et IPv4 minimaux */
if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) > data_end)
return TC_ACT_OK;
struct iphdr *iph = data + sizeof(struct ethhdr);
__u32 dst_ip = iph->daddr;
/* Recherche directe dans la table de hachage BPF pour WireGuard */
__u32 *ifindex = bpf_map_lookup_elem(&route_map, &dst_ip);
if (ifindex) {
/* Redirection directe du paquet sans traverser la pile IP complete */
return bpf_redirect(*ifindex, 0);
}
return TC_ACT_OK;
}
Attaché à l'interface réseau physique, ce classificateur inspecte les paquets entrants, résout la correspondance de destination dans une table de hachage et redirige immédiatement la trame vers la file d'attente du tunnel concerné. L'opération s'effectue sans duplication mémoire, réduisant de plus de 40 % les cycles processeur consommés par paquet.
Horodatage EDT et élimination des micro-rafales
L'irrégularité du débit constitue une vulnérabilité majeure des tunnels à haute vitesse. Lorsque de multiples clients sollicitent simultanément des flux volumineux, les émetteurs TCP génèrent des grappes denses de paquets. Les algorithmes d'ordonnancement traditionnels comme TBF (Token Bucket Filter) ou HTB (Hierarchical Token Bucket) freinent ces pointes en retenant les paquets excédentaires dans des files protégées par des verrous tournants (spinlocks). Lors de pics de charge, la contention sur ces verrous entrave l'extensibilité multicœur.
Le noyau Linux moderne surmonte cet écueil grâce au mécanisme Early Departure Time (EDT). Au lieu d'accumuler des paquets dans des structures tampons soumises à verrouillage, le sous-système calcule un instant prévisionnel d'émission (skb->tstamp) pour chaque paquet.
En intégrant eBPF TC sur la trajectoire sortante (egress), la mise en forme s'effectue de manière non bloquante :
- Le programme eBPF évalue le délai requis entre paquets selon le quota de bande passante alloué au client.
- Le programme actualise l'horodatage
skb->tstamp = max(temps_actuel, dernier_depart + taille_paquet / debit). - La discipline de file d'attente équitable
sch_fqtransmet les paquets sur le lien physique en respectant scrupuleusement cet échéancier, éliminant tout blocage mémoire intermédiaire.
Déploiement en production : chargement via clsact
L'activation d'eBPF TC s'effectue via l'outillage standard iproute2 :
# 1. Attacher la discipline clsact a l'interface WAN physique
tc qdisc add dev eth0 clsact
# 2. Charger le classificateur BPF sur le crochet Ingress en mode direct-action
tc filter add dev eth0 ingress bpf da obj vpn_router.o sec tc_ingress
# 3. Charger le regulateur de debit EDT sur le crochet Egress
tc filter add dev eth0 egress bpf da obj vpn_shaper.o sec tc_egress
# 4. Verifier les filtres actifs et les statistiques de traitement
tc filter show dev eth0 ingress
tc filter show dev eth0 egress
Grâce à l'isolation propre apportée par clsact, les opérations de mise à jour des programmes s'effectuent sans aucune perte de paquets et sans coupure de service.
Application dans l'architecture RiceGuard Anycast
Dans son infrastructure distribuée Anycast, RiceGuard exploite eBPF TC pour garantir une qualité de service constante :
- Régulation stricte par session : RiceGuard implémente les filtres eBPF de sortie directement sur les passerelles, attribuant des horloges EDT distinctes à chaque flux pour éviter qu'un trafic consommateur ne sature la latence des flux interactifs.
- Télémétrie dynamique via tables BPF : les filtres d'entrée enregistrent en continu les métriques de trafic (débits, volumes, détection de trames corrompues) dans des mémoires annulaires (ring buffers), alimentant les modules de supervision sans sollicitation excessive de l'espace utilisateur.
- Accélération matérielle SmartNIC : sur les nœuds disposant de cartes réseau avancées, les filtres eBPF TC sont compilés directement dans les moteurs de traitement matériel, assurant un aiguillage à 100 Gbit/s avec une latence sub-microseconde.
Grâce à l'association d'eBPF TC et de la régulation EDT sans verrou, WireGuard et RiceGuard garantissent une efficacité opérationnelle remarquable et une isolation rigoureuse des flux réseau.



