O que limita o número máximo de conexões em um servidor Linux?

89

Que parâmetro do kernel ou outras configurações controlam o número máximo de soquetes TCP que podem ser abertos em um servidor Linux? Quais são as vantagens de permitir mais conexões?

Notei durante o teste de carga de um servidor Apache com ab que é muito fácil maximizar as conexões abertas no servidor. Se você deixar de lado a opção ab's -k, que permite a reutilização da conexão, e solicitar que ele envie mais de 10.000 solicitações, o Apache atenderá as primeiras 11.000 solicitações e, em seguida, interromperá por 60 segundos. Uma olhada na saída netstat mostra 11.000 conexões no estado TIME_WAIT. Aparentemente, isso é normal. As conexões são mantidas em aberto por 60 segundos, mesmo depois que o cliente é concluído por razões de confiabilidade do TCP .

Parece que essa seria uma maneira fácil de fazer DoS um servidor e estou me perguntando quais são as afinações e precauções habituais para isso.

Aqui está a minha saída de teste:

# ab -c 5 -n 50000 http://localhost/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 5000 requests
Completed 10000 requests
apr_poll: The timeout specified has expired (70007)
Total of 11655 requests completed

Aqui está o comando netstat que eu executo durante o teste:

 # netstat --inet -p | grep "localhost:www" | sed -e 's/ \+/ /g' | cut -d' ' -f 1-4,6-7 | sort | uniq -c 
  11651 tcp 0 0 localhost:www TIME_WAIT -
      1 tcp 0 1 localhost:44423 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44424 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44425 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44426 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44428 SYN_SENT 7831/ab
Ben Williams
fonte

Respostas:

64

Eu finalmente encontrei a definição que foi realmente limitar o número de conexões: net.ipv4.netfilter.ip_conntrack_max. Isso foi definido como 11.776 e o ​​que eu definir é o número de solicitações que posso atender em meu teste antes de ter que esperar tcp_fin_timeoutsegundos para que mais conexões se tornem disponíveis. A conntracktabela é o que o kernel usa para rastrear o estado das conexões; assim que estiver cheio, o kernel começa a soltar pacotes e a imprimir isso no log:

Jun  2 20:39:14 XXXX-XXX kernel: ip_conntrack: table full, dropping packet.

O próximo passo foi fazer com que o kernel reciclasse todas essas conexões no TIME_WAITestado, em vez de descartar pacotes. Eu poderia conseguir isso ativando tcp_tw_recycleou aumentando ip_conntrack_maxpara ser maior do que o número de portas locais disponibilizadas para conexões por ip_local_port_range. Eu acho que uma vez que o kernel está fora das portas locais, ele começa a reciclar conexões. Isso usa mais conexões de rastreamento de memória, mas parece ser a melhor solução do que ativar, tcp_tw_recyclepois os documentos sugerem que isso é perigoso.

Com esta configuração, posso executar ab o dia todo e nunca ficar sem conexões:

net.ipv4.netfilter.ip_conntrack_max = 32768
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_orphan_retries = 1
net.ipv4.tcp_fin_timeout = 25
net.ipv4.tcp_max_orphans = 8192
net.ipv4.ip_local_port_range = 32768    61000

A tcp_max_orphansconfiguração não teve nenhum efeito nos meus testes e não sei por quê. Eu acho que fecharia as conexões no TIME_WAITestado uma vez que existissem 8192 deles, mas não faz isso por mim.

Ben Williams
fonte
3
Onde configuramos esses parâmetros?
Codevalley
2
@Codevalley Isso pode ser, mas no Ubuntu servidor dependente do sistema vão em /etc/sysctl.conf
Ben Williams
24

Você realmente quer ver o que o sistema de arquivos / proc tem a oferecer a esse respeito.

