Outline VPN: свой сервер и ключи доступа

Outline VPN на своём VPS: установка сервера Shadowsocks, ключи доступа и лимиты трафика, префиксы маскировки и честная оценка того, как Outline работает в России.

Outline — это сервер на базе Shadowsocks, приложение Outline Manager для администратора и клиенты для всех популярных платформ. Проект создан в Jigsaw, сейчас его репозитории ведёт организация OutlineFoundation на GitHub. Актуально на сентябрь 2026 года: сервер shadowbox 1.12.3, клиенты Outline 1.21.

Что понадобится

  • VPS ForestsNet Cloud в Нидерландах или Германии с Ubuntu 22.04/24.04 или Debian 12.
  • Доступ по SSH под root или пользователем с sudo — см. «Консоль VNC и первое подключение».
  • Домен с A-записью на IP сервера — по желанию, но с ним переезд на другой IP не требует перевыпуска ключей.
  • Outline Manager для Windows, macOS или Linux — тоже по желанию: всё то же доступно через API.
Совет: в пакет трафика ForestsNet Cloud идёт только исходящий трафик, и лимиты ключей Outline считает по нему же — по байтам, которые сервер отправляет клиентам и сайтам.

Что такое Outline и когда он уместен

Как устроен

Сервер — Docker-контейнер shadowbox: внутри работают outline-ss-server (Shadowsocks на Go), API управления на Node.js и Prometheus для учёта трафика. API слушает отдельный порт по HTTPS с самоподписанным сертификатом и отвечает только на запросы с секретным путём. Соседний контейнер watchtower раз в час проверяет обновления образа.

Ключ доступа — ссылка ss:// с адресом, портом, шифром (по умолчанию chacha20-ietf-poly1305) и паролем; обычно все ключи живут на одном порту. На чужие данные сервер не отвечает и держит соединение до таймаута, повторы записанных рукопожатий отбрасывает — так он защищается от активного зондирования. Журналов активности пользователей нет, Prometheus хранит метрики трафика за 31 день.

Насколько он устойчив в 2025–2026

Shadowsocks — «полностью зашифрованный» протокол: с первого байта поток похож на случайный шум, и цензор распознаёт его эвристиками. Великий китайский файрвол с ноября 2021 года пропускает трафик, похожий на известные протоколы, а остальной блокирует. Ответом Outline стали префиксы из шага 5.

В России картина такая:

  • С весны 2024 года ТСПУ распознаёт Shadowsocks и VMess по следам TLS-рукопожатия внутри туннеля: клиент отправляет минимум три пакета от 411 байт, а сервер шлёт пакеты чаще клиента. Префикс меняет только первые байты, а эта проверка смотрит на размеры и порядок пакетов.
  • На ntc.party в августе 2024 года писали, что префиксы у МегаФона, Билайна, Tele2 и Ростелекома помогают частично или не помогают вовсе. В июле–августе 2025-го Outline переставал работать у многих абонентов Ростелекома, Билайна, МегаФона и Yota; один из участников заметил, что проходят только соединения на порты до 1024.
  • Часть мер от протокола не зависит. С июня 2025 года фиксируют «заморозку»: TCP-соединение к подсетям зарубежных хостингов замирает после 15–20 КБ данных. При отключениях мобильного интернета включаются «белые списки», и напрямую до зарубежного сервера не проходит никакой VPN.

Серверная часть Outline при этом почти не меняется: релизов не было с февраля 2025 года, стабильный shadowbox 1.12.3 содержит outline-ss-server 1.7.3 без поддержки WebSocket. Развиваются клиент и SDK.

Итог: всё решают оператор, регион и подсеть сервера. У одних Outline работает месяцами, у других перестаёт за день, а на мобильном интернете в России он ненадёжен.

Outline, VLESS Reality или AmneziaWG

  • Outline — когда важны простота и скорость запуска: сервер одной командой, ключ ссылкой, лимиты трафика без отдельной панели. Подходит для семьи и небольшой команды, поездок, стран с мягкой фильтрацией и как запасной канал.
  • VLESS + Reality — если пользователи выходят в сеть через мобильный интернет в России. Соединение выглядит как TLS 1.3 к настоящему сайту; по отзывам это один из самых устойчивых вариантов, хотя с конца 2025 года его точечно блокируют в отдельных регионах. См. «VLESS + Reality в 3x-ui».
  • AmneziaWG — если нужен полноценный VPN уровня WireGuard поверх UDP с обфускацией: «Свой сервер AmneziaWG».

