Domanda

Ho bisogno di Telnet allo switch Cisco utilizzando PHP ed eseguire il comando show interface status e ottenere risultati. Ho provato alcune classi PHP che ho trovato su internet ma nessuno di loro potrebbe connettersi al dispositivo. Quindi ho provato a scrivere la sceneggiatura da solo, ma ho lo stesso problema, non riesco a connettermi al dispositivo.

L'host mi invia messaggi banner e quindi nuova linea con username:. Mando il mio nome utente con \r\n, aspetta un po 'di tempo e cerca di leggere i dati, ma mi sembra che l'host stia semplicemente ignorando i miei personaggi di nuova linea. Questa è la risposta che ho ottenuto (esplodere ('\ n') in risposta):

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

Perché non ho ricevuto rapido password? L'ho provato con l'invio di intestazioni telnet, e senza, nessun cambiamento. Qualcuno può aiutarmi?

Ecco il mio codice

<?
$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);
?>
.

Aggiornamento Se invii il nome utente all'inizio, e poi ho letto, ricevo la richiesta della password. Non lo capisco, perché non riesco a leggere innanzitutto i messaggi dall'host e poi invia la mia risposta. Il modo in cui funziona ora (invia risposta e quindi leggere per prompt) non è il senso! (E ho ancora il "% di autenticazione non riuscito". Evento message con password / nome corretto).

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

È stato utile?

Soluzione

Okay, quindi non so quale fosse il problema, ma dopo "pochi" test sono stato in grado di scrivere questa classe che funziona per me.Non so perché altre lezioni di telnet non funzionano in altre cose che fanno praticamente lo stesso.Quindi se qualcuno avrà problemi simili, puoi provare questo:

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
  // $@_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: i miei dispositivi Prompt è "hostname #", quindi è possibile che sia necessario modificare la funzione di accesso per rendere questo codice con il prompt del tuo dispositivo (quindi potresti aver bisogno in getoutputof ())

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top