parallel-ssh
parallel-ssh copied to clipboard
Local SSH Port Forwarding (Tunneling) Example
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.
I figured out what I was doing wrong.
- Use serv.serve_forever() instead of serv.start()
- Run it in a thread
- 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