diff --git a/README.md b/README.md index 6fe7373..5446395 100644 --- a/README.md +++ b/README.md @@ -1,48 +1,64 @@ -# Ansible-роль: Hysteria2 Server +# Hysteria2 Ansible — ветка **Salamander** -Ansible-роль для установки [Hysteria 2](https://v2.hysteria.network/) на Debian/Ubuntu VPS: ACME-сертификат, masquerade под nginx, несколько пользователей, экспорт URL/QR и HTML-каталог. +> **Ветка:** `salamander` +> **Режим:** обфускация **Salamander** (без masquerade-сайта nginx) +> **Основная ветка `main`:** masquerade под HTTPS-сайт — см. другую ветку + +Ansible-роль для установки [Hysteria 2](https://v2.hysteria.network/) на Debian/Ubuntu VPS с **Salamander obfs** — запутывание пакетов для обхода DPI, когда masquerade под «обычный сайт» недостаточен. + +--- + +## Чем Salamander отличается от `main` + +| | **`main` (masquerade)** | **`salamander` (эта ветка)** | +|---|---|---| +| Маскировка | HTTPS-сайт nginx + Let's Encrypt | **Salamander obfs** — пакеты выглядят как шум | +| Порт 80/tcp | Нужен (ACME HTTP + masquerade) | **Не нужен** | +| ACME | `type: http` | `type: tls` (TLS-ALPN на 443) | +| Сайт-заглушка | `/var/www/masq` | **Нет** | +| Obfs-пароль | — | **Обязателен** (один на сервер) | +| URI клиента | `hysteria2://user:pass@domain:443` | + `obfs=salamander&obfs-password=...` | +| Лучше когда | Нужен «легитимный» сайт в браузере | Агрессивный DPI, блокировка QUIC fingerprint | + +--- ## Быстрый старт ```bash -cd ~/Разработка/hysteria2 +git clone https://git.antropoff.ru/DevOpsTools/hysteria2.git +cd hysteria2 +git checkout salamander -make init # inventory, group_vars, vault, .vault_pass -# отредактировать: -# inventory/hosts.yml -# group_vars/all.yml -# group_vars/hysteria2_servers/vault.yml +make init +# отредактировать inventory/hosts.yml, group_vars/all.yml, vault -make vault-encrypt # зашифровать пароли VPS -make ping # проверить SSH -make install # установка → output/ → браузер откроется сам +make vault-encrypt +make ping +make install # → output/index.html откроется в браузере ``` +--- + ## Makefile | Команда | Описание | |---|---| -| `make help` | Справка | | `make init` | Создать конфиги из `.example` | | `make ping` | Проверить SSH к VPS | -| `make status` | `systemctl status hysteria-server` | -| `make install` | Установка + экспорт + `output/index.html` + открытие в браузере | +| `make install` | Установка Salamander + экспорт URL/QR/HTML | | `make update` | Обновить бинарник, конфиг, перевыпустить экспорт | -| `make export` | Только экспорт URL/QR/HTML | +| `make export` | Только экспорт (URL, QR, HTML) | | `make uninstall` | Удалить Hysteria2 с VPS | | `make vault-encrypt` | Зашифровать vault | -| `make vault-edit` | Редактировать vault | - -### Примеры ```bash make install LIMIT=vps-de -make update LIMIT=vps-nl -make export -make uninstall LIMIT=vps-de EXTRA_VARS='hysteria2_uninstall_remove_local_output=true' -make install EXTRA_VARS='hysteria2_open_browser=false' # без авто-открытия браузера +make update EXTRA_VARS='hysteria2_wait_for_acme=false' +make install EXTRA_VARS='hysteria2_open_browser=false' ``` +--- + ## Inventory ```yaml @@ -55,132 +71,217 @@ all: ansible_port: 2222 # SSH-порт (если не 22) ansible_user: root ansible_password: "{{ vault_ssh_passwords['vps-de'] }}" - hysteria2_domain: vpn-de.example.com + hysteria2_domain: vpn-de.example.com # для TLS/SNI и ACME hysteria2_users: - my - friend - - vps-nl: - ansible_host: 203.0.113.20 - ansible_user: root - ansible_password: "{{ vault_ssh_passwords['vps-nl'] }}" - hysteria2_domain: vpn-nl.dynu.net - hysteria2_users: - - alice - - bob ``` -### SSH-подключение к VPS - -| Параметр | Где | Описание | -|---|---|---| -| `ansible_host` | inventory | IP VPS | -| `ansible_port` | inventory | SSH-порт (по умолчанию `22`) | -| `ansible_user` | inventory | Пользователь SSH (обычно `root`) | -| `ansible_password` | inventory + vault | Пароль из `vault_ssh_passwords` | -| `ansible_ssh_private_key_file` | inventory | Альтернатива паролю — SSH-ключ | +### SSH (VPS) ```yaml # group_vars/hysteria2_servers/vault.yml vault_ssh_passwords: - vps-de: "root-password-1" - vps-nl: "root-password-2" + vps-de: "root-password" ``` -Ключи в `vault_ssh_passwords` совпадают с **именами хостов** в inventory. +Пароли VPN и Salamander obfs тоже можно хранить в vault — см. ниже. -## Пароли VPN-пользователей +--- -1. **Vault** (рекомендуется): +## Как работает Salamander в этом проекте + +### Сервер (`/etc/hysteria/config.yaml`) ```yaml -vault_hysteria2_user_passwords: - vps-de: - friend: "Aingae0Okit1eek4eeZahFohVei4akee" +listen: 0.0.0.0:443 + +acme: + type: tls # сертификат без порта 80 + domains: + - vpn-de.example.com + email: admin@example.com + +auth: + type: userpass + userpass: + my: "..." + friend: "..." + +obfs: + type: salamander + salamander: + password: "общий_obfs_пароль_сервера" ``` -2. **Per-host в inventory**: +### Клиент (генерируется автоматически) ```yaml -hysteria2_user_passwords: - friend: "custom-password" +server: vpn-de.example.com:443 +auth: my:password +obfs: + type: salamander + salamander: + password: общий_obfs_пароль_сервера ``` -3. **Автогенерация** — `pwgen -s 40`, если пароль не задан. +### URI (пример) -При `make update` пароли подтягиваются из `output//server-info.yml`, если не указаны в vault/inventory. +``` +hysteria2://my:password@vpn-de.example.com:443?obfs=salamander&obfs-password=OBFS_PASS#my +``` + +Роль вызывает `hysteria share` — URI и QR уже содержат параметры Salamander. + +--- + +## Пароли + +### VPN-пользователи (`userpass`) + +1. **Vault:** `vault_hysteria2_user_passwords` +2. **Inventory:** `hysteria2_user_passwords` +3. **Авто:** `pwgen -s 40` + +### Salamander obfs (один на сервер) + +1. **Vault (рекомендуется):** + +```yaml +vault_hysteria2_obfs_passwords: + vps-de: "cry_me_a_r1ver_salamander_obfs" +``` + +Подключается через `group_vars/hysteria2_servers/vars.yml`: + +```yaml +``` + +2. **Авто:** `pwgen -s 32` при первой установке +3. **При update:** загружается из `output//server-info.yml` + +> **Важно:** obfs-пароль на сервере и клиенте должен **совпадать**. При `make update` без vault пароль сохраняется из предыдущего экспорта. + +--- + +## Let's Encrypt — обновление сертификата + +**Да, Hysteria2 обновляет сертификат автоматически.** + +При `acme:` в конфиге встроенный ACME-клиент Hysteria2 сам получает и **продлевает** сертификат Let's Encrypt (срок ~90 дней). Перезапуск ansible для продления **не нужен** — процесс `hysteria-server` делает это сам (подтверждено maintainer проекта). + +**Условия для авто-продления:** + +- Сервер **запущен** и доступен из интернета +- Домен по-прежнему указывает на IP VPS +- Порт **443** открыт (для `acme type: tls` — TLS-ALPN challenge) +- Конфиг `acme` не удалён + +Проверка логов: `journalctl -u hysteria-server -f` + +--- + +## Firewall + +Открываются только порты Hysteria2 (по умолчанию **443/tcp** и **443/udp**). + +**Порт 80 не используется** — в отличие от ветки `main`. + +--- ## Результат: папка `output/` ``` output/ -├── index.html ← общий каталог всех серверов (открывается в браузере) +├── index.html ← все серверы (открывается в браузере) ├── vps-de/ -│ ├── index.html ← страница сервера -│ ├── my.url -│ ├── my.png ← QR PNG -│ ├── my.qr.txt ← QR ASCII +│ ├── index.html ← страница сервера + obfs-пароль +│ ├── my.url ← URI с obfs=salamander +│ ├── my.png ← QR │ ├── my.txt -│ └── server-info.yml +│ └── server-info.yml ← mode, obfs_password, users └── vps-nl/ └── ... ``` -### HTML-страницы +HTML-страницы показывают: -**`output/index.html`** — общий каталог: -- все серверы и пользователи на одной странице -- навигация по серверам -- поля ссылки/пароля с кнопкой копирования +- режим **Salamander** +- **obfs-password** с кнопкой копирования +- пароль и URL каждого пользователя - QR-коды -- ссылки на файлы и страницы серверов -**`output//index.html`** — страница одного сервера (тот же стиль, все пользователи сервера). - -После `make install`, `make update` и `make export` **`output/index.html` автоматически открывается в браузере** (macOS: `open`, Linux: `xdg-open`). - -Отключить авто-открытие: - -```yaml -# group_vars/all.yml -hysteria2_open_browser: false -``` - -Или: `make install EXTRA_VARS='hysteria2_open_browser=false'` - -## QR-коды - -PNG генерируются средствами Ansible (без Python): - -1. `apt install qrencode` на VPS (остаётся установленным) -2. `qrencode -o user.png "hysteria2://..."` -3. `fetch` — скачивание PNG на control node - -ASCII QR — `hysteria share --qr` → `user.qr.txt`. +--- ## Переменные | Переменная | Где | Описание | |---|---|---| -| `hysteria2_domain` | host | Домен с A-записью на IP | -| `hysteria2_users` | host | Список имён VPN-пользователей | -| `hysteria2_acme_email` | group | Email для Let's Encrypt | -| `hysteria2_user_passwords` | host/vault | Свои пароли VPN | -| `hysteria2_output_dir` | group | Папка экспорта (по умолчанию `./output`) | -| `hysteria2_output_name` | host | Имя подпапки (по умолчанию `inventory_hostname`) | -| `hysteria2_generate_qr_png` | group | PNG QR через `qrencode` | -| `hysteria2_open_browser` | group | Открыть `output/index.html` после экспорта | -| `hysteria2_uninstall_remove_local_output` | extra-vars | Удалить `output//` при uninstall | +| `hysteria2_mode` | defaults | `salamander` (информативно) | +| `hysteria2_domain` | host | Домен для TLS/SNI/ACME | +| `hysteria2_users` | host | VPN-пользователи | +| `hysteria2_acme_email` | group | Email Let's Encrypt | +| `hysteria2_obfs_password` | host/vault | Пароль Salamander (или авто) | +| `hysteria2_obfs_password_length` | group | Длина автопароля obfs (32) | +| `hysteria2_listen_port` | group | Порт (443) | +| `hysteria2_open_browser` | group | Открыть `output/index.html` | +| `vault_hysteria2_obfs_passwords` | vault | obfs-пароли по серверам | + +--- + +## Когда выбирать эту ветку + +**Используйте `salamander`, если:** + +- masquerade из `main` блокируют или «палят» по fingerprint +- не нужен фейковый сайт в браузере +- готовы хранить **дополнительный** obfs-пароль + +**Используйте `main`, если:** + +- нужен «нормальный» HTTPS-сайт при проверке домена +- достаточно маскировки под nginx +- хотите минимум параметров в URI + +--- ## Безопасность -- `output/` содержит пароли и URL — в `.gitignore` -- `inventory/hosts.yml`, `vault.yml`, `.vault_pass` — не коммитить -- После `make init` выполните `make vault-encrypt` +- `output/` содержит пароли, obfs-ключи и URL — **не коммитить** +- `make vault-encrypt` обязателен после `make init` +- Salamander **не делает** вас невидимым: IP VPS и постоянный UDP-поток всё ещё можно анализировать + +--- ## Требования - Ansible 2.14+ -- Debian/Ubuntu VPS с sudo -- Домен с A-записью на IP сервера -- Для авто-открытия браузера: macOS или Linux с `xdg-open` +- Debian/Ubuntu VPS +- Домен с A-записью на IP (для ACME TLS) +- Клиент Hysteria2 с поддержкой Salamander (Shadowrocket, NekoBox, Hiddify и др.) + +--- + +## Структура роли + +``` +roles/hysteria2/ +├── tasks/ +│ ├── obfs.yml ← генерация/загрузка obfs-пароля +│ ├── configure.yml ← без masquerade, только Salamander +│ └── export_global.yml ← общий output/index.html +└── templates/ + ├── config.yaml.j2 ← acme tls + obfs salamander + └── client.yaml.j2 ← клиент с obfs +``` + +--- + +## Переключение между ветками + +```bash +git checkout main # masquerade + nginx +git checkout salamander # Salamander obfs +``` + +Конфиги на **уже установленном** сервере **не меняются** при переключении ветки в git — нужен `make install` или `make update` на целевой ветке (это **перекатит** конфиг сервера). diff --git a/group_vars/all.yml.example b/group_vars/all.yml.example index 10756c4..167cb26 100644 --- a/group_vars/all.yml.example +++ b/group_vars/all.yml.example @@ -17,8 +17,11 @@ hysteria2_output_dir: "{{ playbook_dir }}/output" # Открывать output/index.html в браузере после install/update/export # hysteria2_open_browser: true -# Порт Hysteria2 +# Порт Hysteria2 (Salamander — достаточно открыть только его, 80/tcp не нужен) hysteria2_listen_port: 443 -# Открывать порты в ufw (80/tcp, 443/tcp, 443/udp) +# Открывать порты в ufw ({{ hysteria2_listen_port }}/tcp и /udp) hysteria2_configure_firewall: true + +# Длина пароля Salamander obfs (pwgen) +# hysteria2_obfs_password_length: 32 diff --git a/group_vars/hysteria2_servers/vars.yml.example b/group_vars/hysteria2_servers/vars.yml.example index 95c129d..649fbd2 100644 --- a/group_vars/hysteria2_servers/vars.yml.example +++ b/group_vars/hysteria2_servers/vars.yml.example @@ -3,3 +3,5 @@ # Файл group_vars/hysteria2_servers/vault.yml должен быть зашифрован (make vault-encrypt). # Проброс VPN-паролей из vault в переменные роли (опционально) + +# Опционально: фиксированный пароль Salamander obfs для сервера diff --git a/group_vars/hysteria2_servers/vault.yml.example b/group_vars/hysteria2_servers/vault.yml.example index f0e2b21..8b44498 100644 --- a/group_vars/hysteria2_servers/vault.yml.example +++ b/group_vars/hysteria2_servers/vault.yml.example @@ -14,5 +14,8 @@ vault_ssh_passwords: # vault_hysteria2_user_passwords: # vps-de: # friend: "Aingae0Okit1eek4eeZahFohVei4akee" -# vps-nl: -# alice: "CustomAlicePassword40chars................" + +# Опционально: пароль Salamander obfs (один на сервер) +# vault_hysteria2_obfs_passwords: +# vps-de: "cry_me_a_r1ver_salamander_obfs_pass" +# vps-nl: "another_obfs_password_32chars!!" diff --git a/roles/hysteria2/defaults/main.yml b/roles/hysteria2/defaults/main.yml index 2733dfc..e795a1c 100644 --- a/roles/hysteria2/defaults/main.yml +++ b/roles/hysteria2/defaults/main.yml @@ -1,5 +1,8 @@ --- -# Домен сервера (A-запись → IP VPS). Задаётся per-host в inventory. +# Режим развёртывания (ветка salamander) +hysteria2_mode: salamander + +# Домен сервера (A-запись → IP VPS). Используется для TLS/SNI и ACME. hysteria2_domain: "" # Email для ACME / Let's Encrypt @@ -9,34 +12,31 @@ hysteria2_acme_email: "" hysteria2_users: [] # Опционально: фиксированные пароли { username: password } -# Пустое значение или отсутствие ключа — автогенерация через pwgen + +# Пароль обфускации Salamander (общий для сервера). +# Пусто — автогенерация через pwgen или загрузка из output//server-info.yml +hysteria2_obfs_password: "" hysteria2_password_length: 40 +hysteria2_obfs_password_length: 32 hysteria2_listen_port: 443 hysteria2_upgrade_system: true hysteria2_configure_firewall: true -hysteria2_masq_dir: /var/www/masq hysteria2_config_path: /etc/hysteria/config.yaml hysteria2_service_name: hysteria-server -# Локальный каталог для экспорта URL и QR (на control node) hysteria2_output_dir: "{{ playbook_dir }}/output" hysteria2_output_name: "{{ inventory_hostname }}" -# Генерировать PNG QR-коды через qrencode (apt на VPS, fetch на control node) hysteria2_generate_qr_png: true hysteria2_qr_png_size: 6 hysteria2_qr_png_margin: 2 hysteria2_qr_png_error_correction: M -# Ждать ACME при первом запуске (отключите при update: make update) hysteria2_wait_for_acme: true - -# Открыть output/index.html в браузере после install/update/export hysteria2_open_browser: true # --- uninstall --- hysteria2_uninstall_remove_config: true -hysteria2_uninstall_remove_masq: true hysteria2_uninstall_remove_local_output: false diff --git a/roles/hysteria2/meta/main.yml b/roles/hysteria2/meta/main.yml index 4863d73..5fd57ac 100644 --- a/roles/hysteria2/meta/main.yml +++ b/roles/hysteria2/meta/main.yml @@ -2,7 +2,7 @@ galaxy_info: role_name: hysteria2 author: inecs - description: Install Hysteria2 VPN server with masquerade site and export client URLs with QR codes + description: Install Hysteria2 VPN server with Salamander obfs and export client URLs with QR codes license: MIT min_ansible_version: "2.14" platforms: diff --git a/roles/hysteria2/tasks/configure.yml b/roles/hysteria2/tasks/configure.yml index f88af1f..15b6e7e 100644 --- a/roles/hysteria2/tasks/configure.yml +++ b/roles/hysteria2/tasks/configure.yml @@ -1,24 +1,11 @@ --- -- name: Create masquerade web directory - ansible.builtin.file: - path: "{{ hysteria2_masq_dir }}" - state: directory - mode: "0755" - -- name: Deploy masquerade index.html - ansible.builtin.template: - src: masq/index.html.j2 - dest: "{{ hysteria2_masq_dir }}/index.html" - mode: "0644" - notify: Restart hysteria-server - - name: Remove default Hysteria config if present ansible.builtin.file: path: "{{ hysteria2_config_path }}" state: absent when: not ansible_check_mode -- name: Deploy Hysteria2 server config +- name: Deploy Hysteria2 Salamander server config ansible.builtin.template: src: config.yaml.j2 dest: "{{ hysteria2_config_path }}" @@ -42,12 +29,11 @@ failed_when: false when: hysteria2_configure_firewall | bool -- name: Allow HTTP and HTTPS in ufw +- name: Allow Hysteria2 port in ufw (Salamander — только {{ hysteria2_listen_port }}) ansible.builtin.command: "ufw allow {{ item }}" loop: - - 80/tcp - - 443/tcp - - 443/udp + - "{{ hysteria2_listen_port }}/tcp" + - "{{ hysteria2_listen_port }}/udp" register: _hysteria2_ufw_allow changed_when: "'Skipping' not in (_hysteria2_ufw_allow.stdout | default(''))" failed_when: false @@ -55,10 +41,10 @@ - hysteria2_configure_firewall | bool - "'active' in (_hysteria2_ufw_status.stdout | default(''))" -- name: Wait for ACME certificate (first start may take several minutes) +- name: Wait for ACME TLS certificate (first start may take several minutes) ansible.builtin.pause: seconds: 30 - prompt: "Ожидание получения ACME-сертификата для {{ hysteria2_domain }}..." + prompt: "Ожидание получения ACME TLS-сертификата для {{ hysteria2_domain }}..." when: hysteria2_wait_for_acme | default(true) | bool - name: Verify hysteria-server is running diff --git a/roles/hysteria2/tasks/export.yml b/roles/hysteria2/tasks/export.yml index 5f1b739..a540396 100644 --- a/roles/hysteria2/tasks/export.yml +++ b/roles/hysteria2/tasks/export.yml @@ -31,8 +31,10 @@ mode: "0600" content: | server: {{ hysteria2_output_name }} + mode: salamander domain: {{ hysteria2_domain }} port: {{ hysteria2_listen_port }} + obfs_password: "{{ hysteria2_obfs_password }}" users: {% for user in hysteria2_export_users %} - name: {{ user.name }} @@ -53,6 +55,7 @@ mode: "0644" vars: generated_at: "{{ ansible_date_time.date }} {{ ansible_date_time.time }}" + hysteria2_obfs_password: "{{ hysteria2_obfs_password }}" delegate_to: localhost become: false diff --git a/roles/hysteria2/tasks/export_global.yml b/roles/hysteria2/tasks/export_global.yml index baea209..6a2918c 100644 --- a/roles/hysteria2/tasks/export_global.yml +++ b/roles/hysteria2/tasks/export_global.yml @@ -33,6 +33,8 @@ name: "{{ _info.server }}" domain: "{{ _info.domain }}" port: "{{ _info.port }}" + mode: "{{ _info.mode | default('salamander') }}" + obfs_password: "{{ _info.obfs_password | default('') }}" dir: "{{ item.item.path | dirname | basename }}" users: "{{ _info.users }}" become: false diff --git a/roles/hysteria2/tasks/main.yml b/roles/hysteria2/tasks/main.yml index 14c8d03..e9cbf98 100644 --- a/roles/hysteria2/tasks/main.yml +++ b/roles/hysteria2/tasks/main.yml @@ -7,6 +7,10 @@ ansible.builtin.import_tasks: users.yml tags: [install, update, export] +- name: Resolve Salamander obfs password + ansible.builtin.import_tasks: obfs.yml + tags: [install, update, export] + - name: Install packages and Hysteria2 binary ansible.builtin.import_tasks: install.yml tags: [install] diff --git a/roles/hysteria2/tasks/obfs.yml b/roles/hysteria2/tasks/obfs.yml new file mode 100644 index 0000000..0ed50f2 --- /dev/null +++ b/roles/hysteria2/tasks/obfs.yml @@ -0,0 +1,65 @@ +--- +- name: Check for saved Salamander password from previous install + ansible.builtin.stat: + path: "{{ hysteria2_output_dir }}/{{ hysteria2_output_name }}/server-info.yml" + register: _hysteria2_saved_info + delegate_to: localhost + become: false + tags: + - install + - update + - export + +- name: Load saved Salamander obfs password + when: _hysteria2_saved_info.stat.exists + block: + - name: Read server-info.yml for obfs password + ansible.builtin.slurp: + path: "{{ hysteria2_output_dir }}/{{ hysteria2_output_name }}/server-info.yml" + register: _hysteria2_saved_info_raw + delegate_to: localhost + become: false + + - name: Parse saved obfs password + ansible.builtin.set_fact: + _hysteria2_saved_obfs_password: "{{ (_hysteria2_saved_info_raw.content | b64decode | from_yaml).obfs_password | default('') }}" + delegate_to: localhost + become: false + tags: + - install + - update + - export + +- name: Resolve Salamander obfs password + ansible.builtin.set_fact: + hysteria2_obfs_password: >- + {{ + hysteria2_obfs_password + | default(_hysteria2_saved_obfs_password | default(''), true) + }} + tags: + - install + - update + - export + +- name: Generate Salamander obfs password with pwgen + ansible.builtin.command: + cmd: "pwgen -s {{ hysteria2_obfs_password_length }} 1" + register: _hysteria2_obfs_pwgen + changed_when: false + when: hysteria2_obfs_password | length == 0 + tags: + - install + - update + - export + +- name: Apply generated Salamander obfs password + ansible.builtin.set_fact: + hysteria2_obfs_password: "{{ _hysteria2_obfs_pwgen.stdout }}" + when: + - _hysteria2_obfs_pwgen is defined + - not (_hysteria2_obfs_pwgen.skipped | default(false)) + tags: + - install + - update + - export diff --git a/roles/hysteria2/tasks/share_user.yml b/roles/hysteria2/tasks/share_user.yml index bdbf798..7a0fdcd 100644 --- a/roles/hysteria2/tasks/share_user.yml +++ b/roles/hysteria2/tasks/share_user.yml @@ -34,6 +34,8 @@ Domain: {{ hysteria2_domain }}:{{ hysteria2_listen_port }} User: {{ hysteria2_current_user.name }} Password: {{ hysteria2_current_user.password }} + Mode: salamander + Obfs password: {{ hysteria2_obfs_password }} URL: {{ _hysteria2_client_url }} diff --git a/roles/hysteria2/tasks/uninstall.yml b/roles/hysteria2/tasks/uninstall.yml index 10c0121..aad4b04 100644 --- a/roles/hysteria2/tasks/uninstall.yml +++ b/roles/hysteria2/tasks/uninstall.yml @@ -19,12 +19,6 @@ state: absent when: hysteria2_uninstall_remove_config | bool -- name: Remove masquerade web directory - ansible.builtin.file: - path: "{{ hysteria2_masq_dir }}" - state: absent - when: hysteria2_uninstall_remove_masq | bool - - name: Reload systemd after uninstall ansible.builtin.systemd: daemon_reload: true @@ -32,7 +26,7 @@ - name: Show uninstall result ansible.builtin.debug: msg: >- - Hysteria2 удалён с {{ inventory_hostname }}. + Hysteria2 (Salamander) удалён с {{ inventory_hostname }}. {% if not hysteria2_uninstall_remove_local_output | bool %} Локальные URL/QR в {{ hysteria2_output_dir }}/{{ hysteria2_output_name }}/ сохранены. {% endif %} diff --git a/roles/hysteria2/tasks/validate.yml b/roles/hysteria2/tasks/validate.yml index 59672fa..eedd78b 100644 --- a/roles/hysteria2/tasks/validate.yml +++ b/roles/hysteria2/tasks/validate.yml @@ -7,7 +7,7 @@ - hysteria2_users | length > 0 fail_msg: | Задайте для каждого хоста: - hysteria2_domain — домен с A-записью на IP сервера + hysteria2_domain — домен с A-записью на IP сервера (используется для TLS/SNI) hysteria2_users — список имён пользователей, например [my, friend] И в group_vars/all.yml: hysteria2_acme_email — email для Let's Encrypt diff --git a/roles/hysteria2/templates/client.yaml.j2 b/roles/hysteria2/templates/client.yaml.j2 index 8b09cef..43420cd 100644 --- a/roles/hysteria2/templates/client.yaml.j2 +++ b/roles/hysteria2/templates/client.yaml.j2 @@ -1,3 +1,8 @@ server: {{ hysteria2_domain }}:{{ hysteria2_listen_port }} auth: {{ hysteria2_current_user.name }}:{{ hysteria2_current_user.password }} + +obfs: + type: salamander + salamander: + password: {{ hysteria2_obfs_password }} diff --git a/roles/hysteria2/templates/config.yaml.j2 b/roles/hysteria2/templates/config.yaml.j2 index 9a6f4e0..c393df1 100644 --- a/roles/hysteria2/templates/config.yaml.j2 +++ b/roles/hysteria2/templates/config.yaml.j2 @@ -1,7 +1,7 @@ listen: 0.0.0.0:{{ hysteria2_listen_port }} acme: - type: http + type: tls domains: - {{ hysteria2_domain }} email: {{ hysteria2_acme_email }} @@ -13,10 +13,7 @@ auth: {{ user.name }}: "{{ user.password }}" {% endfor %} -masquerade: - type: file - file: - dir: {{ hysteria2_masq_dir }} - listenHTTP: :80 - listenHTTPS: :{{ hysteria2_listen_port }} - forceHTTPS: true +obfs: + type: salamander + salamander: + password: "{{ hysteria2_obfs_password }}" diff --git a/roles/hysteria2/templates/export/global-index.html.j2 b/roles/hysteria2/templates/export/global-index.html.j2 index d90a831..ec63c7a 100644 --- a/roles/hysteria2/templates/export/global-index.html.j2 +++ b/roles/hysteria2/templates/export/global-index.html.j2 @@ -160,6 +160,17 @@ font-weight: 600; } .server-link:hover { background: var(--accent-soft); border-color: var(--accent); } + .badge-salamander { + display: inline-block; + margin-top: 0.35rem; + padding: 0.2rem 0.6rem; + border-radius: 999px; + font-size: 0.72rem; + font-weight: 700; + background: var(--accent-soft-2); + color: var(--accent-2); + } + .server-obfs { margin-top: 0.75rem; width: 100%; } .users-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); @@ -286,8 +297,8 @@
-

