2010-06-05 18 views
1

J'appelle :: connect() sur un port d'application spéciale dans mon application et il fonctionne très bien en général, cependant, entre deux machines particulières, de l'un à l'autre, il échoue avec EHOSTUNREACH qui signifie « Pas de route pour accueillir. "Pourquoi est-ce que :: connect() retourne EHOSTUNREACH quand ssh fonctionne correctement?

Si je peux ssh sur le port 22 sans problème, ce qui pourrait se passer ici que :: connect() échoue toujours pour cette paire de machine particulière?

ssh Exécution des rendements en mode verbose:

[localMachine ~] ssh -v -p 22 remoteMachine 
OpenSSH_3.9p1, OpenSSL 0.9.7a Feb 19 2003 
debug1: Reading configuration data /etc/ssh/ssh_config 
debug1: Applying options for * 
debug1: Connecting to remoteMachine [10.34.49.107] port 22. 
debug1: Connection established. 
debug1: identity file /home/WilliamKF/.ssh/identity type -1 
debug1: identity file /home/WilliamKF/.ssh/id_rsa type 1 
debug1: identity file /home/WilliamKF/.ssh/id_dsa type -1 
debug1: Remote protocol version 2.0, remote software version OpenSSH_4.3 
debug1: match: OpenSSH_4.3 pat OpenSSH* 
debug1: Enabling compatibility mode for protocol 2.0 
debug1: Local version string SSH-2.0-OpenSSH_3.9p1 
debug1: SSH2_MSG_KEXINIT sent 
debug1: SSH2_MSG_KEXINIT received 
debug1: kex: server->client aes128-cbc hmac-md5 none 
debug1: kex: client->server aes128-cbc hmac-md5 none 
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent 
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP 
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent 
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY 
debug1: Host 'remoteMachine' is known and matches the RSA host key. 
debug1: Found key in /home/WilliamKF/.ssh/known_hosts:47 
debug1: ssh_rsa_verify: signature correct 
debug1: SSH2_MSG_NEWKEYS sent 
debug1: expecting SSH2_MSG_NEWKEYS 
debug1: SSH2_MSG_NEWKEYS received 
debug1: SSH2_MSG_SERVICE_REQUEST sent 
debug1: SSH2_MSG_SERVICE_ACCEPT received 
debug1: Authentications that can continue: publickey,gssapi-with-mic,password 
debug1: Next authentication method: gssapi-with-mic 
debug1: Authentications that can continue: publickey,gssapi-with-mic,password 
debug1: Authentications that can continue: publickey,gssapi-with-mic,password 
debug1: Next authentication method: publickey 
debug1: Trying private key: /home/WilliamKF/.ssh/identity 
debug1: Offering public key: /home/WilliamKF/.ssh/id_rsa 
debug1: Server accepts key: pkalg ssh-rsa blen 149 
debug1: read PEM private key done: type RSA 
debug1: Authentication succeeded (publickey). 
debug1: channel 0: new [client-session] 
debug1: Entering interactive session. 

est ici la fonction du côté client:

void // virtual 
Sender::connectTCP() 
{ 
    // First build the feedback channel's socket & make it reuseable 
    // so we don't get the nasty message. 
    if (0 > (setFbSocket(socket(AF_INET, SOCK_STREAM, 0)))) { 
    THROW_ERR("failed to create the command socket: "); 
    } 

    setSocketOptions(); 

    // Build the localIp address and bind it to the feedback socket. 
    // Although it's not traditional for a client to bind the sending socket 
    // to a the local address, we do it to prevent connect() from using an 
    // ephemeral port which (our site's firewall may block). Also build the 
    // remoteIp address. 
    buildAddr(getTCPcommandLocalAddr(), getLocalHost().c_str(), 
      getLocFbPort()); 
    deepBind(getFbSocket(), getTCPcommandLocalAddr()); 
    buildAddr(getTCPcommandRemoteAddr(), getRemoteHost().c_str(), 
      getRemFbPort()); 

    // Connect to the receiver at the remote addr. Make multiple attempts 
    // when we get a connection refused errno (ECONNREFUSED). ECONNREFUSED 
    // means no one is listening at the other end ... which my be the result 
    // of a race condition (i.e., we're calling connect before the server has 
    // gotten to listen.) 
    const int timeoutMinutes = 5; 
    const int timeoutSeconds = timeoutMinutes * 60; 
    int conCount = timeoutSeconds; 

    while ((conCount > 0) && 
     (0 > ::connect(getFbSocket(), 
         (sockaddr*)&getTCPcommandRemoteAddr(), 
         sizeof(sockaddr)))) { 
    switch (errno) { 
     case ECONNREFUSED: { 
     ::sleep(1); 
     --conCount; 
     // Warn every 15 seconds, but don't warn at 5 minutes exactly. 
     if ((conCount % 15) == 0 && conCount) { 
      clog << "Warning: The server connection" 
       << " has been refused for " 
       << timeFromSeconds(timeoutSeconds - conCount) 
       << ", will continue to retry for up to " 
       << timeoutMinutes << " minutes.\n" 
       << "Perhaps ports " << getRemFbPort() << " and " 
       << getRemDataPort() 
       << 
      " are not being routed properly to the server or alternatively " 
      "perhaps nothing on the server is listening to those ports?\n"; 
     } 
     continue; 
     } 
     case EHOSTUNREACH: { 
     clog << "Error: Command connect failed: No route to host '" 
      << getRemoteHost() << "'." << endl; 
     throw; 
     } 
     default: { 
     clog << "Error: Command connect failed: " 
      << strerror(errno) << endl; 
     throw; 
     } 
    } 
    } 
    if (conCount == 0) { 
    clog << "Error: Command connect" 
     << " continually refused after retrying for " << timeoutMinutes 
     << " minutes: " 
     << strerror(errno) << endl; 

    throw; 
    } 

    setCmdBlocking(); 
    setDataBlocking(); 
    setFbIsConn(true); 

    clog << "Application has connected to " 
     << getRemoteHost() << ":" << getRemFbPort() << endl; 
} 
+0

-t-il fonctionner pour d'autres machines? Vous avez un code à poster? –

+0

Oui, cela fonctionne pour toutes les autres machines. – WilliamKF

Répondre

4

Pourriez-vous être en cours d'exécution dans un filtrage pare-feu sur le port de destination? Essayez-vous une connexion au port 22 ou au port sur lequel sshd s'exécute; ou un autre port?

+0

D'abord, il se connecte via ssh sur le port 22, où il négocie le port pour lequel :: connect() est appelé. – WilliamKF

+0

Le port de destination était bloqué par un pare-feu pour le serveur distant. – WilliamKF

+0

Sucrée; content que tu l'aies trouvé. :) Je l'ai deviné parce que j'associe "hôte inaccessible" et "réseau inaccessible" avec des pare-feu ces jours-ci. –

0

Quelque chose d'étrange avec une résolution de nom? (Pourriez-vous être se trébuché par un fichier hosts? Par un AAAA (IPv6) enregistrement dans le DNS qui ne tient pas compte ssh? Ssh_config?) Peut-être ssh actif utile en mode verbose pour voir ce que l'hôte il est la connexion à.

1

Il semble que vous la fin du client liant explicitement de la prise - si l'adresse que vous liant à se trouve être inaccessible dans la zone de serveur (par exemple en raison d'un problème de routage). Pour être en mesure de dire cela d'un problème de pare-feu potentiel (ce qui permet par exemple le pare-feu le port 22, mais reniant votre port d'application), essayez de telnet à l'hôte cible: port plutôt que-ment ssh sur le port 22.

+0

Telnet vers le port sur lequel la connexion échoue obtient également le message «Aucune route vers l'hôte». Erreur. – WilliamKF