nikovpn.py: фиксы выбора протокола и сквозной проверки
- choose_candidates: кандидату назначается его собственный протокол из scheme, а не общий выбранный — иначе TUIC/Naive-ссылки собирались как hysteria2 и не работали - verify_tunnel: SSH-форвард строится через rt.ssh_args() — теперь передаются --identity/sshpass (раньше проверка падала с нестандартным именем ключа) - BatchMode=yes только без пароля (с sshpass он ломал авторизацию) - stop_service: добивает sing-box/ipt2socks вне procd — иначе Text file busy при перезаливке бинарников
This commit is contained in:
parent
d4d00aa0e1
commit
c887b77784
1 changed files with 22 additions and 6 deletions
28
nikovpn.py
28
nikovpn.py
|
|
@ -65,7 +65,7 @@ class Router:
|
|||
def __init__(self, host, user="root", port=22, password=None, key=None):
|
||||
self.host, self.user, self.port = host, user, port
|
||||
opts = ["-o", "StrictHostKeyChecking=accept-new",
|
||||
"-o", "ConnectTimeout=10", "-o", "BatchMode=yes"]
|
||||
"-o", "ConnectTimeout=10"]
|
||||
pre = []
|
||||
if password is not None:
|
||||
if not shutil_which("sshpass"):
|
||||
|
|
@ -73,10 +73,16 @@ class Router:
|
|||
pre = ["sshpass", "-p", password]
|
||||
opts += ["-o", "PreferredAuthentications=password",
|
||||
"-o", "PubkeyAuthentication=no"]
|
||||
else:
|
||||
opts += ["-o", "BatchMode=yes"]
|
||||
if key:
|
||||
opts += ["-i", str(key)]
|
||||
self.pre, self.opts = pre, opts
|
||||
self.base = pre + ["ssh", "-p", str(port)] + opts + [f"{user}@{host}"]
|
||||
|
||||
def ssh_args(self, *extra):
|
||||
return self.pre + ["ssh", "-p", str(self.port)] + self.opts + list(extra)
|
||||
|
||||
def run(self, cmd, timeout=180, input_bytes=None, check=False):
|
||||
r = subprocess.run(self.base + [cmd], capture_output=True,
|
||||
timeout=timeout,
|
||||
|
|
@ -287,7 +293,7 @@ def choose_candidates(rt: Router, links_text: bytes, naive_ok: bool) -> list:
|
|||
rest = [l for l in group if not host_alive(l)]
|
||||
picked += alive + rest
|
||||
for l in picked:
|
||||
l["protocol"] = proto
|
||||
l["protocol"] = l["scheme"].split("+")[0]
|
||||
l["sni"] = qp(l, "sni") or l["host"]
|
||||
return picked
|
||||
|
||||
|
|
@ -721,6 +727,16 @@ def human(n):
|
|||
def stop_service(rt: Router):
|
||||
if rt.exists("/etc/init.d/nikovpn"):
|
||||
rt.run("/etc/init.d/nikovpn stop >/dev/null 2>&1")
|
||||
# процессы, запущенные в обход procd, держат бинарники (Text file busy)
|
||||
rt.run("kill $(pgrep sing-box) 2>/dev/null; "
|
||||
"kill $(pgrep ipt2socks) 2>/dev/null")
|
||||
for _ in range(5):
|
||||
_, out, _ = rt.run("pgrep sing-box; pgrep ipt2socks")
|
||||
if not out.strip():
|
||||
break
|
||||
rt.run("kill -9 $(pgrep sing-box) 2>/dev/null; "
|
||||
"kill -9 $(pgrep ipt2socks) 2>/dev/null")
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
def verify_tunnel(rt: Router, local_port: int) -> str | None:
|
||||
|
|
@ -733,9 +749,9 @@ def verify_tunnel(rt: Router, local_port: int) -> str | None:
|
|||
t.bind(("127.0.0.1", 0))
|
||||
local_port = t.getsockname()[1]
|
||||
fwd = subprocess.Popen(
|
||||
["ssh", "-p", str(rt.port), "-o", "StrictHostKeyChecking=accept-new",
|
||||
"-o", "BatchMode=yes", "-f", "-N", "-L",
|
||||
f"{local_port}:127.0.0.1:{SOCKS_PORT}", f"{rt.user}@{rt.host}"],
|
||||
rt.ssh_args("-f", "-N", "-L",
|
||||
f"{local_port}:127.0.0.1:{SOCKS_PORT}",
|
||||
f"{rt.user}@{rt.host}"),
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
time.sleep(1.5)
|
||||
r = subprocess.run(
|
||||
|
|
@ -832,7 +848,7 @@ def do_install(rt: Router, args, update=False):
|
|||
if code != 200 or not links.strip():
|
||||
die(f"не удалось получить список серверов (код {code})")
|
||||
|
||||
cands = choose_candidates(rt, links, naive_ok)
|
||||
cands = choose_candidates(rt, links, bool(naive_ok))
|
||||
if not cands:
|
||||
die("пустой список кандидатов")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue