Você precisa de diretivas de escuta IPv4 e IPv6 separadas no nginx?

72

Eu já vi vários exemplos de configuração para lidar com hosts virtuais IPv4 e IPv6 de pilha dupla no nginx. Muitos sugerem esse padrão:

listen 80;
listen [::]:80 ipv6only=on;

Tanto quanto eu posso ver, isso alcança exatamente o mesmo que:

listen [::]:80 ipv6only=off;

Por que você usaria o primeiro? A única razão pela qual consigo pensar é se você precisa de parâmetros adicionais específicos para cada protocolo, por exemplo, se você deseja apenas configurar o deferredIPv4.

Synchro
fonte
Defendido como nada a ver com a versão da pilha IP, é uma opção TCP.
Xavier Lucas
11
Claro, mas você o define nas listendiretivas e as opções são aplicadas por host: par de portas.
Synchro 20/10
Hum, eu realmente não consigo imaginar um caso em que você queira fazer isso. Eu acho que a única razão é histórica e Michael Hampton acertou em cheio.
Xavier Lucas

Respostas:

48

Provavelmente, esse é o único motivo pelo qual você usaria a construção anterior atualmente.

A razão pela qual você está vendo isso provavelmente é que o padrão foi ipv6onlyalterado no nginx 1.3.4. Antes disso, o padrão era off; nas versões mais recentes, o padrão é on.

Isso acontece ao interagir com a opção de soquete IPV6_V6ONLY no Linux e opções semelhantes em outros sistemas operacionais, cujos padrões não são necessariamente previsíveis. Portanto, a construção anterior era necessária antes da 1.3.4 para garantir que você realmente estivesse ouvindo conexões no IPv4 e no IPv6.

A alteração no padrão nginx para ipv6onlygarante que o padrão do sistema operacional para soquetes de pilha dupla seja irrelevante. Agora, o nginx se liga explicitamente ao IPv4, IPv6 ou a ambos, nunca dependendo do sistema operacional para criar um soquete de pilha dupla por padrão.

De fato, minhas configurações padrão do nginx para pré-1.3.4 têm a primeira configuração e pós-1.3.4 têm a segunda configuração.

Porém, como vincular um soquete de pilha dupla é apenas para Linux, minhas configurações atuais agora se parecem mais com o primeiro exemplo, mas sem ipv6onlydefinir, com a saber:

listen [::]:80;
listen 80;
Michael Hampton
fonte
4
Alguns sistemas operacionais não executam soquetes duplos ipv4 e ipv6, como o OpenBSD, portanto, você precisará ouvir duas vezes.
Justin Cormack
@JustinCormack Sim, você está certo, e eu levo isso em conta há algum tempo. Só não tinha atualizado este post até agora.
Michael Hampton
11
listen localhost:8080;parece ouvir ambos (1.12.2) e usando proxy_pass http://localhost:8080iria carregar equilíbrio entre :: 1 e 127.0.0.1 - Eu tive que adicionar uma linha para o IPv6 para obter IP real nos logsset_real_ip_from 127.0.0.1; set_real_ip_from ::1; real_ip_header X-Forwarded-For;
Antony Gibbs
65

Se você hospedar vários domínios vhost com uma única instância Nginx, não poderá usar a diretiva de escuta combinada única

listen [::]:80 ipv6only=off;

para cada um deles. O Nginx possui uma peculiaridade estranha, na qual você pode especificar o ipv6onlyparâmetro apenas uma vez para cada porta, ou ele falhará ao iniciar. Isso significa que você não pode especificá-lo para cada bloco de servidor de domínio vhost.

Como Michael mencionou, começando com o Nginx 1.3.4, o ipv6onlyparâmetro padrão é on.

Portanto, se você deseja hospedar vários domínios no IPv4 e no IPv6 com um único servidor Nginx, será forçado a usar duas diretivas de escuta para cada bloco do servidor de domínio:

listen 80;
listen [::]:80; 

Além disso, como Sander mencionou, o uso ipv6only=offtem a desvantagem de que os endereços IPv4 são convertidos para IPv6. Isso pode causar problemas se seu aplicativo verificar IP em listas negras como Akismet ou StopForumSpam, porque, a menos que você crie uma camada de conversão reversa, o aplicativo verificará a tradução IPv6 do endereço IPv4 do remetente de spam, que não corresponderá a nenhum dos endereços IPv4 em a lista negra.

Jeff Widman
fonte
2
Sim, é o mesmo que mencionei deferred, e outras diretivas por protocolo. Seria útil se eles pudessem ser especificados separadamente da diretiva listen pelo motivo que você diz.
Synchro
11
E o cerne da questão é que você precisa especificar a diretiva de escuta para cada domínio separadamente. Caso contrário, o que aconteceria? o site funcionaria bem via ipv4 e via ipv6 mostraria a página de boas-vindas do nginx. ROFL
Silver Moon
2
Obrigado pela explicação completa! Eu estava recebendo um erro confuso quando especifiquei ipv6only=offa mesma porta duas vezes. Sua resposta resolveu o problema!
11
Além disso, se você quiser usar 2 vhosts ambos ouvindo 443: listen 443; listen [::]:443;. Usando listen [::]:80 ipv6only=off;irá lançar um erro nginx essa porta já está em uso
lukeaus
16

Com o ipv6only=offestilo de configuração, os endereços IPv4 podem ser mostrados como endereços IPv6 usando os endereços IPv6 mapeados para IPv4 (somente software), por exemplo, arquivos de log, variáveis ​​de ambiente (REMOTE_ADDR) etc.

Sander Steffann
fonte
3
Sim, eles são mostrados desta maneira.
Michael Hampton
2

Para meu entendimento (e de acordo com os documentos em http://nginx.org/en/docs/http/ngx_http_core_module.html#listen ), usando apenas

listen 80;

... é suficiente se você deseja canalizar o tráfego IPv4 e IPv6 na mesma porta.

fevangelou
fonte
11
Isso já foi estabelecido e mencionado na pergunta. Por favor, veja as outras respostas para a diferença.
Synchro
3
Não era para mim, eu precisava dos dois. wget e curl em que falha ao usar o ipv6 até adicionar a linha "listen [::]: 80 ipv6only = on;"
Basil A