diff --git a/ansible/playbooks/openvpn-phone.yml b/ansible/playbooks/openvpn-phone.yml index 6560e6e..e93af19 100644 --- a/ansible/playbooks/openvpn-phone.yml +++ b/ansible/playbooks/openvpn-phone.yml @@ -2,17 +2,19 @@ # ============================================================================ # Road-warrior OpenVPN профиль для телефона (Android). # -# Отдельный TLS point-to-point инстанс на ru-vps (порт 9444/tcp, tun2, -# сеть 10.80.0.0/30), параллельный тоннелю site-to-site (tun0, homelab-openvpn) -# и профилю ноутбука (tun1, openvpn-laptop.yml). Клиент подключается один за -# раз. +# Отдельный OpenVPN server-инстанс на ru-vps (порт 9444/tcp, tun2, пул +# 10.80.0.0/29), параллельный тоннелю site-to-site (tun0, homelab-openvpn) +# и профилю ноутбука (tun1, openvpn-laptop.yml). # # КРИПТО: peer-fingerprint, БЕЗ CA/PKI. # На ru-vps генерятся две самоподписанные EC-пары (server.* и client.*), -# каждая сторона пинит другую по SHA256-отпечатку. Это «quick setup» -# из man-страницы OpenVPN 2.6+. Прежняя схема со static key (--secret) -# отброшена: OpenVPN 2.7 в Android-клиенте запускать её отказывается -# ("No tls-client or tls-server option"), а 2.8 уберёт совсем. +# стороны пинят друг друга по SHA256-отпечатку. Прежняя схема со static +# key (--secret) отброшена: OpenVPN 2.7 в Android-клиенте её не запускает. +# +# РЕЖИМ: полноценный `server` (не p2p), маршруты в LAN раздаются через +# `push "route ..."`. Через p2p static-key/tls «OpenVPN for Android» +# локальные `route` из конфига не подхватывал — тоннель вставал, но +# трафик в LAN не заворачивался. Через push маршруты ставит любой клиент. # # КЛИЕНТ # Android — «OpenVPN for Android» (Arne Schwabe) или OpenVPN Connect: @@ -21,7 +23,7 @@ # ЧТО ДЕЛАЕТ # Ставит openvpn на ru-vps, генерит EC-пары (один раз), открывает # 9444/tcp в UFW, поднимает systemd-юнит homelab-openvpn-phone, NAT'ит -# 10.80.0.0/30 -> LAN через tun0, кладёт готовый профиль в +# 10.80.0.0/29 -> LAN через tun0, кладёт готовый профиль в # ansible/generated/ada-phone.ovpn (mode 0600, содержит приватный ключ). # # ЗАПУСК @@ -43,9 +45,10 @@ phone_openvpn_port: 9444 phone_openvpn_interface: tun2 phone_openvpn_site_interface: tun0 - phone_openvpn_network_cidr: 10.80.0.0/30 - phone_openvpn_server_ip: 10.80.0.1 - phone_openvpn_client_ip: 10.80.0.2 + # server-режим: нужен пул адресов, поэтому /29, а не /30 p2p. + phone_openvpn_network_cidr: 10.80.0.0/29 + phone_openvpn_server_subnet: 10.80.0.0 + phone_openvpn_server_netmask: 255.255.255.248 phone_openvpn_remote: 157.22.231.198 phone_openvpn_data_ciphers: "AES-256-GCM:AES-128-GCM" phone_openvpn_client_config_local: "{{ playbook_dir }}/../generated/{{ phone_profile_name }}.ovpn" @@ -191,6 +194,27 @@ src: "{{ phone_openvpn_network_cidr }}" dest: "{{ homelab_lan_cidr }}" + # Переходная уборка: p2p-версия использовала /30. Убрать после ~2026-11. + - name: Drop the legacy /30 ufw forward rule + community.general.ufw: + route: true + rule: allow + delete: true + interface_in: "{{ phone_openvpn_interface }}" + interface_out: "{{ phone_openvpn_site_interface }}" + src: 10.80.0.0/30 + dest: "{{ homelab_lan_cidr }}" + + - name: Drop the legacy /30 MASQUERADE rule + ansible.builtin.iptables: + table: nat + chain: POSTROUTING + source: 10.80.0.0/30 + destination: "{{ homelab_lan_cidr }}" + out_interface: "{{ phone_openvpn_site_interface }}" + jump: MASQUERADE + state: absent + - name: Render phone OpenVPN server config ansible.builtin.copy: dest: "{{ phone_openvpn_config }}" @@ -200,19 +224,22 @@ content: | dev {{ phone_openvpn_interface }} dev-type tun - ifconfig {{ phone_openvpn_server_ip }} {{ phone_openvpn_client_ip }} proto tcp-server port {{ phone_openvpn_port }} - tls-server + server {{ phone_openvpn_server_subnet }} {{ phone_openvpn_server_netmask }} + topology subnet dh none cert {{ phone_openvpn_server_cert }} key {{ phone_openvpn_server_key }} peer-fingerprint {{ phone_openvpn_client_fp }} data-ciphers {{ phone_openvpn_data_ciphers }} auth SHA256 + keepalive 10 60 + {% for route in phone_openvpn_routes %} + push "route {{ route.network }} {{ route.netmask }}" + {% endfor %} persist-key persist-tun - keepalive 10 60 verb 3 notify: restart phone openvpn @@ -302,12 +329,11 @@ dest: "{{ phone_openvpn_client_config_local }}" mode: "0600" content: | + client dev tun dev-type tun proto tcp-client remote {{ phone_openvpn_remote }} {{ phone_openvpn_port }} - ifconfig {{ phone_openvpn_client_ip }} {{ phone_openvpn_server_ip }} - tls-client peer-fingerprint {{ phone_openvpn_server_fp }} data-ciphers {{ phone_openvpn_data_ciphers }} auth SHA256 @@ -316,9 +342,6 @@ resolv-retry infinite nobind verb 3 - {% for route in phone_openvpn_routes %} - route {{ route.network }} {{ route.netmask }} - {% endfor %} {{ phone_openvpn_client_cert_raw.content | b64decode | trim }}