mirror of
https://github.com/naruxde/revpicommander.git
synced 2026-08-16 05:45:53 +02:00
feat: Enhance SSH tunnel handling with Unix socket support
Support forwarding Unix sockets in SSH tunnels by extending `SSHLocalTunnel`. Update logic to detect and handle remote Unix socket configurations. Signed-off-by: Sven Sager <akira@narux.de>
This commit is contained in:
@@ -16,6 +16,7 @@ from re import search
|
||||
from threading import Lock
|
||||
from uuid import uuid4
|
||||
from xmlrpc.client import Binary, ServerProxy, Transport
|
||||
from configparser import ConfigParser
|
||||
|
||||
from PyQt5 import QtCore
|
||||
import asyncssh
|
||||
@@ -365,10 +366,12 @@ class ConnectionManager(QtCore.QThread):
|
||||
|
||||
ssh_tunnel_server = None
|
||||
ssh_tunnel_port = 0
|
||||
ssh_tunnel_socket = None
|
||||
|
||||
socket.setdefaulttimeout(revpi_settings.timeout)
|
||||
|
||||
if revpi_settings.ssh_use_tunnel:
|
||||
# We first connect to find out which target to tunnel
|
||||
ssh_tunnel_server = SSHLocalTunnel(
|
||||
revpi_settings.port,
|
||||
revpi_settings.address,
|
||||
@@ -377,6 +380,37 @@ class ConnectionManager(QtCore.QThread):
|
||||
try:
|
||||
ssh_tunnel_port = ssh_tunnel_server.connect_by_credentials(revpi_settings.ssh_user, ssh_pass)
|
||||
|
||||
# Check for Unix socket on remote system
|
||||
try:
|
||||
stdout, stderr = ssh_tunnel_server.send_cmd("cat /etc/revpipyload/revpipyload.conf")
|
||||
if stdout:
|
||||
config = ConfigParser()
|
||||
config.read_string(stdout)
|
||||
if config.has_section("XMLRPC"):
|
||||
bindip = config.get("XMLRPC", "bindip", fallback="").strip()
|
||||
if bindip == "socket":
|
||||
ssh_tunnel_socket = "/run/revpipyload/xmlrpc.socket"
|
||||
elif bindip.startswith("/") or bindip.startswith("./"):
|
||||
ssh_tunnel_socket = bindip
|
||||
|
||||
if ssh_tunnel_socket:
|
||||
log.debug("Using remote unix socket: %s", ssh_tunnel_socket)
|
||||
# Forward local port 0 (dynamic) to remote unix socket
|
||||
ssh_tunnel_server.disconnect()
|
||||
ssh_tunnel_server = SSHLocalTunnel(
|
||||
ssh_tunnel_socket,
|
||||
revpi_settings.address,
|
||||
revpi_settings.ssh_port
|
||||
)
|
||||
ssh_tunnel_port = ssh_tunnel_server.connect_by_credentials(
|
||||
revpi_settings.ssh_user, ssh_pass
|
||||
)
|
||||
else:
|
||||
log.debug("Using remote TCP socket: %s", bindip)
|
||||
|
||||
except Exception as e:
|
||||
log.warning(f"Could not check remote config for unix socket: {e}")
|
||||
|
||||
if getattr(revpi_settings, "ssh_enable_revpipyload", False):
|
||||
ssh_tunnel_server.send_cmd("sudo systemctl enable --now revpipyload")
|
||||
|
||||
@@ -723,7 +757,7 @@ def create_server_proxy(revpi_settings: RevPiSettings, ssh_tunnel_port: int = No
|
||||
:param ssh_tunnel_port: Use this port if an SSH tunnel is already established
|
||||
:return: ServerProxy instance
|
||||
"""
|
||||
if revpi_settings.is_unix_socket:
|
||||
if not ssh_tunnel_port and revpi_settings.is_unix_socket:
|
||||
return ServerProxy("http://localhost", transport=UnixStreamTransport(revpi_settings.address))
|
||||
|
||||
if ssh_tunnel_port:
|
||||
|
||||
@@ -18,15 +18,15 @@ log = getLogger("ssh_tunneling")
|
||||
|
||||
class SSHLocalTunnel:
|
||||
|
||||
def __init__(self, remote_tunnel_port: int, ssh_host: str, ssh_port: int = 22):
|
||||
def __init__(self, remote_target: Union[int, str], ssh_host: str, ssh_port: int = 22):
|
||||
"""
|
||||
Connect to a ssh remote host and tunnel a port to your host.
|
||||
Connect to a ssh remote host and tunnel a port or unix socket to your host.
|
||||
|
||||
:param remote_tunnel_port: Port on the remote host to tunnel through ssh
|
||||
:param remote_target: Port or unix socket path on the remote host to tunnel through ssh
|
||||
:param ssh_host: ssh remote host address
|
||||
:param ssh_port: ssh remote host port
|
||||
"""
|
||||
self._remote_tunnel_port = remote_tunnel_port
|
||||
self._remote_target = remote_target
|
||||
self._ssh_host = ssh_host
|
||||
self._ssh_port = ssh_port
|
||||
|
||||
@@ -72,9 +72,14 @@ class SSHLocalTunnel:
|
||||
config=None, # Do not parse local config
|
||||
) as conn:
|
||||
self._conn = conn
|
||||
# Forward local port 0 (dynamic) to remote 127.0.0.1:remote_tunnel_port
|
||||
# Forward local port 0 (dynamic) to remote target (port or unix socket)
|
||||
if isinstance(self._remote_target, int):
|
||||
self._server = await conn.forward_local_port(
|
||||
'127.0.0.1', 0, '127.0.0.1', self._remote_tunnel_port
|
||||
'127.0.0.1', 0, '127.0.0.1', self._remote_target
|
||||
)
|
||||
else:
|
||||
self._server = await conn.forward_local_port_to_path(
|
||||
'127.0.0.1', 0, self._remote_target
|
||||
)
|
||||
self._local_tunnel_port = self._server.get_port()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user