Comment les ports source sont-ils déterminés et comment puis-je le forcer à utiliser un port spécifique

26

Lorsque je me connecte à https://www.google.co.uk, cela passe à 216.58.198.228:443. Ensuite, une connexion avec moi s'ouvre sur [Mon adresse IP]: 63998.

Ma question est de savoir comment le port 63998 est choisi et existe-t-il un moyen de le forcer à être 63999.

TheGathron
la source
9
existe-t-il un moyen de le forcer à 63999 Avez-vous des raisons d'essayer de le faire?
AL
1
Si vous écrivez une application, vous pouvez ouvrir n'importe quel port source (inutilisé) de votre choix. Mais ce n'est pas une bonne idée et vous ne savez pas pourquoi vous voulez cela?
pjc50
6
@ pjc50 En effet, cette question semble avoir un problème XY .
Dev
1
J'ai "soumis une modification pour changer le titre en" source "plutôt que" local ", car les numéros de port de destination sont" locaux "pour la machine de destination, mais la source du paquet TCP SYN initial est sans ambiguïté celle de l'initiateur de la connexion.
Monty Plus dur

Réponses:

39

Comment les ports locaux sont-ils déterminés

Le numéro de port est choisi par le logiciel d'implémentation TCP à partir d'une gamme de numéros de port appelés ports éphémères .

Le mécanisme exact de choix du numéro de port et de la plage à utiliser dépend du système d'exploitation.


Existe-t-il un moyen de le forcer à 63999.

Cela peut être fait en modifiant la configuration du logiciel d'implémentation TCP.

Des instructions sur la configuration de la gamme de ports éphémères pour une variété de différents systèmes d'exploitation peuvent être trouvées dans Changer la gamme de ports éphémères .

  • Les instructions pour Linux et Windows sont incluses dans cette réponse ci-dessous pour référence.

Cependant, ce n'est pas une bonne idée de restreindre la plage à un seul port, par exemple 63999.

  • En fait, sur Windows, cela n'est pas possible car:

    La plage minimale de ports pouvant être définie est de 255.


La gamme du port éphémère

Une connexion TCP / IPv4 se compose de deux points de terminaison, et chaque point de terminaison se compose d'une adresse IP et d'un numéro de port. Par conséquent, lorsqu'un utilisateur client se connecte à un ordinateur serveur, une connexion établie peut être considérée comme le quadruple de (IP du serveur, port du serveur, IP du client, port du client).

Habituellement, trois des quatre sont facilement connus - la machine cliente utilise sa propre adresse IP et lors de la connexion à un service distant, l'adresse IP et le numéro de port de service de la machine serveur sont requis.

Ce qui n'est pas immédiatement évident, c'est que lorsqu'une connexion est établie, le côté client de la connexion utilise un numéro de port. Sauf si un programme client demande explicitement un numéro de port spécifique, le numéro de port utilisé est un numéro de port éphémère.

Les ports éphémères sont des ports temporaires attribués par la pile IP d'une machine et sont attribués à partir d'une plage de ports désignée à cet effet. Lorsque la connexion se termine, le port éphémère est disponible pour réutilisation, bien que la plupart des piles IP ne réutilisent pas ce numéro de port tant que le pool entier de ports éphémères n'a pas été utilisé.

Ainsi, si le programme client se reconnecte, un numéro de port éphémère différent lui sera attribué pour son côté de la nouvelle connexion.

Source La gamme du port éphémère


Modification de la plage de ports éphémères

Linux:

Linux vous permet de visualiser et de modifier la plage de ports éphémères en utilisant simplement le fichier /proc/sys/net/ipv4/ip_local_port_range. Par exemple, cela montre la configuration par défaut sur un système kernel 2.2:

$ cat /proc/sys/net/ipv4/ip_local_port_range 
1024 4999

Pour changer cela à la plage préférée, vous pouvez faire (en tant que superutilisateur):

# echo "49152 65535" > /proc/sys/net/ipv4/ip_local_port_range 

Notez que vous devrez effectuer cette opération à chaque démarrage du système. Veillez donc à ajouter une ligne à un script de démarrage du système, de sorte que /etc/rc.local votre plage soit toujours utilisée.

Notez également que le noyau Linux 2.4 utilisera par défaut la plage de 32768 à 61000 si une mémoire de noyau adéquate est disponible, donc la modification de la plage peut ne pas être nécessaire sur les systèmes Linux plus récents.

Enfin, notez également que vous pourrez peut-être utiliser l' sysctlinterface pour modifier les paramètres plutôt que d'utiliser le /procsystème de fichiers. Le nom du sysctlparamètre est "net.ipv4.ip_local_port_range". Modifiez le /etc/sysctl.conffichier si vous l'avez ou demandez à un script de démarrage d'exécuter la sysctlcommande manuellement si vous souhaitez modifier ce paramètre à l'aide de sysctl.

Windows Vista / Windows Server 2008 et plus récent:

À partir de Windows Vista et Windows Server 2008, Windows utilise désormais une large gamme (49152-65535) par défaut, selon l'article 929851 de la base de connaissances Microsoft . Ce même article montre également comment vous pouvez modifier la plage si vous le souhaitez, mais la plage par défaut est désormais suffisante pour la plupart des serveurs.

Source Modification de la plage de ports éphémères

Vous pouvez afficher la plage de ports dynamiques sur un ordinateur qui exécute un ordinateur Windows Vista ou Windows Server 2008 à l'aide des netshcommandes suivantes :

netsh int ipv4 show dynamicport tcp
netsh int ipv4 show dynamicport udp
netsh int ipv6 show dynamicport tcp
netsh int ipv6 show dynamicport udp 

Remarques:

  • La plage est définie séparément pour chaque transport et pour chaque version d'IP.
  • La plage de ports est désormais véritablement une plage avec un point de départ et un point final.
  • Les clients Microsoft qui déploient des serveurs exécutant Windows Server 2008 peuvent rencontrer des problèmes de communication RPC entre les serveurs si des pare-feu sont utilisés sur le réseau interne.
  • Dans ces cas, nous vous recommandons de reconfigurer les pare-feu pour autoriser le trafic entre les serveurs dans la plage de ports dynamiques de 49152 through 65535.
  • Cette gamme s'ajoute aux ports bien connus utilisés par les services et les applications.
  • Ou bien, la plage de ports utilisée par les serveurs peut être modifiée sur chaque serveur.

Vous ajustez cette plage à l'aide de la netshcommande, comme suit:

netsh int <ipv4|ipv6> set dynamic <tcp|udp> start=number num=range

Cette commande définit la plage de ports dynamiques pour TCP. Le port de démarrage est numéro et le nombre total de ports est plage. Voici des exemples de commandes:

netsh int ipv4 set dynamicport tcp start=10000 num=1000
netsh int ipv4 set dynamicport udp start=10000 num=1000
netsh int ipv6 set dynamicport tcp start=10000 num=1000
netsh int ipv6 set dynamicport udp start=10000 num=1000

Ces exemples de commandes définissent la plage de ports dynamique pour commencer au port 10000 et se terminer au port 10999(1000 ports).

Remarques:

  • La plage minimale de ports pouvant être définie est 255.
  • Le port de démarrage minimum pouvant être défini est 1025.
  • Le port d'extrémité maximal (basé sur la plage en cours de configuration) ne peut pas dépasser 65535.
  • Pour dupliquer le comportement par défaut de Windows Server 2003, utilisez 1025comme port de démarrage, puis utilisez 3976comme plage pour TCP et UDP. Il en résulte un port de début 1025et un port de fin 5000.

Source de l'article 929851 de la base de connaissances Microsoft :

Windows XP et versions antérieures:

Pour les anciens systèmes d'exploitation Windows (Windows XP et versions antérieures), Windows utilise la plage BSD traditionnelle de 1024 à 4999 pour sa plage de ports éphémères. Malheureusement, il semble que vous ne pouvez définir que la limite supérieure de la plage de ports éphémères. Voici des informations extraites de l'article 196271 de la base de connaissances Microsoft :

  • Démarrez l'Éditeur du Registre ( Regedt32.exe).
  • Recherchez la clé suivante dans le Registre:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

  • Dans le menu "Edition", cliquez sur "Ajouter une valeur", puis ajoutez la valeur de Registre suivante:

    Nom de la valeur: MaxUserPortType de données: REG_DWORDValeur: 65534(par exemple)

    Plage valide: 5000-65534(décimal) Par défaut: 0x1388(5000 décimal)

    Description: ce paramètre contrôle le numéro de port maximal utilisé lorsqu'une application demande un port utilisateur disponible au système. Normalement, les ports éphémères (c'est-à-dire de courte durée) sont alloués entre les valeurs de 1024et 5000inclus.

  • Quittez l'Éditeur du Registre.

Remarque: Il existe un autre article de la base de connaissances pertinent ( 812873 ) qui prétend vous permettre de définir une plage d'exclusion, ce qui pourrait signifier que vous pouvez exclure des ports 1024-9999(par exemple) pour que la plage de ports éphémère soit 10000-65534. Cependant, nous n'avons pas été en mesure de le faire fonctionner (en octobre 2004).

Source Modification de la plage de ports éphémères

