fix
This commit is contained in:
1 parent
c17738a62f
commit
38a3e9e495
1 file changed
+56
@@ -133,6 +133,48 @@ static __always_inline bool is_local_ip(__u32 ip_be)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────
|
||||||
|
// DECISÃO DE ESCOPO (depois de 4 rodadas de bugs encontrados e
|
||||||
|
// corrigidos — porta, dual-stack, loopback, tamanho — todos legítimos,
|
||||||
|
// mas o problema de fundo continuou aparecendo especificamente em
|
||||||
|
// tráfego HTTP via proxy: nginx↔Nextcloud, nginx↔Atlas, nginx↔OnlyOffice,
|
||||||
|
// sempre — "upstream prematurely closed connection" / timeout, mesmo em
|
||||||
|
// respostas pequenas, em serviços sem nenhuma relação entre si):
|
||||||
|
//
|
||||||
|
// Em TODOS os testes, sem uma única exceção, tráfego banco/cache
|
||||||
|
// (MariaDB, Redis) redirecionou correto e nunca corrompeu nada — nem em
|
||||||
|
// rajada, nem sob concorrência. Tráfego HTTP via proxy reverso
|
||||||
|
// (streaming, HTTP/2, keep-alive, chunked) é o único padrão onde o
|
||||||
|
// problema aparece, e é mais sensível a qualquer perturbação sutil no
|
||||||
|
// fluxo de bytes.
|
||||||
|
//
|
||||||
|
// Em vez de continuar caçando o bug exato do mecanismo de redirect do
|
||||||
|
// kernel, restringimos o REGISTRO no sockhash a conexões onde um dos
|
||||||
|
// lados é porta de banco/cache. Tráfego HTTP nunca entra no mapa —
|
||||||
|
// nunca é candidato a redirect, sempre usa o caminho normal de rede
|
||||||
|
// (comprovadamente 100% íntegro, inclusive em teste isolado de 500MB
|
||||||
|
// via nc). Perde-se a aceleração pra proxy HTTP; mantém-se pro tipo de
|
||||||
|
// tráfego (muitos round-trips pequenos de banco/cache) onde o ganho de
|
||||||
|
// latência é maior E onde já provamos que funciona sem risco.
|
||||||
|
//
|
||||||
|
// IMPORTANTE: key.sport/key.dport NÃO são o número literal da porta —
|
||||||
|
// já passam pela transformação bpf_htonl(porta)>>16 (ver
|
||||||
|
// extract_key_from_ops). Comparar direto com 3306/6379 nunca bateria.
|
||||||
|
// Os valores abaixo são o RESULTADO dessa mesma transformação aplicada
|
||||||
|
// às portas reais, verificados nos traces de produção desta sessão
|
||||||
|
// (ex: MariaDB sempre apareceu com dport/sport=59916, nunca 3306) e
|
||||||
|
// confirmados by matemática: bpf_htonl(3306)>>16 = 0xEA0C = 59916;
|
||||||
|
// bpf_htonl(6379)>>16 = 0xEB18 = 60184.
|
||||||
|
// ─────────────────────────────────────────────────────────
|
||||||
|
#define SOCKMAP_PORT_MARIADB_ENC 59916 // 3306 já transformado
|
||||||
|
#define SOCKMAP_PORT_REDIS_ENC 60184 // 6379 já transformado
|
||||||
|
|
||||||
|
static __always_inline bool is_accelerated_key(struct sock_key *key)
|
||||||
|
{
|
||||||
|
return key->sport == SOCKMAP_PORT_MARIADB_ENC || key->dport == SOCKMAP_PORT_MARIADB_ENC ||
|
||||||
|
key->sport == SOCKMAP_PORT_REDIS_ENC || key->dport == SOCKMAP_PORT_REDIS_ENC;
|
||||||
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────
|
||||||
// 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)
|
||||||
@@ -216,6 +258,12 @@ int bpf_sockops_handler(struct bpf_sock_ops *skops)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Escopo: só banco/cache (ver comentário em is_accelerated_key) ──
|
||||||
|
if (!is_accelerated_key(&key)) {
|
||||||
|
stats_inc(3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (skops->family == SOCKMAP_AF_INET6)
|
if (skops->family == SOCKMAP_AF_INET6)
|
||||||
bpf_printk("REG via IPv6 mapeado: op=%u sip=%x dip=%x", op, key.sip4, key.dip4);
|
bpf_printk("REG via IPv6 mapeado: op=%u sip=%x dip=%x", op, key.sip4, key.dip4);
|
||||||
|
|
||||||
@@ -323,6 +371,14 @@ int bpf_msg_redirect(struct sk_msg_md *msg)
|
|||||||
key.dport = bpf_htonl(msg->local_port) >> 16;
|
key.dport = bpf_htonl(msg->local_port) >> 16;
|
||||||
key.family = SOCKMAP_AF_INET; // normalizado, ver extract_key_from_ops
|
key.family = SOCKMAP_AF_INET; // normalizado, ver extract_key_from_ops
|
||||||
|
|
||||||
|
// Cinto e suspensório: mesmo que o registro já esteja restrito a
|
||||||
|
// banco/cache, confere de novo aqui — garante que nenhum tráfego
|
||||||
|
// HTTP tenta redirect mesmo que uma entrada antiga/inesperada exista.
|
||||||
|
if (!is_accelerated_key(&key)) {
|
||||||
|
stats_inc(2);
|
||||||
|
return SK_PASS;
|
||||||
|
}
|
||||||
|
|
||||||
// Tenta redirecionar diretamente para o socket par.
|
// Tenta redirecionar diretamente para o socket par.
|
||||||
int ret = bpf_msg_redirect_hash(msg, &sock_hash, &key, BPF_F_INGRESS);
|
int ret = bpf_msg_redirect_hash(msg, &sock_hash, &key, BPF_F_INGRESS);
|
||||||
if (ret == SK_PASS) {
|
if (ret == SK_PASS) {
|
||||||
|
|||||||
Reference in new issue
Block a user