Question

Pyzor utilise UDP / IP comme protocole de communication. Nous avons récemment changé le serveur public à une nouvelle machine, et a commencé à recevoir des rapports de nombreux temps morts. J'ai découvert que je pouvais résoudre le problème si je changé l'adresse IP qui a été demandé de eth0:1 à eth0.

Je peux reproduire ce problème avec un exemple simple:

Ceci est le code du serveur:

#! /usr/bin/env python

import SocketServer

class RequestHandler(SocketServer.DatagramRequestHandler):
    def handle(self):
        print self.packet
        self.wfile.write("Pong")

s = SocketServer.UDPServer(("0.0.0.0", 24440), RequestHandler)
s.serve_forever()

Ceci est le code client (188.40.77.206 est eth0 188.40.77.236 est le même serveur, mais est eth0:1.):

>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.sendto('ping', 0, ("188.40.77.206", 24440))
4
>>> s.recvfrom(1024)
('Pong', ('188.40.77.206', 24440))
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.sendto('ping', 0, ("188.40.77.236", 24440))
4
>>> s.recvfrom(1024)
[never gets anything]

Le serveur reçoit le « ping » paquet dans les deux cas (paquet et envoie donc le « pong » dans les deux cas).

Bizarrement, cette fait le travail de certains endroits (à savoir que je vais obtenir une réponse à la fois IP). Par exemple, cela fonctionne à partir 188.40.37.137 (même réseau / centre de données, serveur différent), mais aussi de 89.18.189.160 (autre centre de données). Dans ces cas, la réponse recvfrom a le IP eth0, plutôt que celui qui a été connecté.

Est-ce juste une règle de UDP? Est-ce un problème / limitation de la classe Python UDPServer? Est-ce quelque chose que je fais mal? Est-il possible que je puisse avoir ce travail en dehors d'une simple connexion à l'adresse IP de eth0 (ou l'écoute sur l'adresse IP spécifique plutôt que 0.0.0.0)?

Était-ce utile?

La solution

Je suis tombé sur ce avec un serveur TFTP. Mon serveur avait deux adresses IP face au même réseau. Comme UDP est sans connexion, il peut y avoir des problèmes avec les adresses IP ne sont pas définies comme prévu dans cette situation. La séquence que j'avais été:

  1. Le client envoie le paquet initial au serveur à une adresse IP particulière
  2. Server lit l'adresse source du client à partir du paquet entrant et envoie une réponse.
    1. Cependant, dans la réponse, est définie en fonction des tables de routage « Adresse source » du serveur, et il se prépare à la autre adresse IP.
    2. Il n'a pas été possible de contrôler l'adresse IP « source » du serveur, car le système d'exploitation ne nous dit pas quelle adresse IP la demande est arrivée par.
  3. Le client obtient une réponse de l ' « autre » adresse IP et le rejette.

La solution dans mon cas était de lier spécifiquement le serveur TFTP à l'adresse IP que je voulais écouter, plutôt que de se lier à toutes les interfaces.

J'ai trouvé un texte qui peut être pertinent pour un homme Linux page pour tftpd (serveur TFTP). Ici, il est:

 Unfortunately, on multi-homed systems, it is impossible for tftpd to
 determine the address on which a packet was received. As a result, tftpd
 uses two different mechanisms to guess the best source address to use for
 replies. If the socket that inetd(8) passed to tftpd is bound to a par‐
 ticular address, tftpd uses that address for replies. Otherwise, tftpd
 uses ‘‘UDP connect’’ to let the kernel choose the reply address based on
 the destination of the replies and the routing tables. This means that
 most setups will work transparently, while in cases where the reply
 address must be fixed, the virtual hosting feature of inetd(8) can be
 used to ensure that replies go out from the correct address.  These con‐
 siderations are important, because most tftp clients will reject reply
 packets that appear to come from an unexpected address.

Voir cette réponse qui montre que sur Linux il est possible de lire l'adresse locale pour les paquets UDP entrants et mettez-le pour les paquets sortants. Il est possible en C; Je ne suis pas sûr de Python bien.

Autres conseils

  

Est-ce juste une règle de UDP?

Non.

  

Est-ce un problème / limitation de la   classe Python UDPServer?

Douteux.

  

Est-ce quelque chose que je fais mal?

Votre programme semble correct.

Il y a un certain nombre de raisons pour lesquelles la datagrammes ne se rend pas au serveur. UDP est donc votre client connexion envoie juste le ping loin dans l'éther sans savoir si quelqu'un reçoit.

Voyez si vous êtes autorisé à se lier à cette adresse. Il y a un grand petit programme appelé netcat qui fonctionne très bien pour l'accès réseau bas niveau. Ce n'est pas toujours disponible sur tous les systèmes, mais il est facile de télécharger et compiler.

nc -l -s 188.40.77.236 -p 24440 -u

Si vous exécutez votre programme client comme avant, vous devriez voir « Ping » imprimé sur votre terminal. (Vous pouvez taper Pong et le ramener à votre client. Il est un peu amusant de jouer avec.) Si vous obtenez le ping, les problèmes de réseau ne sont pas le problème et quelque chose ne va pas avec le programme serveur Python ou les bibliothèques. Si vous ne recevez pas le ping, vous ne pouvez pas faire la connexion. "Contactez votre administrateur réseau pour une assistance."

Les choses à vérifier comprendrait ...

  1. problèmes de pare-feu?
  2. Problèmes de configuration avec des interfaces réseau crénelage.
  3. problèmes d'autorisation de l'utilisateur.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top