Sous Linux, comment savoir combien de ports éphémères restent disponibles?

17

Existe-t-il une méthode sous Linux pour vérifier combien de ports éphémères restent disponibles? Je vois parfois des erreurs "Adresse déjà utilisée" suite à un manque de ports éphémères. Un redémarrage de la machine résoudra cela, mais il serait préférable de l'attraper avant qu'il ne se produise.

JMc
la source
Si vous rencontrez des erreurs de ce type, je suggérerais soit que vous abusez du système en n'utilisant pas le bon logiciel ou l'architecture pour un travail, soit que votre logiciel se comporte mal ou est mal configuré. Peut-être que vos délais d'attente sont trop longs pour votre application ou que quelque chose laisse les connexions ouvertes sans les utiliser?
Caleb
1
Il existe de nombreuses applications valides qui nécessitent des ports éphémères supplémentaires au-delà des valeurs par défaut du système d'exploitation.
GregB

Réponses:

26

La plage de ports éphermiques est spécifiée dans /proc/sys/net/ipv4/ip_local_port_range. Vous pouvez probablement l'étendre pour qu'il fonctionne de 16k à 64k.

Vous pouvez voir le nombre de connexions ouvertes utilisant netstat -an. Les sockets peuvent être bloqués dans l'état TIME_WAIT si vous ouvrez et fermez un grand nombre de connexions. Dans certains endroits, cela est inévitable, mais vous devrez peut-être déterminer si vous avez besoin d'un pool de connexion si tel est le cas.

Si TIME_WAIT est le problème, vous pouvez définir net.ipv4.tcp_tw_reuse/ net.ipv4.tcp_tw_recyclepour accélérer le renouvellement de la connexion.

Sean
la source
+1, merci d'avoir pris le temps de donner des détails précis à ce type.
Caleb
Nous avons une gamme de 32800 à 61000. Nous constatons simplement qu'une fois ceux-ci utilisés, le système d'exploitation ne les réutilisera plus. C'est un comportement attendu, mais je m'attendrais à ce que le système d'exploitation redémarre au début une fois qu'il a atteint le dernier port disponible. Mais cela ne semble pas arriver. De plus, juste pour noter, ce n'est pas une occurrence extrêmement régulière. C'est intermittent mais nous avons un grand nombre de serveurs.
JMc
1
Pour être conforme à la RFC 6335, il /proc/sys/net/ipv4/ip_local_port_range doit s'agir d'un sous-ensemble de 49152-65535. Ainsi, la réduction de l'extrémité inférieure de la plage à un niveau inférieur à 49152 présente un certain risque.
kasperd
ne jamais utiliser net.ipv4.tcp_tw_recycle ni net.ipv4.tcp_tw_reuse sauf si vous êtes désespéré et savez exactement ce que vous faites. Vous exposez votre service à un problème d'extrémités potentiel.
Kiwy
3

Gardez à l'esprit que cette limite s'applique par tuple unique (IP source, IP homologue, port homologue). Par conséquent, vous devrez regrouper la sortie de netstat/ sspar chacun de ces tuples et vérifier à quel point chaque groupe est proche de la limite de connexion.

Cet article explique comment vous pouvez effectuer ce regroupement plus en détail. Pour vérifier à quel point chaque groupe est proche de la limite dans Ruby, vous pouvez traiter la sssortie comme:

#!/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
la source