Merge pull request 'clan-cli: Make clan ssh automatically start tor' (#2623) from Qubasa/clan-core:Qubasa-main into main
This commit is contained in:
@@ -2,16 +2,16 @@ import argparse
|
||||
import ipaddress
|
||||
import json
|
||||
import logging
|
||||
import shlex
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from clan_cli.async_run import AsyncRuntime
|
||||
from clan_cli.cmd import run
|
||||
from clan_cli.errors import ClanError, TorConnectionError, TorSocksError
|
||||
from clan_cli.errors import ClanError
|
||||
from clan_cli.nix import nix_shell
|
||||
from clan_cli.ssh.host import Host, is_ssh_reachable
|
||||
from clan_cli.ssh.tor import TorTarget, ssh_tor_reachable
|
||||
from clan_cli.ssh.tor import TorTarget, spawn_tor, ssh_tor_reachable
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -63,12 +63,13 @@ def parse_qr_code(picture_file: Path) -> DeployInfo:
|
||||
return DeployInfo.from_json(json.loads(data))
|
||||
|
||||
|
||||
def ssh_shell_from_deploy(deploy_info: DeployInfo) -> None:
|
||||
def ssh_shell_from_deploy(deploy_info: DeployInfo, runtime: AsyncRuntime) -> None:
|
||||
if host := find_reachable_host(deploy_info):
|
||||
host.connect_ssh_shell(password=deploy_info.pwd)
|
||||
else:
|
||||
log.info("Could not reach host via clearnet 'addrs'")
|
||||
log.info(f"Trying to reach host via tor '{deploy_info.tor}'")
|
||||
spawn_tor(runtime)
|
||||
if not deploy_info.tor:
|
||||
msg = "No tor address provided, please provide a tor address."
|
||||
raise ClanError(msg)
|
||||
@@ -98,15 +99,9 @@ def ssh_command(args: argparse.Namespace) -> None:
|
||||
if not deploy_info:
|
||||
msg = "No --json or --png data provided"
|
||||
raise ClanError(msg)
|
||||
try:
|
||||
ssh_shell_from_deploy(deploy_info)
|
||||
except TorSocksError as ex:
|
||||
log.error(ex)
|
||||
tor_cmd = nix_shell(["nixpkgs#tor"], ["tor"])
|
||||
log.error("Is Tor running? If not, you can start it by running:")
|
||||
log.error(f"{' '.join(shlex.quote(arg) for arg in tor_cmd)}")
|
||||
except TorConnectionError:
|
||||
log.error("The onion address is not reachable via Tor.")
|
||||
|
||||
with AsyncRuntime() as runtime:
|
||||
ssh_shell_from_deploy(deploy_info, runtime)
|
||||
|
||||
|
||||
def register_parser(parser: argparse.ArgumentParser) -> None:
|
||||
|
||||
@@ -185,6 +185,7 @@ class Host:
|
||||
ssh_opts.extend(["-i", self.key])
|
||||
|
||||
if tor_socks:
|
||||
packages.append("nixpkgs#netcat")
|
||||
ssh_opts.append("-o")
|
||||
ssh_opts.append("ProxyCommand=nc -x 127.0.0.1:9050 -X 5 %h %p")
|
||||
|
||||
|
||||
@@ -4,9 +4,11 @@ import argparse
|
||||
import logging
|
||||
import socket
|
||||
import struct
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
|
||||
from clan_cli.cmd import run
|
||||
from clan_cli.async_run import AsyncRuntime
|
||||
from clan_cli.cmd import Log, RunOpts, run
|
||||
from clan_cli.errors import TorConnectionError, TorSocksError
|
||||
from clan_cli.nix import nix_shell
|
||||
|
||||
@@ -96,14 +98,42 @@ def fetch_onion_content(target: TorTarget) -> str:
|
||||
return response.decode("utf-8", errors="replace")
|
||||
|
||||
|
||||
def spawn_tor() -> None:
|
||||
def is_tor_running() -> bool:
|
||||
"""Checks if Tor is online."""
|
||||
try:
|
||||
tor_online_test()
|
||||
except TorSocksError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def spawn_tor(runtime: AsyncRuntime) -> None:
|
||||
"""
|
||||
Spawns a Tor process using `nix-shell`.
|
||||
Spawns a Tor process using `nix-shell` if Tor is not already running.
|
||||
"""
|
||||
cmd_args = ["tor"]
|
||||
packages = ["nixpkgs#tor"]
|
||||
cmd = nix_shell(packages, cmd_args)
|
||||
run(cmd)
|
||||
|
||||
def start_tor() -> None:
|
||||
"""Starts Tor process using nix-shell."""
|
||||
cmd_args = ["tor", "--HardwareAccel", "1"]
|
||||
packages = ["nixpkgs#tor"]
|
||||
cmd = nix_shell(packages, cmd_args)
|
||||
runtime.async_run(None, run, cmd, RunOpts(log=Log.BOTH))
|
||||
log.debug("Attempting to start Tor")
|
||||
|
||||
# Check if Tor is already running
|
||||
if is_tor_running():
|
||||
log.info("Tor is running")
|
||||
return
|
||||
|
||||
# Attempt to start Tor
|
||||
start_tor()
|
||||
|
||||
# Continuously check if Tor has started
|
||||
while not is_tor_running():
|
||||
log.debug("Waiting for Tor to start...")
|
||||
time.sleep(0.2)
|
||||
log.info("Tor is now running")
|
||||
|
||||
|
||||
def tor_online_test() -> bool:
|
||||
|
||||
Reference in New Issue
Block a user