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";
}
?>
'khối if'-'else' và' switch'-'case' khối hầu như giống nhau. –