mirror of
https://github.com/naruxde/revpicommander.git
synced 2026-08-16 13:47:04 +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 threading import Lock
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from xmlrpc.client import Binary, ServerProxy, Transport
|
from xmlrpc.client import Binary, ServerProxy, Transport
|
||||||
|
from configparser import ConfigParser
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
import asyncssh
|
import asyncssh
|
||||||
@@ -365,10 +366,12 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
|
|
||||||
ssh_tunnel_server = None
|
ssh_tunnel_server = None
|
||||||
ssh_tunnel_port = 0
|
ssh_tunnel_port = 0
|
||||||
|
ssh_tunnel_socket = None
|
||||||
|
|
||||||
socket.setdefaulttimeout(revpi_settings.timeout)
|
socket.setdefaulttimeout(revpi_settings.timeout)
|
||||||
|
|
||||||
if revpi_settings.ssh_use_tunnel:
|
if revpi_settings.ssh_use_tunnel:
|
||||||
|
# We first connect to find out which target to tunnel
|
||||||
ssh_tunnel_server = SSHLocalTunnel(
|
ssh_tunnel_server = SSHLocalTunnel(
|
||||||
revpi_settings.port,
|
revpi_settings.port,
|
||||||
revpi_settings.address,
|
revpi_settings.address,
|
||||||
@@ -377,6 +380,37 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
try:
|
try:
|
||||||
ssh_tunnel_port = ssh_tunnel_server.connect_by_credentials(revpi_settings.ssh_user, ssh_pass)
|
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):
|
if getattr(revpi_settings, "ssh_enable_revpipyload", False):
|
||||||
ssh_tunnel_server.send_cmd("sudo systemctl enable --now revpipyload")
|
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
|
:param ssh_tunnel_port: Use this port if an SSH tunnel is already established
|
||||||
:return: ServerProxy instance
|
: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))
|
return ServerProxy("http://localhost", transport=UnixStreamTransport(revpi_settings.address))
|
||||||
|
|
||||||
if ssh_tunnel_port:
|
if ssh_tunnel_port:
|
||||||
|
|||||||
@@ -18,15 +18,15 @@ log = getLogger("ssh_tunneling")
|
|||||||
|
|
||||||
class SSHLocalTunnel:
|
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_host: ssh remote host address
|
||||||
:param ssh_port: ssh remote host port
|
: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_host = ssh_host
|
||||||
self._ssh_port = ssh_port
|
self._ssh_port = ssh_port
|
||||||
|
|
||||||
@@ -72,10 +72,15 @@ class SSHLocalTunnel:
|
|||||||
config=None, # Do not parse local config
|
config=None, # Do not parse local config
|
||||||
) as conn:
|
) as conn:
|
||||||
self._conn = 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)
|
||||||
self._server = await conn.forward_local_port(
|
if isinstance(self._remote_target, int):
|
||||||
'127.0.0.1', 0, '127.0.0.1', self._remote_tunnel_port
|
self._server = await conn.forward_local_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()
|
self._local_tunnel_port = self._server.get_port()
|
||||||
|
|
||||||
self._started.set()
|
self._started.set()
|
||||||
|
|||||||
Reference in New Issue
Block a user