Um programa que se conecta ao gancho XDP do kernel Linux por meio de (e)BPF para processamento rápido de pacotes e executa encaminhamento básico da camada 3/4. Este programa faz mapeamento de portas de origem semelhante a IPTables e NFTables para lidar com conexões. As conexões existentes são priorizadas com base nos pacotes da conexão por nanossegundo. Isso significa que quando a porta se esgotar, as conexões com menos pacotes por nanossegundo serão substituídas. Acredito que isso seja melhor, pois as conexões com pacotes mais altos por nanossegundo serão mais sensíveis.
Além disso, se a configuração de rede do host ou a placa de interface de rede (NIC) não suportar o gancho XDP DRV (também conhecido como nativo; ocorre antes da criação do SKB), o programa tentará se conectar ao gancho XDP SKB (também conhecido como genérico; ocorre após o SKB criação que é onde IPTables e NFTables são processados através do módulo netfilter
do kernel). Você pode usar substituições por meio da linha de comando para forçar os modos SKB ou descarregamento.
Dito isso, os motivos para a configuração de rede de um host não suportar o gancho DRV do XDP podem ser os seguintes.
Espero que este projeto ajude os engenheiros/programadores de rede existentes interessados em utilizar o XDP ou qualquer pessoa interessada em entrar nessas áreas! Roteadores/encaminhamento de pacotes de alto desempenho e mitigação/prevenção de (D)DoS são partes tão importantes da segurança cibernética e compreender o conceito de rede e fluxo de pacotes em um nível baixo-médio certamente ajudaria aqueles que estão seguindo uma carreira na área.
AVISO - Ainda há muitas coisas que precisam ser feitas neste projeto e, no momento, ele suporta apenas IPv4. O suporte IPv6 será adicionado antes do lançamento oficial. A partir de agora, o programa pode incluir bugs e recursos de encaminhamento ainda não estão disponíveis.
As portas de origem máximas padrão que podem ser usadas por endereço de ligação são 21 e são definidas aqui (você pode ajustá-las se desejar). Usamos o intervalo de portas 500 - 520 por padrão, mas isso pode ser configurado.
No início, tentei usar a maioria das portas disponíveis (1 - 65534). No entanto, devido às limitações do verificador BPF, tive que aumentar algumas constantes dentro do kernel Linux e recompilar o kernel. Fiz patches para eles e tenho tudo documentado aqui. Consigo executar o programa com no máximo 65.534 portas por endereço de ligação sem problemas com o kernel personalizado que construí usando os patches que fiz. Porém, tenha em mente que quanto mais portas de origem estiverem disponíveis, mais processamento o programa XDP terá que realizar ao verificar as portas disponíveis.
Se você planeja usar isso para produção, eu sugiro compilar seu próprio kernel com as constantes levantadas acima. 21 portas de origem máximas por endereço de ligação não é muito, mas infelizmente, as restrições padrão do verificador BPF não nos permitem ir mais longe atualmente.
O principal código que causa essas limitações está localizado aqui e ocorre quando tentamos encontrar a melhor porta de origem para usar em uma nova conexão. Na verdade, não há outra maneira de verificar a melhor porta de origem disponível com a quantidade de flexibilidade que temos, pelo que entendi, já que devemos percorrer todas as portas de origem e verificar o valor dos pacotes por nanossegundo (mapas BPF pesquisam por chave).
Você precisará make
, clang
, libelf
e llvm
já que usamos esses pacotes para construir o projeto. Além disso, você também precisará libconfig
( libconfig-dev
é o pacote nos sistemas Ubuntu/Debian) para analisar o arquivo de configuração.
Para Ubuntu/Debian, o seguinte deve funcionar.
apt install build-essential make clang libelf-dev llvm libconfig-dev
Eu presumo que os nomes dos pacotes sejam semelhantes em outras distribuições Linux.
Para usar xdpfwd-add
e xdpfwd-del
, você deve montar o sistema de arquivos BPF, pois o programa XDP fixa os mapas BPF em /sys/fs/bpf/xdpfwd
. Há uma grande chance de que isso já tenha sido feito para você via iproute2
ou algo semelhante, mas se não for, você pode usar o seguinte comando.
mount -t bpf bpf /sys/fs/bpf/
O uso básico da linha de comando inclui o seguinte.
-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.
Descarregar seu programa XDP/BPF para a NIC do seu sistema permite o processamento de pacotes mais rápido que você pode obter devido ao processamento/encaminhamento dos pacotes pela NIC com seu hardware. No entanto, não existem muitos fabricantes de NIC que suportam esse recurso e você está limitado à memória/processamento da NIC (por exemplo, os tamanhos dos seus mapas BPF serão extremamente limitados). Além disso, geralmente existem limitações de verificador BPF mais rígidas para programas BPF descarregados, mas você pode tentar entrar em contato com o fabricante da NIC para ver se eles lhe darão uma versão especial do driver da NIC, aumentando essas limitações (foi o que fiz com um fabricante eu usei).
No momento, não tenho conhecimento de nenhum fabricante de NIC que consiga descarregar essa ferramenta completamente para a NIC devido à complexidade do BPF e aos requisitos de loop. Para ser honesto, na era atual das redes, acredito que é melhor deixar os programas descarregados para pesquisas de mapas BPF e inspeção mínima de pacotes. Por exemplo, uma simples pesquisa no mapa da tabela de rotas da camada 2 do BPF e, em seguida, TX os pacotes retornam da NIC. No entanto, o XDP ainda é muito novo e imagino que veremos essas limitações afrouxadas ou eliminadas nos próximos anos. É por isso que adicionei suporte ao modo offload neste programa.
O executável xdpfwd-add
que é adicionado ao $PATH
via /usr/bin
na instalação aceita os seguintes argumentos.
-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.
Isso adicionará uma regra de encaminhamento enquanto o programa XDP estiver em execução.
O executável xdpfwd-del
que é adicionado ao $PATH
via /usr/bin
na instalação aceita os seguintes argumentos.
-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.
Isso excluirá uma regra de encaminhamento enquanto o programa XDP estiver em execução.
O arquivo de configuração padrão está localizado em /etc/xdpfwd/xdpfwd.conf
e usa a sintaxe libconfig
. Aqui está um exemplo de configuração usando todos os seus recursos atuais.
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).
},
...
);
Supondo que você baixou todos os pacotes necessários, construir este projeto deve ser simples. Você pode usar os seguintes comandos shell e Bash!
# 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