DavidPostill
la source
1
Pour au moins Windows, il semble qu'il soit possible de restreindre la plage de ports à l'échelle du système. Dans la plupart des cas, c'est probablement une mauvaise idée, en particulier le limiter à un port serait: Voir KB 929851 , les commandes répertoriées fonctionnent au moins sur Windows 7.
Seth
@Seth Oui. J'étais réticent à le mentionner car l'OP n'a pas mentionné son système d'exploitation et je ne voulais pas étendre la réponse pour couvrir N systèmes d'exploitation ...
DavidPostill
Vous avez raison à ce sujet. Après tout, il existe de nombreux systèmes d'exploitation. C'est juste quelque chose que je suis tombé sur en essayant à l'origine de répondre à cette question. Comme votre réponse était plus rapide, j'ai pensé l'ajouter. C'est une réponse vraiment bien écrite! :) Je viens de l'ajouter comme indication que parfois la modification de la configuration est suffisante plutôt que la reprogrammation (peut-être que ma compréhension est juste différente - pour moi, cela ressemble à une recompilation).
Seth
1
En fait, sous Linux aussi, c'est très simple: faites simplement echo "49152 65535"> / proc / sys / net / ipv4 / ip_local_port_range . C'est si simple que cela peut être fait par commande .
MariusMatutiae
2
Plutôt que de changer la plage de ports éphémères, il serait préférable que l'application appelle l' bindappel système avant d'appeler connect. Certaines applications ont une option pour le faire, d'autres non.
kasperd
9

La réponse de David Postill est parfaitement juste. Je voudrais juste ajouter quelque chose, en soulignant que changer la plage de ports éphémères sous Linux est si simple, que l'OP a une réponse affirmative.

Vous modifiez l'EPR comme suit:

echo "40000 60000" > /proc/sys/net/ipv4/ip_local_port_range 

et vous pouvez sélectionner le port 50000 (à titre d'exemple) avec le script suivant:

OLD_RANGE=$(cat /proc/sys/net/ipv4/ip_local_port_range)
MY_PORT=50000
echo "$MY_PORT $MY_PORT" > /proc/sys/net/ipv4/ip_local_port_range
sudo -u SomeUser SomeApplication  & 
echo $OLD_RANGE" > /proc/sys/net/ipv4/ip_local_port_range 

Une mise en garde ici: comme il n'y a qu'un seul port dans la plage, une autre application peut vous l'arracher entre l'exécution des troisième et quatrième lignes ci-dessus; aussi, même s'il n'y a pas de condition de concurrence, vous paralyserez toutes les autres applications jusqu'à ce que vous restauriez un grand EPR, c'est pourquoi j'ai restauré la gamme d'origine dès que possible.

Ainsi, si le système d'exploitation des PO avait été Linux, la réponse aurait été que cela aurait pu être fait facilement.

Étonnamment, ce n'est pas aussi simple sur les BSD, dont certains n'ont même pas de paramètre de noyau d'exécution pour l'EPR. MacOS X, FreeBSD et OpenBSD nécessitent de modifier le fichier /etc/sysctl.conf , mais ils ont des choix différents pour l'EPR.

Indépendamment de ce qui précède et de l'OS, le fait que quelque chose puisse être fait ne signifie pas que cela devrait être fait: pourquoi diable en avez-vous besoin? Je ne peux pas penser à un seul cas d'utilisation.

MariusMatutiae
la source
Pour l'exemple Linux +1.
DavidPostill
Hehe. BSD / OS nécessite de recompiler le noyau :)
DavidPostill
1
@DavidPostill C'est une grosse déception.
MariusMatutiae
Il y a une faille dans votre exemple de code. Votre distribution de caractères est très mal placée. De plus, ce serait une bonne idée de rendre BIND_PORTfacultatif, de sorte que le code puisse toujours être utilisé exactement de la même manière que l'original. Je pense que htons(bind_port_env ? atoi(bind_port_env) : 0)ferait la bonne chose.
kasperd
1

Il convient d'ajouter que le noyau Linux possède également

net.ipv4.ip_local_reserved_ports

bouton qui fait quelque peu l'opposé mais néanmoins il pourrait être très utile car de cette façon vous pouvez "percer un trou" pour les services qui ouvrent des ports spécifiques dans une gamme de ports autrement éphémère.

Bref extrait de la documentation :

Spécifiez les ports réservés aux applications tierces connues. Ces ports ne seront pas utilisés par les attributions automatiques de ports (par exemple lors de l'appel de connect () ou bind () avec le numéro de port 0). Le comportement d'allocation de port explicite est inchangé.

Le format utilisé pour l'entrée et la sortie est une liste de plages séparées par des virgules (par exemple "1,2-4,10-10" pour les ports 1, 2, 3, 4 et 10). L'écriture dans le fichier effacera tous les ports précédemment réservés et mettra à jour la liste actuelle avec celle donnée en entrée.

poige
la source