php script to execute commands on Cisco router - php

I need to write a script to connect to a Cisco router and execute commands. The linux server and the Cisco router use ssh keys so no username/password are required. I have worked out how to make the connection, but I don't know how to issue the commands and read the responses.
Note: It has to be in php to integrate with some other stuff we have going on.
Here is what I have so far :-
<?php
$connection = ssh2_connect("n.n.n.n", 22, array("hostkey"=>"ssh-rsa"));
if(!$connection)
{
die("Could not connect to the Router \n\r");
exit();
}
if (ssh2_auth_none ($connection, "username"))
{
echo("Public Key Authentication Successful\n\r");
}
else
{
die("Public Key Authentication Failed");
exit();
}
// New commands based on help received
try
{
$command = "dir";
$stream = ssh2_exec($connection, $command);
// added to test if the ssh2_exec command returns false - which it does, issue is with the command ???
if(!$stream)
{
echo("Command returned False\n\r");
exit();
}
$errorStream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
stream_set_blocking($errorStream, true);
stream_set_blocking($stream, true);
$errorStreamContent = stream_get_contents($errorStream);
$streamContent = stream_get_contents($stream);
echo("ErrorStream : " . $errorStreamContent . "\n" . "Stream : " .
$streamContent . "\n\r");
}
catch(exception $e)
{
echo("Error : " . $e);
exit();
}
?>
Output is now as follows :-
Public Key Authentication Successful
Command returned False
Can anyone give me the correct way to issue commands and read any result ? Thanks.

I managed to fix this by using ssh2_auth_pubkey_file to pass the ssh keys to the router and authenticate. After that it works fine.

Related

Setup ProxyCommand and ProxyAgent in ssh2

I need to establish a connection to an remote ssh server (debug2) via php. Inside the console everything works fine for me, but I doesnt get my php code running. I get following errormessage:
ssh2_auth_pubkey_file(): Authentication failed for [Username] using public key: Callback returned error
How can I establish a proper connection to debug2 without an registration on this.example.com?
My current code look like this:
if (!function_exists("ssh2_connect")) die("function ssh2_connect doesn't exist" . PHP_EOL);
if(!($con = ssh2_connect("this.example.com", 22))){
echo "fail: unable to establish connection" . PHP_EOL;
} else {
if(!ssh2_auth_pubkey_file($con, "[Username]", $pubkeyfile, $privkeyfile)) {
echo "fail: unable to authenticate" . PHP_EOL;
//The point where the script fails
} else {
echo "okay: logged in..." . PHP_EOL;
$tunnel = ssh2_tunnel($con, 'xx.xx.xxx.17', 22);
if (!($stream = ssh2_exec($tunnel, "ls -al" ))) {
echo "fail: unable to execute command" . PHP_EOL;
} else {
stream_set_blocking($stream, true);
$data = "";
while ($buf = fread($stream,4096)) {
$data .= $buf;
}
fclose($stream);
}
}
}
My current ssh_config:
Host example
HostName this.example.com
User [Username]
ForwardAgent yes
IdentityFile ~/.ssh/id_rsa
Host debug2
ProxyCommand ssh exmaple -W xx.xx.xxx.17:22
User [otherusername2]
IdentityFile ~/.ssh/id_rsa

Shell commands in PHP does not execute on remote server

I have one problem. I write a script in PHP which connect to a remote server. The script copy a file and looks like this
<?php
$pubKey = "/path/to/public/key";
$privKey = "/path/to/private/key";
$srcFile = "/path/to/local/app.apk";
$dstFile = "/path/to/remote/app.apk";
$con = ssh2_connect("xxx.xxx.xx.xxx", "22", array("hostkey" => "ssh-rsa"));
if(ssh2_auth_pubkey_file($con, "user", $pubKey, $privKey, "pw"))
{
sftp = ssh2_sftp($con);
$sftpStream = fopen("ssh2.sftp://" . $sftp . $dstFile, "w");
try
{
if(!$sftpStream) throw new Exception("Could not open remote file: " . $dstFile);
$dataToSend = file_get_contents($srcFile);
if($dataToSend === false) throw new Exception("Could not open local file: " . $srcFile);
if(fwrite( $sftpStream, $dataToSend) === false) throw new Exception("Could not send data from file: " . $srcFile);
fclose($sftpStream);
$shell = ssh2_shell($con, "xterm");
fwrite($shell, "su system");
fwrite($con, "pm install -r " . $dstFile);
echo "passed through";
}
catch (Exception $e)
{
error_log("Exception: " . $e->getMessage());
fclose($sftpStream);
}
}
?>
The method ssh2_scp_send always failed so I tried it like this way and it works fine. The method ssh2_scp_send return an error like
PHP Warning: ssh2_scp_send(): Failed copying file in /srv/www/htdocs/index.php on line 10
and line 10 was the method. I have had the correct permission on the remote server and on my local pc.
I also tried something like this
ssh2_exec($con, "su system");
ssh2_exec($con, "pm install -r " . $dstFile);
I have tried to write the path to the app.apk manual too, but nothing works. It doesn't install the app on the remote server but it walks through my code because my website is displaying the message "passed through".
What can be the reason why the command does not executed on the shell on my remote server?

Is read() necessary before write() with SSH via PHPSecLib?

I have written a small script that issues a series of commands via write() to a linux machine, with a 5 second sleep() between each one. The exact same commands work when entered manually but despite being connected successfully, do not seem to work when used from a PHP script.
As this is the case, I am curious if using read() is absolutely necessary prior to issuing a write() command?
<?php
include('Net/SSH2.php');
$serverhostname = "IP_HERE";
$ssh_username = "root";
$ssh_password = "PASS_HERE";
// Establish new SSH2 Connection
$connection = new Net_SSH2($serverhostname, 22);
if($connection->login($ssh_username, $ssh_password))
{
echo "LOGGED IN! </br>";
sleep(5);
$result = $connection->write('en PASS_HERE\r\n');
echo "RESULT: " . $result . " </br>";
sleep(5);
$result = $connection->write('configure terminal\r\n');
echo "RESULT: " . $result . " </br>";
sleep(5);
$result = $connection->write('interface ve 110\r\n');
echo "RESULT: " . $result . " </br>";
sleep(5);
$result = $connection->write('port-name Test_Brett\r\n');
echo "RESULT: " . $result . " </br>";
}
else
{
echo "SSH Connection Failed. Check that the remote host is online and accepting connections!";
}
?>
UPDATE
$result = $connection->write('en PASS_HERE\n');
$result = $connection->write('configure terminal\n');
$result = $connection->write('interface ve 110\n');
$result = $connection->write('port-name Test_Brett\n');
$connection->setTimeout(5);
echo $connection->read();
I just did this:
$connection->write("ls -la\n");
$connection->write("pwd\n");
$connection->setTimeout(5);
echo $connection->read();
And it seemed to perform the commands just fine without a read() between the two write()'s. But it could be that a read() has to be done, even if just once, at the end.
What I'd do if I were you is, instead of doing sleep(5) do $connection->setTimeout(5); $connection->read();. You can throw away the return value of read(). If you knew what to expect back you could just do $connection->read('pattern'), which would be faster, but if you don't, I'd do the $connection->setTimeout(5); route just to be on the safe side.

Read the Pre-login ssh banner from PHP