Остальные варианты сравниваются в статье «Протоколы для своего VPN».

Шаг 1. Выберите порты и откройте их

Установочный скрипт по умолчанию берёт случайные порты. Задайте их сами, чтобы заранее знать, что открыть в файрволе:

  • Порт API — любой свободный, например 51443/tcp. Он нужен только администратору.
  • Порт ключей — для пользователей, по TCP и UDP. Если на сервере нет веб-сервера, начните с 443: для префиксов порт должен совпадать с протоколом, под который вы маскируетесь.

Если есть домен, направьте A-запись, например vpn.example.com, на IP сервера. Порты откройте в ufw, SSH — первым, иначе включение файрвола оборвёт сессию. Подробнее — в статье «Файрвол ufw: порты».

sudo ufw allow OpenSSH
sudo ufw allow 51443/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp
sudo ufw enable
Совет: Docker обычно публикует порты в обход ufw, но shadowbox запускается в сети хоста (--net host), поэтому правила ufw действуют на него как на обычный процесс.

Шаг 2. Установите Outline Server

Запустите официальный скрипт. Если домена нет, уберите --hostname — скрипт сам определит внешний IPv4. Скрипту нужны wget и curl; на минимальном образе сначала выполните sudo apt install -y wget curl.

sudo bash -c "$(wget -qO- https://raw.githubusercontent.com/OutlineFoundation/outline-apps/master/server_manager/install_scripts/install_server.sh)" install_server.sh --hostname vpn.example.com --api-port 51443 --keys-port 443

Если Docker не установлен, скрипт предложит поставить его через get.docker.com — ответьте Y. Затем он создаст /opt/outline с секретным путём API длиной 128 бит и самоподписанным сертификатом, запустит shadowbox из образа quay.io/outline/shadowbox:stable и watchtower, создаст первый ключ и выведет строку для менеджера:

CONGRATULATIONS! Your Outline server is up and running.

To manage your Outline server, please copy the following line (including curly
brackets) into Step 2 of the Outline Manager interface:

{"apiUrl":"https://vpn.example.com:51443/СЕКРЕТНЫЙ_ПУТЬ","certSha256":"ОТПЕЧАТОК"}
Важно: эта строка даёт полный доступ к управлению сервером. Не публикуйте её; копия хранится в /opt/outline/access.txt.

Если в проверке файрвола скрипт написал BLOCKED, порты закрыты — вернитесь к шагу 1. Проверьте контейнеры:

sudo docker ps --format '{{.Names}}: {{.Status}}'
Готово: в выводе есть shadowbox и watchtower со статусом Up.

Шаг 3. Подключите Outline Manager

Скачайте менеджер с getoutline.org или по прямым ссылкам из официального списка загрузок. Сборки из Telegram и с файлообменников не используйте.

В менеджере нажмите + и выберите «Настройте Outline где угодно». Команду из инструкции выполнять не нужно, сервер уже стоит. Вставьте JSON-строку из шага 2 в поле «Вставьте сюда информацию, полученную при выполнении скрипта установки» и нажмите «Готово». Менеджер сверит отпечаток сертификата certSha256 и откроет сервер.

Если строка потерялась, соберите её из access.txt:

sudo awk -F: '/^certSha256:/{c=$2} /^apiUrl:/{sub(/^apiUrl:/,""); a=$0} END{printf "{\"apiUrl\":\"%s\",\"certSha256\":\"%s\"}\n", a, c}' /opt/outline/access.txt

Шаг 4. Создайте и раздайте ключи

Создание и раздача

Нажмите «Добавить новый ключ», переименуйте его по имени человека и нажмите значок «Поделиться». «Копировать ключ доступа» даёт строку ss://…, «Копировать приглашение» — текст со ссылкой на установку клиента. Передавайте ключ по защищённому каналу: у кого строка, тот и подключается.

Выдавайте каждому свой ключ. Один ключ работает на всех устройствах человека, но общий ключ на группу нельзя отозвать у кого-то одного.

Лимиты трафика

