From e7b1979ae3de2288d8ba77f46d0cd8136373677b Mon Sep 17 00:00:00 2001 From: Rodrigo Martins Date: Wed, 26 Feb 2025 19:10:15 -0300 Subject: [PATCH] commit --- tc_nat_setup.sh | 116 ++++++++++++++++++++++++++++++++++++++++++ verify_nat.sh | 80 +++++++++++++++++++++++++++++ xdp_accelerated_nat.c | 2 +- 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 tc_nat_setup.sh create mode 100644 verify_nat.sh diff --git a/tc_nat_setup.sh b/tc_nat_setup.sh new file mode 100644 index 0000000..fc3c918 --- /dev/null +++ b/tc_nat_setup.sh @@ -0,0 +1,116 @@ +#!/bin/bash + +# Script para configurar NAT BPF com TC + +# Parâmetros +INTERFACE=${1:-"enp0s6"} +TARGET_IP=${2:-"10.15.0.45"} +GATEWAY_IP=${3:-"10.0.0.87"} + +echo "=== Configurando NAT BPF com TC ===" +echo "Interface: $INTERFACE" +echo "IP alvo (container): $TARGET_IP" +echo "Gateway IP: $GATEWAY_IP" + +# Compilar programa TC BPF +echo "Compilando programa TC BPF..." +clang -O2 -Wall -target bpf -g -D__TARGET_ARCH_arm64 -c tc_nat.c -o tc_nat.o -I/usr/include/bpf -I/usr/include/ + +if [ $? -ne 0 ]; then + echo "Erro na compilação do programa TC!" + exit 1 +fi + +# Verificar seções no arquivo objeto BPF +echo "Verificando seções no arquivo objeto..." +llvm-objdump -h tc_nat.o + +# Remover programas TC existentes na interface +echo "Removendo programas TC existentes na interface $INTERFACE..." +tc filter del dev $INTERFACE ingress 2>/dev/null +tc filter del dev $INTERFACE egress 2>/dev/null +tc qdisc del dev $INTERFACE clsact 2>/dev/null + +# Configurar qdisc +echo "Configurando qdisc no $INTERFACE..." +tc qdisc add dev $INTERFACE clsact + +# Carregar programas TC +echo "Carregando programa TC ingress..." +tc filter add dev $INTERFACE ingress prio 1 handle 1 bpf da obj tc_nat.o sec tc_ingress +if [ $? -ne 0 ]; then + echo "Erro ao carregar o programa ingress!" + exit 1 +fi + +echo "Carregando programa TC egress..." +tc filter add dev $INTERFACE egress prio 1 handle 1 bpf da obj tc_nat.o sec tc_egress +if [ $? -ne 0 ]; then + echo "Erro ao carregar o programa egress!" + exit 1 +fi + +# Encontrar IDs dos mapas +echo "Encontrando IDs dos mapas BPF..." +DNAT_MAP_ID=$(bpftool map list | grep -m1 "name dnat_port_map" | awk '{print $1}' | tr -d ':') +SNAT_MAP_ID=$(bpftool map list | grep -m1 "name snat_networks" | awk '{print $1}' | tr -d ':') + +if [ -z "$DNAT_MAP_ID" ] || [ -z "$SNAT_MAP_ID" ]; then + echo "Não foi possível encontrar todos os mapas BPF necessários." + exit 1 +fi + +echo "IDs dos mapas: DNAT=$DNAT_MAP_ID, SNAT=$SNAT_MAP_ID" + +# Limpar mapas existentes +echo "Limpando mapas existentes..." +echo "Limpando DNAT..." +bpftool map dump id $DNAT_MAP_ID -j | grep -o '"key": [0-9]*' | awk '{print $2}' | \ +while read key; do + [ ! -z "$key" ] && bpftool map delete id $DNAT_MAP_ID key hex $(printf "%04x" $key | sed 's/\(..\)\(..\)/\2 \1/') +done + +echo "Limpando SNAT..." +bpftool map dump id $SNAT_MAP_ID -j | grep -o '"key": [0-9]*' | awk '{print $2}' | \ +while read key; do + [ ! -z "$key" ] && bpftool map delete id $SNAT_MAP_ID key hex $(printf "%08x" $key | sed 's/\(..\)\(..\)\(..\)\(..\)/\4 \3 \2 \1/') +done + +# Configurar regras DNAT +echo "Configurando regras DNAT..." + +# Função auxiliar para converter IP para valores em little-endian +ip_to_hex_le() { + local ip=$1 + IFS='.' read -r -a octets <<< "$ip" + printf "%02x %02x %02x %02x" "${octets[3]}" "${octets[2]}" "${octets[1]}" "${octets[0]}" +} + +# Função auxiliar para converter porta para little-endian +port_to_hex_le() { + local port=$1 + printf "%02x %02x" $((port & 0xFF)) $(((port >> 8) & 0xFF)) +} + +# Obter valores em hex +TARGET_IP_HEX=$(ip_to_hex_le $TARGET_IP) + +# Configurar redirecionamento HTTP +echo "Configurando redirecionamento HTTP (porta 80)..." +bpftool map update id $DNAT_MAP_ID key hex "$(port_to_hex_le 80)" value hex "$TARGET_IP_HEX $(port_to_hex_le 80) 00 00" + +# Configurar redirecionamento HTTPS +echo "Configurando redirecionamento HTTPS (porta 443)..." +bpftool map update id $DNAT_MAP_ID key hex "$(port_to_hex_le 443)" value hex "$TARGET_IP_HEX $(port_to_hex_le 443) 00 00" + +# Configurar redes para SNAT +echo "Configurando redes para SNAT..." +bpftool map update id $SNAT_MAP_ID key hex "00 00 0f 0a" value hex "01" # 10.15.0.0/16 +bpftool map update id $SNAT_MAP_ID key hex "00 00 11 ac" value hex "01" # 172.17.0.0/16 + +# Habilitar IP forwarding +echo "Habilitando ip_forward..." +echo 1 > /proc/sys/net/ipv4/ip_forward + +echo "NAT BPF configurado com sucesso. Utilize 'tc filter show dev $INTERFACE ingress' para verificar." +echo "Para ver logs: cat /sys/kernel/debug/tracing/trace_pipe" diff --git a/verify_nat.sh b/verify_nat.sh new file mode 100644 index 0000000..88cc1d1 --- /dev/null +++ b/verify_nat.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# Script para verificar se o NAT está funcionando corretamente + +INTERFACE=${1:-"enp0s6"} +TARGET_IP=${2:-"10.15.0.45"} + +echo "=== Verificando Configuração NAT ===" +echo "Interface: $INTERFACE" +echo "Container alvo: $TARGET_IP" + +# Verificar se os programas TC estão carregados +echo -e "\n[Programas TC]" +tc filter show dev $INTERFACE ingress | grep -i bpf +tc filter show dev $INTERFACE egress | grep -i bpf + +# Verificar mapas BPF +echo -e "\n[Mapas BPF]" +DNAT_MAP_ID=$(bpftool map list | grep -m1 "name dnat_port_map" | awk '{print $1}' | tr -d ':') +SNAT_MAP_ID=$(bpftool map list | grep -m1 "name snat_networks" | awk '{print $1}' | tr -d ':') + +if [ -n "$DNAT_MAP_ID" ]; then + echo "Mapa DNAT (ID: $DNAT_MAP_ID):" + bpftool map dump id $DNAT_MAP_ID +else + echo "Mapa DNAT não encontrado" +fi + +if [ -n "$SNAT_MAP_ID" ]; then + echo -e "\nMapa SNAT (ID: $SNAT_MAP_ID):" + bpftool map dump id $SNAT_MAP_ID +else + echo -e "\nMapa SNAT não encontrado" +fi + +# Verificar IP forwarding +echo -e "\n[IP Forwarding]" +IP_FWD=$(cat /proc/sys/net/ipv4/ip_forward) +echo "IP forwarding: $IP_FWD" +if [ "$IP_FWD" != "1" ]; then + echo "AVISO: IP forwarding está desativado. Ative com:" + echo " echo 1 > /proc/sys/net/ipv4/ip_forward" +fi + +# Verificar conectividade com o alvo +echo -e "\n[Conectividade]" +ping -c 1 -W 1 $TARGET_IP > /dev/null +if [ $? -eq 0 ]; then + echo "Ping para $TARGET_IP: OK" +else + echo "Ping para $TARGET_IP: FALHOU" +fi + +# Testar HTTP/HTTPS +echo -e "\n[Teste HTTP]" +curl -s -m 2 --head http://$TARGET_IP > /dev/null +if [ $? -eq 0 ]; then + echo "Acesso HTTP direto para $TARGET_IP: OK" +else + echo "Acesso HTTP direto para $TARGET_IP: FALHOU" +fi + +# Obter IP externo +EXTERNAL_IP=$(ip -br addr show $INTERFACE | awk '{print $3}' | cut -d'/' -f1) +echo -e "\n[Teste NAT]" +echo "IP externo: $EXTERNAL_IP" +curl -s -m 2 --head http://$EXTERNAL_IP > /dev/null +if [ $? -eq 0 ]; then + echo "Acesso HTTP via NAT ($EXTERNAL_IP): OK" +else + echo "Acesso HTTP via NAT ($EXTERNAL_IP): FALHOU" +fi + +# Verificar logs recentes +echo -e "\n[Logs Recentes]" +echo "Últimas 5 linhas do trace_pipe (pode estar vazio se não houver atividade recente):" +cat /sys/kernel/debug/tracing/trace_pipe | head -n 5 + +echo -e "\nPara monitorar logs em tempo real: cat /sys/kernel/debug/tracing/trace_pipe" +echo "Para visualizar conexões atuais: ss -tan" diff --git a/xdp_accelerated_nat.c b/xdp_accelerated_nat.c index a2a9b5d..6526f21 100644 --- a/xdp_accelerated_nat.c +++ b/xdp_accelerated_nat.c @@ -135,7 +135,7 @@ static __always_inline __u16 ip_checksum(struct iphdr *ip) { /* Função simplificada para atualizar checksum */ static __always_inline __u16 update_checksum(__u16 old_checksum, __u32 old_value, __u32 new_value) { - __u32 sum = ~((uint32_t)old_checksum) & 0xFFFF; + __u32 sum = ~((__u32)old_checksum) & 0xFFFF; sum += ~(old_value >> 16) & 0xFFFF; sum += ~old_value & 0xFFFF; sum += (new_value >> 16) & 0xFFFF;