DevSecOpsARTIGO

Nginx: não é possível determinar uma requisição de endereço no upstream

Há alguns dias, eu me deparei com uma mensagem de erro interessante no Nginx. Veja os detalhes!

Há alguns dias, eu me deparei com uma mensagem de erro interessante no Nginx.

[crit] 12889#0: *32401195 connect() to 127.0.0.1:80 failed (99: Cannot assign requested address) while connecting to upstream

Minha configuração foi muito simples. Isso foi um proxy Nginx que fez toda a criptografia SSL e enviou o tráfego para instância de Varnish, sendo executado em port :80 em localhost. A grande questão aqui é que foi um tráfego bastante elevado de proxy Nginx.

Mesmo com keepalive ativado no upstream do nginx, o erro apareceu. Mas o que isso significa?

Portas TCP e limites

É bom saber uma coisa ou duas sobre redes, além de apenas servidores, de vez em quando. O problema ocorreu porque o servidor não poderia ter uma porta TCP livre rápido o suficiente para fazer a conexão com 127.0.0.1.

$ ss -s
Total: 3130 (kernel 3431)
TCP:   51582 (estab 2866, closed 48611, orphaned 92, synrecv 0, timewait 48611/0), ports 35279

A ferramenta ss oferece estatísticas sobre soquetes/portas no servidor. Neste caso, eu tinha 51.582 sessões TCP em uso (tanto ativas, fechadas, à espera de serem fechada, …).

Um servidor normal tem aproximadamente 28.000 portas TCP possíveis que podem ser usadas ​​para fazer uma conexão TCP para um sistema remoto (ou local). Tudo o que fala por meio de um endereço IP irá escolher uma porta livre dessas para servir como porta de origem para a conexão de saída. Esse intervalo de porta é definido pelo parâmetro sysctl ip_local_port_range.

$ cat /proc/sys/net/ipv4/ip_local_port_range
32768	61000

$ sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768	61000

O formato é porta “minimum maximum“. Assim, 61.000-32.768 = 28 232 portas-fonte disponíveis.

Um proxy SSL Nginx que se conecta a uma instância Varnish rodando em localhost será parecido com isto em sua netstat.

$ netstat -anp | grep 127.0.0.1
...
tcp        0      0 127.0.0.1:37713         127.0.0.1:80            TIME_WAIT   -

O principal tópico aqui é a conexão de fonte de 127.0.0.1:37713 que se conecta ao seu endpoint 127.0.0.1:80. Para cada origem de conexão, uma nova fonte porta TCP é selecionada a partir do intervalo no parâmetro ip_local_port_range.

A combinação de um IP de origem, porta de origem, IP de destino e destino IP deve ser única. Isso é o que é chamado um quadruplet em termos de rede. Você provavelmente não pode (facilmente) mudar o IP de origem. A porta de origem é escolhida de forma dinâmica. Isso só deixa a o IP de destino e a porta de destino livres para brincar.

Resolvendo a limitação da porta de origem

Há algumas correções fáceis. Primeiro, o ip_local_port_range pode ser aumentado em uma máquina Linux (para obter mais material de leitura, ver aumentar o intervalo ip_local_port_range de portas TCP no Linux).

$ echo 15000 64000 > /proc/sys/net/ipv4/ip_local_port_range

Isso efetivamente aumenta o intervalo de portas totais do padrão de 28.232 para 49.000 portas.

Se isso não for suficiente, você pode adicionar mais IPs de destino para se conectar. Lembre-se de que cada conexão consiste em 4 partes (chamadas quadruplets) com porta de origem e IP de origem, IP de destino e porta de destino. Se você não pode mudar a porta de origem ou IP, basta alterar os IPs de destino.

Considere este tipo de definição para o upstream em Nginx;

upstream varnish {
  server 127.0.0.1:80;
}

Essa definição pode ser usada em suas configurações nginx com a diretiva proxy_pass.

server {
  listen 443;
  ...
  location / {
    proxy_pass http://varnish;
    ...
  }
}

Agora, se você sabe que cada servidor tem geralmente 2 IPs ou mais, é muito fácil adicionar mais quadriplets à sua pilha de rede, fazendo uma adição ao seu IP Nginx upstream. Você já adicionou 127.0.0.1, mas o servidor terá um outro IP (será público ou DHCP IP) que você pode adicionar com segurança também, se o seu servidor web se liga a todas as portas.

upstream varnish {
  server 127.0.0.1:80;
  server 31.193.180.217:80;
  server 10.50.5.1:80;
  ...
}

Cada IP que você adicionar em seu upstream está efetivamente adicionando 49.000 portas locais para a sua pilha de rede. Você pode até adicionar IPs locais não-roteáveis ​​para o servidor, como aliases de interface, apenas para usar como novos IPs de destino para as suas configurações de proxy.

***

Mattias Geniar faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://ma.ttias.be/nginx-cannot-assign-requested-address-for-upstream/

Trabalha com programação de linguagens e servidores há mais de 10 anos. Atualmente, trabalha na Nucleus como desenvolvedor e engenheiro de sistemas. Seus interesses incluem Linux, Apache, MySQL e PHP.

Ver perfil