Общий лимит задаётся на вкладке «Настройки» в блоке «Ограничения на передачу данных», лимит отдельного ключа — пунктом «Лимит трафика» в его меню. Как это работает:

  • Считается скользящее окно за 30 дней, а не календарный месяц.
  • Проверка идёт раз в час, так что ключ может выйти за лимит на объём часового трафика.
  • Учитывается исходящий трафик сервера: к клиенту и к сайтам.
  • Исчерпавший лимит ключ молча перестаёт подключаться, пока расход за 30 дней не опустится ниже порога.

Отзыв и смена адреса

Удалённый ключ перестаёт подключаться. «Имя хоста» и «Порт для новых ключей доступа» в настройках влияют только на ключи, выданные после изменения: у пользователей остаются старые ссылки. Поэтому адрес сервера лучше сразу сделать доменом или раздавать динамические ключи.

Управление через API

Менеджер не обязателен: те же действия выполняются запросами к API прямо с сервера. Это выручает, когда из вашей сети сервер недоступен.

API_URL=$(sudo sed -n 's/^apiUrl://p' /opt/outline/access.txt)
curl -sk "$API_URL/server"
curl -sk "$API_URL/access-keys"
curl -sk -X POST -H 'Content-Type: application/json' -d '{"name":"anna","limit":{"bytes":50000000000}}' "$API_URL/access-keys"
curl -sk -X PUT -H 'Content-Type: application/json' -d '{"limit":{"bytes":100000000000}}' "$API_URL/access-keys/3/data-limit"
curl -sk -X DELETE "$API_URL/access-keys/3"

По порядку: настройки сервера с версией, список ключей, новый ключ anna с лимитом 50 ГБ, лимит 100 ГБ для ключа с id 3, удаление этого ключа. Общий лимит — запрос PUT на $API_URL/server/access-key-data-limit с тем же телом, остальные методы — в спецификации api.yml.

Динамические ключи ssconf://

Статический ключ ss:// жёстко хранит адрес, порт и пароль. Динамический хранит только адрес конфигурации, а клиент скачивает её при каждом подключении. Так можно сменить IP, порт или префикс, не рассылая новые ключи.

  1. Возьмите password и method ключа из вывода curl -sk "$API_URL/access-keys".
  2. Сохраните конфигурацию в файл и выложите по HTTPS туда, где она не зависит от IP VPN-сервера.
  3. Замените в адресе файла https:// на ssconf:// и добавьте название после #, например ssconf://example.org/k/7f3a9c/anna.yaml#anna.

Клиент понимает три формата: ссылку ss:// (с версии 1.8.1), JSON (с 1.8.0) и YAML (с 1.15.0). В YAML TCP и UDP настраиваются по отдельности:

transport:
  $type: tcpudp
  tcp:
    $type: shadowsocks
    endpoint: vpn.example.com:443
    cipher: chacha20-ietf-poly1305
    secret: ПАРОЛЬ_КЛЮЧА
  udp:
    $type: shadowsocks
    endpoint: vpn.example.com:443
    cipher: chacha20-ietf-poly1305
    secret: ПАРОЛЬ_КЛЮЧА
Важно: в конфигурации лежит пароль, поэтому путь к файлу делайте длинным и неугадываемым. Клиент скачивает её напрямую, ещё до поднятия туннеля: если площадка с конфигом недоступна, подключения не будет.

Шаг 5. Настройте префикс маскировки

Префикс — несколько байтов, которые клиент ставит в начало соли Shadowsocks. Соединение начинается так же, как разрешённый протокол, и эвристики вида «пропускаем всё, что похоже на известное» его не трогают. Сервер менять не нужно: для него префикс — часть случайной соли.

Условия из документации Outline:

  • Клиент версии 1.9.0 или новее.
  • Не длиннее 16 байт: длинный префикс повышает риск совпадения солей, а это ослабляет шифрование и само по себе заметно.
  • Порт ключа соответствует протоколу, под который вы маскируетесь.

Примеры для TCP из документации, в URL-кодировке:

  • HTTP-запрос, порт 80: POST%20
  • HTTP-ответ, порт 80: HTTP%2F1.1%20
  • TLS ClientHello, порт 443: %16%03%01%00%C2%A8%01%01
  • TLS ServerHello, порт 443: %16%03%03%40%00%02
  • SSH, порт 22: SSH-2.0%0D%0A

