Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local SSH Port Forwarding (Tunneling) Example #383

Open
nhansendev opened this issue Jul 3, 2023 · 1 comment
Open

Local SSH Port Forwarding (Tunneling) Example #383

nhansendev opened this issue Jul 3, 2023 · 1 comment

Comments

@nhansendev
Copy link

Is your feature request related to a problem? Please describe.
I'm trying to determine if/how parallel-ssh can be used for local port forwarding (tunneling) in a way that allows for arbitrary socket connections. The description for the Tunnel Server sounds exactly like what I need (I think), but I do not see any clear documentation/tutorials on its usage.

Local port forwarding server for tunneling connections from remote SSH server.
Accepts connections on an available bind_address port once started and tunnels data to/from remote SSH host for each connection.

I've tried the following, but while the SSH client connection is accepted, the socket is rejected:

from pssh.clients import SSHClient
from pssh.clients.native.tunnel import TunnelServer
import socket

client = SSHClient(REMOTE_IP, UNAME)

serv = TunnelServer(client, HOST, PORT, bind_address=HOST)
serv.start()

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))

ConnectionRefusedError: [Errno 111] Connection refused

Describe the solution you'd like
An example showing the correct usage of a TunnelServer for SSH local port forwarding.

Describe alternatives you've considered
Using a different library, but I am not able to for my project.

@nhansendev
Copy link
Author

I figured out what I was doing wrong.

  1. Use serv.serve_forever() instead of serv.start()
  2. Run it in a thread
  3. Connect the socket on the serv.listen_port instead

Working class example:

from pssh.clients import SSHClient
from pssh.clients.native.tunnel import TunnelServer
import threading, time

class PsshTunnel:
    def __init__(self, remote_ip, username, host="localhost", port=8080):
        self.remote_ip = remote_ip
        self.username = username
        self.host = host
        self.port = port

    def _run(self):
        client = SSHClient(self.remote_ip, self.username)

        self.serv = TunnelServer(client, self.host, self.port, bind_address=self.host)
        self.serv.serve_forever()

    def start(self):
        self.th = threading.Thread(target=self._run, daemon=True)
        self.th.start()
        # Give it time to connect
        time.sleep(3)

    def stop(self):
        self.serv.stop()

    @property
    def socket_port(self):
        return self.serv.listen_port

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant