SO_REUSEADDR et INADDR_ANY

Le
Nicolas George
Il me semblait qu'il était légal d'avoir deux serveurs qui écoutent sur le
même port, un sur une adresse particulière et l'autre sur INADDR_ANY, pour
peu que SO_REUSEADDR soit utilisé.

Stevens confirme (UNP page 195) :

# SO_REUSEADDR allows multiple instances of the same server to be started on
# the same port, as long as each instance binds a different local IP
# address. [] The first HTTP server would call bind with a local IP
# address of 192.69.10.128 and a local port of 80 [] The third server
# would call bind with the willcard as the local IP address and a local port
# of 80. Again, SO_REUSEADDR is required for the final call to succeed.

Or sous Linux (2.6.21.4, pour les tests les plus détaillés), ça ne marche
pas. Par exemple, si je lance en parallèle :

strace netcat -l -p 1234
strace netcat -l -s 127.0.0.1 -p 1234

J'obtiens ceci (je simplifie la notation des structures par strace pour que
ce soit plus lisible) :

premier> setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
premier> bind(3, {AF_INET, 1234, 0.0.0.0}, 16) = 0
second> setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
second> bind(3, {AF_INET, 1234, 127.0.0.1), 16) = -1 EADDRINUSE (Address already in use)

Ou, si j'inverse l'ordre de lancement, l'échec est inversé. Si j'ajoute un
-s 10.0.0.1 à celui qui écoute sur le wildcard, ça fonctionne.

Est-ce que c'est moi qui rate quelque chose, ou bien est-ce que c'est Linux
qui fait n'importe quoi ?
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Stephane Chazelas
Le #756622
2007-07-12, 09:59(+00), Nicolas George:
Il me semblait qu'il était légal d'avoir deux serveurs qui écoutent sur le
même port, un sur une adresse particulière et l'autre sur INADDR_ANY, pour
peu que SO_REUSEADDR soit utilisé.

Stevens confirme (UNP page 195) :

# SO_REUSEADDR allows multiple instances of the same server to be started on
# the same port, as long as each instance binds a different local IP
# address. [...] The first HTTP server would call bind with a local IP
# address of 192.69.10.128 and a local port of 80 [...] The third server
# would call bind with the willcard as the local IP address and a local port
# of 80. Again, SO_REUSEADDR is required for the final call to succeed.

Or sous Linux (2.6.21.4, pour les tests les plus détaillés), ça ne marche
pas. Par exemple, si je lance en parallèle :
[...]


socket(7) sur une debian:

SO_REUSEADDR
Indicates that the rules used in validating
addresses supplied in a bind(2) call should allow
reuse of local addresses. For PF_INET sockets
this means that a socket may bind, except when
there is an active listening socket bound to the
address. When the listening socket is bound to
INADDR_ANY with a specific port then it is not
possible to bind to this port for any local
address.

--
Stéphane

Nicolas George
Le #756307
Stephane Chazelas wrote in message
socket(7) sur une debian:


Bien vu, j'avais oublié de regarder là. Donc c'est Linux qui fait n'importe
quoi, et en plus il le fait exprès. Génial.

Cyrille Lefevre
Le #756304
Stephane Chazelas wrote in message
socket(7) sur une debian:


Bien vu, j'avais oublié de regarder là. Donc c'est Linux qui fait n'importe
quoi, et en plus il le fait exprès. Génial.


non, ce n'est pas linux (quoique :)

il me semble normal que tu ne puisses pas te binder sur INADDR_ANY
et qqc d'autre en même temps sur le même port. comme il est aussi
tout à fait normal de pouvoir ce binder sur le même port sur des
adresses différentes sur un même serveur.

Regards, Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.
remove "%nospam" and ".invalid" to answer me.


Nicolas George
Le #756303
Cyrille Lefevre wrote in message
il me semble normal que tu ne puisses pas te binder sur INADDR_ANY
et qqc d'autre en même temps sur le même port.


Pourquoi ? Au contraire, c'est une fonctionnalité tout à fait souhaitable :
un ou plusieurs serveurs sur des adresses particulières, et un autre qui
récupère le reste, c'est quelque chose de tout à fait naturel.

D'autre part, comme je le mentionne dans mon message original, ce
comportement est historiquement permis sous Unix.

Stephane Chazelas
Le #756302
2007-07-12, 21:34(+00), Nicolas George:
Cyrille Lefevre wrote in message
il me semble normal que tu ne puisses pas te binder sur INADDR_ANY
et qqc d'autre en même temps sur le même port.


Pourquoi ? Au contraire, c'est une fonctionnalité tout à fait souhaitable :
un ou plusieurs serveurs sur des adresses particulières, et un autre qui
récupère le reste, c'est quelque chose de tout à fait naturel.

D'autre part, comme je le mentionne dans mon message original, ce
comportement est historiquement permis sous Unix.


C'est permis au moins sous HPUX et Solaris.

Cela dit, je trouve ca un peu douteux. Ca veut dire que
quelqu'un peut piquer le port de quelqu'un d'autre pour peu que
ce quelqu'un d'autre a fait un bind sur INADDR_ANY avec
SO_REUSEADDR.

--
Stéphane


Nicolas George
Le #756301
Stephane Chazelas wrote in message
Cela dit, je trouve ca un peu douteux. Ca veut dire que
quelqu'un peut piquer le port de quelqu'un d'autre pour peu que
ce quelqu'un d'autre a fait un bind sur INADDR_ANY avec
SO_REUSEADDR.


De toutes façons, compter sur l'allocation des ports non-privilégier, c'est
forcément non-fiable.

Stephane Chazelas
Le #756300
2007-07-12, 22:08(+00), Nicolas George:
Stephane Chazelas wrote in message
Cela dit, je trouve ca un peu douteux. Ca veut dire que
quelqu'un peut piquer le port de quelqu'un d'autre pour peu que
ce quelqu'un d'autre a fait un bind sur INADDR_ANY avec
SO_REUSEADDR.


De toutes façons, compter sur l'allocation des ports non-privilégier, c'est
forcément non-fiable.


Comme 6000, 1080... ?

Je viens de verifier, sous Solaris 7 au moins, il y a pas mal de
ports que je peux masquer de la sorte.

--
Stéphane


Olivier Miakinen
Le #756298

D'autre part, comme je le mentionne dans mon message original, ce
comportement est historiquement permis sous Unix.


C'est permis au moins sous HPUX et Solaris.


Je le faisais déjà en 1990 sur Unix SCO, et HPUX, et depuis longtemps
sur Solaris et AIX, pour étendre la MIB d'agents SNMP dont nous n'avions
pas le code source. D'ailleurs le code TCP/IP dans le noyau prévoyait
spécifiquement ce cas en comptant le nombre de « wildcards » utilisés
pour résoudre l'adresse.

Cela dit, je trouve ca un peu douteux. Ca veut dire que
quelqu'un peut piquer le port de quelqu'un d'autre pour peu que
ce quelqu'un d'autre a fait un bind sur INADDR_ANY avec
SO_REUSEADDR.


Oui. Dans le cas de SNMP (port 161) il fallait quand même être root
pour pouvoir faire le bind(). Je ne sais pas si ce setsockopt réclame
lui-même les droits de root lorsque le bind ne l'exige pas.


Stephane Chazelas
Le #755991
2007-07-14, 01:11(+02), Olivier Miakinen:
[...]
Cela dit, je trouve ca un peu douteux. Ca veut dire que
quelqu'un peut piquer le port de quelqu'un d'autre pour peu que
ce quelqu'un d'autre a fait un bind sur INADDR_ANY avec
SO_REUSEADDR.


Oui. Dans le cas de SNMP (port 161) il fallait quand même être root
pour pouvoir faire le bind(). Je ne sais pas si ce setsockopt réclame
lui-même les droits de root lorsque le bind ne l'exige pas.


C'est probablement parce que 161 est un port privilégié (< 1024).

En l'occurrence, sous Solaris 7, je n'ai meme pas l'impression
qu'il soit necessaire que celui qui bind sur INADDR_ANY le fasse
avec SO_REUSEADDR.

Ca me semble un immense trou de securité, vu que je peux
m'intercaller au beau milieu d'une session X de quelqu'un
d'autre par exemple. Je ne sais pas si ca a ete fixé dans les
versions ulterieures.

Le comportement de Linux me semble plus sain.

--
Stéphane


Nicolas George
Le #755990
Stephane Chazelas wrote in message
Ca me semble un immense trou de securité, vu que je peux
m'intercaller au beau milieu d'une session X de quelqu'un
d'autre par exemple.


À condition qu'il utilise une socket INET et pas une socket locale, ce qui
devient de plus en plus rare de nos jours.

Je ne sais pas si ca a ete fixé dans les
versions ulterieures.


s/fixé/corrigé/

Publicité
Poster une réponse
Anonyme