Hysteria2

-

Общий каталог VPN-подключений

+

Hysteria2 · Salamander

+

Общий каталог VPN-подключений с обфускацией Salamander

{{ hysteria2_global_servers | length }} серверов
{{ total_users }} пользователей
@@ -307,6 +318,18 @@

{{ server.name | e }}

{{ server.domain | e }}:{{ server.port }}

+ Salamander +{% if server.obfs_password | default('') | length > 0 %} +
+ +
+ + +
+
+{% endif %}
Страница сервера →
diff --git a/roles/hysteria2/templates/export/index.html.j2 b/roles/hysteria2/templates/export/index.html.j2 index f1f205e..9371a3a 100644 --- a/roles/hysteria2/templates/export/index.html.j2 +++ b/roles/hysteria2/templates/export/index.html.j2 @@ -75,6 +75,15 @@ font-size: 0.8rem; font-weight: 600; } + .badge-salamander { + margin-left: 0.35rem; + background: rgba(163, 113, 247, 0.18); + color: #a371f7; + } + .server-obfs { + margin-top: 1.25rem; + max-width: 100%; + } .user-card { background: var(--bg-card); border: 1px solid var(--border); @@ -235,6 +244,17 @@ Домен: {{ hysteria2_domain }}:{{ hysteria2_listen_port }}

{{ hysteria2_export_users | length }} {{ 'пользователь' if hysteria2_export_users | length == 1 else 'пользователей' }} + Salamander + +
+ +
+ + +
+
{% for user in hysteria2_export_users %} diff --git a/roles/hysteria2/templates/masq/index.html.j2 b/roles/hysteria2/templates/masq/index.html.j2 deleted file mode 100644 index 75bcddc..0000000 --- a/roles/hysteria2/templates/masq/index.html.j2 +++ /dev/null @@ -1,27 +0,0 @@ - - - -Welcome to nginx! - - - -

Welcome to nginx!

-

If you see this page, nginx is successfully installed and working. -Further configuration is required for the web server, reverse proxy, -API gateway, load balancer, content cache, or other features.

- -

For online documentation and support please refer to -nginx.org.
-To engage with the community please visit -community.nginx.org.
-For enterprise grade support, professional services, additional -security features and capabilities please refer to -f5.com/nginx.

- -

Thank you for using nginx.

- -