====== OpenVPN ====== 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 [[https://github.com/angristan/openvpn-install|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: {{:it:linux:desktop:pasted:20250513-214557.png}} Když jsem ji neměl zaškrtnutou, tak mi po připojení k VPN nešel internet. ===== Nastavení DNS serveru pro OpenVPN ===== 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. ===== Problémy s SSH ===== 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 * mssfix 1200 přinutí OpenVPN, aby upravilo MSS v TCP handshake na 1200 B, takže SSHKEX paket nikdy nepřesáhne bezpečnou velikost. * tun-mtu 1400 pak nastavení tun-rozhraní na 1 400 B, aby zbyl dostatek místa i na OpenVPN hlavičky. 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. ===== Automatické připojení k OpenVPN serveru ===== 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:** * Přejmenuj soubor na `myclient.conf` * Přidej (nebo ponech) `keepalive 10 60` * Zkontroluj umístění: `**/etc/openvpn/client/myclient.conf**` * Aktivuj a spusť službu: systemctl enable openvpn-client@myclient systemctl start openvpn-client@myclient **Ověření funkčnosti:** * Stav služby: systemctl status openvpn-client@myclient * Aktivní tunel poznáš podle rozhraní `tun0`: ip a | grep tun0 * Pro zobrazení logů: journalctl -u openvpn-client@myclient ---- ===== Forwarding na zařízení uvnitř sítě ===== 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