Допишите префикс в конец статического ключа:

ss://[email protected]:443/?outline=1&prefix=%16%03%01%00%C2%A8%01%01

В статическом ключе префикс действует только на TCP; для UDP его задают полем prefix в блоке udp YAML-конфигурации. Байты от 0x80 кодируются как символы в UTF-8, поэтому 0xA8 превращается в %C2%A8. Надёжнее всего получить строку через encodeURIComponent() в консоли браузера.

Важно: префикс маскирует только начало соединения. Против распознавания по размерам пакетов, блокировки IP и «заморозки» после 15–20 КБ он бесполезен. Отзывы из России противоречивы: у кого-то префикс TLS выручал на мобильной сети, у кого-то не помогал вовсе.

Shadowsocks поверх WebSocket

Если префиксы не помогают, следующий официальный шаг — Shadowsocks поверх WebSocket с TLS: снаружи это обычный HTTPS на 443-м порту, который можно спрятать за CDN. Нужны клиент 1.15.0+ и YAML-ключ с endpoint типа websocket. Стандартный shadowbox так не умеет: понадобится отдельный outline-ss-server 1.9+ за веб-сервером или Caddy с модулем outlinecaddy, а такими ключами Outline Manager не управляет. Инструкции — в документации: WebSockets и Caddy. CDN при этом не гарантия: в 2025 году в России были массовые сбои у сервисов за Cloudflare.

Шаг 6. Установите клиенты

Официальные клиенты Outline, актуальная ветка — 1.21:

Скопируйте ключ и откройте клиент — он сам заметит ключ в буфере обмена. Иначе нажмите «Добавить сервер», вставьте ключ, затем «Подключить».

На 30 сентября 2026 года Outline есть в российском App Store, но Apple по требованию Роскомнадзора уже удалила оттуда сотни VPN-приложений — держите в запасе APK и прямые ссылки. Сторонние клиенты Shadowsocks с поддержкой SIP002 понимают ключ ss://, но prefix и ssconf:// умеют не все.

Диагностика

Менеджер не видит сервер

  • Закрыт порт API. Проверьте sudo ufw status и запрос со своего компьютера: curl -k https://vpn.example.com:51443/СЕКРЕТНЫЙ_ПУТЬ/server должен вернуть JSON с версией.
  • Не работает контейнер. Смотрите sudo docker ps -a и sudo docker logs --tail 50 shadowbox.
  • Сервер недоступен из вашей сети. Управляйте ключами через API по SSH или подключите менеджер из другой сети.
  • Сервер переустановлен. Секрет и сертификат теперь другие: удалите сервер из менеджера и добавьте заново с новой строкой.

Ключ не подключается

  • Закрыт порт ключей. Нужны и TCP, и UDP: что слушает сервер, покажет sudo ss -tulpn | grep outline-ss, что открыто — sudo ufw status.
  • Устаревший ключ. Ключ удалён, сервер переустановлен или в ключе старый IP.
  • Исчерпан лимит. Проверьте расход ключа в менеджере.
  • Старый клиент. Префиксу нужна версия 1.9.0, YAML-ключам — 1.15.0.
  • Блокировка у оператора. Через Wi-Fi работает, а через мобильный интернет нет — дело не в сервере. Проверьте из той же сети SSH-порт: nc -vz vpn.example.com 22. SSH открывается, а ключ нет — фильтруется протокол; не открывается ничего — заблокирован IP.

Работает, а через время перестаёт

  • Протокол начали распознавать. Попробуйте префикс и другой порт, не помогло — WebSocket или VLESS Reality.
  • Заблокирован IP. Нужен новый IP; с доменом или динамическими ключами пользователям ничего менять не придётся.
  • Исчерпан лимит. Ключ заработает сам, когда расход за 30 дней опустится ниже порога.
  • Включены белые списки. Во время отключений мобильного интернета настройками сервера это не исправить.

Низкая скорость, не работают звонки

  • «Заморозка» после 15–20 КБ. Страницы начинают грузиться и зависают, а мелкие запросы проходят. Проверьте сеть чекером TCP 16-20.
  • Не проходит UDP. Клиент проверяет UDP DNS-запросом к 1.1.1.1 и без UDP переводит DNS на TCP, но звонки, игры и QUIC страдают. Откройте UDP на порту ключей.
  • Не хватает ресурсов сервера. Посмотрите загрузку процессора и канала в top и в панели VPS. Эффекта «TCP поверх TCP» у Shadowsocks нет: клиент завершает соединения у себя, а сервер открывает их заново.

