feat: connectivity — registry-driven peer table, sshuttle/proxy egress, egress UI
The peer table was empty because it was not consulting the peer registry; now peers are driven by PeerRegistry so the Connectivity page reflects actual connected cells. Exit-key handling is unified: all code paths now use the same key derivation so a store-service exit bridge and a manual WireGuard peer both produce consistent routing state. Two new egress exit types are added (sshuttle via SSH tunnel and proxy via redsocks SOCKS5), wiring through connectivity_manager, egress_manager, and app.py routes. This lets a cell route its traffic through an SSH host or a SOCKS5 proxy as an alternative to WireGuard exit nodes. ServiceStoreManager and ServiceBus updated so the egress lifecycle (install / uninstall) is cleanly signalled between components. Connectivity.jsx gains the Service Egress section, letting operators assign and reassign egress methods from the UI without touching config files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+21
-9
@@ -19,19 +19,26 @@ from typing import Any, Dict, List, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
EXIT_TYPES = ("default", "wireguard_ext", "openvpn", "tor")
|
||||
EXIT_TYPES = ("default", "wireguard_ext", "openvpn", "tor", "sshuttle", "proxy")
|
||||
|
||||
# fwmark values — must not collide with ConnectivityManager (0x10, 0x20, 0x30)
|
||||
MARKS = {"wireguard_ext": 0x110, "openvpn": 0x120, "tor": 0x130}
|
||||
# fwmark values — must not collide with ConnectivityManager
|
||||
# (0x10, 0x20, 0x30, 0x40, 0x50)
|
||||
MARKS = {"wireguard_ext": 0x110, "openvpn": 0x120, "tor": 0x130,
|
||||
"sshuttle": 0x140, "proxy": 0x150}
|
||||
|
||||
# Policy routing table IDs
|
||||
TABLES = {"wireguard_ext": 210, "openvpn": 220, "tor": 230}
|
||||
TABLES = {"wireguard_ext": 210, "openvpn": 220, "tor": 230,
|
||||
"sshuttle": 240, "proxy": 250}
|
||||
|
||||
EGRESS_CHAIN = "PIC_EGRESS"
|
||||
|
||||
# Transparent proxy port used by Tor
|
||||
_TOR_TRANS_PORT = 9040
|
||||
|
||||
# Local transparent-proxy ports for redirect-style exits (no exit iface):
|
||||
# traffic is REDIRECTed to the listener of the corresponding exit container.
|
||||
_REDIRECT_PORTS = {"tor": _TOR_TRANS_PORT, "sshuttle": 12300, "proxy": 12345}
|
||||
|
||||
|
||||
class EgressManager:
|
||||
"""Per-service egress enforcement via host iptables fwmark policy-routing."""
|
||||
@@ -94,8 +101,9 @@ class EgressManager:
|
||||
self._ensure_chains()
|
||||
self._ensure_host_ip_rules()
|
||||
self._add_mark_rule(container_ip, MARKS[exit_via], service_id)
|
||||
if exit_via == 'tor':
|
||||
self._add_tor_redirect(container_ip, service_id)
|
||||
if exit_via in _REDIRECT_PORTS:
|
||||
self._add_redirect(container_ip, _REDIRECT_PORTS[exit_via],
|
||||
service_id)
|
||||
except Exception as exc:
|
||||
logger.error('apply_service(%s): %s', service_id, exc)
|
||||
return {'ok': False, 'error': str(exc)}
|
||||
@@ -266,15 +274,19 @@ class EgressManager:
|
||||
'-m', 'comment', '--comment', self._tag(service_id),
|
||||
])
|
||||
|
||||
def _add_tor_redirect(self, service_ip: str, service_id: str) -> None:
|
||||
"""Redirect the service container's TCP traffic to the local Tor TransPort."""
|
||||
def _add_redirect(self, service_ip: str, port: int, service_id: str) -> None:
|
||||
"""Redirect the container's TCP traffic to a local transparent-proxy port."""
|
||||
self._iptables([
|
||||
'-t', 'nat', '-A', EGRESS_CHAIN,
|
||||
'-s', service_ip, '-p', 'tcp',
|
||||
'-j', 'REDIRECT', '--to-ports', str(_TOR_TRANS_PORT),
|
||||
'-j', 'REDIRECT', '--to-ports', str(port),
|
||||
'-m', 'comment', '--comment', self._tag(service_id),
|
||||
])
|
||||
|
||||
def _add_tor_redirect(self, service_ip: str, service_id: str) -> None:
|
||||
"""Redirect the service container's TCP traffic to the local Tor TransPort."""
|
||||
self._add_redirect(service_ip, _TOR_TRANS_PORT, service_id)
|
||||
|
||||
def _clear_egress_rules(self, service_id: str) -> None:
|
||||
"""Remove all rules tagged pic-egr-<service_id> from mangle and nat."""
|
||||
import re as _re
|
||||
|
||||
Reference in New Issue
Block a user