new connection
This commit is contained in:
parent
9f37fd8b78
commit
70004e0645
6
1.py
Normal file
6
1.py
Normal file
@ -0,0 +1,6 @@
|
||||
import keyring
|
||||
|
||||
# keyring.get_password(service_name, username)
|
||||
value = keyring.get_password("openvpn-totp-offad", "static")
|
||||
print(value) # None, если ничего не сохранено
|
||||
|
||||
@ -21,3 +21,7 @@
|
||||
|
||||
Правятся вручную или через пункт меню «Открыть настройки»; перечитываются на лету.
|
||||
Секреты (`secret`, `static`) в конфиге не хранятся — они в keyring под именем `keyring_service`.
|
||||
|
||||
## Сервис для декодирования
|
||||
|
||||
https://2fafast.com/tools/qr-decoder/
|
||||
|
||||
@ -25,13 +25,14 @@ def main():
|
||||
static = os.environ.get("OVPN_STATIC_PASS")
|
||||
|
||||
missing = [name for name, val in
|
||||
(("OVPN_TOTP_SECRET", secret), ("OVPN_STATIC_PASS", static))
|
||||
(("OVPN_TOTP_SECRET", secret),)
|
||||
if not val]
|
||||
if missing:
|
||||
sys.exit(f"Не заданы переменные окружения: {', '.join(missing)}")
|
||||
|
||||
service = keyring_service()
|
||||
keyring.set_password(service, "secret", secret)
|
||||
if static:
|
||||
keyring.set_password(service, "static", static)
|
||||
print(f"Сохранено в keyring (сервис: {service}).")
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"""launch_vpn.py — auth = static+TOTP, конкатенация без разделителя.
|
||||
Параметры берутся из общего vpn_config.json (см. launch_vpn_gui.py);
|
||||
секреты — из keyring."""
|
||||
import subprocess, pyotp, keyring, tempfile, json, os
|
||||
import subprocess, pyotp, keyring, tempfile, json, os, base64
|
||||
|
||||
CONFIG_PATH = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "vpn_config.json")
|
||||
@ -28,12 +28,18 @@ def main():
|
||||
cfg = load_config()
|
||||
service = cfg.get("keyring_service", "openvpn-totp")
|
||||
secret = keyring.get_password(service, "secret")
|
||||
static = keyring.get_password(service, "static")
|
||||
# static — необязателен: если его нет в keyring, пароль = только TOTP-код.
|
||||
static = keyring.get_password(service, "static") or ""
|
||||
code = pyotp.TOTP(secret).now()
|
||||
if cfg.get("static_challenge"):
|
||||
password = (f"SCRV1:{base64.b64encode(static.encode()).decode()}"
|
||||
f":{base64.b64encode(code.encode()).decode()}")
|
||||
else:
|
||||
password = f"{static}{code}"
|
||||
fd, path = tempfile.mkstemp(suffix=".txt")
|
||||
try:
|
||||
with os.fdopen(fd, "w", newline="\n") as f:
|
||||
f.write(f"{cfg['username']}\n{static}{code}\n")
|
||||
f.write(f"{cfg['username']}\n{password}\n")
|
||||
subprocess.run([cfg["openvpn_bin"], "--config", cfg["ovpn_config"],
|
||||
"--auth-user-pass", path])
|
||||
finally:
|
||||
|
||||
@ -7,6 +7,7 @@ import threading
|
||||
import tempfile
|
||||
import json
|
||||
import os
|
||||
import base64
|
||||
import pyotp
|
||||
import keyring
|
||||
import pystray
|
||||
@ -32,6 +33,12 @@ DEFAULT_CONFIG = {
|
||||
"dev_node": "OpenVPN Data Channel Offload",
|
||||
# имя сервиса в keyring, откуда берутся secret (TOTP) и static (пароль).
|
||||
"keyring_service": "openvpn-totp",
|
||||
# формат передачи OTP серверу.
|
||||
# False -> пароль = static+code одной строкой (сервер сам отрезает OTP).
|
||||
# True -> формат SCRV1 (static и OTP кодируются раздельно в base64); нужен
|
||||
# для серверов со static-challenge. Саму строку static-challenge при
|
||||
# этом надо УБРАТЬ из .ovpn, иначе openvpn спросит код интерактивно.
|
||||
"static_challenge": False,
|
||||
# путь к лог-файлу openvpn.
|
||||
"log_path": "ovpn.log",
|
||||
|
||||
@ -153,14 +160,24 @@ def is_running() -> bool:
|
||||
return proc is not None and proc.poll() is None
|
||||
|
||||
|
||||
def auth_password(static: str, code: str) -> str:
|
||||
"""Собрать поле пароля для auth-user-pass с учётом режима static_challenge."""
|
||||
if config.get("static_challenge"):
|
||||
s = base64.b64encode(static.encode()).decode()
|
||||
r = base64.b64encode(code.encode()).decode()
|
||||
return f"SCRV1:{s}:{r}"
|
||||
return f"{static}{code}"
|
||||
|
||||
|
||||
def build_auth_file() -> str:
|
||||
service = config.get("keyring_service", "openvpn-totp")
|
||||
secret = keyring.get_password(service, "secret")
|
||||
static = keyring.get_password(service, "static")
|
||||
# static — необязателен: если его нет в keyring, пароль = только TOTP-код.
|
||||
static = keyring.get_password(service, "static") or ""
|
||||
code = pyotp.TOTP(secret).now()
|
||||
fd, path = tempfile.mkstemp(suffix=".txt")
|
||||
with os.fdopen(fd, "w", newline="\n") as f:
|
||||
f.write(f"{config['username']}\n{static}{code}\n")
|
||||
f.write(f"{config['username']}\n{auth_password(static, code)}\n")
|
||||
return path
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user