50 lines
1.8 KiB
Python
50 lines
1.8 KiB
Python
#!/usr/bin/env python3
|
||
"""launch_vpn.py — auth = static+TOTP, конкатенация без разделителя.
|
||
Параметры берутся из общего vpn_config.json (см. launch_vpn_gui.py);
|
||
секреты — из keyring."""
|
||
import subprocess, pyotp, keyring, tempfile, json, os, base64
|
||
|
||
CONFIG_PATH = os.path.join(
|
||
os.path.dirname(os.path.abspath(__file__)), "vpn_config.json")
|
||
DEFAULTS = {
|
||
"username": "boyko_vn",
|
||
"ovpn_config": r"C:\Users\User\app\vpn\ovpn-config-ano.ovpn",
|
||
"openvpn_bin": r"C:\Program Files\OpenVPN\bin\openvpn.exe",
|
||
"keyring_service": "openvpn-totp",
|
||
}
|
||
|
||
def load_config():
|
||
cfg = dict(DEFAULTS)
|
||
try:
|
||
with open(CONFIG_PATH, "r", encoding="utf-8") as f:
|
||
data = json.load(f)
|
||
if isinstance(data, dict):
|
||
cfg.update(data)
|
||
except (OSError, ValueError):
|
||
pass
|
||
return cfg
|
||
|
||
def main():
|
||
cfg = load_config()
|
||
service = cfg.get("keyring_service", "openvpn-totp")
|
||
secret = keyring.get_password(service, "secret")
|
||
# 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{password}\n")
|
||
subprocess.run([cfg["openvpn_bin"], "--config", cfg["ovpn_config"],
|
||
"--auth-user-pass", path])
|
||
finally:
|
||
os.remove(path)
|
||
|
||
if __name__ == "__main__":
|
||
main()
|