2015-06-22 19 views
6

Tôi gặp sự cố đó là bối rối tôi.PHP Telnet/SSH động đăng nhập

Tôi đang cố gắng để tự động đăng nhập CLI để một router và chạy một số lệnh thu được thông qua một trang web. Tuy nhiên tôi không biết nếu router có bật telnet hoặc SSH (có thể là một, cái kia hoặc cả hai) và tôi có danh sách các combo tên người dùng/mật khẩu có thể mà tôi cần truy cập.
Oh, và tôi không thể thay đổi một trong hai loại giao thức hoặc các chứng chỉ trên thiết bị, vì vậy đó là không thực sự là một lựa chọn.

Tôi có thể tìm cách đăng nhập vào router bằng giao thức đã biết và thông tin xác thực đăng nhập và chạy các lệnh cần thiết (bao gồm bên dưới), nhưng tôi không biết mình có nên sử dụng khối if/else hay không thông qua các quyết định telnet/ssh, hoặc nếu một tuyên bố chuyển đổi có thể tốt hơn? Sử dụng Expect bên trong PHP có phải là cách dễ dàng hơn không?

function tunnelRun($commands,$user,$pass, $yubi){ 
    $cpeIP = "1.2.3.4"; 
    $commands_explode = explode("\n", $commands); 

    $screenOut = ""; 

    $ssh = new Net_SSH2('router_jumphost'); 
    if (!$ssh->login($user, $pass . $yubi)) { 
     exit('Login Failed'); 
    } 


    $ssh->setTimeout(2); 
    $ssh->write("ssh -l username $cpeIP\n"); 
    $ssh->read("assword:"); 
    $ssh->write("password\n"); 
    $ssh->read("#"); 
    $ssh->write("\n"); 
    $cpePrompt = $ssh->read('/.*[#|>]/', NET_SSH2_READ_REGEX); 
    $cpePrompt = str_replace("\n", '', trim($cpePrompt)); 
    $ssh->write("config t\n"); 


    foreach ($commands_explode as $i) { 
     $ssh->write("$i\n"); // note the "\n" 
     $ssh->setTimeout(2); 
     $screenOut .= $ssh->read(); 

    } 
    $ssh->write("end\n"); 
    $ssh->read($cpePrompt); 
    $ssh->write("exit\n"); 
    echo "Router Update completed! Results below:<br><br>"; 

    echo "<div id=\"text_out\"><textarea style=\" border:none; width: 700px;\" rows=\"20\">".$screenOut."</textarea></div>"; 

Cập nhật:

Các giải pháp tôi đã đi với là một vòng lặp while/switch. Tôi đã đi con đường Mong đợi, nhưng tôi vẫn tiếp tục gặp vấn đề về việc nhận mô-đun Mong đợi tích hợp vào PHP trên máy chủ của tôi (hộp Windows.) Nếu tôi đã sử dụng máy chủ Unix/Linux Mong đợi sẽ là cách đơn giản nhất để đạt được điều này . Tôi chỉ làm cho nó thành một bản demo làm việc cho bây giờ, vì vậy có rất nhiều biến thể mất tích từ báo cáo trường hợp vẫn còn, và lỗi xử lý vẫn cần BEF đã tìm ra, nhưng ý tưởng cơ bản là ở đó. Tôi vẫn muốn di chuyển các câu lệnh preg_match xung quanh nhiều hơn một chút để thực hiện khớp ở đầu vòng lặp while (vì vậy tôi không spam toàn bộ trường hợp với các dòng preg_match khác nhau), nhưng điều đó có thể chứng minh được nhiều công việc hơn tôi muốn bây giờ. Hy vọng điều này có thể giúp người khác cố gắng làm như vậy!

<?php 
include('Net/SSH2.php'); 
define('NET_SSH2_LOGGING', NET_SSH2_LOG_COMPLEX); 
ini_set('display_errors', 1); 

$conn = new Net_SSH2('somewhere.outthere.com'); 
if (!$conn->login($user, $pass . $yubi)) { 
    exit('Login Failed'); 
} 

$prompt = "Testing#"; 

$conn->setTimeout(2); 
$conn->write("PS1=\"$prompt\""); 
$conn->read(); 
$conn->write("\n"); 
$screenOut = $conn->read(); 

//echo "$screenOut is set on the shell<br><br>"; 
echo $login_db[3][0]. " ". $login_db[3][1]; 

$logged_in = false; 
$status = "SSH"; 
$status_prev = ""; 
$login_counter = 0; 
while (!$logged_in && $login_counter <=3) { 
    switch ($status) { 

     case "Telnet": 
      break; 
     case "SSH": 
      $conn->write("\n"); 
      $conn->write("ssh -l " . $login_db[$login_counter][0] . " $cpeIP\n"); 
      $status_prev = $status; 
      $status = $conn->read('/\n([.*])$/', NET_SSH2_READ_REGEX); 
      break; 
     case (preg_match('/Permission denied.*/', $status) ? true : false): 
      $conn->write(chr(3)); //Sends Ctrl+C 
      $status = $conn->read(); 
      if (strstr($status, "Testing#")) { 
       $status = "SSH"; 
       $login_counter++; 
       break; 
      } else { 
       break 2; 
      } 
     case (preg_match('/[pP]assword:/', $status) ? true : false): 

      $conn->write($login_db[$login_counter][1] . "\n"); 
      $status_prev = $status; 
      $status = $conn->read('/\n([.*])$/', NET_SSH2_READ_REGEX); 
      break; 
     case (preg_match('/yes\/no/', $status) ? true : false): 
      $conn->write("yes\n"); 
      $status_prev = $status; 
      $status = $conn->read('/\n([.*])$/', NET_SSH2_READ_REGEX); 
      break; 
     case (preg_match('/(^[a-zA-Z0-9_]+[#]$)|(>)/', $status,$matches) ? true : false): 


      $conn->write("show version\n"); 
      $status = $conn->read(">"); 
      if(preg_match('/ADTRAN|Adtran|Cisco/', $status)? true:false){ 
       $logged_in = true; 
       break; 
      } 

     default: 
      echo "<br>Something done messed up! Exiting"; 
      break 2; 

    } 
    //echo "<pre>" . $conn->getLog() . "</pre>"; 
} 
if ($logged_in === true) { 
    echo "<br> Made it out of the While loop cleanly"; 
} else { 
    echo "<br> Made it out of the While loop, but not cleanly"; 
} 
echo "<pre>" . $conn->getLog() . "</pre>"; 

$conn->disconnect(); 
echo "disconnected cleanly"; 
} 
?> 
+0

