2012-05-18 5 views
2

J'ai besoin de telnet à Cisco commutateur en utilisant php et exécuter show interface status commande et obtenir des résultats. J'ai essayé quelques classes php trouvées sur internet mais aucune d'entre elles ne pouvait se connecter à un périphérique. J'ai donc essayé d'écrire le script moi-même, mais j'ai le même problème, je ne peux pas me connecter à l'appareil.Telnet à Cisco passer en utilisant php

L'hôte envoie un message de bannière, puis une nouvelle ligne avec username:. J'envoie mon nom d'utilisateur avec \r\n, attendez un certain temps et essaie de lire les données, mais il me semble que l'hôte ignore simplement mes nouveaux caractères de ligne. C'est la réponse que je suis arrivé (explode ('\ n') sur la réponse):

Array 
(
    [0] => % 
    [1] => User Access Verification 
    [2] => Username: timeout expired! 
) 

Pourquoi ne pas que je RECEVEZ mot de passe? Je l'ai essayé avec l'envoi d'en-têtes telnet, et sans, pas de changement. Est-ce que quelqu'un peut m'aider s'il vous plait?

Voici mon code

<? 
$host = "switchName"; 
$name = "name"; 
$pass = "pass"; 
$port = 23; 
$timeOut = 15; 
$connected = false; 
$skipNullLines = true; 
$timeout = 125000; 


$header1=chr(0xFF).chr(0xFB).chr(0x1F).chr(0xFF).chr(0xFB).chr(0x20).chr(0xFF).chr(0xFB).chr(0x18).chr(0xFF).chr(0xFB).chr(0x27).chr(0xFF).chr(0xFD).chr(0x01).chr(0xFF).chr(0xFB).chr(0x03).chr(0xFF).chr(0xFD).chr(0x03).chr(0xFF).chr(0xFC).chr(0x23).chr(0xFF).chr(0xFC).chr(0x24).chr(0xFF).chr(0xFA).chr(0x1F).chr(0x00).chr(0x50).chr(0x00).chr(0x18).chr(0xFF).chr(0xF0).chr(0xFF).chr(0xFA).chr(0x20).chr(0x00).chr(0x33).chr(0x38).chr(0x34).chr(0x30).chr(0x30).chr(0x2C).chr(0x33).chr(0x38).chr(0x34).chr(0x30).chr(0x30).chr(0xFF).chr(0xF0).chr(0xFF).chr(0xFA).chr(0x27).chr(0x00).chr(0xFF).chr(0xF0).chr(0xFF).chr(0xFA).chr(0x18).chr(0x00).chr(0x41).chr(0x4E).chr(0x53).chr(0x49).chr(0xFF).chr(0xF0); 
$header2=chr(0xFF).chr(0xFC).chr(0x01).chr(0xFF).chr(0xFC).chr(0x22).chr(0xFF).chr(0xFE).chr(0x05).chr(0xFF).chr(0xFC).chr(0x21); 


function read_string() 
{ 
    global $fw,$host,$skipNullLines; 
    $string = ""; 

    while(!feof($fw)) 
    { 
     $read = fgets($fw); 

     $string .= $read; 

     // Probably prompt, stop reading 
     if(strpos($read, ':') !== FALSE || strpos($read, '> (enable)') !== FALSE || strpos($read, $host.'#') !== FALSE) 
     { break; } 
    } 

    $string = explode("\n", $string); 

    // Get rid of null lines 
    $ret = array(); 
    for($i = 0; $i<count($string); $i++) 
    { 
     if(trim($string[$i]) == '' && $skipNullLines) continue; 

     $ret[] = $string[$i]; 
    } 

    return $ret; 
} 

function send_string($string, $force=false) 
{ 
    GLOBAL $timeout,$fw; 
    $string = trim($string); 

    // execute only strings that are preceded by "show" (if not forced) 
    if(!$force && strpos($string, 'show ') !== 0) 
    { 
     return 1; 
    } 

    fputs($fw, $string."\r\n"); 
    echo("SEND:".$string."\r\n"); 
    usleep($timeout); 
} 


