Outline VPN это проект компании Jigsaw, дочерней компании Google. Outline использует протокол Shadowsocks для связи между клиентом и сервером. Трафик шифруется с помощью шифра IETF ChaCha20 и аутентифицируется с помощью IETF Poly1305.
В этой инструкции мы рассмотрим настройку клиента на базе пакета shadowsocks-libev и опционально, поднятие интерфейса с помощью kmod-tun и xjasonlyu/tun2socks. Способ подходит для роутеров с объёмом ОЗУ от 64 Мб и ПЗУ от 8 Мб.
UPD. 14.09.2023 Решение для ошибки ниже найдено, описал в п.4
daemon.err /usr/bin/ss-redir[7401]: accept: No file descriptors available
Нам потребуется доступ к SSH и Веб-интерфейсу LuCI
Установка пакетов на роутере
Получение ключа доступа в Outline Manager
Настройка shadowsocks-libev на роутере
Фикс для OpenWRT 22.03 и выше
Настройка интерфейса с помощью tun2socks
1. Установка пакетов на роутере
Развёртывание Outline VPN на VDS или собственном сервере довольно простое, инструкция есть на официальном сайте проекта:
Outline VPN - Access to the free and open internet (getoutline.org)
и на Хабре:
Outline: Делаем свой личный VPN от Google за 5$ в месяц (и за 1€ для продвинутых) / Хабр (habr.com)
Проблема в том, что официальной инструкции для использования Outline на OpenWRT нету, но так как Outline VPN основан на Shadowsocks мы будет использовать пакеты:
shadowsocks-libev-ss-local
shadowsocks-libev-ss-redir
shadowsocks-libev-ss-rules
shadowsocks-libev-ss-tunnel
И для настройки в интерфейсе LUCI
luci-app-shadowsocks-libev
Устанавливаем пакеты:
opkg update
opkg install shadowsocks-libev-ss-local shadowsocks-libev-ss-redir shadowsocks-libev-ss-rules shadowsocks-libev-ss-tunnel
opkg install luci-app-shadowsocks-libev
Далее нам потребуется ключ доступа к Outline
2. Получение ключа доступа в Outline Manager
Запускаем Outline Manager
Добавляем ключ либо используем существующий
Копируем ключ доступа, в нём содержатся IP адрес сервера и порт подключения и пароль в зашифрованном виде
ss://[пароль-шифрованный]@IP:Port/?outline=1
3. Настройка shadowsocks-libev на роутере
Далее на примере LUCI (OpenWRT 19.07)
Переходим в раздел Службы - Shadowsocks-libev
Переходим во вкладку Remote Servers (Удаленные серверы)
Сюда вставляем IP адрес, порт сервера
Для получения пароля нужен декодер формата Base64, например Base64 Decode and Encode - Online
Вставляем полученный пароль и выбираем нужный метод шифрования из выпадающего списка после чего убираем галку из поля Отключить.
Применяем изменения.
В версиях OpenWRT 21.02 и выше в разделе Remote Servers есть опция Ссылка на импорт, туда просто вставляем наш код доступа из Outline и получаем готовую запись в конфиге.
Далее возвращаемся на вкладку Local Instances (Локальные экземпляры)
ss_redir отвечает за перенаправление трафика в прокси согласно правилам ss-rules
ss_local поднимает socks5 прокси на выбранном порту
ss_server поднимает shadowsocks сервер
ss_tunnel поднимает туннель до заданного узла (например можно настроить туннель до DNS Google по адресу 8.8.8.8:53 и перенаправлять запросы DNS на локальный адрес, например 127.0.0.1#8053, а запросы через shadowsocks будут уходить к Google, будет аналог DNS-over-HTTPS)
Для переадресации трафика в Outline нужен шаблон ss_redir
SS-redir отвечает за перенаправление трафика в прокси согласно правилам ss-rules
Для начала перейдем в ss_redir.hj (или ss_redir.hi или можно создать новый, это не принципиально)
Проверяем чтобы в графе Remote Server был сервер с данными Outline, убираем галку напротив Отключить
Далее переходим на вкладку Redir Rules (Правила Redir)
Если вы хотите перенаправлять весь трафик в Outline, то выбираете чтобы ss-redir for TCP и UDP соответствовал выбранному ранее пункту (hj, hi или тому который вы сделали), если вам нужен обход блокировок только для интернет-сайтов, а UDP трафик (например онлайн-игры) должен идти напрямую, то выбираете только ss-redir for TCP, а UDP оставляете пустым.
По умолчанию весь трафик (TCP и UDP в зависимости от того что вы выбрали в предыдущем пункте) будет идти через прокси, поэтому оставляем вариант forward (направлять всё по умолчанию), убеждаемся что нет галки напротив Отключить и переходим на вкладку Source Settings (Настройки источника)
Здесь можно настроить исключения для IP адресов в вашей локальной сети,
Src ip/net bypass позволяет добавленному в этот список IP ходить в интернет напрямую, игнорируя настройки shadowsocks-libev (список исключений)
Src ip/net forward - IP добавленные в этот список будут ходить в интернет согласно настройкам shadowsocks-libev, этот список важен, если вы выберите чтобы через прокси ходили только выбранные устройства (src default в таком случае будет bypass)
Src ip/net checkdst - IP добавленные в этот список будут ходить через прокси только на узлы, которые указаны в Destination Settings (соответственно не указанные адреса, будут использовать политику по умолчанию)
Src default - политика по умолчанию для адресов источника (локальные IP адреса, вида 192.168.1.1 и пр.)
forward - направлять трафик от любых адресов через прокси
bypass - направлять трафик от любых источников напрямую
checkdst - сверяться со списком адресов назначения в Destination Settings и только в этом случае направлять трафик через прокси.
Здесь оставляем настройки по умолчанию, далее переходим в Destination Settings (Настройки назначения)
Dst ip/net bypass - Для указанных адресов назначения трафик будет идти через напрямую, игнорируя прокси (например IP адреса российского сегмента и т.д., каждая подсеть вида 24.88.32.0/24 указывается отдельной строкой) В этот пункт стоит прописать IP вашего сервера Outline для избежания конфликтов
Dst ip/net forward - Для указанных адресов назначения трафик будет идти через прокси (например заблокированные адреса и т.д., каждая подсеть вида 24.88.32.0/24 указывается отдельной строкой)
Dst ip/net bypass file - здесь можно указать путь к файлу списку адресов, доступ к которым будет осуществляться напрямую, игнорируя прокси (его нужно будет создать или скачать на роутер, например в директорию /etc/shadowsocks-libev или /root)
Dst ip/net forward file - здесь можно указать путь к файлу списку адресов, доступ к которым будет осуществляться через прокси (его нужно будет создать или скачать на роутер, например в директорию /etc/shadowsocks-libev или /root)
Для примера настроим весь трафик через прокси:
Задаём для Dst default - forward (по умолчанию весь трафик будет идти через прокси, о других вариантах будет в конце статьи)
Нажимаем Применить и проверяем работу:
wget -qO- http://ipecho.net/plain | xargs echo
Команда выдаст IP адрес сервера Outline.
Так будет выглядеть конфиг /etc/config/shadowsocks-libev (если вы сделали действия описанные выше, ваш конфиг выглядит аналогично)
config server 'sss0'
option server '$OUTLINE_IP'
option server_port '$PORT'
option method 'chacha20-ietf-poly1305'
option password '$DECRYPTED_PASSWORD'
config ss_redir 'hj' #Setting to redirect all traffic by Redir_rules
option server 'sss0'
option local_address '0.0.0.0'
option local_port '1100'
option mode 'tcp_and_udp'
option timeout '60'
option fast_open '1'
option reuse_port '1'
config ss_rules 'ss_rules' #Rules of traffic redirection
option src_default 'checkdst'
option dst_forward_recentrst '0'
option redir_tcp 'hj'
option redir_udp 'hj'
option local_default 'forward'
option dst_default 'forward' #Forward all traffic
При желании можно использовать Outline только для списка адресов (например списки заблокированных адресов от antifilter.download)
Для этого скачаем файл ipsum.lst (список IP заблокированных РКН с суммаризацией по подсетям, могут быть совпадения с IP адресами не заблокированными)
wget https://antifilter.download/list/ipsum.lst -O /etc/shadowsocks-libev/ipsum.lst
В этом случае в общих настройках меняем forward на check-dst
В разделе Destination Settings (Настройки назначения) меняем политику по умолчанию Dst default на bypass а в пункт Dst ip/net forward file добавляем путь к файлу /etc/shadowsocks-libev/ipsum.lst которые должны работать через прокси.
В новых версиях OpenWRT вместо указания пути к файлу, браузер предложит загрузить файл с ПК (для этого нужно скачать список ipsum.lst с сайта antifilter.download и загрузить его на роутер)
Нажимаем Применить и проверяем работоспособность.
4. Исправляем ошибку ss-redir на OpenWRT 22.03 и выше
Проблема возникает из-за неправильных настроек по умолчанию у Shadowsocks-libev конфликтующих с обновлённым firewall4 основанным на nftables и вызывающая утечку памяти и зависание роутера.
Для её исправления необходимо перейти в раздел Службы - Shadowsocks-libev - Redir Rules - Основные Настройки (General Settings)
Для новой версии обязательно должны быть заполнены пункты:
Extra tcp expression - здесь указывается диапазон TCP портов направляемых через прокси (даже если это все порты, они должны быть указаны), заполняем:
tcp dport { 80-17214, 17216-65535 }
- в моём случае порт Outline - 17215, его я исключил из диапазона, иначе получаю ошибку ss-redir. Обязательно напишите диапазоны с учётом вашего порта Outline или оставьте строку - tcp dport { 80, 443 }
чтобы проксировались только порты 80 и 443.
Extra udp expression - здесь указывается диапазон UDP портов направляемых через прокси (даже если это все порты, они должны быть указаны), заполняем
udp dport { 53-65535 }
здесь я указываю все порты от 53 (DNS) до последнего, добавлять порт Outline в исключения не нужно, т.к. shadowsocks работает через TCP.
Сохраните и Примените изменения.
Этого достаточно чтобы shadowsocks-libev работал на OpenWRT 22.03 и выше.
На этом основная настройка прокси закончена, следующий раздел опциональный и позволит получить более простую маршрутизацию как в случае с OpenVPN и Wireguard.
5. Настройка интерфейса с помощью tun2socks
Этот раздел не обязательный для работы прокси и несколько сложнее чем предыдущие.
Если вам нужен tun2socks и Outline клиент, но без shadowsocks-libev, можете воспользоваться вариантом с установкой по скрипту
раздел далее предусматривает использование shadowsocks-libev ss_local (socks5 прокси)
Вам понадобится около 9Мб свободной памяти роутера.
Для настройки маршрутов с помощью iptables (nftables) будет удобнее использовать shadowsocks в качестве интерфейса tun, для этого необходимо определить архитектуру вашего устройства и скачать пакет с github:
Скачиваем файл:
ARCH=$(grep "OPENWRT_ARCH" /etc/os-release | awk -F '"' '{print $2}')
wget https://github.com/1andrevich/outline-install-wrt/releases/download/v2.5.1/tun2socks-linux-$ARCH -O /tmp/tun2socks
Проверяем работу программы:
chmod +x /tmp/tun2socks
/tmp/tun2socks --help
Если выдаёт справку по командам, значит всё работает и можно двигаться дальше
Далее для настройки маршрутов нужно перейти в Local Instances (Локальные экземпляры)
Выбираем внизу ss-local, вводим название, в моём случае tunnel и жмём добавить.
Вводим значение порта, в примере порт 1080, может быть любым свободным портом.
Нажимаем Cохранить.
Далее отключаем ss-redir:
Нажимаем Применить.
Согласно документации tun2socks рекомендуется присвоить интерфейсу ip адрес (на практике маршрутизация работает и перенаправлением в dev tun2)
Для этого в /etc/config/network добавим следующее содержание:
config interface 'tunnel'
option device 'tun2'
option proto 'static'
option ipaddr '172.16.10.1'
option netmask '255.255.255.252'
Диапазон 172.16.10.0/30 выбран случайно, может быть любой диапазон частных адресов
Так же создаём зону и правило в /etc/config/firewall
config zone
option name 'proxy'
option forward 'REJECT'
option output 'ACCEPT'
option input 'REJECT'
option masq '1'
option mtu_fix '1'
option device 'tun2'
option family 'ipv4'
config forwarding
option name 'lan-proxy'
option dest 'proxy'
option src 'lan'
option family 'ipv4'
Перезагружаем сеть
/etc/init.d/network restart
Далее проверяем работоспособность туннеля tun2socks:
/tmp/tun2socks -device tun2 -proxy 127.0.0.1:1080 -loglevel debug
Запустится туннель с логированием:
Где tun2 наименование туннеля
proxy - адрес socks туннеля указывающий на shadowsocks на порту 1080 (если вы меняли порт в ss-local, укажите свой).
Проверяем доступность интерфейса:
ping -n 172.16.10.2
Для проверки работоспособности можно временно добавить маршрут к сайту ipecho.net (не закрывая tun2socks, в параллельной вкладке).
ip route add 34.160.111.0/24 dev tun2
Обращаемся к сайту и смотрим логи:
wget -qO- http://ipecho.net/plain | xargs echo
Если всё работает, команда вернёт IP вашего прокси.
Можно закрывать tun2socks и удалить маршрут:
ip route del 34.160.111.0/24
Теперь перенесём файл в постоянную память устройства (Это потребует свободного места около 9Мб на роутере)
mv /tmp/tun2socks /usr/bin/tun2socks
Во избежание последующих проблем маршрутизации добавим статический маршрут до сервера Outline в LuCI
Переходим в Сеть - Статические маршруты
И добавляем маршрут до вашего сервера
Не забываем проверить доступность сервера после добавления маршрута
ping $Ваш_Сервер_Outline_IP
Теперь настроим службу, чтобы интерфейс начинал работать при загрузке роутера.
Здесь хочу выразить огромную благодарность пользователю itdog за информацию по настройке службы tun2socks (и за обзор темы впринципе).
В файл /etc/init.d/tun2socks вносим следующее содержание, например при помощи vi:
vi /etc/init.d/tun2socks
#!/bin/sh /etc/rc.common
USE_PROCD=1
# starts after network starts
START=99
# stops before networking stops
STOP=89
PROG=/usr/bin/tun2socks
IF="tun2"
HOST="127.0.0.1"
PORT="1080"
start_service() {
procd_open_instance
procd_set_param user root
procd_set_param command "$PROG" -device "$IF" -proxy "$HOST":"$PORT"
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
procd_close_instance
# ip route add "$OUTLINEIP" via "$DEFGW" #Adds route to OUTLINE Server
# echo 'route to Outline Server added'
#ip route save default > /tmp/defroute.save #Saves existing default route
echo "tun2socks is working!"
}
service_started() {
# This function checks if the default gateway is Outline, if no changes it
echo 'Replacing default gateway for Outline...'
sleep 2s
#if ip link show $IF | grep -q "UP" ; then
#ip route del default #Deletes existing default route
#ip route add default via 172.16.10.2 dev $IF #Creates default route through the proxy
#fi
}
start() {
start_service
service_started
}
boot() {
# This gets run at boot-time.
start
}
shutdown() {
# This gets run at shutdown/reboot.
stop
}
stop_service() {
service_stop "$PROG"
#ip route restore default < /tmp/defroute.save #Restores saved default route
# ip route del "$OUTLINEIP" via "$DEFGW" #Removes route to OUTLINE Server
echo "tun2socks has stopped!"
}
reload_service() {
stop
sleep 3s
echo "tun2socks restarted!"
start
}
Где IF - интерфейс, в данном примере tun2 (вместо tun0) чтобы избежать конфликтов с существующими туннелями.
PORT - Порт настроенный в ss-local
Если требуется перенаправлять весь трафик в shadowsocks, уберите # перед строками 25, 33, 34, 35, 36, и 54.
Для правильной работы скрипта (сохранение и восстановление маршрута по умолчанию) потребуется установить пакет ip-full
opkg install ip-full
Делаем файл исполняемым:
chmod +x /etc/init.d/tun2socks
Делаем автозапуск:
ln -s /etc/init.d/tun2socks /etc/rc.d/S99tun2socks
Запускаем:
/etc/init.d/tun2socks start
Проверяем, что интерфейс заработал:
ip a | grep 'tun2'
Если заработал, выдаст подобный результат:
tun2: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
inet 172.16.10.1/30 brd 172.16.10.3 scope global tun2
Если нет, ответ будет пустым.
Далее необходимо настроить маршруты к которым роутер будет обращаться через прокси.
Можно настроить маршрут по умолчанию для всего трафика (убрать # перед строками), либо настроить точечный обход блокировок (в конце статьи)
для настройки маршрута по умолчанию необходимо сначала создать маршрут до сервера Outline через ваш шлюз по умолчанию
Если настроен маршрут по умолчанию, проверяем работоспособность:
wget -qO- http://ipecho.net/plain | xargs echo
Команда вернёт IP адрес сервера Outline.
Для точечного обхода блокировок и настройки таких маршрутов:
Точечный обход блокировок на роутере OpenWrt c помощью BGP / Хабр (habr.com) С помощью BGP (bird2).
Точечный обход блокировок PKH на роутере с OpenWrt с помощью WireGuard и DNSCrypt / Хабр (habr.com) (путём скачивания списков и настройкой маршрутов в iptables, nftables).
P.S. Для замены уже не самого свежего shadowsocks-libev (и переставшего обновляться), если позволяет оборудование, можно использовать требующие больше 16Мб памяти и 128 Мб ОЗУ, но гораздо более функциональные V2RayA и Homeproxy.