I'm trying to use the libssh2-php library functions to connect to an ssh server from PHP. That's all great, but I can't figure out how to read the pre-login banner in PHP. The Pre-login banner is text displayed before SSH prompts for a login, and as far as I can tell I can't get a stream from the connection object.
So given this code, is there any way to do a read prior to logging in?
<?php
if (!function_exists("ssh2_connect")) die("function ssh2_connect doesn't exist");
// log in at server1.example.com on port 22
if(!($con = ssh2_connect("server1.example.com", 22))){
echo "fail: unable to establish connection\n";
} else {
//####### Would really like to get a stream right here to read pre-login banner
// try to authenticate with username root, password secretpassword
if(!ssh2_auth_password($con, "root", "secretpassword")) {
echo "fail: unable to authenticate\n";
} else {
// allright, we're in!
echo "okay: logged in...\n";
// execute a command
if (!($stream = ssh2_exec($con, "ls -al" ))) {
echo "fail: unable to execute command\n";
} else {
// collect returning data from command
stream_set_blocking($stream, true);
$data = "";
while ($buf = fread($stream,4096)) {
$data .= $buf;
}
fclose($stream);
}
}
}
?>
You can do this with phpseclib, a pure PHP SSH implementation. The banner should be obtainable by doing $ssh->getLastError() (returns a string) or $ssh->getErrors() (returns an array of strings).
Quoting the source of it:
// see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
if (($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) && !($this->bitmap & NET_SSH2_MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
$this->_string_shift($payload, 1);
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->errors[] = 'SSH_MSG_USERAUTH_BANNER: ' . utf8_decode($this->_string_shift($payload, $length));
$payload = $this->_get_binary_packet();
}
Update (after discussion):
Currently I see no way to do this in php except from implementing it on your own. Sending a feature request to developers of the ssh2 extension might be best way to start.
Original (stupid) answer:
The login banner will appear after the login

php ssh2_exec not executing 'su' command

I'm having lots of fun with ssh2 for php.(!)
I am testing by ssh-ing into localhost (running ubuntu). I have managed to connect and authenticate with my username( not root ), and some commands (like 'ls' return some info, which is promising. Definitely getting somewhere.
What I want to be able to do next is issue an 'su' command and then give the root password.
I don't get an error, and a resource is returned, but there seems to be no data in the stream. (I'm kind of expecting a 'Password:' prompt). I can't authenticate directly with the root password, because that is disabled for ssh.
Is there any reason why 'su' would return with some text, do you think?
Should I be expecting the 'Password:' prompt back?
Here's my code:
function changeServerPassword( $ip, $port, $sshUser, $sshPassword, $rootPassword, $newRootPassword, $newSSHPassword = false) {
// login to server using $sshUser and $sshPassword
// su as root and enter $rootPassword
// if any of the above steps fail, return with appropriate error message
if (!function_exists("ssh2_connect")) die("function ssh2_connect doesn't exist");
// log in
// Do I have to make sure that port is a number?
if(!($con = ssh2_connect($ip, $port))){
echo "fail: unable to establish connection\n";
} else {
// try to authenticate with username root, password secretpassword
if(!ssh2_auth_password($con, $sshUser, $sshPassword)) {
echo "fail: unable to authenticate\n";
} else {
// alright, we're in!
echo "okay: logged in...<br />";
//
if (!($stream = ssh2_exec($con, "su"))) {
echo "fail: unable to execute command\n";
} else {
echo $stream."<br />";
// collect returning data from command
stream_set_blocking($stream, true);
echo "after stream_set_blocking<br />";
$data = "";
while ($buf = fread($stream,4096)) {
$data .= $buf;
}
echo "data len: " . strlen($data) . "<br />";
echo $data."<br />";
fclose($stream);
}
}
}
}
borrowed from http://kevin.vanzonneveld.net/techblog/article/make_ssh_connections_with_php/
respect.
The output I get is:
okay: logged in...
Resource id #3
after stream_set_blocking
data len: 0
Thanks in advance for any help :)
Joe
You should try the latest SVN version of phpseclib - a pure PHP SSH implementation - instead. Here's how you'd do su with that:
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('localhost', 22);
$ssh->login('username', 'password');
$ssh->read('[prompt]');
$ssh->write("su - user\n");
$ssh->read('Password:');
$ssh->write("Password\n");
echo $ssh->read('[prompt]');
?>
Maybe try something like bash -c su or su root and bash -c "su root"?
All you have to do is append your superuser password at the moment you execute the "su" command. You can make the following modification to your code.
$cmd = "su";
$cmd = "echo '" . $sshPassword . "' | sudo -S " . $cmd;
if (!($stream = ssh2_exec($con, $cmd))) {
...
}

Categories