Issue
I'm trying to use parallel-ssh to setup a simple ssh tunnel. (I'm not able to use the sshtunnel package due to its dependencies.)
What I expect to happen is that once the tunnel is created I can arbitrarily connect/disconnect sockets to the matching port, but that's not working.
Can someone clarify why the below code can successfully connect the client over ssh, but doesn't allow the socket to connect?
The error message from the socket is:
ConnectionRefusedError: [Errno 111] Connection refused
Example code:
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))
Solution
Through a bit of trial, error, and reviewing the source code I found a solution:
- Instead of
serv.start()
callserv.serve_forever()
- Run it in a thread
- The port that the new socket connects to is the
serv.listen_port
None of this was made clear via the documentation, unfortunately.
Example working class:
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
Answered By - Mandias Answer Checked By - Katrina (WPSolving Volunteer)