$fw = fsockopen($host, $port, $errno, $errorstr, $timeOut);  
if($fw == false) 
{ 
    echo("Cant connect"); 
} 
else 
{ 
    echo("Connected<br>"); 
    $connected = true; 

    stream_set_timeout($fw, $timeout); 

// fputs($fw, $header1); 
// usleep($timeout); 
// fputs($fw, $header2); 
// usleep($timeout); 
    print_r(read_string()); 
    send_string("test", true); 
    print_r(read_string()); 
} 

fclose($fw); 
?> 

MISE À JOUR Si je vous envoie le nom d'utilisateur d'abord, puis je lis, je reçois l'invite de mot de passe. Je ne comprends pas, pourquoi je ne peux pas lire d'abord les messages de l'hôte, puis envoyer ma réponse. La façon dont cela fonctionne pour moi maintenant (envoyer la réponse, puis lire pour invite) est aucun sens! (et j'ai toujours l'événement de message "% Authentication failed." avec le mot de passe/nom de droite).

... 
$connected = true; 
stream_set_timeout($fw, $timeout); 
send_string("name", true); 
send_string("password", true); 
print_r(read_string()); 
... 

Répondre

4

Ok, donc je ne sais pas quel était le problème, mais après des tests « peu » j'ai pu écrire cette classe qui fonctionne pour moi. Je ne sais pas pourquoi d'autres classes de telnet ne fonctionnent pas bien qu'elles font à peu près la même chose. Donc, si quelqu'un aura le même problème, vous pouvez essayer ceci:

class TELNET 
{ 
    private $host; 
    private $name; 
    private $pass; 
    private $port; 
    private $connected; 
    private $connect_timeout; 
    private $stream_timetout; 

    private $socket; 

    public function TELNET() 
    { 
    $this->port = 23; 
    $this->connected = false;   // connected? 
    $this->connect_timeout = 10;  // timeout while asking for connection 
    $this->stream_timeout = 380000; // timeout between I/O operations 
    } 

    public function __destruct() 
    { 
    if($this->connected) { fclose($this->socket); } 
    } 

    // Connects to host 
    // @$_host - addres (or hostname) of host 
    // @$_user - name of user to log in as 
    // [email protected]_pass - password of user 
    // 
    // Return: TRUE on success, other way function will return error string got by fsockopen() 
    public function Connect($_host, $_user, $_pass) 
    { 
    // If connected successfully 
    if(($this->socket = @fsockopen($_host, $this->port, $errno, $errorstr, $this->connect_timeout)) !== FALSE) 
    { 
     $this->host = $_host; 
     $this->user = $_user; 
     $this->pass = $_pass; 

     $this->connected = true; 

     stream_set_timeout($this->socket, 0, 380000); 
     stream_set_blocking($this->socket, 1); 

     return true; 
    } 
    // else if coulnt connect 
    else return $errorstr; 
    } 


    // LogIn to host 
    // 
    // RETURN: will return true on success, other way returns false 
    public function LogIn() 
    { 
    if(!$this->connected) return false; 

    // Send name and password 
    $this->SendString($this->user, true); 
    $this->SendString($this->pass, true); 

    // read answer 
    $data = $this->ReadTo(array('#')); 

    // did we get the prompt from host? 
    if(strtolower(trim($data[count($data)-1])) == strtolower($this->host).'#') return true; 
    else return false; 
    } 


