fixed4337
This commit is contained in:
1 parent
0a37f06ce6
commit
e97a83c989
2 files changed
+34
-5
No files matched your search
@@ -97,13 +97,30 @@ static __always_inline bool is_local_ip(__u32 ip_be)
|
|||||||
// Extrai a chave de conexão a partir do contexto sock_ops
|
// Extrai a chave de conexão a partir do contexto sock_ops
|
||||||
// (usado quando uma conexão TCP é estabelecida)
|
// (usado quando uma conexão TCP é estabelecida)
|
||||||
// ─────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────
|
||||||
|
// BUG CORRIGIDO: o código antigo misturava dois domínios de codificação
|
||||||
|
// de porta sem converter os dois pro mesmo formato.
|
||||||
|
// - ops->local_port vem em HOST byte order (puro, ex: 6379)
|
||||||
|
// - ops->remote_port vem com o valor em network byte order alojado nos
|
||||||
|
// 16 bits SUPERIORES de um campo de 32 bits — não é um u32 comum em
|
||||||
|
// network order, então bpf_ntohl() sozinho faz um byte-swap completo
|
||||||
|
// de 32 bits e produz um número sem relação com a porta real.
|
||||||
|
// A comparação `sport == local_port do outro lado` só funciona se AMBOS
|
||||||
|
// os valores estiverem no MESMO domínio. Em vez de tentar decifrar o
|
||||||
|
// valor "verdadeiro" da porta (o que exigiria confiar numa convenção que
|
||||||
|
// não dá pra validar sem testar em kernel real), a correção normaliza os
|
||||||
|
// dois pro domínio de remote_port: extrai remote_port com ">> 16" (sem
|
||||||
|
// ntohl) e converte local_port PRA esse mesmo domínio com
|
||||||
|
// "bpf_htonl(local_port) >> 16". Assim os dois lados de uma conexão
|
||||||
|
// calculam exatamente o mesmo valor pro mesmo par de portas, não importa
|
||||||
|
// qual seja a codificação exata do kernel — o que importa é que os dois
|
||||||
|
// membros do par usem a MESMA transformação simétrica.
|
||||||
static __always_inline void
|
static __always_inline void
|
||||||
extract_key_from_ops(struct bpf_sock_ops *ops, struct sock_key *key)
|
extract_key_from_ops(struct bpf_sock_ops *ops, struct sock_key *key)
|
||||||
{
|
{
|
||||||
key->sip4 = ops->local_ip4;
|
key->sip4 = ops->local_ip4;
|
||||||
key->dip4 = ops->remote_ip4;
|
key->dip4 = ops->remote_ip4;
|
||||||
key->sport = ops->local_port; // já em host byte order
|
key->sport = bpf_htonl(ops->local_port) >> 16;
|
||||||
key->dport = bpf_ntohl(ops->remote_port); // converter de network para host
|
key->dport = ops->remote_port >> 16;
|
||||||
key->family = ops->family;
|
key->family = ops->family;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,11 +218,15 @@ int bpf_msg_redirect(struct sk_msg_md *msg)
|
|||||||
// Construímos a chave do socket PAR (invertendo src/dst).
|
// Construímos a chave do socket PAR (invertendo src/dst).
|
||||||
// Se A→B enviou dados, queremos encontrar no mapa a entrada
|
// Se A→B enviou dados, queremos encontrar no mapa a entrada
|
||||||
// que B registrou: {sip=B, dip=A, sport=portaB, dport=portaA}
|
// que B registrou: {sip=B, dip=A, sport=portaB, dport=portaA}
|
||||||
|
//
|
||||||
|
// Mesma normalização de porta usada em extract_key_from_ops (mesmo
|
||||||
|
// domínio dos dois lados): remote_port só com ">> 16", local_port
|
||||||
|
// convertido pra esse domínio via "bpf_htonl(...) >> 16".
|
||||||
struct sock_key key = {};
|
struct sock_key key = {};
|
||||||
key.sip4 = msg->remote_ip4; // IP remoto = IP do par
|
key.sip4 = msg->remote_ip4; // IP remoto = IP do par
|
||||||
key.dip4 = msg->local_ip4; // IP local = nosso IP
|
key.dip4 = msg->local_ip4; // IP local = nosso IP
|
||||||
key.sport = bpf_ntohl(msg->remote_port); // remote_port está em network order
|
key.sport = msg->remote_port >> 16;
|
||||||
key.dport = msg->local_port; // local_port está em host order
|
key.dport = bpf_htonl(msg->local_port) >> 16;
|
||||||
key.family = msg->family;
|
key.family = msg->family;
|
||||||
|
|
||||||
// Tenta redirecionar diretamente para o socket par.
|
// Tenta redirecionar diretamente para o socket par.
|
||||||
|
|||||||
@@ -52,4 +52,12 @@ ip link set dev wg0 xdp obj /home/rodrigo/server-mv/xdp/xdp_wg_mtu_optimizer.o s
|
|||||||
# então esse link precisa ser reaplicado se a rede "dockernet" for recriada.
|
# então esse link precisa ser reaplicado se a rede "dockernet" for recriada.
|
||||||
ip link set dev br-02f7820020b4 xdp obj /home/rodrigo/server-mv/xdp/bridge_xdp.o sec xdp
|
ip link set dev br-02f7820020b4 xdp obj /home/rodrigo/server-mv/xdp/bridge_xdp.o sec xdp
|
||||||
|
|
||||||
cd /home/docker/ebpf-sockmap/ && make load
|
# eBPF sockmap: DESATIVADO DE PROPÓSITO. Causou timeout/connection reset
|
||||||
|
# em conexões container-a-container (nginx->redis/mariadb/anatomia-web),
|
||||||
|
# incluindo depois de corrigir o bug de NAT (masquerade sem -o enp0s6,
|
||||||
|
# já corrigido em nftables.conf) — ou seja, o bug é na lógica de
|
||||||
|
# match/redirect do sk_msg em bpf/sockmap.bpf.c, não só no NAT. Não
|
||||||
|
# reativar em produção sem antes rastrear com bpf_printk num ambiente
|
||||||
|
# de teste. Ganho é só performance (bypass de socket local entre
|
||||||
|
# containers no mesmo host); o site funciona normalmente sem isso.
|
||||||
|
# cd /home/docker/ebpf-sockmap/ && make load
|
||||||
Reference in new issue
Block a user