Установка поддержки протокола Shadowsocks на роутерах Keenetic
@zloy_recruter, ред и публ @Вася ПупкинЭтот файл распространяется под лицензией Creative Commons.
Текущая редакция 25.01.2024 v 1.01 beta
Для начала стоит сказать, что вам подойдёт любой Keenetic, имеющий порт USB. Можно при сильном желании установить и в собственную память роутера, но многие не рекомендуют этого делать, поскольку память самого Keenetic-а куда более ранима, чем flash, да и в случае чего, флешку всегда можно просто поменять.
Данная инструкция написана на основе статей уважаемых людей на Хабре тут и здесь со своими исправлениями и некоторыми дополнениями.
Прежде всего, я бы рекомендовал изменить на вашем роутере настройки DNS по умолчанию от провайдера на другие, а именно на DNS-over-HTTPS или DNS-over-TLS. Это полезно сделать в любом случае, независимо от того, будете вы использовать в будущем VPN на своём роутере, или нет. Часть провайдеров вообще не допускает в своих сетях указания в свойствах соединения посторонних DNS (пример – Akado), некоторые интернет-провайдеры перехватывают запросы DNS, а какие-то пока нет. Поэтому лучше сразу настроить DNS с шифрованием один раз и надолго забыть об этом. Для этого идём в настройки роутера через веб-интерфейс и проверяем, установлены ли нужные модули.
Управление – параметры системы – кнопка «изменить набор компонентов»:

В строке поиска по компонентам пишем «DNS» и видим примерно следующее:

Прокси-сервер DNS-over-HTTPS и DNS-over-TLS – ставим галочки, если они не стоят, сохраняем изменения и перезагружаем роутер.
После перезагрузки заходим снова в веб-интерфейс роутера и следуем по пунктам меню Сетевые правила – интернет-фильтры – вкладка «настройка DNS»:

Щёлкаем на раздел «Системный» и значок карандашика рядом, убираем галочку «транзит запросов» - ОК:

Следом в правой части нажимаем «Добавить сервер», и вписываем следующие параметры:
Изменения сохраняем.

Обратите внимание, что бегунок с настройками DNS вашего провайдера должен быть отключен, как на Рис 3. На этом настройка DNS с шифрованием закончена, теперь ваш провайдер не будет понимать, на какие сайты вы ходите.
По такому же принципу установите парочку необходимых модулей, как на Рис 6, без них ничего не получится:

На этом подготовительные процедуры на самом роутере сделаны, и мы переходим к подготовке флешки, на которую будем устанавливать Entware в качестве дополнительной операционной системы для Keenetic.
Вам подойдет любая флешка, даже старая и с небольшим объёмом памяти, хоть 256 Мб, если ещё найдёте такую в наше время. (Лезем в ящик со старым хламом, проверяем зазоры между подушками дивана или допрашиваем свою котейку, куда она загнала старую флешку, играясь с ней).
1. Подготовка флешки:
Поскольку Entware является linux-подобной операционкой, то и файловая система ей нужна соответствующая. Мы будем форматировать флешку в формат ext4. Конечно, быстрей всего эта процедура делается в Linux, всего несколько секунд, но он далеко не у всех установлен дома, поэтому, будем это делать из-под Windows, благо, утилит под такую задачу много. Ищем через поисковик MiniTool Partition Wizard Free и скачиваем, устанавливаем, запускаем. Видим в списке дисков нашу флешку, форматируем со следующими параметрами:

Форматирование в ext4 в Windows в разы дольше чем в Linux, поэтому, надо набраться терпения и подождать завершения процедуры. Можно вставлять флешку в роутер!
2. Подготовка установки Entware
Качаем установщик для Keenetic DSL, LTE, VOX, DSL (KN-2010), DUO (KN-2110)
http://bin.entware.net/mipssf-k3.4/installer/mips-installer.tar.gz
Для остальных моделей Keenetic -
http://bin.entware.net/mipselsf-k3.4/installer/mipsel-installer.tar.gz
Заходим снова в веб-интерфейс роутера, Управление – Приложения. В списке видим нашу флешку, выбираем её и создаем в корне папку install (так же с маленькой буквы, это важно):

Следом ставим курсор уже на созданную папку install, нажимаем значок со стрелочкой вверх и записываем туда наш скачанный дистрибутив. Процедура аналогичная тому, как вы загружаете любой файл на веб-страницах.

Заходим в раздел Управление – OPKG, выбираем нашу флешку и удаляем сценарий в окошечке, если он есть и нажимаем кнопку «Сохранить»:

После этого подождите пару минут, а лучше потом зайдите в раздел Управление – Диагностика – кнопка «Показать журнал», должно быть что-то вроде
I [May 24 20:37:57] ndm: Opkg::Manager: configured init script: "/opt/etc/init.d/rc.unslung".
I [May 24 20:37:57] ndm: Core::Session: client disconnected.
I [May 24 20:37:57] ndm: Core::Server: started Session /var/run/ndm.core.socket.
I [May 24 20:37:57] ndm: Core::System::Configuration: saving (ndmq/ci).
I [May 24 20:37:57] ndm: Core::Session: client disconnected.
I [May 24 20:37:57] installer: Можно открыть SSH-сессию для соединения с устройством (логин - root, пароль - keenetic, порт - 222).
I [May 24 20:37:57] installer: [5/5] Установка системы пакетов "Entware" завершена! Не забудьте сменить пароль и номер порта!
Закрываем веб-интерфейс с настройками роутера.
3. Настройка Entware
Скачиваем Putty и запускаем её. Вбиваем следующие настройки (если что, их можно сохранить кнопкой Save):

Скорей всего, утилита обнаружит сертификат и сообщит об этом, нажимаем «Accept».
Вводим логин «root» (без кавычек), нажимаем Enter, пароль «keenetic» (также без кавычек) (при вводе пароля курсор не двигается – это нормально), также Enter. Должно отобразиться:

Вводим команду passwd, она меняет пароль. Вводим новый пароль дважды. Внимание! Созданный тут пароль и пароль от вашего роутера при входе в настройки веб-интерфейса – РАЗНЫЕ пароли в будущем. При вводе нового пароля курсор не двигается, поэтому не пугаемся, что «клавиатура не работает».
Обновляем пакеты OPKG командой opkg update:

Начинаем настраивать наш Entware.
Для этого продолжаем в Putty вводить команды:
opkg install mc bind-dig cron dnsmasq-full ipset iptables shadowsocks-libev-ss-redir shadowsocks-libev-config shadowsocks-libev-ss-local
После чего, ждём установки всех этих пакетов.
· Инициализация ipset, создание множества IP-адресов unblock (100-ipset.sh).
Проверьте, что в системе вашего маршрутизатора есть поддержка множества hash:net (как оказалась, не во всех маршрутизаторах Keenetic она есть):
ipset create test hash:net
· Если команда никаких ошибок и сообщений не выдала, значит поддержка есть, и просто следуйте инструкции дальше. В противном случае (есть ошибка) в следующем скрипте вам нужно заменить hash:net на hash:ip. При этом вы потеряете возможность разблокировки по диапазону и CIDR.
Скорее всего, у Вас ошибок не будет.
· Создайте пустое множество адресов с именем unblock при загрузке маршрутизатора. Для этого создайте файл /opt/etc/ndm/fs.d/100-ipset.sh:
mcedit /opt/etc/ndm/fs.d/100-ipset.sh
Вставляем содержимое с помощью сочетания клавиш Shift+Insert. Далее в этой инструкции мы также будем использовать это сочетания клавиш.
#!/bin/sh
[ "$1" != "start" ] && exit 0
ipset create unblock hash:net -exist
exit 0
После этого нажимаем сохранить (клавиша F2), соглашаемся (Enter) и выход (клавиша F10). Эти сочетания также будут использоваться далее.
· Дайте права на исполнение:
chmod +x /opt/etc/ndm/fs.d/100-ipset.sh
Теперь нам нужен ключ HighLoad VPN, мы его разложим на адрес, порт и пароль. Кто-то любит делать это через декодеры, например, этот сайт. Я же обычно добавляю ключ в одноименное приложение Shadowsocks, заодно и проверяю работоспособность VPN в текущий момент. Приложение само разбирает ключ по нужным нам параметрам при добавлении. Ещё один способ – нажать в боте кнопку Статус, вам будет показан ваш ключ уже в расшифрованном виде.

Возвращаемся в Putty и выполняем команду
mcedit /opt/etc/shadowsocks.json
Редактируем наш файл исходя из полученных данных из ключа:
{
"server":"hl-fi2-basic.undef.network",
"mode":"tcp_and_udp",
"server_port":4081,
"password":"z4DbflmблаблаблаlzjmjyhWQZ",
"timeout": 300,
"method":"chacha20-ietf-poly1305",
"local_address":"192.168.1.1",
"local_port": 1082,
"fast_open": true
}

Сохраняем и выходим (напомню - F2, F10).
Редактируем исполняемый файл Shadowsocks:
mcedit /opt/etc/init.d/S22shadowsocks
Меняем ss-local на ss-redir:

