Egress IP Family Policy (IPv4/IPv6) (Português (Brasil))
Sumário
Seção intitulada “Sumário”- O que é
- Por que existe
- Os três valores
- Como configurá-la
- Como
autoé resolvido - Como
ipv4/ipv6são aplicados - Compatibilidade com SOCKS5
- Comportamento de falha segura
- Modelo de dados
- Documentação relacionada
O que é
Seção intitulada “O que é”Cada proxy no registro possui um campo family com três valores possíveis, validados por um enum do Zod:
family: z.enum(["auto", "ipv4", "ipv6"]).optional().default("auto"),O valor padrão do campo é "auto", o que preserva o comportamento anterior de pilha dupla. Defini-lo como ipv4 ou ipv6 fixa a família de conexão desse proxy.
A diretiva é normalizada em todos os locais por meio de um único helper, de modo que qualquer valor desconhecido seja convertido em auto:
export type ProxyFamily = "auto" | "ipv4" | "ipv6";
export function parseProxyFamily(value: unknown): ProxyFamily { return value === "ipv4" || value === "ipv6" ? value : "auto";}Por que existe
Seção intitulada “Por que existe”Introduzida no PR #3777. Os problemas que motivaram sua criação:
| Problema | O que a diretiva corrige |
|---|---|
| Vazamento de saída exclusivamente IPv6 para IPv4 | Quando um host de proxy possui registros A e AAAA (ou o sistema operacional prefere IPv4), o Happy Eyeballs pode estabelecer a conexão de saída por IPv4 mesmo quando você pretende usar um caminho exclusivamente IPv6. Fixar ipv6 elimina esse vazamento. |
| Revogação por anomalia de saída compartilhada | Provedores com rotação (codex/openai) revogam tokens quando muitas contas usam o mesmo IP de saída em alto volume. Controlar a família de saída ajuda a manter as contas em caminhos de saída distintos e previsíveis (consulte src/lib/proxyEgress.ts para ver os diagnósticos de IP de saída relacionados a isso). |
| Saída determinística para conformidade/testes | Quando é necessário garantir que o tráfego saia por uma família específica, auto não é suficiente. |
A diretiva é intencionalmente definida por proxy, e não globalmente — proxies diferentes no seu pool podem ter políticas diferentes.
Os Três Valores
Seção intitulada “Os Três Valores”| Valor | Rótulo na UI | Comportamento |
|---|---|---|
auto |
Automático (dual-stack) |
O sistema operacional escolhe a família. Para um host de proxy que seja um IP literal, a família é intrínseca ao literal; para um nome de host, ambas as famílias são elegíveis. Esse é o padrão. |
ipv4 |
Somente IPv4 |
Restringe a conexão ao IPv4. A conexão falha de forma segura se o host do proxy não tiver um registro IPv4 (A). |
ipv6 |
Somente IPv6 |
Restringe a conexão ao IPv6. A conexão falha de forma segura se o host do proxy não tiver um registro IPv6 (AAAA). |
As strings da UI ficam em src/i18n/messages/en.json (labelFamily, familyAuto, familyIpv4, familyIpv6, familyHint).
Como Configurar
Seção intitulada “Como Configurar”O seletor fica no formulário de proxy da aba Pool de Proxies:
- Abra Painel → Configurações → Proxy → Pool de Proxies
- Adicione ou edite um proxy
- Defina o menu suspenso Família de IP como
Automático (dual-stack),Somente IPv4ouSomente IPv6 - Salve
O controle é renderizado por ProxyRegistryManager.tsx (montado em proxy/ProxyPoolTab.tsx).
O campo family faz parte dos payloads de criação/atualização do registro de proxies, é validado por createProxyRegistrySchema / updateProxyRegistrySchema (src/shared/validation/schemas.ts) e processado por POST / PATCH /api/v1/management/proxies:
# Criar um proxy somente IPv6curl -X POST http://localhost:20128/api/v1/management/proxies \ -H "Content-Type: application/json" \ -d '{ "name": "IPv6 egress", "type": "socks5", "host": "proxy.example.com", "port": 1080, "family": "ipv6" }'
# Alterar um proxy existente para somente IPv4curl -X PATCH http://localhost:20128/api/v1/management/proxies \ -H "Content-Type: application/json" \ -d '{ "id": "proxy-uuid-here", "family": "ipv4" }'O mesmo campo também é aceito pelo objeto de configuração de proxy inline usado para entradas de proxy upstream (upstream_proxy_config.family; consulte Modelo de Dados).
Para o restante da API de CRUD/atribuição de proxies, consulte PROXY_GUIDE.md.
Como auto é Resolvido
Seção intitulada “Como auto é Resolvido”Quando family é auto, o OmniRoute não acrescenta nenhuma diretiva — a URL do proxy é usada sem alterações, e a família da conexão é determinada intrinsecamente.
No momento da construção da URL (proxyConfigToUrl / normalizeProxyUrl em open-sse/utils/proxyDispatcher.ts), um proxy auto resulta em uma URL simples, sem marcador:
const fam = parseProxyFamily(config.family);const normalized = normalizeProxyUrl(proxyUrlStr, "context proxy", { allowSocks5,});return fam === "auto" ? normalized : `${normalized}?family=${fam}`;No momento do despacho (resolveDispatcherFamily), auto é resolvido para a família intrínseca de um host com IP literal ou para null (deixando o sistema operacional decidir) no caso de um nome de host:
function resolveDispatcherFamily(parsed: URL): 4 | 6 | null { const directive = parseProxyFamily(parsed.searchParams.get("family") ?? undefined); const literal = detectIpLiteralFamily(parsed.hostname); if (directive === "auto") return literal; // null para um nome de host → o sistema operacional escolhe // ...}Portanto:
auto+ host com IP literal (192.0.2.1/[2001:db8::1]) → família desse literal.auto+ nome de host →null→ resolução dual-stack padrão do sistema operacional.
Como ipv4 / ipv6 São Aplicados
Seção intitulada “Como ipv4 / ipv6 São Aplicados”Uma diretiva diferente de auto é transmitida como um único marcador de consulta sintético — ?family=ipv4 ou ?family=ipv6 — anexado uma vez à URL normalizada do proxy. normalizeProxyUrl remove e anexa novamente esse marcador exatamente uma vez, garantindo que ele nunca corrompa a análise da porta.
Quando o dispatcher é criado, o marcador é lido e convertido em uma família de conexão concreta. Se o host for um literal de IP da família oposta, o OmniRoute lança um erro (a contradição resulta em falha fechada):
const want = directive === "ipv6" ? 6 : 4;if (literal !== null && literal !== want) { throw new Error( `[ProxyDispatcher] Proxy family directive ${directive} contradicts ${literal === 6 ? "IPv6" : "IPv4"} literal host` );}A família concreta é então fixada no conector:
- Proxies HTTP/HTTPS (
ProxyAgent):proxyTls: { family, autoSelectFamily: false }— desabilita o Happy Eyeballs para que a família escolhida seja a única utilizada na conexão. - Proxies SOCKS5: um conector personalizado encaminha
socket_options: { family, autoSelectFamily: false }ao cliente SOCKS (consulte Compatibilidade com SOCKS5).
Compatibilidade com SOCKS5
Seção intitulada “Compatibilidade com SOCKS5”A fixação de família funciona com proxies SOCKS5, mas o fetch-socks padrão não expõe as opções de socket necessárias para fixar a família do salto até o proxy. O OmniRoute inclui seu próprio conector para essa finalidade:
export function buildSocksFamilySocketOptions(family: 4 | 6 | null): Record<string, unknown> { if (family === 6) return { family: 6, autoSelectFamily: false }; if (family === 4) return { family: 4, autoSelectFamily: false }; return {};}Todos os despachos SOCKS5 passam por createSocksDispatcherWithFamily, independentemente de family (incluindo null / auto sobre um nome de host): buildSocksFamilySocketOptions(null) produz {}, e o mesmo caminho de SocksClient.createConnection + buildConnector para TLS é usado com a fixação por socket_options, para que o Happy Eyeballs não possa escolher IPv4 para uma política de saída exclusiva de IPv6.
O suporte a SOCKS5 é habilitado por padrão (pode ser desabilitado por meio de ENABLE_SOCKS5_PROXY=false); consulte PROXY_GUIDE.md → Variáveis de Ambiente.
Comportamento de Falha Fechada
Seção intitulada “Comportamento de Falha Fechada”O objetivo da diretiva é recusar a conexão em vez de recorrer silenciosamente à família errada. Duas proteções garantem isso:
-
Contradição de literal — uma diretiva que contradiz um host expresso como literal de IP lança um erro durante a criação do dispatcher (
resolveDispatcherFamily, mostrado acima). -
Verificação preliminar de DNS do nome de host — para um proxy com nome de host e uma família fixada,
proxyFetch.tsverifica se o nome de host realmente possui um registro na família exigida antes de iniciar o tráfego de saída, por meio deassertHostnameSupportsFamily:open-sse/utils/proxyFamilyResolve.ts const hasFamily = records.some((r) => r.family === family);if (!hasFamily) {throw new Error(`[ProxyFamily] Proxy host ${host} has no ${family === 6 ? "IPv6 (AAAA)" : "IPv4 (A)"} record; ` +`refusing ${family === 6 ? "IPv6" : "IPv4"}-only egress (fail-closed)`);}Em caso de falha,
proxyFetch.tsmarca o erro comcode = "PROXY_FAMILY_UNAVAILABLE"estatusCode = 503. Uma falha na resolução de DNS também é tratada como falha fechada (o tráfego de saída é recusado).
Hosts expressos como literais de IP não exigem ação na verificação preliminar de DNS — sua família é intrínseca e dispensa consulta.
Modelo de Dados
Seção intitulada “Modelo de Dados”A coluna family foi adicionada pela migração 099_proxy_family.sql a duas tabelas:
-- src/lib/db/migrations/099_proxy_family.sqlALTER TABLE proxy_registry ADD COLUMN family TEXT NOT NULL DEFAULT 'auto';ALTER TABLE upstream_proxy_config ADD COLUMN family TEXT NOT NULL DEFAULT 'auto';proxy_registry.family— a diretiva por proxy para entradas do registro (src/lib/db/proxies.ts). As consultas de resolução selecionamfamilyjunto às demais colunas de proxy, e um valor ausente ou que não seja uma string é convertido em"auto".upstream_proxy_config.family— a diretiva para entradas de proxy upstream (src/lib/db/upstreamProxy.ts), com o mesmo valor padrão"auto".
Quando um objeto de proxy resolvido contém um family diferente de auto, proxyConfigToUrl acrescenta o marcador ?family= para que a configuração fixada seja preservada até o dispatcher.
Documentação Relacionada
Seção intitulada “Documentação Relacionada”📖 Documentação relacionada:
- Guia de Proxy — sistema de proxy completo: CRUD do registro, resolução em 4 níveis, rotação, verificação de integridade e referência da API
docs/security/STEALTH_GUIDE.md(git; não compilado em/docs) — camadas de impressão digital TLS e da CLI que operam sobre o proxy- Níveis de Proteção de Rotas — aplicação obrigatória de loopback para rotas exclusivamente locais
HagiCode
HagiCode é um ambiente de programação com agentes, fluxos estruturados, execução multiagente e visualizações Hero Dungeon.
Transforme ideias em software útil com um fluxo de trabalho com agentes mais inteligente, rápido e agradável.

- SmartFluxos estruturados transformam intenções em um caminho executável da ideia à entrega.
- EfficientFluxos multiagente mantêm pesquisa, implementação e revisão em andamento simultaneamente.
- FunO Hero Dungeon torna longas sessões de programação mais visuais e colaborativas.