This commit is contained in:
rodrigo committed 2025-02-28 20:31:39 -03:00
1 parent 2640132012
commit a6869cb8d7
3 files changed
+124 -50

No files matched your search

+41 -18
View File
@@ -4,7 +4,8 @@
echo "Compilando programa XDP de otimização para WireGuard..." echo "Compilando programa XDP de otimização para WireGuard..."
clang -O2 -target bpf -c xdp_wg_mtu_optimizer.c -o xdp_wg_mtu_optimizer.o \ clang -O2 -target bpf -c xdp_wg_mtu_optimizer.c -o xdp_wg_mtu_optimizer.o \
-I/usr/include/bpf -I/usr/include/ \ -I/usr/include/bpf -I/usr/include/ \
-Wno-unused-function -D__TARGET_ARCH_arm64 -Wno-unused-function -Wno-compare-distinct-pointer-types \
-D__TARGET_ARCH_arm64 -g
# Verificar se a compilação foi bem-sucedida # Verificar se a compilação foi bem-sucedida
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
@@ -12,31 +13,55 @@ if [ $? -ne 0 ]; then
exit 1 exit 1
fi fi
# Implantar o programa XDP na interface WireGuard # Gerar BTF para o programa
echo "Implantando programa XDP na interface wg0..." echo "Gerando BTF information..."
ip link set dev wg0 xdp object xdp_wg_mtu_optimizer.o verbose llvm-strip -g xdp_wg_mtu_optimizer.o
pahole -J xdp_wg_mtu_optimizer.o
# Verificar se carregou corretamente # Verificar se existe a ferramenta bpftool
if [ $? -eq 0 ]; then if ! command -v bpftool &> /dev/null; then
echo "Programa XDP de otimização para WireGuard carregado com sucesso" echo "AVISO: bpftool não encontrado, tentando carregar sem BTF"
fi
# Tentar várias opções para carregar o programa XDP
echo "Tentando carregar o programa XDP na interface wg0..."
LOADED=0
# Opção 1: Tentativa direta
if ip link set dev wg0 xdp obj xdp_wg_mtu_optimizer.o sec xdp verbose; then
LOADED=1
echo "Programa XDP carregado com sucesso!"
else else
echo "ERRO: Falha ao carregar programa XDP na interface wg0" echo "Primeira tentativa falhou, tentando com modo generic..."
echo "Tentando adicionar o programa em modo 'generic' (menos eficiente, mas mais compatível)..."
ip link set dev wg0 xdp object xdp_wg_mtu_optimizer.o section xdp verbose mode generic
if [ $? -eq 0 ]; then # Opção 2: Modo generic
echo "Programa XDP carregado em modo generic com sucesso" if ip link set dev wg0 xdp obj xdp_wg_mtu_optimizer.o sec xdp verbose mode generic; then
LOADED=1
echo "Programa XDP carregado em modo generic!"
else else
echo "ERRO: Falha ao carregar programa XDP mesmo em modo generic" echo "Tentando com interface de loopback para testes..."
exit 1
# Opção 3: Testes em interface loopback
if ip link set dev lo xdp obj xdp_wg_mtu_optimizer.o sec xdp verbose mode generic; then
echo "AVISO: Programa carregado apenas na interface loopback para testes"
echo "Por favor, resolva os problemas de compatibilidade antes de usar em produção"
LOADED=1
else
echo "ERRO: Todas as tentativas de carregamento do XDP falharam"
fi
fi fi
fi fi
# Configurar MTU eficiente para WireGuard # Verificar resultado do carregamento
if [ $LOADED -eq 0 ]; then
echo "Não foi possível carregar o programa XDP"
exit 1
fi
# Configurações de MTU e kernel que ainda funcionam mesmo sem o XDP totalmente carregado
echo "Configurando MTU otimizado para interface WireGuard..." echo "Configurando MTU otimizado para interface WireGuard..."
ip link set dev wg0 mtu 1420 ip link set dev wg0 mtu 1420
# Configurar ajustes do kernel para melhorar fragmentação IP e PMTUD
echo "Aplicando ajustes de kernel para otimização de MTU..." echo "Aplicando ajustes de kernel para otimização de MTU..."
sysctl -w net.ipv4.ip_forward=1 sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.tcp_mtu_probing=1 sysctl -w net.ipv4.tcp_mtu_probing=1
@@ -46,5 +71,3 @@ sysctl -w net.ipv4.tcp_base_mss=1024
echo "" echo ""
echo "=== Otimização de MTU para WireGuard ativa ===" echo "=== Otimização de MTU para WireGuard ativa ==="
ip link show dev wg0 | grep -E 'mtu|xdp' ip link show dev wg0 | grep -E 'mtu|xdp'
echo ""
echo "Para monitorar estatísticas: bpftool map dump name mtu_stats_map"
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
# Este script implementa otimizações de MTU para WireGuard
# mesmo sem o programa XDP, caso não seja possível carregá-lo
echo "Aplicando otimizações manuais de MTU para WireGuard..."
# 1. Definir MTU ótimo para WireGuard (padrão recomendado)
ip link set dev wg0 mtu 1420
echo "MTU do WireGuard ajustado para 1420"
# 2. Habilitar TCP MSS clamping via iptables
# Isso força o MSS para um valor seguro, evitando fragmentação
iptables -t mangle -A FORWARD -o wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1380
ip6tables -t mangle -A FORWARD -o wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1380
echo "TCP MSS clamping configurado para pacotes via WireGuard"
# 3. Otimizações de kernel para fragmentação e PMTU
sysctl -w net.ipv4.tcp_mtu_probing=1
sysctl -w net.ipv4.ip_no_pmtu_disc=0
sysctl -w net.ipv4.tcp_base_mss=1024
echo "Configurações de kernel ajustadas para melhor detecção de PMTU"
# 4. Aplicar marcação específica para pacotes WireGuard no QoS existente
tc filter add dev enp0s6 parent 1: protocol ip prio 1 u32 \
match ip protocol 17 0xff \
match ip dport 32100 0xffff \
flowid 1:10
echo "Priorização de QoS específica para WireGuard adicionada"
echo ""
echo "=== Otimizações de MTU para WireGuard aplicadas sem código XDP ==="
echo "Status da interface wg0:"
ip link show dev wg0 | grep mtu
+49 -32
View File
@@ -7,6 +7,7 @@
#include <linux/in.h> #include <linux/in.h>
#include <bpf/bpf_helpers.h> #include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h> #include <bpf/bpf_endian.h>
#include <stdint.h>
// Configurações de MTU para WireGuard // Configurações de MTU para WireGuard
#define WG_OVERHEAD 60 // Overhead do WireGuard (cabeçalhos + criptografia) #define WG_OVERHEAD 60 // Overhead do WireGuard (cabeçalhos + criptografia)
@@ -52,10 +53,10 @@ static __always_inline void update_stats(__u64 *stat_counter) {
} }
} }
// Função para ajustar TCP MSS // Função para ajustar TCP MSS - corrigido tipos de ponteiro
static __always_inline int adjust_tcp_mss(struct tcphdr *tcp, void *data_end, __u16 max_mss) { static __always_inline int adjust_tcp_mss(struct tcphdr *tcp, void *data_end_ptr, __u16 max_mss) {
void *tcp_end = (void *)tcp + sizeof(struct tcphdr); void *tcp_end = (void *)tcp + sizeof(struct tcphdr);
if (tcp_end > data_end) if (tcp_end > data_end_ptr)
return 0; return 0;
if (!tcp->syn) if (!tcp->syn)
@@ -65,17 +66,20 @@ static __always_inline int adjust_tcp_mss(struct tcphdr *tcp, void *data_end, __
__u8 *tcp_opt_ptr = (__u8 *)tcp + sizeof(struct tcphdr); __u8 *tcp_opt_ptr = (__u8 *)tcp + sizeof(struct tcphdr);
__u8 *tcp_opt_end = (__u8 *)tcp + tcp_hdr_len; __u8 *tcp_opt_end = (__u8 *)tcp + tcp_hdr_len;
if (tcp_opt_end > data_end) // Corrigido: cast explícito para comparação de tipos de ponteiro
if ((void *)tcp_opt_end > data_end_ptr)
return 0; return 0;
// Procurar opção MSS (kind=2, len=4) nas opções TCP // Procurar opção MSS (kind=2, len=4) nas opções TCP
#pragma unroll #pragma unroll 4 // Limite de desenrolamento para evitar erros
for (int i = 0; i < 40; i += tcp_opt_ptr[1]) { // máximo de 40 bytes de opções for (int i = 0; i < 40 && tcp_opt_ptr + 1 < tcp_opt_end; i += tcp_opt_ptr[1]) {
if (tcp_opt_ptr + 2 > tcp_opt_end || tcp_opt_ptr + 2 > data_end) // Corrigido: verificações de limites com cast explícito
if ((void *)(tcp_opt_ptr + 2) > data_end_ptr || (tcp_opt_ptr + 2) > tcp_opt_end)
break; break;
if (tcp_opt_ptr[0] == 2 && tcp_opt_ptr[1] == 4) { // MSS option if (tcp_opt_ptr[0] == 2 && tcp_opt_ptr[1] == 4) { // MSS option
if (tcp_opt_ptr + 4 > tcp_opt_end || tcp_opt_ptr + 4 > data_end) // Corrigido: verificações de limites com cast explícito
if ((void *)(tcp_opt_ptr + 4) > data_end_ptr || (tcp_opt_ptr + 4) > tcp_opt_end)
break; break;
// Extrair valor MSS atual (network byte order) // Extrair valor MSS atual (network byte order)
@@ -85,7 +89,11 @@ static __always_inline int adjust_tcp_mss(struct tcphdr *tcp, void *data_end, __
// Ajustar MSS se necessário // Ajustar MSS se necessário
if (current_mss > max_mss) { if (current_mss > max_mss) {
*mss_ptr = bpf_htons(max_mss); *mss_ptr = bpf_htons(max_mss);
update_stats(&((struct mtu_stats *)bpf_map_lookup_elem(&mtu_stats_map, &(__u32){0}))->mss_adjusted); __u32 zero = 0;
struct mtu_stats *stats = bpf_map_lookup_elem(&mtu_stats_map, &zero);
if (stats) {
stats->mss_adjusted++;
}
return 1; return 1;
} }
break; break;
@@ -104,10 +112,8 @@ static __always_inline int adjust_tcp_mss(struct tcphdr *tcp, void *data_end, __
} }
// Função para enviar ICMP "Fragmentation needed" para indicar Path MTU Discovery // Função para enviar ICMP "Fragmentation needed" para indicar Path MTU Discovery
static __always_inline int send_icmp_frag_needed(struct xdp_md *ctx, struct ethhdr *eth, static __always_inline int send_icmp_frag_needed(struct iphdr *iph, __u16 mtu) {
struct iphdr *iph, __u16 mtu) { // Simplificado para evitar problemas de compilação
// Enviar "Pacote muito grande" / "Fragmentação necessária mas DF está ativo"
// Aqui sinalizamos ao kernel para enviar o ICMP, já que é difícil construí-lo no XDP
// Verificar se o pacote tem DF (Don't Fragment) ativo // Verificar se o pacote tem DF (Don't Fragment) ativo
__u16 frag_off = bpf_ntohs(iph->frag_off); __u16 frag_off = bpf_ntohs(iph->frag_off);
@@ -120,37 +126,42 @@ static __always_inline int send_icmp_frag_needed(struct xdp_md *ctx, struct ethh
bpf_map_update_elem(&path_mtu_map, &dest_ip, &recommended_mtu, BPF_ANY); bpf_map_update_elem(&path_mtu_map, &dest_ip, &recommended_mtu, BPF_ANY);
// Incrementar contador de PMTU // Incrementar contador de PMTU
update_stats(&((struct mtu_stats *)bpf_map_lookup_elem(&mtu_stats_map, &(__u32){0}))->pmtu_triggered); __u32 zero = 0;
struct mtu_stats *stats = bpf_map_lookup_elem(&mtu_stats_map, &zero);
if (stats) {
stats->pmtu_triggered++;
}
// Sinalizar ao kernel para dropar e enviar ICMP // Sinalizar ao kernel para dropar e enviar ICMP
return XDP_ABORTED; return XDP_ABORTED;
} }
// Programa XDP principal para otimização de pacotes WireGuard // Programa XDP principal para otimização de pacotes WireGuard - simplificado e corrigido
SEC("xdp") SEC("xdp")
int xdp_wg_optimizer(struct xdp_md *ctx) { int xdp_wg_optimizer(struct xdp_md *ctx) {
void *data_end = (void *)(long)ctx->data_end; void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data; void *data = (void *)(long)ctx->data;
struct ethhdr *eth; __u32 zero = 0;
struct iphdr *iph;
__u32 key = 0;
// Inicializar contadores // Inicializar contadores
struct mtu_stats *stats = bpf_map_lookup_elem(&mtu_stats_map, &key); struct mtu_stats *stats = bpf_map_lookup_elem(&mtu_stats_map, &zero);
if (stats) { if (stats) {
stats->total_packets++; stats->total_packets++;
} }
// Validação básica dos cabeçalhos // Verificar tamanho mínimo para cabeçalho Ethernet + IP
eth = data; if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) > data_end)
if ((void*)(eth + 1) > data_end)
return XDP_PASS; return XDP_PASS;
struct ethhdr *eth = data;
// Processamos apenas tráfego IPv4 // Processamos apenas tráfego IPv4
if (eth->h_proto != bpf_htons(ETH_P_IP)) if (eth->h_proto != bpf_htons(ETH_P_IP))
return XDP_PASS; return XDP_PASS;
iph = (void*)(eth + 1); struct iphdr *iph = (void*)(eth + 1);
// Verificar se o cabeçalho IP é válido
if ((void*)(iph + 1) > data_end) if ((void*)(iph + 1) > data_end)
return XDP_PASS; return XDP_PASS;
@@ -159,27 +170,32 @@ int xdp_wg_optimizer(struct xdp_md *ctx) {
// 1. Verificação de MTU - pacote maior que o MTU do WireGuard? // 1. Verificação de MTU - pacote maior que o MTU do WireGuard?
if (tot_len > MAX_WG_MTU) { if (tot_len > MAX_WG_MTU) {
update_stats(&((struct mtu_stats *)bpf_map_lookup_elem(&mtu_stats_map, &key))->oversized_packets); if (stats) {
stats->oversized_packets++;
}
// Verificar se podemos fragmentar (sem flag DF) ou se precisamos sinalizar PMTUD // Verificar se podemos fragmentar (sem flag DF) ou se precisamos sinalizar PMTUD
__u16 frag_off = bpf_ntohs(iph->frag_off); __u16 frag_off = bpf_ntohs(iph->frag_off);
if (frag_off & 0x4000) { // Don't Fragment está ativo if (frag_off & 0x4000) { // Don't Fragment está ativo
return send_icmp_frag_needed(ctx, eth, iph, MAX_WG_MTU); return send_icmp_frag_needed(iph, MAX_WG_MTU);
} else { } else {
// Pacote pode ser fragmentado, deixar para o kernel // Pacote pode ser fragmentado, deixar para o kernel
update_stats(&((struct mtu_stats *)bpf_map_lookup_elem(&mtu_stats_map, &key))->fragmented); if (stats) {
stats->fragmented++;
}
return XDP_PASS; return XDP_PASS;
} }
} }
// 2. Otimização TCP MSS para sessões TCP novas // 2. Otimização TCP MSS para sessões TCP novas
if (iph->protocol == IPPROTO_TCP) { if (iph->protocol == IPPROTO_TCP) {
struct tcphdr *tcp = (void*)(iph) + ip_hdr_len; // Verificar se temos cabeçalho TCP completo
void *tcp_start = (void*)iph + ip_hdr_len;
struct tcphdr *tcp = tcp_start;
if ((void*)(tcp + 1) <= data_end) { if ((void*)(tcp + 1) <= data_end) {
if (adjust_tcp_mss(tcp, data_end, MSS_CLAMPING_VALUE)) { adjust_tcp_mss(tcp, data_end, MSS_CLAMPING_VALUE);
// MSS foi ajustado
}
} }
} }
@@ -189,8 +205,9 @@ int xdp_wg_optimizer(struct xdp_md *ctx) {
if (known_mtu && tot_len > *known_mtu) { if (known_mtu && tot_len > *known_mtu) {
// Pacote excede MTU já conhecido para este destino // Pacote excede MTU já conhecido para este destino
if (iph->frag_off & bpf_htons(0x4000)) { // DF bit set __u16 frag_off = bpf_ntohs(iph->frag_off);
return send_icmp_frag_needed(ctx, eth, iph, *known_mtu); if (frag_off & 0x4000) { // DF bit set
return send_icmp_frag_needed(iph, *known_mtu);
} }
} }