Revert: drop the phone road-warrior OpenVPN attempt
lint / yamllint + ansible-lint + syntax-check (push) Canceled after 0s
lint / yamllint + ansible-lint + syntax-check (push) Canceled after 0s
Rolled back per the user's request. Three variants were tried on ru-vps
(static key; TLS peer-fingerprint p2p; server mode with push routes and an
inline <ca>). The server side worked each time, but the "OpenVPN for
Android" client consistently failed at config build ("Used 101 tries to
get current version of the profile"), which looks like an app/OS issue
rather than the config.
Repo: remove playbooks/openvpn-phone.yml, its Make target, and the shared
homelab_vpn_client_routes var; restore openvpn-laptop.yml to its prior
state (its pre-existing `become: false` on delegate_to: localhost is noted
in plan.md, left untouched). ru-vps teardown done out of band: unit, tun2,
ufw/nat rules for 9444 and 10.80.0.0/29, and /etc/openvpn/homelab-phone
removed; the site tunnel (homelab-openvpn, tun0) was not touched and is
verified active.
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
c5c33986da
commit
d45391a261
@@ -221,10 +221,6 @@ openvpn: ## Поднять OpenVPN-транспорт ru-vps <-> ovpn-mini (ну
|
|||||||
openvpn-laptop: ## Настроить OpenVPN-профиль ноутбука
|
openvpn-laptop: ## Настроить OpenVPN-профиль ноутбука
|
||||||
$(ANSIBLE_PLAYBOOK) playbooks/openvpn-laptop.yml $(EXTRA)
|
$(ANSIBLE_PLAYBOOK) playbooks/openvpn-laptop.yml $(EXTRA)
|
||||||
|
|
||||||
.PHONY: openvpn-phone
|
|
||||||
openvpn-phone: ## Настроить OpenVPN-профиль телефона (Android), профиль -> ansible/generated/ada-phone.ovpn
|
|
||||||
$(ANSIBLE_PLAYBOOK) playbooks/openvpn-phone.yml $(EXTRA)
|
|
||||||
|
|
||||||
.PHONY: bash-config
|
.PHONY: bash-config
|
||||||
bash-config: ## Раскатать единый bash-конфиг на shell_hosts
|
bash-config: ## Раскатать единый bash-конфиг на shell_hosts
|
||||||
$(ANSIBLE_PLAYBOOK) playbooks/bash-config.yml $(EXTRA)
|
$(ANSIBLE_PLAYBOOK) playbooks/bash-config.yml $(EXTRA)
|
||||||
|
|||||||
@@ -23,19 +23,6 @@ homelab_service_range: 192.168.1.5-192.168.1.40
|
|||||||
# Total votes меньше Expected votes и флаг NV у узлов.
|
# Total votes меньше Expected votes и флаг NV у узлов.
|
||||||
homelab_pve_egress_ip: 85.143.112.108
|
homelab_pve_egress_ip: 85.143.112.108
|
||||||
|
|
||||||
# Маршруты, которые road-warrior профили (openvpn-laptop.yml, openvpn-phone.yml)
|
|
||||||
# добавляют клиенту. НЕ весь homelab_lan_cidr: домашняя сеть клиента почти
|
|
||||||
# наверняка тоже 192.168.1.0/24, полный /24 перебил бы её. Диапазон покрывает
|
|
||||||
# 192.168.1.5-.7, .8-.15, .16-.31, .32-.39, .40 — все managed-хосты и дашборд
|
|
||||||
# (192.168.1.30), но не роутер (.1) и не игровой сервер (.100).
|
|
||||||
homelab_vpn_client_routes:
|
|
||||||
- {network: 192.168.1.5, netmask: 255.255.255.255}
|
|
||||||
- {network: 192.168.1.6, netmask: 255.255.255.254}
|
|
||||||
- {network: 192.168.1.8, netmask: 255.255.255.248}
|
|
||||||
- {network: 192.168.1.16, netmask: 255.255.255.240}
|
|
||||||
- {network: 192.168.1.32, netmask: 255.255.255.248}
|
|
||||||
- {network: 192.168.1.40, netmask: 255.255.255.255}
|
|
||||||
|
|
||||||
openvpn_network_cidr: 10.78.0.0/30
|
openvpn_network_cidr: 10.78.0.0/30
|
||||||
openvpn_listen_port: 8443
|
openvpn_listen_port: 8443
|
||||||
openvpn_forwarded_services:
|
openvpn_forwarded_services:
|
||||||
|
|||||||
@@ -16,8 +16,19 @@
|
|||||||
laptop_openvpn_client_ip: 10.79.0.2
|
laptop_openvpn_client_ip: 10.79.0.2
|
||||||
laptop_openvpn_remote: 157.22.231.198
|
laptop_openvpn_remote: 157.22.231.198
|
||||||
laptop_openvpn_client_config_local: "{{ playbook_dir }}/../generated/{{ laptop_profile_name }}.ovpn"
|
laptop_openvpn_client_config_local: "{{ playbook_dir }}/../generated/{{ laptop_profile_name }}.ovpn"
|
||||||
# Общий список с openvpn-phone.yml — см. group_vars/all/main.yml.
|
laptop_openvpn_home_routes:
|
||||||
laptop_openvpn_home_routes: "{{ homelab_vpn_client_routes }}"
|
- network: 192.168.1.5
|
||||||
|
netmask: 255.255.255.255
|
||||||
|
- network: 192.168.1.6
|
||||||
|
netmask: 255.255.255.254
|
||||||
|
- network: 192.168.1.8
|
||||||
|
netmask: 255.255.255.248
|
||||||
|
- network: 192.168.1.16
|
||||||
|
netmask: 255.255.255.240
|
||||||
|
- network: 192.168.1.32
|
||||||
|
netmask: 255.255.255.248
|
||||||
|
- network: 192.168.1.40
|
||||||
|
netmask: 255.255.255.255
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Install OpenVPN packages
|
- name: Install OpenVPN packages
|
||||||
@@ -145,10 +156,8 @@
|
|||||||
path: "{{ playbook_dir }}/../generated"
|
path: "{{ playbook_dir }}/../generated"
|
||||||
state: directory
|
state: directory
|
||||||
mode: "0700"
|
mode: "0700"
|
||||||
|
become: false
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
vars:
|
|
||||||
ansible_connection: local
|
|
||||||
ansible_become: false
|
|
||||||
|
|
||||||
- name: Write local laptop OpenVPN profile
|
- name: Write local laptop OpenVPN profile
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
@@ -173,10 +182,8 @@
|
|||||||
<secret>
|
<secret>
|
||||||
{{ laptop_openvpn_static_key_raw.content | b64decode }}
|
{{ laptop_openvpn_static_key_raw.content | b64decode }}
|
||||||
</secret>
|
</secret>
|
||||||
|
become: false
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
vars:
|
|
||||||
ansible_connection: local
|
|
||||||
ansible_become: false
|
|
||||||
no_log: true
|
no_log: true
|
||||||
|
|
||||||
handlers:
|
handlers:
|
||||||
|
|||||||
@@ -1,377 +0,0 @@
|
|||||||
---
|
|
||||||
# ============================================================================
|
|
||||||
# Road-warrior OpenVPN профиль для телефона (Android).
|
|
||||||
#
|
|
||||||
# Отдельный 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-отпечатку. Прежняя схема со 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:
|
|
||||||
# TLS-конфиг понимают оба. Профиль самодостаточный (cert+key внутри).
|
|
||||||
#
|
|
||||||
# ЧТО ДЕЛАЕТ
|
|
||||||
# Ставит openvpn на ru-vps, генерит EC-пары (один раз), открывает
|
|
||||||
# 9444/tcp в UFW, поднимает systemd-юнит homelab-openvpn-phone, NAT'ит
|
|
||||||
# 10.80.0.0/29 -> LAN через tun0, кладёт готовый профиль в
|
|
||||||
# ansible/generated/ada-phone.ovpn (mode 0600, содержит приватный ключ).
|
|
||||||
#
|
|
||||||
# ЗАПУСК
|
|
||||||
# make openvpn-phone
|
|
||||||
# ============================================================================
|
|
||||||
- name: Configure OpenVPN phone access through ru-vps
|
|
||||||
hosts: ru-vps
|
|
||||||
gather_facts: true
|
|
||||||
become: true
|
|
||||||
vars:
|
|
||||||
phone_profile_name: ada-phone
|
|
||||||
phone_openvpn_dir: /etc/openvpn/homelab-phone
|
|
||||||
phone_openvpn_config: /etc/openvpn/homelab-phone/server.conf
|
|
||||||
phone_openvpn_server_cert: /etc/openvpn/homelab-phone/server.crt
|
|
||||||
phone_openvpn_server_key: /etc/openvpn/homelab-phone/server.key
|
|
||||||
phone_openvpn_client_cert: /etc/openvpn/homelab-phone/client.crt
|
|
||||||
phone_openvpn_client_key: /etc/openvpn/homelab-phone/client.key
|
|
||||||
phone_openvpn_service: homelab-openvpn-phone
|
|
||||||
phone_openvpn_port: 9444
|
|
||||||
phone_openvpn_interface: tun2
|
|
||||||
phone_openvpn_site_interface: tun0
|
|
||||||
# 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"
|
|
||||||
phone_openvpn_routes: "{{ homelab_vpn_client_routes }}"
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
- name: Install OpenVPN packages
|
|
||||||
ansible.builtin.apt:
|
|
||||||
name:
|
|
||||||
- openvpn
|
|
||||||
- iptables
|
|
||||||
- openssl
|
|
||||||
state: present
|
|
||||||
update_cache: true
|
|
||||||
|
|
||||||
- name: Ensure phone OpenVPN config directory exists
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ phone_openvpn_dir }}"
|
|
||||||
state: directory
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0700"
|
|
||||||
|
|
||||||
- name: Remove the obsolete static key (crypto model changed to TLS)
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ phone_openvpn_dir }}/static.key"
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Generate the server EC keypair if missing
|
|
||||||
ansible.builtin.command:
|
|
||||||
argv:
|
|
||||||
- openssl
|
|
||||||
- req
|
|
||||||
- -x509
|
|
||||||
- -newkey
|
|
||||||
- ec
|
|
||||||
- -pkeyopt
|
|
||||||
- ec_paramgen_curve:prime256v1
|
|
||||||
- -keyout
|
|
||||||
- "{{ phone_openvpn_server_key }}"
|
|
||||||
- -out
|
|
||||||
- "{{ phone_openvpn_server_cert }}"
|
|
||||||
- -nodes
|
|
||||||
- -sha256
|
|
||||||
- -days
|
|
||||||
- "3650"
|
|
||||||
- -subj
|
|
||||||
- /CN=homelab-phone-server
|
|
||||||
args:
|
|
||||||
creates: "{{ phone_openvpn_server_cert }}"
|
|
||||||
no_log: true
|
|
||||||
|
|
||||||
- name: Generate the client EC keypair if missing
|
|
||||||
ansible.builtin.command:
|
|
||||||
argv:
|
|
||||||
- openssl
|
|
||||||
- req
|
|
||||||
- -x509
|
|
||||||
- -newkey
|
|
||||||
- ec
|
|
||||||
- -pkeyopt
|
|
||||||
- ec_paramgen_curve:prime256v1
|
|
||||||
- -keyout
|
|
||||||
- "{{ phone_openvpn_client_key }}"
|
|
||||||
- -out
|
|
||||||
- "{{ phone_openvpn_client_cert }}"
|
|
||||||
- -nodes
|
|
||||||
- -sha256
|
|
||||||
- -days
|
|
||||||
- "3650"
|
|
||||||
- -subj
|
|
||||||
- /CN=homelab-phone-client
|
|
||||||
args:
|
|
||||||
creates: "{{ phone_openvpn_client_cert }}"
|
|
||||||
no_log: true
|
|
||||||
|
|
||||||
- name: Enforce key permissions
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ item }}"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0600"
|
|
||||||
loop:
|
|
||||||
- "{{ phone_openvpn_server_key }}"
|
|
||||||
- "{{ phone_openvpn_client_key }}"
|
|
||||||
|
|
||||||
- name: Read the server certificate fingerprint
|
|
||||||
ansible.builtin.command:
|
|
||||||
argv:
|
|
||||||
- openssl
|
|
||||||
- x509
|
|
||||||
- -in
|
|
||||||
- "{{ phone_openvpn_server_cert }}"
|
|
||||||
- -noout
|
|
||||||
- -fingerprint
|
|
||||||
- -sha256
|
|
||||||
register: phone_openvpn_server_fp_raw
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Read the client certificate fingerprint
|
|
||||||
ansible.builtin.command:
|
|
||||||
argv:
|
|
||||||
- openssl
|
|
||||||
- x509
|
|
||||||
- -in
|
|
||||||
- "{{ phone_openvpn_client_cert }}"
|
|
||||||
- -noout
|
|
||||||
- -fingerprint
|
|
||||||
- -sha256
|
|
||||||
register: phone_openvpn_client_fp_raw
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Extract the bare colon-separated fingerprints
|
|
||||||
# openssl печатает "sha256 Fingerprint=AB:CD:...", отпечаток без '='.
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
phone_openvpn_server_fp: "{{ phone_openvpn_server_fp_raw.stdout | regex_replace('^.*=', '') | trim }}"
|
|
||||||
phone_openvpn_client_fp: "{{ phone_openvpn_client_fp_raw.stdout | regex_replace('^.*=', '') | trim }}"
|
|
||||||
|
|
||||||
- name: Enable IPv4 forwarding on ru-vps
|
|
||||||
ansible.posix.sysctl:
|
|
||||||
name: net.ipv4.ip_forward
|
|
||||||
value: "1"
|
|
||||||
state: present
|
|
||||||
reload: true
|
|
||||||
|
|
||||||
- name: Allow phone OpenVPN TCP in UFW
|
|
||||||
ansible.builtin.command: "ufw allow {{ phone_openvpn_port }}/tcp"
|
|
||||||
register: ufw_allow_phone_openvpn
|
|
||||||
changed_when: "'Rule added' in ufw_allow_phone_openvpn.stdout or 'Rules updated' in ufw_allow_phone_openvpn.stdout"
|
|
||||||
failed_when: false
|
|
||||||
|
|
||||||
# Road-warrior трафик tun2 -> tun0 ФОРВАРДИТСЯ через ru-vps, а policy
|
|
||||||
# FORWARD = DROP. Сайт-тоннель этого правила не требовал (он несёт
|
|
||||||
# собственный трафик ru-vps, не forward). ufw route allow переживает
|
|
||||||
# `ufw reload`, в отличие от сырого iptables -I FORWARD. Обратное
|
|
||||||
# направление покрыто глобальным RELATED,ESTABLISHED в ufw-before-forward.
|
|
||||||
- name: Allow forwarding phone VPN traffic into the LAN
|
|
||||||
community.general.ufw:
|
|
||||||
route: true
|
|
||||||
rule: allow
|
|
||||||
interface_in: "{{ phone_openvpn_interface }}"
|
|
||||||
interface_out: "{{ phone_openvpn_site_interface }}"
|
|
||||||
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 }}"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0600"
|
|
||||||
content: |
|
|
||||||
dev {{ phone_openvpn_interface }}
|
|
||||||
dev-type tun
|
|
||||||
proto tcp-server
|
|
||||||
port {{ phone_openvpn_port }}
|
|
||||||
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
|
|
||||||
verb 3
|
|
||||||
notify: restart phone openvpn
|
|
||||||
|
|
||||||
- name: Render phone OpenVPN up script
|
|
||||||
ansible.builtin.copy:
|
|
||||||
dest: "{{ phone_openvpn_dir }}/up.sh"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0700"
|
|
||||||
content: |
|
|
||||||
#!/bin/sh
|
|
||||||
iptables -t nat -C POSTROUTING -s {{ phone_openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o {{ phone_openvpn_site_interface }} -j MASQUERADE 2>/dev/null || \
|
|
||||||
iptables -t nat -A POSTROUTING -s {{ phone_openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o {{ phone_openvpn_site_interface }} -j MASQUERADE
|
|
||||||
notify: restart phone openvpn
|
|
||||||
|
|
||||||
- name: Render phone OpenVPN down script
|
|
||||||
ansible.builtin.copy:
|
|
||||||
dest: "{{ phone_openvpn_dir }}/down.sh"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0700"
|
|
||||||
content: |
|
|
||||||
#!/bin/sh
|
|
||||||
iptables -t nat -D POSTROUTING -s {{ phone_openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o {{ phone_openvpn_site_interface }} -j MASQUERADE 2>/dev/null || true
|
|
||||||
notify: restart phone openvpn
|
|
||||||
|
|
||||||
- name: Render phone OpenVPN systemd service
|
|
||||||
ansible.builtin.copy:
|
|
||||||
dest: "/etc/systemd/system/{{ phone_openvpn_service }}.service"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0644"
|
|
||||||
content: |
|
|
||||||
[Unit]
|
|
||||||
Description=HomeLab OpenVPN phone access
|
|
||||||
After=network-online.target homelab-openvpn.service
|
|
||||||
Wants=network-online.target
|
|
||||||
Requires=homelab-openvpn.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStartPre={{ phone_openvpn_dir }}/up.sh
|
|
||||||
ExecStart=/usr/sbin/openvpn --config {{ phone_openvpn_config }}
|
|
||||||
ExecStopPost={{ phone_openvpn_dir }}/down.sh
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
notify:
|
|
||||||
- reload systemd
|
|
||||||
- restart phone openvpn
|
|
||||||
|
|
||||||
- name: Flush handlers before starting phone OpenVPN
|
|
||||||
ansible.builtin.meta: flush_handlers
|
|
||||||
|
|
||||||
- name: Enable and start phone OpenVPN
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: "{{ phone_openvpn_service }}"
|
|
||||||
state: started
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
- name: Read the server certificate for the profile CA block
|
|
||||||
# client-режим ics-openvpn отказывается собирать конфиг без <ca>.
|
|
||||||
# Серверный самоподписанный сертификат сам себе trust anchor; реальную
|
|
||||||
# проверку всё равно делает peer-fingerprint.
|
|
||||||
ansible.builtin.slurp:
|
|
||||||
src: "{{ phone_openvpn_server_cert }}"
|
|
||||||
register: phone_openvpn_server_cert_raw
|
|
||||||
no_log: true
|
|
||||||
|
|
||||||
- name: Read the client certificate for the profile
|
|
||||||
ansible.builtin.slurp:
|
|
||||||
src: "{{ phone_openvpn_client_cert }}"
|
|
||||||
register: phone_openvpn_client_cert_raw
|
|
||||||
no_log: true
|
|
||||||
|
|
||||||
- name: Read the client key for the profile
|
|
||||||
ansible.builtin.slurp:
|
|
||||||
src: "{{ phone_openvpn_client_key }}"
|
|
||||||
register: phone_openvpn_client_key_raw
|
|
||||||
no_log: true
|
|
||||||
|
|
||||||
- name: Ensure local generated directory exists
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ playbook_dir }}/../generated"
|
|
||||||
state: directory
|
|
||||||
mode: "0700"
|
|
||||||
delegate_to: localhost
|
|
||||||
vars:
|
|
||||||
ansible_connection: local
|
|
||||||
ansible_become: false
|
|
||||||
|
|
||||||
- name: Write local phone OpenVPN profile
|
|
||||||
ansible.builtin.copy:
|
|
||||||
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 }}
|
|
||||||
peer-fingerprint {{ phone_openvpn_server_fp }}
|
|
||||||
data-ciphers {{ phone_openvpn_data_ciphers }}
|
|
||||||
auth SHA256
|
|
||||||
persist-key
|
|
||||||
persist-tun
|
|
||||||
resolv-retry infinite
|
|
||||||
nobind
|
|
||||||
verb 3
|
|
||||||
<ca>
|
|
||||||
{{ phone_openvpn_server_cert_raw.content | b64decode | trim }}
|
|
||||||
</ca>
|
|
||||||
<cert>
|
|
||||||
{{ phone_openvpn_client_cert_raw.content | b64decode | trim }}
|
|
||||||
</cert>
|
|
||||||
<key>
|
|
||||||
{{ phone_openvpn_client_key_raw.content | b64decode | trim }}
|
|
||||||
</key>
|
|
||||||
delegate_to: localhost
|
|
||||||
vars:
|
|
||||||
ansible_connection: local
|
|
||||||
ansible_become: false
|
|
||||||
no_log: true
|
|
||||||
|
|
||||||
handlers:
|
|
||||||
- name: reload systemd
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
daemon_reload: true
|
|
||||||
|
|
||||||
- name: restart phone openvpn
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: "{{ phone_openvpn_service }}"
|
|
||||||
state: restarted
|
|
||||||
+21
-27
@@ -2,36 +2,30 @@
|
|||||||
|
|
||||||
## Активные задачи
|
## Активные задачи
|
||||||
|
|
||||||
### Road-warrior OpenVPN для телефона
|
### Road-warrior OpenVPN для телефона — откачено
|
||||||
|
|
||||||
Выполнено 2026-09-03. `playbooks/openvpn-phone.yml` (`make openvpn-phone`)
|
2026-09-03: пробовали поднять клиентский OpenVPN для телефона (Android),
|
||||||
поднимает на ru-vps отдельный TLS point-to-point инстанс: порт 9444/tcp,
|
чтобы смотреть дашборд вне LAN. Перебрали три варианта на `ru-vps` (static
|
||||||
`tun2`, сеть 10.80.0.0/30, юнит `homelab-openvpn-phone`, NAT
|
key -> TLS peer-fingerprint p2p -> `server`-режим с `push route` и `<ca>`).
|
||||||
`10.80.0.0/30 -> LAN` через `tun0`. Профиль (с приватным ключом) —
|
На стороне ru-vps всё работало (тоннель вставал, TLS OK), но клиент
|
||||||
`ansible/generated/ada-phone.ovpn` (gitignored).
|
«OpenVPN for Android» стабильно падал на «сборка конфигурации / Used 101
|
||||||
|
tries to get current version of the profile». По решению пользователя всё
|
||||||
|
откачено: `homelab-openvpn-phone`, `tun2`, правила UFW/NAT для 9444 и
|
||||||
|
`10.80.0.0/29`, `/etc/openvpn/homelab-phone` сняты с `ru-vps`; `playbooks/
|
||||||
|
openvpn-phone.yml`, Make-цель и `homelab_vpn_client_routes` удалены из
|
||||||
|
репозитория. Сайт-тоннель `homelab-openvpn` (tun0) не затрагивался.
|
||||||
|
|
||||||
Крипто: **peer-fingerprint, без CA/PKI**. На ru-vps генерятся две
|
Если возвращаться: скорее всего проблема на стороне приложения (battery
|
||||||
самоподписанные EC-пары (`server.*`, `client.*`), стороны пинят друг друга
|
optimization / сохранение профиля), а не конфига; либо собрать полноценный
|
||||||
по SHA256-отпечатку (`peer-fingerprint`), `data-ciphers AES-256-GCM`. Первая
|
PKI через `community.crypto` и `<ca>`+`remote-cert-tls server`, либо
|
||||||
попытка была на static key (`--secret`) — Android-клиент несёт OpenVPN 2.7 и
|
попробовать WireGuard.
|
||||||
запускать её отказался («No tls-client or tls-server option»; 2.8 уберёт
|
|
||||||
совсем). Клиент на Android — «OpenVPN for Android» (Arne Schwabe) или
|
|
||||||
OpenVPN Connect: TLS-конфиг понимают оба.
|
|
||||||
|
|
||||||
Прогон идемпотентен (`changed=0` на повторе). Проверено: сервис active,
|
Предсуществующий баг, замеченный по ходу и НЕ тронутый: в
|
||||||
OpenVPN 2.6.19 слушает 9444, `tun2` up, `Using certificate fingerprint to
|
`openvpn-laptop.yml` (в проде не применялся) задачи с `delegate_to:
|
||||||
verify peer`, UFW 9444/tcp, NAT-правило на месте, с ru-vps
|
localhost` используют ключ `become: false`, который не подавляет
|
||||||
`192.168.1.30:8082` достижим. Маршруты клиента вынесены в
|
унаследованный `ansible_become: true` — при запуске упрётся в «sudo: a
|
||||||
`homelab_vpn_client_routes` (`group_vars/all/main.yml`) — общий список с
|
password is required». Чинится `vars: {ansible_connection: local,
|
||||||
`openvpn-laptop.yml`, не весь `/24` (домашняя сеть телефона тоже
|
ansible_become: false}`.
|
||||||
192.168.1.0/24).
|
|
||||||
|
|
||||||
Побочно: в `openvpn-laptop.yml` и `openvpn-phone.yml` локальная запись
|
|
||||||
профиля переведена с `become: false` на `vars: {ansible_connection: local,
|
|
||||||
ansible_become: false}` — ключ `become: false` на `delegate_to: localhost`
|
|
||||||
не подавлял унаследованный `ansible_become: true` (sudo password required).
|
|
||||||
`openvpn-laptop.yml` по-прежнему на static key и на живом ru-vps не
|
|
||||||
применялся — при реальном использовании ему нужен тот же перевод на TLS.
|
|
||||||
|
|
||||||
### Дашборд-обзор инфраструктуры (Homepage)
|
### Дашборд-обзор инфраструктуры (Homepage)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user