fix(openvpn-phone): use OpenVPN server mode, push routes to the client
lint / yamllint + ansible-lint + syntax-check (push) Canceled after 0s
lint / yamllint + ansible-lint + syntax-check (push) Canceled after 0s
The TLS tunnel came up but no LAN traffic flowed: "OpenVPN for Android" does not install the config-local `route` statements from a route-based p2p setup, so nothing was directed into tun. Zero packets ever reached tun2 on ru-vps. Switch the instance to a real `server` (topology subnet, 10.80.0.0/29 pool) and hand the LAN routes to the client via `push "route ..."`. Pushed routes are installed by every OpenVPN client, mobile included. The client profile drops to a plain `client` config (pull), keeping peer-fingerprint auth and inline cert/key. Also: widen NAT/forward from /30 to /29 (server mode needs a pool) and drop the now-stale /30 ufw route + MASQUERADE left by the p2p version. Verified on ru-vps: "Initialization Sequence Completed", tun2 10.80.0.1/29, ufw shows only the /29 forward rule, make openvpn-phone idempotent. The regenerated ada-phone.ovpn must be re-imported on the phone. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbuZrUoevfBgCpf5DCF4DG
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
dfcee00232
commit
203751d874
@@ -2,17 +2,19 @@
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Road-warrior OpenVPN профиль для телефона (Android).
|
# Road-warrior OpenVPN профиль для телефона (Android).
|
||||||
#
|
#
|
||||||
# Отдельный TLS point-to-point инстанс на ru-vps (порт 9444/tcp, tun2,
|
# Отдельный OpenVPN server-инстанс на ru-vps (порт 9444/tcp, tun2, пул
|
||||||
# сеть 10.80.0.0/30), параллельный тоннелю site-to-site (tun0, homelab-openvpn)
|
# 10.80.0.0/29), параллельный тоннелю site-to-site (tun0, homelab-openvpn)
|
||||||
# и профилю ноутбука (tun1, openvpn-laptop.yml). Клиент подключается один за
|
# и профилю ноутбука (tun1, openvpn-laptop.yml).
|
||||||
# раз.
|
|
||||||
#
|
#
|
||||||
# КРИПТО: peer-fingerprint, БЕЗ CA/PKI.
|
# КРИПТО: peer-fingerprint, БЕЗ CA/PKI.
|
||||||
# На ru-vps генерятся две самоподписанные EC-пары (server.* и client.*),
|
# На ru-vps генерятся две самоподписанные EC-пары (server.* и client.*),
|
||||||
# каждая сторона пинит другую по SHA256-отпечатку. Это «quick setup»
|
# стороны пинят друг друга по SHA256-отпечатку. Прежняя схема со static
|
||||||
# из man-страницы OpenVPN 2.6+. Прежняя схема со static key (--secret)
|
# key (--secret) отброшена: OpenVPN 2.7 в Android-клиенте её не запускает.
|
||||||
# отброшена: OpenVPN 2.7 в Android-клиенте запускать её отказывается
|
#
|
||||||
# ("No tls-client or tls-server option"), а 2.8 уберёт совсем.
|
# РЕЖИМ: полноценный `server` (не p2p), маршруты в LAN раздаются через
|
||||||
|
# `push "route ..."`. Через p2p static-key/tls «OpenVPN for Android»
|
||||||
|
# локальные `route` из конфига не подхватывал — тоннель вставал, но
|
||||||
|
# трафик в LAN не заворачивался. Через push маршруты ставит любой клиент.
|
||||||
#
|
#
|
||||||
# КЛИЕНТ
|
# КЛИЕНТ
|
||||||
# Android — «OpenVPN for Android» (Arne Schwabe) или OpenVPN Connect:
|
# Android — «OpenVPN for Android» (Arne Schwabe) или OpenVPN Connect:
|
||||||
@@ -21,7 +23,7 @@
|
|||||||
# ЧТО ДЕЛАЕТ
|
# ЧТО ДЕЛАЕТ
|
||||||
# Ставит openvpn на ru-vps, генерит EC-пары (один раз), открывает
|
# Ставит openvpn на ru-vps, генерит EC-пары (один раз), открывает
|
||||||
# 9444/tcp в UFW, поднимает systemd-юнит homelab-openvpn-phone, NAT'ит
|
# 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, содержит приватный ключ).
|
# ansible/generated/ada-phone.ovpn (mode 0600, содержит приватный ключ).
|
||||||
#
|
#
|
||||||
# ЗАПУСК
|
# ЗАПУСК
|
||||||
@@ -43,9 +45,10 @@
|
|||||||
phone_openvpn_port: 9444
|
phone_openvpn_port: 9444
|
||||||
phone_openvpn_interface: tun2
|
phone_openvpn_interface: tun2
|
||||||
phone_openvpn_site_interface: tun0
|
phone_openvpn_site_interface: tun0
|
||||||
phone_openvpn_network_cidr: 10.80.0.0/30
|
# server-режим: нужен пул адресов, поэтому /29, а не /30 p2p.
|
||||||
phone_openvpn_server_ip: 10.80.0.1
|
phone_openvpn_network_cidr: 10.80.0.0/29
|
||||||
phone_openvpn_client_ip: 10.80.0.2
|
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_remote: 157.22.231.198
|
||||||
phone_openvpn_data_ciphers: "AES-256-GCM:AES-128-GCM"
|
phone_openvpn_data_ciphers: "AES-256-GCM:AES-128-GCM"
|
||||||
phone_openvpn_client_config_local: "{{ playbook_dir }}/../generated/{{ phone_profile_name }}.ovpn"
|
phone_openvpn_client_config_local: "{{ playbook_dir }}/../generated/{{ phone_profile_name }}.ovpn"
|
||||||
@@ -191,6 +194,27 @@
|
|||||||
src: "{{ phone_openvpn_network_cidr }}"
|
src: "{{ phone_openvpn_network_cidr }}"
|
||||||
dest: "{{ homelab_lan_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
|
- name: Render phone OpenVPN server config
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: "{{ phone_openvpn_config }}"
|
dest: "{{ phone_openvpn_config }}"
|
||||||
@@ -200,19 +224,22 @@
|
|||||||
content: |
|
content: |
|
||||||
dev {{ phone_openvpn_interface }}
|
dev {{ phone_openvpn_interface }}
|
||||||
dev-type tun
|
dev-type tun
|
||||||
ifconfig {{ phone_openvpn_server_ip }} {{ phone_openvpn_client_ip }}
|
|
||||||
proto tcp-server
|
proto tcp-server
|
||||||
port {{ phone_openvpn_port }}
|
port {{ phone_openvpn_port }}
|
||||||
tls-server
|
server {{ phone_openvpn_server_subnet }} {{ phone_openvpn_server_netmask }}
|
||||||
|
topology subnet
|
||||||
dh none
|
dh none
|
||||||
cert {{ phone_openvpn_server_cert }}
|
cert {{ phone_openvpn_server_cert }}
|
||||||
key {{ phone_openvpn_server_key }}
|
key {{ phone_openvpn_server_key }}
|
||||||
peer-fingerprint {{ phone_openvpn_client_fp }}
|
peer-fingerprint {{ phone_openvpn_client_fp }}
|
||||||
data-ciphers {{ phone_openvpn_data_ciphers }}
|
data-ciphers {{ phone_openvpn_data_ciphers }}
|
||||||
auth SHA256
|
auth SHA256
|
||||||
|
keepalive 10 60
|
||||||
|
{% for route in phone_openvpn_routes %}
|
||||||
|
push "route {{ route.network }} {{ route.netmask }}"
|
||||||
|
{% endfor %}
|
||||||
persist-key
|
persist-key
|
||||||
persist-tun
|
persist-tun
|
||||||
keepalive 10 60
|
|
||||||
verb 3
|
verb 3
|
||||||
notify: restart phone openvpn
|
notify: restart phone openvpn
|
||||||
|
|
||||||
@@ -302,12 +329,11 @@
|
|||||||
dest: "{{ phone_openvpn_client_config_local }}"
|
dest: "{{ phone_openvpn_client_config_local }}"
|
||||||
mode: "0600"
|
mode: "0600"
|
||||||
content: |
|
content: |
|
||||||
|
client
|
||||||
dev tun
|
dev tun
|
||||||
dev-type tun
|
dev-type tun
|
||||||
proto tcp-client
|
proto tcp-client
|
||||||
remote {{ phone_openvpn_remote }} {{ phone_openvpn_port }}
|
remote {{ phone_openvpn_remote }} {{ phone_openvpn_port }}
|
||||||
ifconfig {{ phone_openvpn_client_ip }} {{ phone_openvpn_server_ip }}
|
|
||||||
tls-client
|
|
||||||
peer-fingerprint {{ phone_openvpn_server_fp }}
|
peer-fingerprint {{ phone_openvpn_server_fp }}
|
||||||
data-ciphers {{ phone_openvpn_data_ciphers }}
|
data-ciphers {{ phone_openvpn_data_ciphers }}
|
||||||
auth SHA256
|
auth SHA256
|
||||||
@@ -316,9 +342,6 @@
|
|||||||
resolv-retry infinite
|
resolv-retry infinite
|
||||||
nobind
|
nobind
|
||||||
verb 3
|
verb 3
|
||||||
{% for route in phone_openvpn_routes %}
|
|
||||||
route {{ route.network }} {{ route.netmask }}
|
|
||||||
{% endfor %}
|
|
||||||
<cert>
|
<cert>
|
||||||
{{ phone_openvpn_client_cert_raw.content | b64decode | trim }}
|
{{ phone_openvpn_client_cert_raw.content | b64decode | trim }}
|
||||||
</cert>
|
</cert>
|
||||||
|
|||||||
Reference in New Issue
Block a user