    // Function will execute command on host and returns output 
    // 
    // @$_command - command to be executed, only commands beginning with "show " can be executed, you can change this by adding 
    //    "true" (bool type) as the second argument for function SendString($command) inside this function (3rd line) 
    // 
    function GetOutputOf($_command) 
    { 
    if(!$this->connected) return false; 

    $this->SendString($_command); 

    $output = array(); 
    $work = true; 

    // 
    // Read whole output 
    // 
    // read_to(array(STRINGS)), STRINGS are meant as possible endings of outputs 
    while($work && $data = $this->ReadTo(array("--More--","#"))) 
    { 
     // CHeck wheter we actually did read any data 
     $null_data = true; 
     foreach($data as $line) 
     { 
     if(trim($line) != "") {$null_data = false;break;} 
     } 
     if($null_data) { break;} 

     // if device is paging output, send space to get rest 
     if(trim($data[count($data)-1]) == '--More--') 
     { 
     // delete line with prompt (or "--More--") 
     unset($data[count($data)-1]); 

     // if second line is blank, delete it 
     if(trim($data[1]) == '') unset($data[1]); 
     // If first line contains send command, delete it 
     if(strpos($data[0], $_command)!==FALSE) unset($data[0]); 

     // send space 
     fputs($this->socket, " "); 
     } 

     // ak ma vystup max dva riadky 
     // alebo sme uz nacitali prompt 
     // IF we got prompt (line ending with #) 
     // OR string that we've read has only one line 
     // THEN we reached end of data and stop reading 
     if(strpos($data[count($data)-1], '#')!==FALSE /* || (count($data) == 1 && $data[0] == "")*/ ) 
     { 
     // delete line with prompt 
     unset($data[count($data)-1]); 

     // if second line is blank, delete it 
     if(trim($data[1]) == '') unset($data[1]); 
     // If first line contains send command, delete it 
     if(strpos($data[0], $_command)!==FALSE) unset($data[0]); 

     // stop while cyclus 
     $work = false; 
     } 

     // get rid of empty lines at the end 
     for($i = count($data)-1; $i>0; $i--) 
     { 
     if(trim($data[$i]) == "") unset($data[$i]); 
     else break; 
     } 

     // add new data to $output 
     foreach($data as $v) 
     { $output[] = $v; } 
    } 

    // return output 
    return $output; 
    } 


    // Read from host until occurence of any index from $array_of_stops 
    // @array_of_stops - array that contains strings of texts that may be at the end of output 
    // RETURNS: output of command as array of lines 
    function ReadTo($array_of_stops) 
    { 
    $ret = array(); 
    $max_empty_lines = 3; 
    $count_empty_lines = 0; 

    while(!feof($this->socket)) 
    { 
     $read = fgets($this->socket); 
     $ret[] = $read; 

     // 
     // Stop reading after (int)"$max_empty_lines" empty lines 
    // 
     if(trim($read) == "") 
     { 
     if($count_empty_lines++ > $max_empty_lines) break; 
     } 
     else $count_empty_lines = 0; 

     // 
     // Does last line of readed data contain any of "Stop" strings ?? 
     $found = false; 
     foreach($array_of_stops AS $stop) 
     { 
     if(strpos($read, $stop) !== FALSE) { $found = true; break; } 
     } 
     // If so, stop reading 
     if($found) break; 
    } 

    return $ret; 
    } 



    // Send string to host 
    // If force is set to false (default), function sends to host only strings that begins with "show " 
    // 
    // @$string - command to be executed 
    // @$force - force command? Execute if not preceeded by "show " ? 
    // @$newLine - append character of new line at the end of command? 
    function SendString($string, $force=false, $newLine=true) 
    { 
    $t1 = microtime(true); 
    $string = trim($string); 

    // execute only strings that are preceded by "show" 
    // and execute only one command (no new line characters) ! 
    if(!$force && strpos($string, 'show ') !== 0 && count(explode("\n", $string)) == 1) 
    { 
     return 1; 
    } 


    if($newLine) $string .= "\n"; 
    fputs($this->socket, $string); 

    $t2 = microtime(true); 
    } 

} 


// EXAMPLE 
$host = "hostname"; 
$name = "username"; 
$pass = "password"; 


$t = new TELNET(); 
echo("CONNECT:".$t->Connect($host, $name, $pass)."<br>"); 
echo("LOGIN:".(int)$t->LogIn()); 
echo("<br>OUTPUT:<br>"); 
print_r($t->GetOutputOf("show snmp")); 
print_r($t->GetOutputOf("show users")); 
print_r($t->GetOutputOf("show interface status")); 

PS: mes périphériques Prompt est « nom d'hôte # », de sorte que vous devrez peut-être modifier la fonction de connexion pour faire ce travail de code avec l'invite de votre appareil (donc vous pouvez avoir besoin de GetOutputOf())

Questions connexes