Целый год (или два) я откладывал публикацию данной статьи по главной причине — мной уже были опубликованы две статьи, в которых я описал процесс создания маршрутизатора в SOCKS из самого обычного ноутбука с Debian.

Однако, с тех пор стабильная версия Debian обновилась до Buster, мне в личку обратилось достаточное количество людей с просьбой помочь в настройке, а значит, мои предыдущие статьи не являются исчерпывающими. Что ж, я и сам догадывался, что методы, изложеннные в них, не до конца раскрывают все тонкости настройки Linux для маршрутизации в SOСKS. К тому же они написаны для Debian Stretch, а после обновления до Buster, в системе инициализации systemd, я заметил небольшие изменения во взаимодействии служб. Да и в самих статьях я не использовал systemd-networkd, хотя она лучше всего подходит для сложных сетевых конфигураций.

Кроме вышеуказаных изменений, в мою конфигурацию добавились такие службы как hostapd — служба для виртуализации точки доступа, ntp для синхронизации времени клиентов локальной сети, dnscrypt-proxy для шифрования соединений по протоколу DNS и отключения рекламы на клиентах локальной сети, а также, как я упомянал ранее, systemd-networkd для конфигруации сетевых интерфейсов.

Вот простейшая блок-схема, внутреннего устройства такого маршрутизатора.



Итак, я напомню, какие цели преследует цикл данных статей:

  1. Маршрутизировать в SOCKS все соединения ОС, а также соединения всех устройств, состоящих в одной сети с ноутбуком.
  2. Ноутбук в моем случае должен оставаться полностью мобильным. То есть, давать возможность использовать окружение рабочего стола и не быть привязанным к физическому местуположению.
  3. Последний пункт подразумевает подключение и маршрутизацию только через встроенный беспроводной интерфейс.
  4. Ну, и конечно, создание исчерпывающего руководства, а также разбор соответсвующих технологий в меру моих скромных познаний.

Что будет рассмотрено в данной статье:

  1. git — скачаем репоизитории проектов tun2socks, необходимого для маршрутизации трафика TCP в SOCKS, и create_ap — скрипта для автоматизации настройки виртуальной точки доступа с помощью hostapd.
  2. tun2socks — построим и установим в систему службу systemd.
  3. systemd-networkd — настроим беспроводной и виртуальные интерфейсы, таблицы статической маршрутизации и перенаправление пакетов.
  4. create_ap — установим службу systemd в систему, настроим и запустим виртуальную точку доступа.

Необязательные шаги:

  • ntp — установим и настроим сервер для сихронизации времени на клиентах виртуальной точки доступа.
  • dnscrypt-proxy — зашифруем запросы DNS, маршрутизируем их в SOCKS и отключим рекламные домены для локальной сети.

Зачем всё это?


Это один из способов организации защиты TCP-соединений локальной сети. Главное преимущество — все соединения идут в SOCKS, если для них не построен статический маршрут через оригинальный шлюз. Это значит, что не нужно прописывать настройки SOCKS-сервера ни отдельным программам, ни клиентам в локальной сети — они все идут в SOCKS по-умолчанию, так как он является шлюзом по-умолчанию, пока мы не укажем обратного.

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

С точки зрения провайдера мы постоянно подключены к одному серверу с зашифрованным трафиком.

Соответственно, все устройства подключаются к виртуальной точке доступа ноутбука.

Прежде, чем вы начнете


Почти все конфиги доступны в репозитории.

Установите в систему tun2socks


Пока на вашей машине есть интернет, скачайте все необходимые инструменты.

apt update

apt install git make cmake

Скачайте пакет badvpn
git clone https://github.com/ambrop72/badvpn

В вашей системе появится папка badvpn. Создайте отдельную папку для сборки

mkdir badvpn-build

Перейдите в нее

cd badvpn-build

Соберите tun2socks

cmake ../badvpn -DBUILD_NOTHING_BY_DEFAULT=1 -DBUILD_TUN2SOCKS=1

Установите в систему

make install

  • Параметр -DBUILD_NOTHING_BY_DEFAULT=1 отключает сборку всех компонентов репозитория badvpn.
  • DBUILD_TUN2SOCKS=1 включает в сборку компонент tun2socks.
  • make install — установит бинарник tun2socks в вашу систему по адресу /usr/local/bin/badvpn-tun2socks.

Установите службу tun2socks в systemd


