En Linux, ¿cómo puedo saber cuántos puertos efímeros quedan disponibles?

17

¿Hay algún método en Linux para verificar cuántos puertos efímeros quedan disponibles? Ocasionalmente veo errores de "Dirección ya en uso" como resultado de quedarse sin puertos efímeros. Un reinicio de la máquina resolverá esto, pero sería mejor detectarlo antes de que ocurra.

JMc
fuente
Si está cometiendo errores como ese, le sugiero que o esté abusando del sistema al no usar el software o la arquitectura adecuados para un trabajo, o su software se está comportando mal o está mal configurado. ¿Quizás sus tiempos de espera son demasiado largos para su aplicación o algo está dejando las conexiones abiertas sin usarlas?
Caleb
1
Hay muchas aplicaciones válidas que requieren puertos efímeros adicionales más allá de los valores predeterminados del sistema operativo.
GregB

Respuestas:

26

El rango de puertos ephermal se especifica en /proc/sys/net/ipv4/ip_local_port_range. Probablemente pueda extenderlo para que se ejecute de 16k a 64k.

Puede ver la cantidad de conexiones abiertas usando netstat -an. Los sockets pueden estar atascados en el estado TIME_WAIT si está abriendo y cerrando muchas conexiones. En algunos lugares esto es inevitable, pero es posible que deba considerar si necesita un grupo de conexión, si este es el caso.

Si TIME_WAIT es el problema, puede configurar net.ipv4.tcp_tw_reuse/ net.ipv4.tcp_tw_recyclepara acelerar la rotación de la conexión.

Sean
fuente
+1, gracias por tomarse el tiempo para darle detalles exactos a este tipo.
Caleb
Tenemos un rango de 32800 a 61000. Encontramos que una vez que se hayan utilizado, el sistema operativo no los volverá a utilizar. Este es el comportamiento esperado, pero esperaría que el sistema operativo se inicie nuevamente al principio una vez que llegue al último puerto disponible. Sin embargo, esto no parece suceder. Además, solo para tener en cuenta, esta no es una ocurrencia muy regular. Es intermitente pero tenemos una gran cantidad de servidores.
JMc
1
Para cumplir con RFC 6335 /proc/sys/net/ipv4/ip_local_port_range debe ser un subconjunto de 49152-65535. Por lo tanto, reducir el extremo inferior del rango a menos de 49152 conlleva cierto riesgo.
kasperd
nunca use net.ipv4.tcp_tw_recycle ni net.ipv4.tcp_tw_reuse excepto si está desesperado y sabe exactamente lo que está haciendo. Estás exponiendo tu servicio a posibles problemas extremos.
Kiwy
3

Tenga en cuenta que este límite se aplica por tupla única (IP de origen, IP de igual, puerto de igual). Por lo tanto, deberá agrupar la salida de netstat/ sspor cada una de estas tuplas y verificar qué tan cerca está cada grupo del límite de conexión.

Esta publicación explica cómo puedes hacer esta agrupación con más detalle. Para verificar qué tan cerca está cada grupo al límite en Ruby, puede procesar ssresultados como:

#!/usr/bin/ruby

first_port, last_port = IO.read('/proc/sys/net/ipv4/ip_local_port_range').split.map(&:to_i)
ephemeral_port_max = last_port - first_port + 1
ephemeral_port_warning = ephemeral_port_max / 3 * 2

conns = `ss --numeric --tcp state connected "( sport >= :#{first_port} and sport <= :#{last_port} )"`

groups = Hash.new(0)
conns.lines.each do |conn|
  state, recvq, sendq, local, peer = conn.split
  local_ip, local_port = local.split(':')
  group = [local_ip, peer]
  groups[group] += 1
end

groups_requiring_warning =
  groups.select { |k, v| v > ephemeral_port_warning }
  .to_a
  .sort_by { |v1, v2| v1[1] <=> v2[1] } # Sort groups in descending order of number of connections

groups_requiring_warning.each do |group, used_port_count|
  puts "Connections from #{group[0]} to #{group[1]} "\
    "have used #{used_port_count} ephemeral ports out of #{ephemeral_port_max} max"\
    "(#{((used_port_count.to_f / ephemeral_port_max) * 100).round(2)}% used)"
end
Will Sewell
fuente