Un programme qui s'attache au hook XDP du noyau Linux via (e)BPF pour un traitement rapide des paquets et effectue un transfert de base de couche 3/4. Ce programme effectue un mappage de port source similaire à IPTables et NFTables pour gérer les connexions. Les connexions existantes sont hiérarchisées en fonction du nombre de paquets de connexion par nanoseconde. Cela signifie qu'en cas d'épuisement des ports, les connexions contenant le moins de paquets par nanoseconde seront remplacées. Je pense que c'est mieux car les connexions avec des paquets plus élevés par nanoseconde seront plus sensibles.
De plus, si la configuration réseau ou la carte d'interface réseau (NIC) de l'hôte ne prend pas en charge le hook XDP DRV (AKA natif ; se produit avant la création du SKB), le programme tentera de se connecter au hook XDP SKB (AKA générique ; se produit après la création du SKB). création (où les IPTables et NFTables sont traitées via le module du noyau netfilter
). Vous pouvez utiliser des remplacements via la ligne de commande pour forcer les modes SKB ou de déchargement.
Cela dit, les raisons pour lesquelles la configuration réseau d'un hôte ne prend pas en charge le hook DRV de XDP peuvent être les suivantes.
J'espère que ce projet aidera les ingénieurs/programmeurs réseau existants intéressés par l'utilisation de XDP ou toute personne intéressée à se lancer dans ces domaines ! Les routeurs/transfert de paquets hautement performants et l'atténuation/prévention des (D)DoS sont des éléments si importants de la cybersécurité et comprendre le concept de réseau et de flux de paquets à un niveau bas-moyen aiderait certainement ceux qui poursuivent une carrière dans ce domaine ?
AVERTISSEMENT - Il y a encore beaucoup de choses à faire sur ce projet et pour le moment, il ne prend en charge qu'IPv4. La prise en charge d'IPv6 sera ajoutée avant la sortie officielle. Pour le moment, le programme peut inclure des bugs et les fonctionnalités de transfert ne sont pas encore disponibles.
Le nombre maximum de ports source par défaut pouvant être utilisés par adresse de liaison est de 21 et est défini ici (vous pouvez les ajuster si vous le souhaitez). Nous utilisons la plage de ports 500 à 520 par défaut, mais cela peut être configuré.
Au début, j'essayais d'utiliser la plupart des ports disponibles (1 à 65534). Cependant, en raison des limitations du vérificateur BPF, j'ai dû augmenter quelques constantes dans le noyau Linux et recompiler le noyau. J'ai créé des correctifs pour ceux-ci et j'ai tout documenté ici. Je suis capable d'exécuter le programme avec 65 534 ports maximum par adresse de liaison sans aucun problème avec le noyau personnalisé que j'ai construit à l'aide des correctifs que j'ai créés. Cependant, gardez à l’esprit que plus il y a de ports sources disponibles, plus le programme XDP devra effectuer de traitements lors de la vérification des ports disponibles.
Si vous envisagez de l'utiliser pour la production, je vous suggère fortement de compiler votre propre noyau avec les constantes évoquées ci-dessus. 21 ports source maximum par adresse de liaison, ce n'est pas beaucoup, mais malheureusement, les restrictions par défaut du vérificateur BPF ne nous permettent pas d'aller plus loin actuellement.
Le code principal à l'origine de ces limitations se trouve ici et apparaît lorsque nous essayons de trouver le meilleur port source à utiliser pour une nouvelle connexion. Il n'y a vraiment aucun autre moyen de vérifier le meilleur port source disponible avec la flexibilité dont nous disposons, à ma connaissance, puisque nous devons parcourir tous les ports sources et vérifier la valeur des paquets par nanoseconde (recherche de cartes BPF par clé).
Vous aurez besoin make
, clang
, libelf
et llvm
puisque nous utilisons ces packages pour construire le projet. De plus, vous aurez également besoin libconfig
( libconfig-dev
est le package sur les systèmes Ubuntu/Debian) pour analyser le fichier de configuration.
Pour Ubuntu/Debian, ce qui suit devrait fonctionner.
apt install build-essential make clang libelf-dev llvm libconfig-dev
Je suppose que les noms de packages sont similaires sur d'autres distributions Linux.
Pour utiliser xdpfwd-add
et xdpfwd-del
, vous devez monter le système de fichiers BPF puisque le programme XDP épingle les cartes BPF sur /sys/fs/bpf/xdpfwd
. Il y a de fortes chances que cela soit déjà fait pour vous via iproute2
ou quelque chose de similaire, mais si ce n'est pas le cas, vous pouvez utiliser la commande suivante.
mount -t bpf bpf /sys/fs/bpf/
L'utilisation de base de la ligne de commande comprend les éléments suivants.
-o --offload => Attempt to load XDP program with HW/offload mode. If fails, will try DRV and SKB mode in that order.
-s --skb => Force program to load in SKB/generic mode.
-t --time => The amount of time in seconds to run the program for. Unset or 0 = infinite.
-c --config => Location to XDP Forward config (default is /etc/xdpfwd/xdpfwd.conf).
-l --list => List all forwarding rules.
-h --help => Print out command line usage.
Le déchargement de votre programme XDP/BPF sur la carte réseau de votre système permet le traitement des paquets le plus rapide que vous puissiez obtenir grâce au traitement/transfert des paquets par la carte réseau avec son matériel. Cependant, peu de fabricants de cartes réseau prennent en charge cette fonctionnalité et vous êtes limité à la mémoire/au traitement de la carte réseau (par exemple, la taille de votre carte BPF sera extrêmement limitée). De plus, il existe généralement des limitations plus strictes du vérificateur BPF pour les programmes BPF déchargés, mais vous pouvez essayer de contacter le fabricant de la carte réseau pour voir s'il vous fournira une version spéciale de son pilote NIC augmentant ces limitations (c'est ce que j'ai fait avec un fabricant). j'ai utilisé).
Pour l'instant, je ne connais aucun fabricant de carte réseau capable de décharger complètement cet outil sur la carte réseau en raison de sa complexité BPF et de ses exigences en matière de boucle. Pour être honnête, à l'ère actuelle des réseaux, je pense qu'il est préférable de laisser les programmes déchargés aux recherches de cartes BPF et à l'inspection minimale des paquets. Par exemple, une simple recherche de carte de table de routage BPF de couche 2, puis renvoyer les paquets hors de la carte réseau. Cependant, XDP est encore très nouveau et j'imagine que nous allons voir ces limitations assouplies ou levées dans les prochaines années. C'est pourquoi j'ai ajouté la prise en charge du mode de déchargement dans ce programme.
L'exécutable xdpfwd-add
qui est ajouté au $PATH
via /usr/bin
lors de l'installation accepte les arguments suivants.
-b --baddr => The address to bind/look for.
-B --bport => The port to bind/look for.
-d --daddr => The destination address.
-D --dport => The destination port.
-p --protocol => The protocol (either "tcp", "udp", "icmp", or unset for all).
-a --save => Save rule to config file.
Cela ajoutera une règle de transfert pendant l'exécution du programme XDP.
L'exécutable xdpfwd-del
qui est ajouté au $PATH
via /usr/bin
lors de l'installation accepte les arguments suivants.
-b --baddr => The address to bind/look for.
-B --bport => The port to bind/look for.
-p --protocol => The protocol (either "tcp", "udp", "icmp", or unset for all).
-a --save => Remove rule from config file.
Cela supprimera une règle de transfert pendant l'exécution du programme XDP.
Le fichier de configuration par défaut se trouve dans /etc/xdpfwd/xdpfwd.conf
et utilise la syntaxe libconfig
. Voici un exemple de configuration utilisant toutes ses fonctionnalités actuelles.
interface = "ens18"; // The interface the XDP program attaches to.
// Forwarding rules array.
forwarding = (
{
bind = "10.50.0.3", // The bind address which incoming packets must match.
bindport = 80, // The bind port which incoming packets must match.
protocol = "tcp", // The protocol (as of right now "udp", "tcp", and "icmp" are supported). Right now, you must specify a protocol. However, in the future I will be implementing functionality so you don't have to and it'll do full layer-3 forwarding.
dest = "10.50.0.4", // The address we're forwarding to.
destport = 8080 // The port we're forwarding to (if not set, will use the bind port).
},
...
);
En supposant que vous avez téléchargé tous les packages requis, la construction de ce projet devrait être simple. Vous pouvez utiliser les commandes shell et Bash suivantes !
# Clone respository and its sub-modules such as LibBPF.
git clone --recursive https://github.com/gamemann/XDP-Forwarding
# Change directory.
cd XDP-Forwarding
# Make project using all cores.
make -j $( nproc )
# Install binaries to PATH as root so you may use 'xdpfwd', 'xdpfwd-add', 'xdpfwd-del'.
sudo make install