diff --git a/gui/app.py b/gui/app.py index eb52a26..479345e 100644 --- a/gui/app.py +++ b/gui/app.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import base64 import io +import ipaddress import os import secrets import sqlite3 @@ -658,6 +659,15 @@ def peer_rename(peer_id: int): return ("", 204) +def _cidr_parts(cidr: str): + """Return (network_address, netmask) for a CIDR string.""" + try: + net = ipaddress.ip_network(cidr.strip(), strict=False) + return str(net.network_address), str(net.netmask) + except Exception: + return cidr.strip(), "" + + @app.route("/scripts") def scripts(): commands = { @@ -666,14 +676,33 @@ def scripts(): "apply_wg": "wg syncconf wg0 <(wg-quick strip /etc/wireguard/wg0.conf)", } paths = [ - "sudo", "/usr/local/sbin/wg-peerctl", + "/usr/local/sbin/wg-peerctl", "/etc/wireguard/wg0.conf", "/etc/wireguard/wg-meta.env", "/var/log/wireguard-server-install.log", "/var/log/wireguard-client-install.log", "/var/log/wireguard-peerctl.log", ] - return render_template("scripts.html", commands=commands, paths=paths) + + route_peers = [] + with db_conn() as conn: + cur = conn.cursor() + cur.execute( + "SELECT name, client_address, advertised_routes FROM peers " + "WHERE advertised_routes IS NOT NULL AND advertised_routes != '' ORDER BY name" + ) + for row in cur.fetchall(): + wg_ip = (row["client_address"] or "").split("/")[0] + routes = [] + for r in (row["advertised_routes"] or "").split(","): + r = r.strip() + if r: + net, mask = _cidr_parts(r) + routes.append({"cidr": r, "net": net, "mask": mask}) + if wg_ip and routes: + route_peers.append({"name": row["name"], "wg_ip": wg_ip, "routes": routes}) + + return render_template("scripts.html", commands=commands, paths=paths, route_peers=route_peers) if __name__ == "__main__": diff --git a/gui/static/style.css b/gui/static/style.css index 20085f0..c7f4f23 100644 --- a/gui/static/style.css +++ b/gui/static/style.css @@ -103,24 +103,25 @@ body { .logout-btn:hover { background: #fee2e2; color: #dc2626; } -.made-by { - font-family: 'Dancing Script', cursive; - font-size: 18px; - color: #b0b8cc; +.page-footer { text-align: center; - padding: 8px 0 4px; + padding: 18px 32px 24px; + font-family: 'Dancing Script', cursive; + font-size: 20px; + color: #c4cad8; letter-spacing: 0.02em; } -.made-by a { +.page-footer a { color: inherit; text-decoration: none; + transition: color 0.15s; } -.made-by a:hover { color: var(--accent); } +.page-footer a:hover { color: var(--accent); } /* ─── Layout ────────────────────────────────────────────────── */ -.layout { margin-left: var(--sidebar-w); flex: 1; display: flex; flex-direction: column; } +.layout { margin-left: var(--sidebar-w); flex: 1; display: flex; flex-direction: column; min-height: 100vh; } main { padding: 28px 32px; flex: 1; max-width: 1400px; width: 100%; } /* ─── Page header ───────────────────────────────────────────── */ diff --git a/gui/templates/base.html b/gui/templates/base.html index b443cf9..d0a7b57 100644 --- a/gui/templates/base.html +++ b/gui/templates/base.html @@ -32,7 +32,6 @@ Выйти -
Made by Galyaviev
@@ -49,6 +48,9 @@ {% endwith %} {% block content %}{% endblock %} +
diff --git a/gui/templates/scripts.html b/gui/templates/scripts.html index 1240d2f..12b5583 100644 --- a/gui/templates/scripts.html +++ b/gui/templates/scripts.html @@ -12,13 +12,58 @@
{{ key }}
{{ cmd }}
- +
{% endfor %} +{% if route_peers %} +
+

Маршруты к клиентам за peer

+

+ Команды для других VPN-клиентов, чтобы они могли достучаться до сетей за peer-ом. +

+ +
+ + +
+ +
+ {% for peer in route_peers %} +
+
{{ peer.name }}  — WG IP: {{ peer.wg_ip }}
+ + {% for route in peer.routes %} +
+
sudo ip route add {{ route.cidr }} via {{ peer.wg_ip }}
+ + +
+ {% endfor %} +
+ {% endfor %} +
+ +
+ Постоянные маршруты:
+ Linux: добавьте в /etc/rc.local или конфиг интерфейса.
+ Windows: добавьте флаг -proute -p add ... — маршрут сохранится после перезагрузки. +
+
+{% endif %} +

Важные пути