EvilFreelancer / routeros-api-php

Mikrotik RouterOS API PHP client for your applications
https://mikrotik.com/software
MIT License
397 stars 145 forks source link

Export bug ? #32

Closed mickaelmonsieur closed 4 years ago

mickaelmonsieur commented 4 years ago

Version of RouterOS +100 routers tested. 6.43.x to 6.45.X

To Reproduce examples/export.php

Expected behavior I have only this response:

Array
(
    [0] => !done
)

Best regads, Mickael

EvilFreelancer commented 4 years ago

Hello! Yeah, I know about this issue (btw the second issue is importing config), by some reasons ROS don't want show results of export to response from API and we see only "!done".

I tried to find a solution of this issue, but the only thing I managed to come up with was a series of "print" requests from which I can compose a set of basic configurations.

Did you happen to see how this issue was solved (if someone solved it of course) in other projects working with the API? If you saw something similar, please share the link, I will implement this solution into the project.

UPD: Typos fixed.

mickaelmonsieur commented 4 years ago

Hello ! Thank you for your opinion. No, I don't have the solution.

EvilFreelancer commented 4 years ago

I saw advises like "save config to file then copy via scp" probably it will be helpful for you.

UPD: Not API-way but better than nothing, when i worked as network engineer in small ISP we used tftp for uploading Cisco configs to backup server.

EvilFreelancer commented 4 years ago

Hello! I think I figured out how to solve this issue, need to write a telnet/ssh client that will make a request through the command line interface.

To do this, will need to rewrite my demo script from TCL to the PHP script format and add ability to call this code through method, eg ->export()

HGriessel commented 4 years ago

I used the below for export it uses python script which you can run as the process you going to have to install pip, to install python package paramiko, you can use anaconda to for python enviroments.

import paramiko

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('myDefaultGateway', username='myUsername', password='myPassword')
stdin, stdout, stderr = client.exec_command('ip firewall connection print')

for line in stdout:
    print(line.strip('\n'))
client.close()
EvilFreelancer commented 4 years ago

@Griessmeister yeah, nice idea, btw, did you have similar sollution but on php?

UPD: It will save my time for researching and ill begin with implementation (instead of searching) when will have spare time.

matracine commented 4 years ago

You can also deploy a ssh key on the mikrotik and associate it to a backup user. The export via shell is trivial : ssh -i /path/to/privatekey backup@myrouter /export > /path/to/backup.txt

EvilFreelancer commented 4 years ago

Hello @matracine ! Nice to see you :) so you think i just need implement exec() call which will trigger ssh? To make it work via library i mean.

matracine commented 4 years ago

@EvilFreelancer You can use phpseclib/phpseclib:~2.0

`use phpseclib\Net\SSH2;

... $ssh = new SSH2($this->connectionConfiguration['host']); if (!$ssh->login($this->connectionConfiguration['login'], $this->connectionConfiguration['password'])) { throw new \Exception("Error during ssh connection to the router"); } $ssh->write("/export\n"); $export = $ssh->read(); // ??? Did not try it. ` I use this lib to transfer files via SSH/SCP, works like a charm.

EvilFreelancer commented 4 years ago

@matracine oh, pretty awesome solution, thanks! Ill begin with implementation today, after work.

HGriessel commented 4 years ago

Here is how I implemented it via PHP it requires php-ssh2

sudo apt-get install php-ssh2.

$connection = ssh2_connect($this->host, 22);
        ssh2_auth_password($connection, $this->user, $this->pass);

        $stream = ssh2_exec($connection, 'export');
        stream_set_blocking($stream, true);
        $stream_out = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
        return stream_get_contents($stream_out);
matracine commented 4 years ago

@matracine oh, pretty awesome solution, thanks! Ill begin with implementation today, after work.

@EvilFreelancer This solution does not need to deploy a public key on the router, which is mandatory to log via a "simple" shell.

@Griessmeister nice and more complete than mine ;)

EvilFreelancer commented 4 years ago

@Griessmeister thanks for idea, but as you can see need to install additional extension which not available in default distribution of php, i think idea with phpseclib (which use standard crypt extensions) by @matracine is little bit more flexible.

HGriessel commented 4 years ago

@matracine as @EvilFreelancer stated yours does not require any additional extensions which are better suited to @EvilFreelancer needs

EvilFreelancer commented 4 years ago

Hello! Sorry for long response, here is the solution:

use \RouterOS\Client;

// Initiate client with config object
$client = new Client([
    'host'     => '192.168.1.3',
    'user'     => 'admin',
    'pass'     => 'admin',
    'ssh_port' => 22222,
]);

// Execute export command via ssh, because API /export method has a bug
$response = $client->export();

print_r($response);

For now it available in development branch, but soon i'll done with other issues and will release the 1.3.0 version with all fixes and export method support.

EvilFreelancer commented 4 years ago

Hello! Version 1.3.0 was released today, from now possible to use export() method of Client class, and /export endpoint via Query class, additional arguments of export command supported. @mickaelmonsieur can you check it please?

EvilFreelancer commented 4 years ago

There is no answer for a couple of days and judging by my tests everything works as it should, so I close the issue. If someone suddenly has ideas or suggestions, then this issue can be reopened :)