Pro servisní účely jsem potřeboval rychle rozběhnout OpenVPN. Nejprve jsem se docela trápil s nastavením konfiguračních souborů a certifikátů. Nicméně pak jsem objevil skript, který většinu věcí udělá za mě.
Projekt se skriptem se jmenuje openvpn-install.
Stažení je jednoduché:
curl -O https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh chmod +x openvpn-install.sh
A pak už jenom spustit:
./openvpn-install.sh
Zbytkem provede jednoduchý průvodce. Pokud chci vytvářet další uživatele a jejich certifikáty po instalaci, stačí skript spustit znovu a v nabídce se objeví možnost Add a client. Úplně stejně budu postupovat, pokud budu chtít vypnout nějakého klienta.
Skript mi vytvořil soubor /etc/iptables/add-openvpn-rules.sh, ve kterém bylo nachystáno routování do vnitřní sítě. Nemusel jsem se tedy trápit s tím, že když se připojím do VPN sítě, tak se nedostanu do vnitřní sítě.
Tady je obsah souboru:
#!/bin/sh iptables -t nat -I POSTROUTING 1 -s 10.8.0.0/24 -o wan -j MASQUERADE iptables -I INPUT 1 -i tun0 -j ACCEPT iptables -I FORWARD 1 -i wan -o tun0 -j ACCEPT iptables -I FORWARD 1 -i tun0 -o wan -j ACCEPT iptables -I INPUT 1 -i wan -p udp --dport 1194 -j ACCEPT
Dále pak vytvoří soubor /etc/systemd/system/multi-user.target.wants/iptables-openvpn.service, který nastavuje v systemd spouštění skriptu s iptables:
[Unit] Description=iptables rules for OpenVPN Before=network-online.target Wants=network-online.target [Service] Type=oneshot ExecStart=/etc/iptables/add-openvpn-rules.sh ExecStop=/etc/iptables/rm-openvpn-rules.sh RemainAfterExit=yes [Install] WantedBy=multi-user.target
A jako další vytvoří soubor pro spouštění vpnserveru /etc/systemd/system/multi-user.target.wants/openvpn@server.service.
Dále mi ve složce /etc/openvpn vytvořil konfigurační soubor server.conf.
Pokud chci zařídit, aby po připojení k VPN nešel internet přes VPN server, tak je potřeba v konfiguračním souboru serveru zakomentovat tento řádek:
#push "redirect-gateway def1 bypass-dhcp"
Dále je možné mít klidně více instancí OpenVPN serveru. Stačí zkopírovat konfigurační soubor server.conf a vytvořit například server2.conf. V souboru editovat vše potřebné a poté spustit další instanci serveru:
openvpn --config server2.conf
Pokud mám VPN server nastavená tak, že nebude směřovat tok internetu přes server, je potřeba ještě u VPN klienta u připojení zaškrtnout tuto volbu:
Když jsem ji neměl zaškrtnutou, tak mi po připojení k VPN nešel internet.
Při konfiguraci OpenVPN serveru je možné nastavit, jaký DNS server bude klient používat po připojení. To se provádí přidáním následujícího řádku do konfigurace OpenVPN serveru:
push "dhcp-option DNS 192.168.1.50"
Tento příkaz zajistí, že klient po připojení použije DNS server s IP adresou 192.168.1.50. Lze přidat i více DNS serverů, přičemž první uvedený bude primární.
Po připojení přes OpenVPN jsem ověřil nastavení DNS serveru pomocí příkazu:
resolvectl status
Výstup tohoto příkazu zobrazil aktuálně používané DNS servery, což umožňuje ověřit, zda se změna správně projevila.
Měl jsem problém, že ze serveru se mi nedařilo navázat spojení přes SSH u klientského počítače, který byl připojený přes VPN. Přitom ping na počítač fungoval a nmap mi potvrdil, že port s SSH je otevřený. Po delším zkoušení mě to dovedlo k tomu, že patrně dochází k fragmentaci packetů.
OpenVPN ve výchozím nastavení nebrání fragmentaci velkých TCP segmentů uvnitř tun-virt-rozhraní. Vaše MTU (1500 B na tun0) minus kryptografický overhead protokolu UDP/OpenVPN a minus IP/UDP hlavičky vychází někde kolem 1 400 B. Server ale posílá kusy až 1 388 B – to sice vypadá v pořádku, ale když se součet uvnitř šifrovaného UDP tunelu překlene do fragmentů (nebo někde v síti fragmenty zahazují), klient je už nikdy neslepí a TCP je neposkytne uživatelské aplikaci.
Vyřešil jsem to tak, že na konfiguračního souboru serveru jsem přidal:
mssfix 1200 tun-mtu 1400
Bylo mi doporučeno to přidat i do konfiguračního souboru klienta, ale tam jsem to nepřidával a zatím to vypadá, že SSH už funguje.
Cílem je zajistit, aby se OpenVPN klient automaticky připojoval po startu systému a zároveň přesměrovával příchozí síťovou komunikaci na konkrétní zařízení ve vnitřní síti.
Klíčové je vložit konfigurační soubor do složky `/etc/openvpn/client/` a zajistit, aby měl příponu `.conf`. OpenVPN sice podporuje i příponu `.ovpn`, ale pouze `.conf` je systemd schopen automaticky spouštět.
Pro ruční spuštění postačí:
openvpn --config myclient.ovpn
Pro automatické spouštění použij:
systemctl start openvpn-client@myclient.service
Tento příkaz hledá konfigurační soubor `/etc/openvpn/client/myclient.conf`.
Doporučení: Chceš-li využívat výhody systemd (např. automatické restartování), přejmenuj soubor na `myclient.conf`. Obsah souboru může zůstat stejný jako `.ovpn`.
Pro stabilní spojení doporučujeme přidat do konfigurace řádek:
keepalive 10 60
To znamená, že klient každých 10 vteřin pošle „ping“ a po 60 vteřinách bez odpovědi restartuje spojení. Tento zápis je zjednodušený alias pro `–ping 10` a `–ping-restart 60`.
Shrnutí postupu:
systemctl enable openvpn-client@myclient systemctl start openvpn-client@myclient
Ověření funkčnosti:
systemctl status openvpn-client@myclient
ip a | grep tun0
journalctl -u openvpn-client@myclient
Aby bylo možné přeposílat komunikaci z VPN na zařízení v lokální síti, je potřeba povolit IP forwarding.
V souboru `/etc/sysctl.conf` nastav:
net.ipv4.ip_forward=1
Změnu načti pomocí:
sysctl -p
Přesměrování provozu pak zajistí vlastní skripty. Níže je příklad jednoduchého nastavení pro zařízení s IP `192.168.0.120`.
/etc/openvpn/up.sh
#!/usr/bin/env bash set -euo pipefail # Tento skript nakonfiguruje DNAT z OpenVPN (tun0) na interní stroj 10.112.234.112 # Přesměrování všech portů kromě SSH (port 22) s vyčištěním starých pravidel # Kontrola, zda běží pod rootem if [[ "$EUID" -ne 0 ]]; then echo "Prosím spusťte jako root nebo pomocí sudo." >&2 exit 1 fi # Proměnné – upravte podle potřeby VPN_IF="tun0" INT_IF="eth0" DEST_IP="192.168.0.120" EXCLUDE_PORT="22" # 0) Načtení FTP helper modulů #modprobe nf_conntrack_ftp #modprobe nf_nat_ftp # 0b) Připojení FTP helperu pro control channel (port 21) iptables-legacy -t raw -A PREROUTING \ -i "$VPN_IF" \ -p tcp --dport 21 \ -j CT --helper ftp # 1) Vyčištění stávajících pravidel NAT a FORWARD iptables-legacy -t nat -F PREROUTING iptables-legacy -t nat -F POSTROUTING iptables-legacy -F FORWARD # 2) Povolit IP forwarding sysctl -w net.ipv4.ip_forward=1 if ! grep -q '^net.ipv4.ip_forward' /etc/sysctl.conf; then echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf fi # 3) DNAT: přesměrování všech TCP portů kromě SSH na interní stroj iptables-legacy -t nat -A PREROUTING \ -i "$VPN_IF" \ -p tcp -m tcp ! --dport "$EXCLUDE_PORT" \ -j DNAT --to-destination ${DEST_IP} # 4) DNAT: přesměrování všech UDP portů kromě SSH na interní stroj iptables-legacy -t nat -A PREROUTING \ -i "$VPN_IF" \ -p udp -m udp ! --dport "$EXCLUDE_PORT" \ -j DNAT --to-destination ${DEST_IP} # 5) Povolit forward chain pro směry tun0 → eth0 (nové i navázané relace) iptables-legacy -A FORWARD \ -i "$VPN_IF" -o "$INT_IF" -d "$DEST_IP" \ -j ACCEPT iptables-legacy -A FORWARD \ -i "$INT_IF" -o "$VPN_IF" \ -m state --state ESTABLISHED,RELATED \ -j ACCEPT # 6) SNAT/MASQUERADE pro interní stroj, pokud nemá přímou zpětnou cestu iptables-legacy -t nat -A POSTROUTING \ -o "$INT_IF" \ -d "$DEST_IP" \ -j MASQUERADE # Hotovo echo "Vyčištěna stará pravidla a aplikován DNAT pro všechna porty kromě portu ${EXCLUDE_PORT}."
/etc/openvpn/down.sh
#!/usr/bin/env bash set -euo pipefail # Tento skript odstraní pravidla DNAT a SNAT z předchozího setupu # Kontrola, zda běží pod rootem if [[ "$EUID" -ne 0 ]]; then echo "Prosím spusťte jako root nebo pomocí sudo." >&2 exit 1 fi # Proměnné – musí odpovídat setup skriptu VPN_IF="tun0" INT_IF="eth0" DEST_IP="192.168.0.120" EXCLUDE_PORT="22" # Odstranění raw/FTP helper pravidla iptables-legacy -t raw -D PREROUTING -i "$VPN_IF" -p tcp --dport 21 -j CT --helper ftp || true # Vyčištění pravidel NAT a FORWARD vztahujících se k tun0 a DEST_IP iptables-legacy -t nat -D PREROUTING -i "$VPN_IF" -p tcp -m tcp ! --dport "$EXCLUDE_PORT" -j DNAT --to-destination ${DEST_IP} || true iptables-legacy -t nat -D PREROUTING -i "$VPN_IF" -p udp -m udp ! --dport "$EXCLUDE_PORT" -j DNAT --to-destination ${DEST_IP} || true iptables-legacy -t nat -D POSTROUTING -o "$INT_IF" -d "$DEST_IP" -j MASQUERADE || true iptables-legacy -D FORWARD -i "$VPN_IF" -o "$INT_IF" -d "$DEST_IP" -j ACCEPT || true iptables-legacy -D FORWARD -i "$INT_IF" -o "$VPN_IF" -m state --state ESTABLISHED,RELATED -j ACCEPT || true # Volitelné: vrátit ip_forward do výchozí hodnoty (pokud potřebujete) # sysctl -w net.ipv4.ip_forward=0 echo "Pravidla DNAT/SNAT byla odstraněna."
Poznámka: Pokud síťové rozhraní není `eth0`, uprav `$INTERNAL_IF` podle výstupu příkazu `ip a`.
Skripty je potřeba zpřístupnit pro spuštění:
chmod +x /etc/openvpn/up.sh /etc/openvpn/down.sh
A nakonec je přidej do konfiguračního souboru `myclient.conf`:
script-security 2 up /etc/openvpn/up.sh down /etc/openvpn/down.sh
Ověření po navázání tunelu:
iptables-legacy -t nat -L -n -v iptables-legacy -L -n -v