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

+49 -32
View File
@@ -7,6 +7,7 @@
#include <linux/in.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>
#include <stdint.h>
// Configurações de MTU para WireGuard
#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
static __always_inline int adjust_tcp_mss(struct tcphdr *tcp, void *data_end, __u16 max_mss) {
// Função para ajustar TCP MSS - corrigido tipos de ponteiro
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);
if (tcp_end > data_end)
if (tcp_end > data_end_ptr)
return 0;
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_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;
// Procurar opção MSS (kind=2, len=4) nas opções TCP
#pragma unroll
for (int i = 0; i < 40; i += tcp_opt_ptr[1]) { // máximo de 40 bytes de opções
if (tcp_opt_ptr + 2 > tcp_opt_end || tcp_opt_ptr + 2 > data_end)
#pragma unroll 4 // Limite de desenrolamento para evitar erros
for (int i = 0; i < 40 && tcp_opt_ptr + 1 < tcp_opt_end; i += tcp_opt_ptr[1]) {
// 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;
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;
// 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
if (current_mss > 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;
}
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
static __always_inline int send_icmp_frag_needed(struct xdp_md *ctx, struct ethhdr *eth,
struct iphdr *iph, __u16 mtu) {
// 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
static __always_inline int send_icmp_frag_needed(struct iphdr *iph, __u16 mtu) {
// Simplificado para evitar problemas de compilação
// Verificar se o pacote tem DF (Don't Fragment) ativo
__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);
// 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
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")
int xdp_wg_optimizer(struct xdp_md *ctx) {
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth;
struct iphdr *iph;
__u32 key = 0;
__u32 zero = 0;
// 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) {
stats->total_packets++;
}
// Validação básica dos cabeçalhos
eth = data;
if ((void*)(eth + 1) > data_end)
// Verificar tamanho mínimo para cabeçalho Ethernet + IP
if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) > data_end)
return XDP_PASS;
struct ethhdr *eth = data;
// Processamos apenas tráfego IPv4
if (eth->h_proto != bpf_htons(ETH_P_IP))
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)
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?
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
__u16 frag_off = bpf_ntohs(iph->frag_off);
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 {
// 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;
}
}
// 2. Otimização TCP MSS para sessões TCP novas
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 (adjust_tcp_mss(tcp, data_end, MSS_CLAMPING_VALUE)) {
// MSS foi ajustado
}
adjust_tcp_mss(tcp, data_end, MSS_CLAMPING_VALUE);
}
}
@@ -189,8 +205,9 @@ int xdp_wg_optimizer(struct xdp_md *ctx) {
if (known_mtu && tot_len > *known_mtu) {
// Pacote excede MTU já conhecido para este destino
if (iph->frag_off & bpf_htons(0x4000)) { // DF bit set
return send_icmp_frag_needed(ctx, eth, iph, *known_mtu);
__u16 frag_off = bpf_ntohs(iph->frag_off);
if (frag_off & 0x4000) { // DF bit set
return send_icmp_frag_needed(iph, *known_mtu);
}
}