stechstudio / laravel-ssh-tunnel

Easy creation & maintenance of an SSH Tunnel for Laravel/Lumen
MIT License
191 stars 49 forks source link

in docker container: bind [::1]:13306: Cannot assign requested address #51

Closed b166er closed 1 year ago

b166er commented 3 years ago

my docker Container based from "webdevops/php-nginx:8.0" with some modifications like installing "ncat" and "procps"

here my docker run: docker run --rm -d --net mynet --ip 172.15.0.1 --hostname mydev --name mydev -p 1881:80 -e WEB_DOCUMENT_ROOT=/app/public -v ${pwd}:/app mytest_container

i run my custom command: docker exec mydev php /app/artisan test:start -vvv my test console-command:

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
class TestCommand extends Command {
    protected $signature = 'test:start';
    protected $description = '';
    public function handle(): int {
        $exit_code_open = Artisan::call('tunneler:activate'); // start tunnnel
        $posts = DB::connection('mysql_tunnel')->select('SELECT * FROM posts WHERE id=1 LIMIT 0,1'); // fetch posts from db
        $exit_code_close = Artisan::call('tunneler:reset'); // stop tunnnel
        dd($exit_code_open, $exit_code_close, $posts);
        return 0;
    }
}

will generate and execute this command in docker container locally: /usr/bin/ssh -o StrictHostKeyChecking=no -N -i /app/test.key -L 13306:127.0.0.1:3306 -p 22 john@my-server i start this command manually in docker-container with "-v" verbose, here is the result:

>docker exec -it mydev /bin/bash
#/usr/bin/ssh -v -o StrictHostKeyChecking=no  -N -i /app/test.key -L 13306:127.0.0.1:3306 -p 22 john@my-server
OpenSSH_7.9p1 Debian-10+deb10u2, OpenSSL 1.1.1d  10 Sep 2019
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to XXX [X.X.X.X] port 22.
debug1: Connection established.
debug1: identity file /app/test.key type -1
debug1: identity file /app/test.key-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u2
debug1: Remote protocol version 2.0, remote software version OpenSSH_8.6
debug1: match: OpenSSH_8.6 pat OpenSSH* compat 0x04000000
debug1: Authenticating to XXX:22 as 'john'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256@libssh.org
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:qE829s3IFvLXw+IOyhRm453TRwgx/72nq8jpS8neFNw
debug1: Host '[XXX]:22' is known and matches the ECDSA host key.
debug1: Found key in /root/.ssh/known_hosts:1
debug1: rekey after 134217728 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey after 134217728 blocks
debug1: Will attempt key: /app/test.key  explicit
debug1: SSH2_MSG_EXT_INFO received
debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,sk-ssh-ed25519@openssh.com,ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ecdsa-sha2-nistp256@openssh.com,webauthn-sk-ecdsa-sha2-nistp256@openssh.com>
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,keyboard-interactive
debug1: Next authentication method: publickey
debug1: Trying private key: /app/test.key
debug1: Authentication succeeded (publickey).
Authenticated to XXX ([X.X.X.X]:22).
debug1: Local connections to LOCALHOST:13306 forwarded to remote address 127.0.0.1:3306
debug1: Local forwarding listening on 127.0.0.1 port 13306.
debug1: channel 0: new [port listener]
debug1: Local forwarding listening on ::1 port 13306.
bind [::1]:13306: Cannot assign requested address   // <----------- here is the error line --------------- //
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: pledge: network
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug1: Remote: /home/john/.ssh/authorized_keys:1: key options: agent-forwarding port-forwarding pty user-rc x11-forwarding
debug1: client_input_global_request: rtype keepalive@openssh.com want_reply 1
debug1: client_input_global_request: rtype keepalive@openssh.com want_reply 1
debug1: client_input_global_request: rtype keepalive@openssh.com want_reply 1
debug1: client_input_global_request: rtype keepalive@openssh.com want_reply 1
debug1: client_input_global_request: rtype keepalive@openssh.com want_reply 1
debug1: client_input_global_request: rtype keepalive@openssh.com want_reply 1
^Cdebug1: channel 0: free: port listener, nchannels 1
Killed by signal 2.

i found the problem in this line: debug1: Local connections to LOCALHOST:13306 forwarded to remote address 127.0.0.1:3306

docker cannot bind port to localhost or 127.0.0.1, they need a docker-ip, so i extended the sshCommand in class CreateTunnel:__construct() to a custom-address for local binding:

before:

$this->sshCommand = sprintf('%s %s %s -N -i %s -L %d:%s:%d -p %d %s@%s',
    config('tunneler.ssh_path'),
    config('tunneler.ssh_options'),
    config('tunneler.ssh_verbosity'),
    config('tunneler.identity_file'),
    config('tunneler.local_port'),
    config('tunneler.bind_address'),
    config('tunneler.bind_port'),
    config('tunneler.port'),
    config('tunneler.user'),
    config('tunneler.hostname')
);

after:

$this->sshCommand = sprintf('%s %s %s -N -i %s -L %s:%d:%s:%d -p %d %s@%s', // <-- here i added the additional string before local port -L %s:%d...
    config('tunneler.ssh_path'),
    config('tunneler.ssh_options'),
    config('tunneler.ssh_verbosity'),
    config('tunneler.identity_file'),
    config('tunneler.local_address'), // <-- here is additional local_address
    config('tunneler.local_port'),
    config('tunneler.bind_address'),
    config('tunneler.bind_port'),
    config('tunneler.port'),
    config('tunneler.user'),
    config('tunneler.hostname')
);

result: /usr/bin/ssh -o StrictHostKeyChecking=no -N -i /app/test.key -L 172.15.0.1:13306:127.0.0.1:3306 -p 22 john@my-server and now it works!

can you please provide an update with this fix. Thank you!

PS: btw,

  1. can you change comments your config-example in https://github.com/stechstudio/laravel-ssh-tunnel/blob/master/README.md, from ";" to "#" because dotenv-lib in laravel cannot parse lines with ; source: https://github.com/vlucas/phpdotenv#comments
  2. plesae add additional Job and Command for destroying/disconnecting existing connection, because i need to connect in Job Chaining and after ending job, i need to disconnect connection.
b166er commented 1 year ago

closed without changes? can you please explain why?

jszobody commented 1 year ago

This is not something that we need ourselves, we haven't had time to build it for you, and in the past 1.5+ years that this ticket has been open no one else seems to have needed it either.

That said, if you'd like to take a crack at improving this, feel free to submit a pull request and we'll take a look!