Сохраняем и выходим.
Список доменов (и не только) для обхода блокировки (unblock.txt).
Создадим файл /opt/etc/unblock.txt:
mcedit /opt/etc/unblock.txt
Каждая строка может содержать доменное имя, IP-адрес, диапазон или CIDR. Можно использовать символ # для комментирования строк.
Вот мой пример файла unblock.txt:
twitter.com
abs.twimg.com
api.x.com
pbs.twimg.com
t.co
video.twimg.com
api-stream.twitter.com
api.twitter.com
mobile.twitter.com
instagram.com
static.cdninstagram.com
api.instagram.com
facebook.com
static.xx.fbcdn.net
scontent.frix7-1.fna.fbcdn.net
m.facebook.com
threads.net
meta.com
Можете делать его по разделам с названием, как у меня, закомментив заголовки значком #, а можете просто списком доменов с новой строки. ВАЖНО! Не всегда достаточно разблокировать только сам адрес сайта, например, twitter.com. Как правило, такие могучие сервисы как социальные сети, используют много запросов по другим адресам других сервисов (картинки, ленты новостей и т.д.). Обратите внимание, сколько используемых адресов в том же твиттере или фейсбуке.
Сохраняем и выходим.
Скрипт для заполнения множества unblock IP-адресами заданного списка доменов (unblock_ipset.sh) и дополнительного конфигурационного файла dnsmasq из заданного списка доменов (unblock_dnsmasq.sh)
Создадим скрипт /opt/bin/unblock_ipset.sh:
mcedit /opt/bin/unblock_ipset.sh
Вставляем содержимое, затем сохраняем и закрываем:
#!/bin/sh
until ADDRS=$(dig +short google.com @localhost) && [ -n "$ADDRS" ] > /dev/null 2>&1; do sleep 5; done
while read line || [ -n "$line" ]; do
[ -z "$line" ] && continue
[ "${line:0:1}" = "#" ] && continue
cidr=$(echo $line | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}')
if [ ! -z "$cidr" ]; then
ipset -exist add unblock $cidr
continue
fi
range=$(echo $line | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}-[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
if [ ! -z "$range" ]; then
ipset -exist add unblock $range
continue
fi
addr=$(echo $line | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
if [ ! -z "$addr" ]; then
ipset -exist add unblock $addr
continue
fi
dig +short $line @localhost | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | awk '{system("ipset -exist add unblock "$1)}'
done < /opt/etc/unblock.txt
· Даём права на использование:
chmod +x /opt/bin/unblock_ipset.sh
· Создадим скрипт /opt/bin/unblock_dnsmasq.sh:
mcedit /opt/bin/unblock_dnsmasq.sh
· Вставляем содержимое. Затем сохраняем и выходим.
#!/bin/sh
cat /dev/null > /opt/etc/unblock.dnsmasq
while read line || [ -n "$line" ]; do
[ -z "$line" ] && continue
[ "${line:0:1}" = "#" ] && continue
echo $line | grep -Eq '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' && continue
echo "ipset=/$line/unblock" >> /opt/etc/unblock.dnsmasq
done < /opt/etc/unblock.txt
· Даём права на использование:
chmod +x /opt/bin/unblock_dnsmasq.sh
· Запускаем скрипт и затем проверяем создался ли файл. Здесь 2 команды, вводим последовательно:
unblock_dnsmasq.sh
cat /opt/etc/unblock.dnsmasq
Картина будет примерно такая:

Скрипт ручного принудительного обновления системы после редактирования списка доменов (unblock_update.sh).
· Создаём его:
mcedit /opt/bin/unblock_update.sh
· Записываем содержимое, сохраняем и закрываем.
#!/bin/sh
ipset flush unblock
/opt/bin/unblock_dnsmasq.sh
/opt/etc/init.d/S56dnsmasq restart
/opt/bin/unblock_ipset.sh &
· Даём права на использование:
chmod +x /opt/bin/unblock_update.sh
Скрипт автоматического заполнения множества unblock при загрузке маршрутизатора (S99unblock).
· Создаём скрипт:
mcedit /opt/etc/init.d/S99unblock
· Записываем содержимое, сохраняем и закрываем.
#!/bin/sh
[ "$1" != "start" ] && exit 0
/opt/bin/unblock_ipset.sh &
· Даём права на использование:
chmod +x /opt/etc/init.d/S99unblock
Перенаправление пакетов с адресатами из unblock в Shadowsocks.
· Создаём скрипт:
mcedit /opt/etc/ndm/netfilter.d/100-redirect.sh
· Записываем содержимое. Если необходимо – меняем ip адрес роутера и наш порт. Сохраняем и закрываем.
#!/bin/sh
[ "$type" == "ip6tables" ] && exit 0
if [ -z "$(iptables-save 2>/dev/null | grep unblock)" ]; then
ipset create unblock hash:net -exist
iptables -I PREROUTING -w -t nat -i br0 -p tcp -m set --match-set unblock dst -j REDIRECT --to-port 1082
iptables -I PREROUTING -w -t nat -i br0 -p udp -m set --match-set unblock dst -j REDIRECT --to-port 1082
fi
if [ -z "$(iptables-save 2>/dev/null | grep "udp --dport 53 -j DNAT")" ]; then
iptables -w -t nat -I PREROUTING -i br0 -p udp --dport 53 -j DNAT --to 192.168.1.1
fi
if [ -z "$(iptables-save 2>/dev/null | grep "tcp --dport 53 -j DNAT")" ]; then
iptables -w -t nat -I PREROUTING -i br0 -p tcp --dport 53 -j DNAT --to 192.168.1.1
fi
exit 0
· Даём права на использование:
chmod +x /opt/etc/ndm/netfilter.d/100-redirect.sh
Настройка dnsmasq и подключение дополнительного конфигурационного файла к dnsmasq.
· Удалим содержимое конфигурационного файла dnsmasq:
cat /dev/null > /opt/etc/dnsmasq.conf
Теперь следует очень важный момент, мы будем использовать не стандартный открытый DNS 8.8.8.8, как описывается в оригинальной инструкции, а наш настроенный в самом начале DNS over HTTPS (DoH).
Для этого вводим команду, чтобы узнать на каком адресе и порте он крутится:
cat /tmp/ndnproxymain.stat
Получаем что-то вроде этого:

Вот теперь можем настроить dnsmasq по-нашему. ))
Откроем файл конфигурации dnsmasq:
mcedit /opt/etc/dnsmasq.conf
Записываем содержимое. При необходимости меняем ip роутера. Сохраняем и закрываем:
user=nobody
bogus-priv
no-negcache
clear-on-reload
bind-dynamic
listen-address=192.168.1.1
listen-address=127.0.0.1
min-port=4096
cache-size=1536
expand-hosts
log-async
conf-file=/opt/etc/unblock.dnsmasq
no-resolv
server=127.0.0.1#40508
Добавление задачи в cron для периодического обновления содержимого множества unblock.
Откроем файл:
mcedit /opt/etc/crontab
В конец добавляем строку
00 06 * * * root /opt/bin/unblock_ipset.sh
При желании остальные строчки можно закомментировать, поставив решётку в начале. Затем сохраняем и закрываем
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/opt/bin:/opt/sbin
MAILTO=""
HOME=/
# ---------- ---------- Default is Empty ---------- ---------- #
#*/1 * * * * root /opt/bin/run-parts /opt/etc/cron.1min
#*/5 * * * * root /opt/bin/run-parts /opt/etc/cron.5mins
#01 * * * * root /opt/bin/run-parts /opt/etc/cron.hourly
#02 4 * * * root /opt/bin/run-parts /opt/etc/cron.daily
#22 4 * * 0 root /opt/bin/run-parts /opt/etc/cron.weekly
#42 4 1 * * root /opt/bin/run-parts /opt/etc/cron.monthly
00 06 * * * root /opt/bin/unblock_ipset.sh
На этом мы закончили настройку нашего Keenetic с частичным обходом блокировок. Перезагружаем роутер и радуемся!
FAQ
- Как изменить ключ?
Подключаемся к роутеру с помощью Putty, останавливаем службу командой
/opt/etc/init.d/S22shadowsocks stop
Далее редактируем нашу конфигурацию, нам нужно изменить всего три параметра: адрес, порт, пароль (всё из нового ключа)
mcedit /opt/etc/shadowsocks.json

Сохраняем изменения, нажав F2 и выходим - F10.
Запускаем снова подключение:
/opt/etc/init.d/S22shadowsocks start –d

- Как проверить подключение?
Для этого есть пара команд, можно набрать любую из них, обе покажут статус подключения (alive или dead)
/opt/etc/init.d/S22shadowsocks status
/opt/etc/init.d/S22shadowsocks check

- После перезагрузки роутера, сайты из списка unblock.txt не открываются
Как показывает практика, не всегда при перезагрузке роутера происходит попытка установки соединения VPN ПОСЛЕ установки основного соединения с интернетом. На всякий случай выполните следующие команды в Putty:
/opt/etc/init.d/S22shadowsocks restart
/opt/etc/init.d/S56dnsmasq restart
- Я запустил вручную shadowsocks соединение, но как только закрываю Putty, соединение сразу закрывается.
Да, это нормально. Для того, чтобы соединение продолжало работать после закрытия Putty, нужно запустить службу фоново:
/opt/etc/init.d/S22shadowsocks start -d
– теперь всё будет продолжать работать и после закрытия Putty.