notebookvb
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
# WireGuard road-warrior na MikroTiku (router-hosted)
|
||||||
|
|
||||||
|
Nastaveno 2026-06-18 podle runbooku `wireguard-mikrotik-runbook.md`.
|
||||||
|
|
||||||
|
## Router
|
||||||
|
- **MikrotikFirewall** (hEX, RouterOS 7.19.6), LAN IP `192.168.1.2`, SSH port **22**.
|
||||||
|
- WAN = `pppoe-out1`, veřejná IP `78.80.38.51` (PPPoE, bere se jako statická).
|
||||||
|
|
||||||
|
## DŮLEŽITÉ — proč port 51821, ne 51820
|
||||||
|
Na routeru **už běží jiná WireGuard VPN na Unraidu** (`192.168.1.76`): NAT rule
|
||||||
|
„WireGuard to Unraid" DST-NATuje příchozí UDP **51820** na Unraid. Proto tahle
|
||||||
|
nová, **na routeru hostovaná** VPN běží na **UDP 51821** (51820 by se nikdy
|
||||||
|
nedostalo k routeru). Existující Unraid VPN ani tunel `10.253.0.0/24` nejsou dotčené.
|
||||||
|
|
||||||
|
## Parametry této VPN
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| WG rozhraní | `wg-vpn`, listen-port **51821** |
|
||||||
|
| Server public key | `CGGFHYR83W8IuTB46cJ49IuL/tL3w4yu3o0hQh0Cxwo=` |
|
||||||
|
| Tunelová síť | `10.10.10.0/24`, router `10.10.10.1` |
|
||||||
|
| Klienti | `10.10.10.2` (client2), `.3` (client3), `.4` (client4) |
|
||||||
|
| Endpoint | `78.80.38.51:51821` |
|
||||||
|
| Split tunel | AllowedIPs = `192.168.1.0/24` (jen LAN přes VPN) |
|
||||||
|
| DNS klientů | `192.168.1.2` (router) |
|
||||||
|
|
||||||
|
## Přidané firewall pravidla (jen accept, nic nemazáno/nepřeřazeno)
|
||||||
|
- input: accept udp dst-port 51821 in-interface=pppoe-out1 „WireGuard in (router)"
|
||||||
|
- input: accept in-interface=wg-vpn „WG -> router (DNS/ping)" (DNS a ping na router z tunelu)
|
||||||
|
- forward: accept in-interface=wg-vpn „WG -> LAN"
|
||||||
|
Všechna vložena PŘED příslušné `drop` v daném chainu.
|
||||||
|
NAT hairpin **nepřidán** — LAN hosti mají router jako default gw, návratová cesta funguje.
|
||||||
|
|
||||||
|
## Skripty
|
||||||
|
- `rosrun.py` — spouští RouterOS příkazy přes SSH. Creds z env: `ROS_HOST/ROS_PORT/ROS_USER/ROS_PASS`.
|
||||||
|
Pozn.: v Git Bash nutné `MSYS_NO_PATHCONV=1` a příkazy přes stdin (ne `--cmd`, mangluje `/...`).
|
||||||
|
- `gen_clients.py` — generuje klíče (wg.exe) + `.conf` + QR PNG do `wg-clients/`, a `_peers_add.rsc`.
|
||||||
|
|
||||||
|
## Klientské konfigurace
|
||||||
|
`wg-clients/clientN.conf` (import na notebook) + `wg-clients/clientN.png` (QR pro mobilní app).
|
||||||
|
**Obsahují privátní klíče** — po rozdání na zařízení smaž, ať neleží zbytečně.
|
||||||
|
|
||||||
|
## Test (jen zvenku, ne z LAN!)
|
||||||
|
Telefon na mobilních datech → naskenuj QR → ověř `ping 192.168.1.2`. Z LAN to
|
||||||
|
handshake neudělá (accept je vázán na in-interface=pppoe-out1, hairpin pro 51821 není).
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
```
|
||||||
|
/interface wireguard peers remove [find interface=wg-vpn]
|
||||||
|
/ip firewall filter remove [find comment="WG -> LAN"]
|
||||||
|
/ip firewall filter remove [find comment="WG -> router (DNS/ping)"]
|
||||||
|
/ip firewall filter remove [find comment="WireGuard in (router)"]
|
||||||
|
/ip address remove [find interface=wg-vpn]
|
||||||
|
/interface wireguard remove [find name=wg-vpn]
|
||||||
|
```
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Generate WireGuard road-warrior client configs + QR PNGs, and emit RouterOS peer-add commands."""
|
||||||
|
import subprocess, pathlib, qrcode
|
||||||
|
|
||||||
|
WG = r"C:\Program Files\WireGuard\wg"
|
||||||
|
SERVER_PUB = "CGGFHYR83W8IuTB46cJ49IuL/tL3w4yu3o0hQh0Cxwo="
|
||||||
|
ENDPOINT = "78.80.38.51:51821"
|
||||||
|
LAN = "192.168.1.0/24" # split tunnel -> only LAN goes through VPN
|
||||||
|
DNS = "192.168.1.2" # router LAN IP
|
||||||
|
|
||||||
|
CLIENTS = [2, 3, 4]
|
||||||
|
outdir = pathlib.Path(__file__).resolve().parent / "wg-clients"
|
||||||
|
outdir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
def wg(*args, inp=None):
|
||||||
|
return subprocess.run([WG, *args], input=inp, capture_output=True,
|
||||||
|
text=True, check=True).stdout.strip()
|
||||||
|
|
||||||
|
|
||||||
|
peer_cmds = []
|
||||||
|
for i in CLIENTS:
|
||||||
|
name = f"client{i}"
|
||||||
|
priv = wg("genkey")
|
||||||
|
pub = wg("pubkey", inp=priv)
|
||||||
|
psk = wg("genpsk")
|
||||||
|
|
||||||
|
conf = f"""[Interface]
|
||||||
|
PrivateKey = {priv}
|
||||||
|
Address = 10.10.10.{i}/32
|
||||||
|
DNS = {DNS}
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = {SERVER_PUB}
|
||||||
|
PresharedKey = {psk}
|
||||||
|
AllowedIPs = {LAN}
|
||||||
|
Endpoint = {ENDPOINT}
|
||||||
|
PersistentKeepalive = 25
|
||||||
|
"""
|
||||||
|
(outdir / f"{name}.conf").write_text(conf, encoding="utf-8")
|
||||||
|
|
||||||
|
img = qrcode.make(conf)
|
||||||
|
img.save(outdir / f"{name}.png")
|
||||||
|
|
||||||
|
peer_cmds.append(
|
||||||
|
f'/interface wireguard peers add interface=wg-vpn '
|
||||||
|
f'public-key="{pub}" preshared-key="{psk}" '
|
||||||
|
f'allowed-address=10.10.10.{i}/32 comment="{name}"'
|
||||||
|
)
|
||||||
|
print(f"[ok] {name}: pub={pub} -> {name}.conf, {name}.png")
|
||||||
|
|
||||||
|
(outdir / "_peers_add.rsc").write_text("\n".join(peer_cmds) + "\n", encoding="utf-8")
|
||||||
|
print("\n--- RouterOS peer-add commands written to wg-clients/_peers_add.rsc ---")
|
||||||
|
for c in peer_cmds:
|
||||||
|
print(c)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# ROLLBACK — obnova Unraid WireGuard objektů na routeru MikrotikFirewall
|
||||||
|
# Odstraněno 2026-06-18 na žádost uživatele. Spusť tyto příkazy pro obnovu.
|
||||||
|
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=192.168.1.76 to-ports=51820 protocol=udp in-interface=pppoe-out1 dst-port=51820 comment="WireGuard to Unraid"
|
||||||
|
/ip firewall filter add chain=input action=accept protocol=udp in-interface=pppoe-out1 dst-port=51820 comment="Allow WireGuard"
|
||||||
|
/ip firewall filter add chain=forward action=accept src-address=10.253.0.0/24 comment="Allow VPN to LAN"
|
||||||
|
/ip firewall filter add chain=forward action=accept dst-address=10.253.0.0/24 comment="Allow LAN to VPN"
|
||||||
|
/ip route add dst-address=10.253.0.0/24 gateway=192.168.1.76 comment="Route to WireGuard VPN via Unraid"
|
||||||
|
# Pozn.: po obnově zkontroluj pořadí filter pravidel (accept musí být PŘED drop).
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Run RouterOS commands over SSH. Creds from env: ROS_HOST, ROS_PORT, ROS_USER, ROS_PASS.
|
||||||
|
Commands: one per line on stdin, or via --cmd. Prints output per command."""
|
||||||
|
import os, sys, paramiko
|
||||||
|
|
||||||
|
host = os.environ["ROS_HOST"]
|
||||||
|
port = int(os.environ.get("ROS_PORT", "22"))
|
||||||
|
user = os.environ["ROS_USER"]
|
||||||
|
pw = os.environ["ROS_PASS"]
|
||||||
|
|
||||||
|
cmds = []
|
||||||
|
if "--cmd" in sys.argv:
|
||||||
|
cmds = [sys.argv[sys.argv.index("--cmd") + 1]]
|
||||||
|
else:
|
||||||
|
cmds = [l.rstrip("\n") for l in sys.stdin if l.strip()]
|
||||||
|
|
||||||
|
cli = paramiko.SSHClient()
|
||||||
|
cli.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
|
cli.connect(host, port=port, username=user, password=pw,
|
||||||
|
look_for_keys=False, allow_agent=False, timeout=20)
|
||||||
|
|
||||||
|
for c in cmds:
|
||||||
|
print(f"\n===== CMD: {c}")
|
||||||
|
stdin, stdout, stderr = cli.exec_command(c, timeout=30)
|
||||||
|
out = stdout.read().decode("utf-8", "replace")
|
||||||
|
err = stderr.read().decode("utf-8", "replace")
|
||||||
|
sys.stdout.write(out)
|
||||||
|
if err.strip():
|
||||||
|
sys.stdout.write("--- stderr ---\n" + err)
|
||||||
|
cli.close()
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
/interface wireguard peers add interface=wg-vpn public-key="nToZ1GzONgfW1ve3O1WeEpGbgzUMhDVKE7qrD/Jc23c=" preshared-key="Y6eHm6MbLa+tyleSgwbPc8oJqLZkXZkMEUJZDU7f5kg=" allowed-address=10.10.10.2/32 comment="client2"
|
||||||
|
/interface wireguard peers add interface=wg-vpn public-key="tqA98HvVupGGYpR1PUe7/j9DO8MtaNP3Fh5tkpqgqD0=" preshared-key="94TmjBE+mTZi3KDy/tWefq/wXPpvmBtjPlX/LZnAKbE=" allowed-address=10.10.10.3/32 comment="client3"
|
||||||
|
/interface wireguard peers add interface=wg-vpn public-key="j/3kzNQ6vmUL4xFmqq5PL6Qf1xVWPzVWEXoOkBIDxFk=" preshared-key="pHR1441168wSrjlLZ2E44J4WrHpLRuWdjfsNHk23CQ8=" allowed-address=10.10.10.4/32 comment="client4"
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[Interface]
|
||||||
|
PrivateKey = YPvh0rKU+xi82eQftBucCnuQzZNqk9jOHLwfEH0wsGk=
|
||||||
|
Address = 10.10.10.2/32
|
||||||
|
DNS = 192.168.1.2
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = CGGFHYR83W8IuTB46cJ49IuL/tL3w4yu3o0hQh0Cxwo=
|
||||||
|
PresharedKey = Y6eHm6MbLa+tyleSgwbPc8oJqLZkXZkMEUJZDU7f5kg=
|
||||||
|
AllowedIPs = 192.168.1.0/24
|
||||||
|
Endpoint = 78.80.38.51:51821
|
||||||
|
PersistentKeepalive = 25
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,11 @@
|
|||||||
|
[Interface]
|
||||||
|
PrivateKey = 8JFWJp/zvoRYl7w2Jon0Xv+9YidiguiC26qGbr4ozlg=
|
||||||
|
Address = 10.10.10.3/32
|
||||||
|
DNS = 192.168.1.2
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = CGGFHYR83W8IuTB46cJ49IuL/tL3w4yu3o0hQh0Cxwo=
|
||||||
|
PresharedKey = 94TmjBE+mTZi3KDy/tWefq/wXPpvmBtjPlX/LZnAKbE=
|
||||||
|
AllowedIPs = 192.168.1.0/24
|
||||||
|
Endpoint = 78.80.38.51:51821
|
||||||
|
PersistentKeepalive = 25
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,11 @@
|
|||||||
|
[Interface]
|
||||||
|
PrivateKey = oLcUtFkDW/e0/xmDgdBMlWIpGGL+eOvMxgnyXxtd5Ww=
|
||||||
|
Address = 10.10.10.4/32
|
||||||
|
DNS = 192.168.1.2
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = CGGFHYR83W8IuTB46cJ49IuL/tL3w4yu3o0hQh0Cxwo=
|
||||||
|
PresharedKey = pHR1441168wSrjlLZ2E44J4WrHpLRuWdjfsNHk23CQ8=
|
||||||
|
AllowedIPs = 192.168.1.0/24
|
||||||
|
Endpoint = 78.80.38.51:51821
|
||||||
|
PersistentKeepalive = 25
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
Reference in New Issue
Block a user