From 4cc7a58aaafdb0bd2013344d16ce55474f12147d Mon Sep 17 00:00:00 2001 From: erjemin Date: Fri, 6 Mar 2026 18:38:30 +0300 Subject: [PATCH] =?UTF-8?q?add:=20=D0=9F=D1=80=D0=BE=D0=B7=D1=80=D0=B0?= =?UTF-8?q?=D1=87=D0=BD=D1=8B=D0=B9=20=D0=BF=D1=80=D0=BE=D0=BA=D1=81=D0=B8?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=B9=D0=BD=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20Shadowsocks=20=D0=B8=20tun2?= =?UTF-8?q?socks=20(03)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...container-via-shadowsocks-and-tun2socks.md | 170 +++++++++++++++++- 1 file changed, 165 insertions(+), 5 deletions(-) diff --git a/docker/docker-proxy-container-via-shadowsocks-and-tun2socks.md b/docker/docker-proxy-container-via-shadowsocks-and-tun2socks.md index b986ca3..7066373 100644 --- a/docker/docker-proxy-container-via-shadowsocks-and-tun2socks.md +++ b/docker/docker-proxy-container-via-shadowsocks-and-tun2socks.md @@ -50,7 +50,7 @@ Traefik на k3s и все еще проходдит через VIP-адрес K Как-то так: ```text - Интернет Интернет + Интернет для upload Интернет для прослушивания ▲ ▲ │ │ │ │ @@ -58,15 +58,15 @@ Traefik на k3s и все еще проходдит через VIP-адрес K │ VPN (Shadowsocks Server) │ │ (SSL) └──────────────────────▲───────┘ │ ╚═════════════════════╗ │ - ┌──▲────▲──┐ + ┌──╨────┴──┐ │ Роутер │ └──▲────▲──┘ ║ │ - для скачивания ║ └──────────────┐ - (канал-VPN) ║ │ + для upload ║ └──────────────┐ + (VPN-тоннель) ║ │ ···Docker Compose (на Synology)································ ║ ·············· │ : ║ : │ -: ┌────────────────┐ ┌───────────────┐ ┌─────────▲──────────┐ : ▲ +: ┌────────────────┐ ┌───────────────┐ ┌─────────╨──────────┐ : ▲ : │ Audiobookshelf ├─────►│ tun2socks ├────────►│ shadowsocks/SOCKS5 │ : │ : └────────────────┘ └───────┬───────┘ └────────────────────┘ : │ : │ для прослушивания : │ @@ -77,3 +77,163 @@ Traefik на k3s и все еще проходдит через VIP-адрес K └───────────────────────────┘ ``` +Почему так сложно? + + - Во-первых, на VPS/VDS, где я держу свои проекты, уже был настроен Shadowsocks-сервер (Outline), Не для обхода + блокировок, а для безопасного доступа и администрирования (а еще для того чтоб посещать Госуслуги и другие ресурсы, + находясь в поездках за границей). Поэтому было логично использовать его. + - Во-вторых, для Docker не существует полноценного VPN-клиента Shadowsocks. Есть только прокси-клиенты (ss-local), + которые предоставляют SOCKS5 интерфейс. + - При этом, и это в-третьих, Audiobookshelf не умеет работать с SOCKS5. Ему нужен настоящий HTTP, причем из-за + встроенной в Audiobookshelf защиты от SSRF атак он не может работать даже с HTTP-прокси, который находится + в Docker сети (например, Privoxy). Ему нужно сделать прозрачную сеть через TUN интерфейс -- тогда он будет + доволен. + - Для этого, в-четвертых, нужно сделать так, чтобы весь трафик контейнера Audiobookshelf автоматически + шел через единственный контейнер (tun2socks), который будет форвардить и http, и https через Shadowsocks (для + скачивания подкастов) и отдавать http-трафик на порт 8000 для прослушивания через Nginx. Именно такая схема + не будет ломать работу SSRF-фильтра и защитит от этого тип атаки (_можно было, конечно, откатить Audiobookshelf + до древней версии 2.6.0, где дыра SSRF еще была, но это не самое безопасное решение, да и на DockerHub уже нет + этой версии_). + +### Старый манифест Docker + +В Docker Station на Synology у меня было: +```yml +version: "3.8" +services: audiobookshelf: + image: advplyr/audiobookshelf:latest + restart: always + ports: + - 8000:80 + volumes: + - ./config:/config + - ./metadata:/metadata + - /volume1/music/_podcasts:/podcasts + - /volume1/music/_audio_books:/audiobooks + environment: + - TZ=Europe/Moscow +``` + +Тут, вроде все просто. На Synology есть папка `/volume1/music/` уже с завода. В ней я создал папки `_podcasts` + и `_audio_books` для хранения книг и подкастов, и смонтировал эти папки в контейнер. Также добавил папки `config` + и `metadata` для хранения конфигурации и метаданных. Эти папки создадются при первом запуске контейнера, и будут + расположены рядом `compose.yml` (в каталоге `/volume1/docker/audiobookshelf/`... папка `/volume1/docker/` тоже + будет создана при установке приложения Docker Station на Synology... нам нужно только создать каталог `audiobookshelf/` + и и выбрать ее при создании проекта в Docker Station). + +Порт 8000 проброшен наружу и Nginx на хосте Orange Pi 5 Plus проксирует на этот порт, добавляет SSL и так далее. + +### Новая схема и манифест для Docker Station + +Теперь у нас будет три контейнера (и определённая зависимость между ними): + +```yml +version: "3.8" + +services: + # [1] Shadowsocks клиент для подключения к Outline/VPS (предоставляет SOCKS5 на порту 1080) + ss-ru: + image: shadowsocks/shadowsocks-libev + container_name: ss-ru + restart: unless-stopped + command: > + ss-local + -s [IP-адрес Outline/VPS] + -p [порт Outline/VPS] + -k [пароль Outline/VPS] + -m [метод шифрования] + -l 1080 + -b 0.0.0.0 + + # [2] Privoxy — HTTP-прокси для Node.js, форвардит через ss-ru + tun2socks: + image: xjasonlyu/tun2socks + container_name: tun2socks + restart: unless-stopped + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun + ports: + - "8000:80" + command: > + -device tun://tun0 + -proxy socks5://ss-ru:1080 + depends_on: + - ss-ru + + # [3] Audiobookshelf, использующий Privoxy для доступа к интернету + audiobookshelf: + image: advplyr/audiobookshelf:2.28.0 + container_name: audiobookshelf + restart: always + network_mode: "service:tun2socks" + volumes: + - ./config:/config + - ./metadata:/metadata + - /volume1/music/_audio_books:/audiobooks + - /volume1/music/_podcasts:/podcasts + environment: + - TZ=Europe/Moscow + depends_on: + tun2socks: + condition: service_started +``` + +Что тут происходит: + +**Первым стартует** контейнер `ss-ru`. Он ни от кого не зависит. Он подключается к моему Outline-серверу и предоставляет + SOCKS5-прокси на порту `1080`. + +Где брать параметры для подключения к Outline/VPS? В панели Outline Manager "Add new Key". Она предоставит строку вида: + `ss://[зашифрованный-base64-ключ--метод-шифрования:пароль]@[IP-адрес Outline/VPS]:[порт Outline/VPS]/?outline=1`. + Параметры `[IP-адрес Outline/VPS]` и `[порт Outline/VPS]` нужно взять непосредственно из этой строки. Метод шифрования + и пароль нужно расшифровать из первой части строки (часть строки между `ss://` и до `@`). Например, командой + в терминале: + ```shell + echo "Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTpDYVF6OERMRDVHd09meTRvVVk1TmxK" | base64 -d +``` + +Получим строку вида `chacha20-ietf-poly1305:пароль`. Таким образом `[метод шифрования]` — это `chacha20-ietf-poly1305`, + а `[пароль Outline/VPS] — это `пароль`. + +**Вторым стартует** контейнер `tun2socks`. Он зависит от `ss-ru`, так что гарантированно запустится после него. Он + использует `ss-ru` как SOCKS5-прокси и создает TUN-интерфейс `tun0` внутри контейнера. Так же он предоставляет + HTTP-интерфейс на порту 80 внутри нашего проекта Docker Station (с него будет отвечать Audiobookshelf) который + проброшен наружу как 8000). + +Контейнер tun2socks использует системный TUN-интерфейс Synology (`/dev/net/tun`). Поэтому контейнеру нужны права +и доступ к этому устройству. Это достигается через: +```yml + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun +``` + +На Synology (да и многих Linux) TUN-интерфейс `/dev/net/tun` обычно закрыт. Нужно будет разрешить доступ к нему: +```bash +# Проверяем, что TUN доступен +ls /dev/net/tun +# Если выдаёт "/dev/net/tun: no such device", то нужно создать устройство +sudo modprobe tun +# И снова проверить, что устройство появилось +ls /dev/net/tun +# Должно вывести: /dev/net/tun +``` + +| Заметим | +| ------- | +| Я пробовал други решения: (1) `Privoxy` -- Проблемы: axios внутри Audiobookshelf плохо работает с proxy, ломаются редиректы,SSRF фильтр, сами RSS загружаются, но SSRF будет блокировать запросы к iTunes, а, значит, не будут получаться метаданные, а без метаданных и mp3-файлы не скачиваются. (2) `redsocks` -- Проблемы: нестабильный iptables redirect (на Synology это вообще не работает, похоже), падение самого redsocks, сложная настройка NAT внутри Docker. + +**Третьим стартует** контейнер `audiobookshelf`. В нем почти все по старому. Но теперь он зависит от `tun2socks`, + так что гарантированно запустится после него. Кроме того у него теперь нет проброса портов `8000:80` (они у нас + теперь в контейнере tun2socks). Вместо этого у него `network_mode: "service:tun2socks"`. Это значит, что он будет + использовать сетевой стек контейнера tun2socks. В результате весь его трафик будет идти через TUN-интерфейс + Дальше уже `tun2socks` определит что с ним делать. Если трафик пришел снаружи, с порта 8000, то он попадёт + в Audiobookshelf, как и раньше. Если же сам Audiobookshelf начнет что-то скачивать, то запрос уйдет через + TUN-интерфейс, попадет в `tun2socks`, который отфорвардит его через SOCKS5-прокси `ss-ru` на Outline/VPS + (на внешнем хостинге). + + ## Запуск и проверка +