Создайте файл /etc/systemd/system/tun2socks.service со следующим содержимым:

[Unit]
Description=SOCKS TCP Relay

[Service]
ExecStart=/usr/local/bin/badvpn-tun2socks --tundev tun2socks --netif-ipaddr 172.16.1.1 --netif-netmask 255.255.255.0 --socks-server-addr 127.0.0.1:9050

[Install]
WantedBy=multi-user.target

  • --tundev — принимает имя виртуального интерфейса, который мы инициализируем с помощью systemd-networkd.
  • --netif-ipaddr — сетевой адрес «маршрутизатора» tun2socks, к которому подключается виртуальный интерфейс. Лучше сделать отдельной зарезервированной подсетью.
  • --socks-server-addr — принимает сокет (адрес: порт сервера SOCKS).

Если ваш SOCKS сервер требует аутентификации, вы можете указать параметры --username и --password.

Далее зарегистрируйте службу

systemctl daemon-reload

И включите

systemctl enable tun2socks

Прежде чем запускать службу, обеспечим её виртуальным сетевым интерфейсом.

Переходим на systemd-networkd


Включаем systemd-networkd:

systemctl enable systemd-networkd

Отключаем текущие сетевые службы.

systemctl disable networking NetworkManager NetworkManager-wait-online

  • NetworkManager-wait-online — это служба, которая ждет наличие работающего сетевого подключения прежде, чем systemd продолжит запуск других служб, зависящих от наличия сети. Мы отключаем её, так как перейдем на аналог systemd-networkd.

Давайте сразу включим его:

systemctl enable systemd-networkd-wait-online

Настройте беспроводной сетевой интерфейс


Создайте файл конфигурации systemd-networkd для беспроводного сетевого интерфейса /etc/systemd/network/25-wlp6s0.network.

[Match]
Name=wlp6s0

[Network]
Address=192.168.1.2/24
IPMasquerade=yes

  • Name — это имя вашего беспроводного интерфейса. Идентифицируйте его командой ip a.
  • IPMasquerade — директива, которая включает маскарадинг и перенаправление пакетов на сетевом интерфейсе.
  • Address отвечает за присвоение IP-адреса беспроводному интерфейсу. Мы указываем его статически потому, что при эквивалентной директиве DHCP=yes, systemd-networkd создаёт в системе шлюз по-умолчанию. Тогда весь трафик пойдет через оригинальный шлюз, а не через будущий виртуальный интерфейс в отличной подсети. Вы можете проверить текущий шлюз по-умолчанию командой
    ip r

Создайте статический маршрут для удалённого сервера SOCKS


Если ваш SOCKS сервер не локальный, а удалённый, то вам необходимо создать для него статический маршрут. Для этого добавьте секцию Route в конец созданного вами файла конфигурации беспроводного интерфейса со следующим содержанием:

[Route]
Gateway=192.168.1.1
Destination=0.0.0.0

  • Gateway — это шлюз по-умолчанию или адрес вашей оригинальной точки доступа.
  • Destination — адрес сервера SOCKS.

Настройте wpa_supplicant для systemd-networkd


systemd-networkd использует wpa_supplicant для подключения к защищенной точке доступа. При попытке «поднять» беспроводной интерфейс systemd-networkd запускает службу wpa_supplicant@имя, где имя — это имя беспроводного интерфейса. Если вы не использовали systemd-networkd до этого момента, то, наверняка, эта служба в вашей системе отсутствует.

Поэтому создайте ее командой:

systemctl enable wpa_supplicant@wlp6s0

Я использовал wlp6s0 в качестве имени своего беспроводного интерфейса. У вас это имя может отличаться. Вы можете узнать его командой
ip l
.

Теперь созданная служба wpa_supplicant@wlp6s0 будет запускаться при «поднятии» беспроводного интерфейса, однако она, в свою очередь, будет искать настройки SSID и пароля точки доступа в файле /etc/wpa_supplicant/wpa_supplicant-wlp6s0. Поэтому необходимо создать его с помощью утилиты wpa_passphrase.

Для этого выполните команду:

wpa_passphrase SSID password>/etc/wpa_supplicant/wpa_supplicant-wlp6s0.conf

где SSID — это имя вашей точки доступа, password — пароль, а wlp6s0 — имя вашего беспроводного интерфейса.

Инициализируйте виртуальный интерфейс для tun2socks