Nessa última página, você pode achar o seguinte interessante:

  • / proc / sys / net / ipv4 / tcp_max_orphans , que controla o número máximo de soquetes mantidos pelo sistema não conectados a algo. Aumentar isso pode consumir até 64kbyte de memória não trocável por soquete órfão .
  • / proc / sys / net / ipv4 / tcp_orphan_retries , que controla a quantidade de tentativas antes que um soquete fique órfão e fechado. Há uma nota específica nessa página sobre servidores da Web que é de interesse direto para você ...
Avery Payne
fonte
tcp_max_orphans é interessante, mas parece que não está funcionando. Quando tento medir soquetes órfãos durante o teste, vejo 11.651 deles, enquanto tcp_max_orphans é 8.092. # netstat --inet -p | grep "localhost: www" | sed -e 's / \ + / / g' | cut -d '' -f 1-4,6-7 | ordenar | uniq -c 11651 tcp 0 0 host local: www TIME_WAIT -
Ben Williams
Olhe para os tcp_orphan_retries definição - a ideia de ser, os soquetes são "abatidos" mais rápido ...
Avery Payne
A sugestão de @Jauder Ho + tcp_orphan_retries parece uma vitória em potencial para a sua situação.
Avery Payne
3

Eu não acho que exista um ajuste para definir isso diretamente. Isso se enquadra na categoria de ajuste de TCP / IP. Para descobrir o que você pode ajustar, tente 'man 7 tcp'. O sysctl ('man 8 sysctl') é usado para configurá-los. 'sysctl -a | grep tcp 'mostrará a maioria do que você pode ajustar, mas não tenho certeza se mostrará todos eles. Além disso, a menos que isso mude, os soquetes TCP / IP se abrem se parecem com descritores de arquivo. Portanto, esta e a próxima seção desse link podem ser o que você está procurando.

Kyle Brandt
fonte
2

Tente definir o seguinte, bem como definir tcp_fin_timeout. Isso deve encerrar TIME_WAIT mais rapidamente.

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
Jauder Ho
fonte
Cuidado aqui! Experimentou da maneira mais difícil. "Isso pode causar queda de quadros com balanceamento de carga e NATs, use somente isso para um servidor que se comunica apenas pela sua rede local." - wiki.archlinux.org/index.php/Sysctl
Henk
@ Henk Acho tcp_tw_recycleque é potencialmente perigoso. tcp_tw_reuseé mais seguro e não vejo motivo para usá-los simultaneamente.
Vladislav Rastrusny
2

O estoque apache (1) costumava ser predefinido para suportar apenas 250 conexões simultâneas - se você quisesse mais, havia um arquivo de cabeçalho a ser modificado para permitir mais sessões simultâneas. Não sei se isso ainda é verdade no Apache 2.

Além disso, você precisa adicionar uma opção para permitir muitos descritores de arquivos abertos para a conta que executa o Apache - algo que os comentários anteriores falham em apontar.

Preste atenção às configurações do trabalhador e que tipo de tempo limite de manutenção permanente você possui no próprio Apache, quantos servidores extras você tem em execução ao mesmo tempo e qual a velocidade com que esses processos extras são eliminados.

rasjani
fonte
1

Você pode reduzir o tempo gasto no estado TIME_WAIT (Defina net.ipv4.tcp_fin_timeout). Você pode substituir o Apache pelo YAWS ou nginx ou algo semelhante.

As trocas de mais conexões geralmente envolvem o uso de memória e, se você tiver um processo de bifurcação, muitos processos filhos que inundam sua CPU.

Devdas
fonte
11
tcp_fin_timeout não serve para definir a expiração do TIME-WAIT, que não pode ser alterada fora da reconstrução do kernel, mas para o FIN, como o nome indica.
Alexandr Kurilin
0

O número absoluto de soquetes que podem ser abertos em um único endereço IP é 2 ^ 16 e é definido pelo TCP / UDP, não pelo kernel.

Jason Tan
fonte
6
Não, não é. Você pode abrir mais, pois a porta local não precisa ser única, desde que os endereços remotos sejam diferentes. Além disso, o OP disse por servidor e você pode ter> 1 endereço por servidor.
MarkR