Не зондируют ли сервер

outline-ss-server считает подозрительные подключения в метрике shadowsocks_tcp_probes. Prometheus слушает только 127.0.0.1, обычно на порту 9090:

curl -sG http://127.0.0.1:9090/api/v1/query --data-urlencode 'query=sum by (status) (increase(shadowsocks_tcp_probes_count[24h]))'

Статусы ERR_REPLAY_CLIENT и ERR_REPLAY_SERVER — повторы чужих рукопожатий, характерный след активного зондирования. ERR_CIPHER — данные, не подошедшие ни к одному ключу: это и зонды, и клиенты с удалёнными ключами.

Безопасность

Базовая защита сервера описана в статьях «Усиление SSH» и «Чеклист базовой защиты VPS». API отвечает только на секретный путь, но сам порт виден любому сканеру. Если у вас постоянный IP, оставьте доступ к API только ему:

sudo ufw delete allow 51443/tcp
sudo ufw allow from 198.51.100.7 to any port 51443 proto tcp

Без постоянного IP порт API можно закрыть совсем и ходить к нему через SSH-туннель: ssh -N -L 51443:127.0.0.1:51443 [email protected], а в JSON-строке для менеджера указать https://127.0.0.1:51443/СЕКРЕТНЫЙ_ПУТЬ. Менеджер проверяет только отпечаток сертификата, имя хоста ему не важно.

Самые чувствительные файлы — /opt/outline/access.txt (полный доступ к API), persisted-state/start_container.sh (секретный путь) и persisted-state/shadowbox_config.json (пароли всех ключей). Не кладите их в общедоступные бэкапы.

Анонимная статистика для разработчиков Outline по умолчанию не отправляется. Через ваш IP пойдёт чужой трафик, и жалобы правообладателей придут вам — см. «Как заблокировать торренты на своём VPN или прокси».

Обновление

watchtower раз в час проверяет образ shadowbox и сам перезапускает контейнер. Но с выходом Docker Engine 29 в ноябре 2025 года старый образ containrrr/watchtower перестал работать с ошибкой client version 1.25 is too old, и в январе 2026 года установочный скрипт перешёл на поддерживаемый форк nickfedor/watchtower. Если сервер ставили раньше, проверьте журнал:

sudo docker logs --tail 5 watchtower

Если там эта ошибка, пересоздайте контейнер с параметрами из скрипта:

sudo docker rm -f watchtower
sudo docker run -d --name watchtower --log-driver local --restart always -v /var/run/docker.sock:/var/run/docker.sock nickfedor/watchtower --cleanup --label-enable --tlsverify --interval 3600

Обновить shadowbox вручную:

sudo docker pull quay.io/outline/shadowbox:stable
sudo /opt/outline/persisted-state/start_container.sh

Если файла start_container.sh нет, сервер ставили старой версией скрипта; такой сервер обновляйте через watchtower.

Бэкап и перенос

Всё состояние лежит в /opt/outline: ключи и лимиты — в persisted-state/shadowbox_config.json, настройки — в shadowbox_server_config.json, сертификат и секрет API — в shadowbox-selfsigned.* и start_container.sh, статистика — в prometheus/. Для целостной копии остановите контейнер на время архивации:

sudo docker stop shadowbox
sudo tar -czpf /root/outline-backup.tar.gz -C /opt outline
sudo docker start shadowbox

На новом VPS установите Docker, скопируйте туда архив, распакуйте его и запустите контейнер — ключи, лимиты и доступ менеджера сохранятся:

curl -fsSL https://get.docker.com | sudo sh
sudo tar -xzpf outline-backup.tar.gz -C /opt
sudo /opt/outline/persisted-state/start_container.sh

watchtower запустите командой из раздела «Обновление». Если сервер работал через домен, осталось поменять A-запись. Если через IP, замените адрес в JSON-строке для менеджера и в поле «Имя хоста», а пользователям раздайте ключи заново.

Важно: в архиве пароли всех ключей и секрет API. Храните его так же бережно, как SSH-ключи.

Источники