Создайте файл для инициализации нового вирутального интерфейса в системе /etc/systemd/network/25-tun2socks.netdev

[NetDev]
Name=tun2socks
Kind=tun

  • Name — это имя, которое systemd-networkd назначит будущему виртуальному интерфейсу при его инициализации.
  • Kind — это тип виртуального интерфейса. Исходя из названия службы tun2socks, вы можете догататься, что она использует интерфейс типа tun.
  • netdev — это расширение файлов, которые systemd-networkd использует для инициализации виртуальных сетевых интерфейсов. Адрес и другие сетевые настройки для этих интерфейсов указываются в .network файлах.

Создайте такой файл /etc/systemd/network/25-tun2socks.network со следующим содержимым:

[Match]
Name=tun2socks

[Network]
Address=172.16.1.2/24
Gateway=172.16.1.1

  • Name — имя виртуального интерфейса, которое вы указали в netdev файле.
  • Address — IP адрес, который будет назначен вирутальному интерфейсу. Должен быть в одной сети с адресом, который вы указали в службе tun2socks
  • Gateway — IP адрес «маршрутизатора» tun2socks, который вы указали при создании службы systemd.

Таким образом, интерфейс tun2socks имеет адрес 172.16.1.2, а служба tun2socks172.16.1.1, то есть является шлюзом для всех соединений с виртуального интерфейса.

Настройте виртуальную точку доступа


Установите зависимости:

apt install util-linux procps hostapd iw haveged

Скачайте репозиторий сreate_ap на свою машину:

git clone https://github.com/oblique/create_ap

Перейдите в папку репозитория на вашей машине:

cd create_ap

Установите в систему:

make install

В вашей системе появится конфиг /etc/create_ap.conf. Вот основные опции для правки:

  • GATEWAY=10.0.0.1 — лучше сделать отдельной зарезервированной подсетью.
  • NO_DNS=1 — выключите, так как этим параметром будет управлять виртуальный интерфейс systemd-networkd.
  • NO_DNSMASQ=1 — выключите по той же причине.
  • WIFI_IFACE=wlp6s0 — беспроводной интерфейс ноутбука.
  • INTERNET_IFACE=tun2socks> — виртуальный интерфейс, созданный для tun2socks.
  • SSID=hostapd — имя виртуальной точки доступа.
  • PASSPHRASE=12345678 — пароль.

Не забудьте включить службу:

systemctl enable create_ap

Включите DHCP сервер в systemd-networkd


Служба create_ap инициализирует в системе виртуальный интерфейс ap0. По идее, на этом интерфейсе «висит» dnsmasq, но зачем устанавливать лишние службы, если systemd-networkd содержит встроенный DHCP-сервер?

Чтобы включить его, определим сетевые настройки для виртуальной точки. Для этого создайте файл /etc/systemd/network/25-ap0.network со следующим содержимым:

[Match]
Name=ap0

[Network]
Address=10.0.0.1/24
DHCPServer=yes

[DHCPServer]
EmitDNS=yes
DNS=10.0.0.1
EmitNTP=yes
NTP=10.0.0.1

После того, как служба сreate_ap инициализирует виртуальный интерфейс ap0, systemd-networkd автоматически присвоит ему IP-адрес и включит DHCP-сервер.

Строки EmitDNS=yes и DNS=10.0.0.1 передают настройки DNS сервера устройствам, подключенным к точке доступа.

Если вы не планируете использовать локальный DNS сервер, — в моём случае это dnscrypt-proxy — можете установить DNS=10.0.0.1 в DNS=192.168.1.1, где 192.168.1.1 — адрес вашего оригинального шлюза. Тогда запросы DNS вашего хоста и локальной сети пойдут в незашифрованном виде через серверы провайдера.

EmitNTP=yes и NTP=192.168.1.1 передают настройки NTP.

То же самое касается строки NTP=10.0.0.1.

Установите и настройте NTP сервер


Установите в систему:

apt install ntp

Правьте конфиг /etc/ntp.conf. Закомментируйте адреса стандартных пулов:

#pool 0.debian.pool.ntp.org iburst
#pool 1.debian.pool.ntp.org iburst
#pool 2.debian.pool.ntp.org iburst
#pool 3.debian.pool.ntp.org iburst

Добавьте адреса публичных серверов, например, Google Public NTP:

server time1.google.com ibrust
server time2.google.com ibrust
server time3.google.com ibrust
server time4.google.com ibrust