'khối if'-'else' và' switch'-'case' khối hầu như giống nhau. –

Trả lời

3

Nếu câu lệnh có thể làm cho mã của bạn trở nên không đọc được.
Trong trường hợp đó tôi sẽ đề nghị bạn sử dụng các khối chuyển đổi hợp cụ thể,
kể từ trường hợp chuyển đổi sẽ cho phép bạn viết mã rõ ràng hơn, và sẽ cho phép bạn để bắt các giá trị đặc biệt hiệu quả hơn.

Sử dụng Expect trong php rất đơn giản:

<?php> 
ini_set("expect.loguser", "Off"); 

$stream = fopen("expect://ssh [email protected] uptime", "r"); 

$cases = array (
    array (0 => "password:", 1 => PASSWORD) 
); 

switch (expect_expectl ($stream, $cases)) { 
    case PASSWORD: 
     fwrite ($stream, "password\n"); 
     break; 
    default: 
     die ("Error was occurred while connecting to the remote host!\n"); 
} 

while ($line = fgets($stream)) { 
     print $line; 
} 
fclose ($stream); 

?> 
+0

Đoạn mã trên trông rất thanh lịch, nhưng bạn đang viết một luồng bạn đã mở dưới dạng chỉ đọc. Để đọc và viết yêu cầu proc_open để gọi thời gian chạy chắc chắn? – symcbean

+0

Thật vậy. proc_open - Thực thi lệnh và mở con trỏ tệp cho đầu vào/đầu ra (được lấy từ: http://php.net/manual/en/function.proc-open.php) –

0

Có một số biến chứng bằng cách sử dụng mong đợi file_wrapper. Nếu đó là tôi, tôi chỉ cần đi cho một kết nối ổ cắm đơn giản cho telnet và thăm dò ý kiến ​​cho các lời nhắc (với một thời gian chờ) nếu kết nối ssh thất bại.

Khi kiểm tra thông thường, telnet client here có vẻ được viết hợp lý - và với một chút đổi tên có thể cung cấp giao diện giống như phần mở rộng máy khách ssh2 (ngoài bit kết nối).

Các vấn đề liên quan