Предоставьте доступ к серверу клиентам из вашей сети:

restrict 10.0.0.0 mask 255.255.255.0

Включите трансляцию в вашу сеть:

broadcast 10.0.0.255

Наконец, добавьте адреса этих серверов в таблицу статической маршрутизации. Для этого откройте файл конфигурации беспроводного интерфейса /etc/systemd/network/25-wlp6s0.network и добавьте в конец секции Route.

[Route]
Gateway=192.168.1.1
Destination=216.239.35.0

[Route]
Gateway=192.168.1.1
Destination=216.239.35.4

[Route]
Gateway=192.168.1.1
Destination=216.239.35.8

[Route]
Gateway=192.168.1.1
Destination=216.239.35.12

Вы можете узнать адреса ваших серверов NTP, используя утилиту host следующим образом:

host time1.google.com

Установите dnscrypt-proxy, уберите рекламу и скройте DNS трафик от провайдера


apt install dnscrypt-proxy

Чтобы обслуживать DNS запросы хоста и локальной сети, правьте сокет /lib/systemd/system/dnscrypt-proxy.socket. Измените следующие строки:

ListenStream=0.0.0.0:53
ListenDatagram=0.0.0.0:53

Перезапустите systemd:

systemctl daemon-reload

Правьте конфиг /etc/dnscrypt-proxy/dnscrypt-proxy.toml:

server_names = ['adguard-dns']

Чтобы направить соединения dnscrypt-proxy через tun2socks, добавьте ниже:

force_tcp = true

Правьте конфиг /etc/resolv.conf, который сообщает DNS сервер хосту.

nameserver 127.0.0.1
nameserver 192.168.1.1

Первая строчка включает использование dnscrypt-proxy, вторая — использует оригинальный шлюз, в случае, когда сервер dnscrypt-proxy недоступен.

Готово!


Перезагрузитесь или остановите действующие сетевые службы:

systemctl stop networking NetworkManager NetworkManager-wait-online

И перезапустите все необходимые:

systemctl restart systemd-networkd tun2socks create_ap dnscrypt-proxy ntp

После перезагрузки или перезапуска у вас появится вторая точка доступа, которая маршрутизирует хост и устройства локальной сети в SOCKS.

Примерно так выглядит вывод
ip a
обычного ноутбука:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: tun2socks: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 500
    link/none 
    inet 172.16.1.2/24 brd 172.16.1.255 scope global tun2socks
       valid_lft forever preferred_lft forever
    inet6 fe80::122b:260:6590:1b0e/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever
3: enp4s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether e8:11:32:0e:01:50 brd ff:ff:ff:ff:ff:ff
4: wlp6s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 4c:ed:de:cb:cf:85 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.2/24 brd 192.168.1.255 scope global wlp6s0
       valid_lft forever preferred_lft forever
    inet6 fe80::4eed:deff:fecb:cf85/64 scope link 
       valid_lft forever preferred_lft forever
5: ap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 4c:ed:de:cb:cf:86 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.1/24 brd 10.0.0.255 scope global ap0
       valid_lft forever preferred_lft forever
    inet6 fe80::4eed:deff:fecb:cf86/64 scope link 
       valid_lft forever preferred_lft forever

В итоге


  1. Провайдер видит только зашифрованное соединение к вашему серверу SOCKS, а значит, ничего не видит.
  2. И всё же он видит ваши NTP запросы, чтобы предотвратить это, удалите статические маршруты для NTP серверов. Одна��о, не факт, что ваш сервер SOCKS разрешает протокол NTP.

Костыль, замеченный на Debain 10


Если попытаться перезапустить сетевую службу из консоли, то она упадет с ошибкой. Связанно это с тем, что её часть в виде виртуального интерфейса привязана к службе tun2socks, а значит используется. Чтобы перезапустить сетевую службу, сначала нужно остановить службу tun2socks. Но, я думаю, если вы дочитали до конца, для вас это точно не проблема!

Ссылки


  1. Статическая маршрутизация в Linux — IBM
  2. systemd-networkd.service — Freedesktop.org
  3. Tun2socks · ambrop72/badvpn Wiki · GitHub
  4. oblique/create_ap: This script creates a NATed or Bridged WiFi Access Point.
  5. dnscrypt-proxy 2 — A flexible DNS proxy, with support for encrypted DNS protocols.