## Погружение в прозрачное проксирование ### Что такое прозрачное проксирование? Проще говоря, прозрачное проксирование не позволяет проксируемому устройству понять, что оно проксируется. Это означает, что на проксируемом устройстве не нужно запускать какое-либо программное обеспечение для проксирования (например, Xray, V2RayNG и т. д.). Когда вы подключаетесь к сети, ваше устройство уже проксируется. Это также означает, что программное обеспечение прокси работает в другом месте, например, на маршрутизаторе, и устройства, подключенные к Интернету через маршрутизатор, автоматически проксируются. ### Реализация прозрачного проксирования В настоящее время существует два основных способа реализации прозрачного проксирования: ### tun2socks Доступно для Windows/Linux (включая Android). Поскольку процесс реализации относительно прост, существует не так много руководств, поэтому я кратко опишу его здесь. **Windows** 1. Установите **[Netch](https://github.com/NetchX/Netch/releases)**, используя режим `[3] [TUN/TAP] Обход локальной сети` для запуска. 2. Включите точку доступа. 3. Откройте `Панель управления` -> `Сеть и Интернет` -> `Центр управления сетями и общим доступом` -> `Изменение параметров адаптера`, найдите `TAP-Windows Adapter` и `Microsoft Wi-Fi Direct Virtual Adapter`. 4. Щелкните правой кнопкой мыши `TAP-Windows Adapter`, `Свойства` -> `Доступ`, установите флажок `Разрешить другим пользователям сети подключаться к Интернету через это подключение к Интернету`, в `Домашнее сетевое подключение` выберите сетевое подключение `Microsoft Wi-Fi Direct Virtual Adapter`, нажмите `ОК`. **Android** 1. Настройте подключение V2RayNG. 2. Включите точку доступа. 3. Настройки точки доступа -> Разрешить использование VPN для точки доступа (эта опция может отсутствовать в некоторых системах Android). ### iptables/nftables iptables и nftables реализуют прозрачное проксирование по одному и тому же принципу, в дальнейшем мы будем использовать iptables. Реализация прозрачного проксирования на основе iptables применима только к системам Linux (включая openwrt/Android). Благодаря своей эффективности по сравнению с tun2socks и возможности настройки на маршрутизаторах, она получила широкое распространение. Существующие три русскоязычных руководства по прозрачному проксированию на самом деле описывают реализацию прозрачного проксирования на основе этого решения: **[Новое руководство по V2Ray на русском языке - Прозрачное проксирование](https://guide.v2fly.org/app/transparent_proxy.html)**, **[Новое руководство по V2Ray на русском языке - Прозрачное проксирование (TPROXY)](https://guide.v2fly.org/app/tproxy.html)**, **[Руководство по настройке прозрачного проксирования (TProxy)](../tproxy.md)**. Первое основано на устаревшем режиме iptables-redirect, который не рекомендуется использовать и приводится только для справки. Второе и третье описывают реализацию прозрачного проксирования на основе режима iptables-tproxy. ## Принцип реализации прозрачного проксирования с помощью iptables Linux использует `Netfilter` для управления сетью, модель `Netfilter` выглядит следующим образом: ![Netfilter](./netfilter.png) **Предположим, что в качестве шлюза используется маршрутизатор (т. е. наш обычный способ подключения к Интернету), тогда:** Направление трафика от устройств локальной сети к Интернету через маршрутизатор: `Цепочка PREROUTING -> Цепочка FORWARD -> Цепочка POSTINGROUTING` Направление трафика от устройств локальной сети к маршрутизатору (например, вход в веб-интерфейс маршрутизатора/подключение к маршрутизатору по ssh/доступ к DNS-серверу маршрутизатора и т. д.): `Цепочка PREROUTING -> Цепочка INPUT -> Хост шлюза` Направление трафика от маршрутизатора к Интернету: `Хост шлюза -> Цепочка OUTPUT -> Цепочка POSTINGROUTING` **Управляя направлением трафика цепочек `PREROUTING` и `OUTPUT` с помощью iptables и перенаправляя его на Xray, мы можем проксировать устройства локальной сети и хост шлюза.** ## В чем сложность прозрачного проксирования? Сложность прозрачного проксирования заключается в маршрутизации, то есть в различении того, какой трафик должен быть прямым, а какой должен проксироваться, поэтому я лично считаю, что термин **разделение трафика** более уместен. Мы можем разделить маршрутизацию на следующие этапы по возрастанию сложности: 1. Проксирование всех запросов. 2. Прямое подключение для локальных IP-адресов/многоадресных IP-адресов, проксирование для остальных запросов. 3. На основе пункта 2, прямое подключение для исходящих запросов, инициированных Xray. 4. На основе пункта 3, прямое подключение для запросов, адресованных китайским IP-адресам, и выбор внутренних и внешних DNS-серверов для разрешения внутренних и внешних доменных имен. Три вышеупомянутых руководства описывают четвертый этап. Поэтому новичкам может быть сложно понять их, читая напрямую. ## Пошаговая реализация прозрачного проксирования на основе iptables-tproxy с нуля ### Прежде чем начать, вам необходимо иметь базовые знания: 1. Примерное представление о протоколах TCP/IP, доменных именах и DNS-серверах. 2. Знание того, что такое WAN-порт, LAN-порт, LAN_IP, WAN_IP и DHCP-сервер. Для пограничных маршрутизаторов есть только один сетевой порт, который мы будем называть LAN-портом. 3. Базовое понимание системы Linux (знание того, как запускать команды). 4. Умение писать конфигурационные файлы клиента в формате json или, по крайней мере, понимать их. ### Предварительная подготовка ::: warning Перед началом работы не забудьте включить пересылку пакетов ipv4 в Linux с помощью команды `sysctl -w net.ipv4.ip_forward=1` ::: **1. Подготовьте шлюз под управлением Linux** Например, маршрутизатор с прошивкой OpenWRT. **2. Подготовьте исполняемый файл Xray и конфигурационный файл на шлюзе (маршрутизаторе)** Конфигурационный файл прослушивает порт 12345 и включает tproxy: ```json { "log": { "loglevel": "warning" }, "inbounds": [ { "port": 12345, "protocol": "dokodemo-door", "settings": { "network": "tcp,udp", "followRedirect": true }, "streamSettings": { "sockopt": { "tproxy": "tproxy" } } } ], "outbounds": [ { // Конфигурация вашего сервера } ] } ``` Мы пойдем от простого к сложному, не будем писать routing, а напишем только один inbound и один outbound. ### Сначала давайте попробуем достичь первого этапа ::: warning Если вы не хотите перезагружать свою машину, лучше сначала попрактиковаться на виртуальной машине ::: Перенаправьте весь трафик цепочки `PREROUTING` в Xray. Запустите Xray и выполните следующие команды: ```bash ip rule add fwmark 1 table 100 ip route add local 0.0.0.0/0 dev lo table 100 iptables -t mangle -N XRAY iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 iptables -t mangle -A PREROUTING -j XRAY ``` После ввода команд, если вы подключены к шлюзу по ssh, вы обнаружите, что соединение ssh разорвано (не беспокойтесь, перезагрузка восстановит его), и прозрачное проксирование не работает; если ваш шлюз - это виртуальная машина, вы обнаружите, что сам шлюз не может получить доступ к Интернету, и в журнале доступа Xray появится множество запросов с исходным адресом, равным целевому адресу, и целевым адресом, равным WAN_IP. Теоретически доступ хоста шлюза к общедоступной сети должен проходить только через цепочки `OUTPUT` и `POSTINGROUTING`, так почему же управление цепочкой `PREROUTING` приводит к тому, что шлюз не может получить доступ к Интернету? Это связано с тем, что сетевое взаимодействие, как правило, двунаправленное, и хотя доступ шлюза к общедоступному IP-адресу не требует прохождения через цепочку `PREROUTING`, информация, возвращаемая сервером на шлюз, должна проходить через цепочку `PREROUTING`, и эта часть перенаправляется на Xray, что приводит к обратным запросам в журнале. Давайте изменим правило, чтобы возвращать трафик, источник которого не находится в локальной сети. Перезагрузите шлюз, запустите Xray и выполните следующие команды: ```bash ip rule add fwmark 1 table 100 ip route add local 0.0.0.0/0 dev lo table 100 iptables -t mangle -N XRAY # "Диапазон LAN-адресов шлюза" можно получить, выполнив команду "ip address | grep -w "inet" | awk '{print $2}'", это будет один из адресов iptables -t mangle -A XRAY ! -s Диапазон LAN-адресов шлюза -j RETURN iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 iptables -t mangle -A PREROUTING -j XRAY ``` Теперь вы обнаружите, что, хотя соединение ssh разорвано, прозрачное проксирование уже работает. Если мы изменим системный DNS на общедоступный DNS, мы сможем нормально просматривать веб-страницы (поскольку в настоящее время шлюз недоступен, мы не можем установить DNS на шлюз). На этом первый этап завершен. Причина, по которой мы не можем получить доступ к шлюзу, заключается в том, что правило проксирования проксирует весь трафик, включая трафик, адресованный шлюзу. Представьте, что вы пытаетесь получить доступ к своему локальному шлюзу с VPS, вы не сможете этого сделать, поэтому нам нужно сделать этот трафик прямым, смотрите второй этап: ### Второй этап Перезагрузите шлюз, запустите Xray и выполните следующие команды: ```bash ip rule add fwmark 1 table 100 ip route add local 0.0.0.0/0 dev lo table 100 iptables -t mangle -N XRAY # Прямое подключение для всех запросов, адресованных сегменту сети шлюза # Получите сегменты сети, выполнив команду "ip address | grep -w "inet" | awk '{print $2}'", как правило, их несколько iptables -t mangle -A XRAY -d Сегмент сети шлюза 1 -j RETURN iptables -t mangle -A XRAY -d Сегмент сети шлюза 2 -j RETURN ... # Прямое подключение для запросов, адресованных многоадресным IP-адресам/адресам класса E/широковещательным IP-адресам iptables -t mangle -A XRAY -d 224.0.0.0/3 -j RETURN iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 iptables -t mangle -A PREROUTING -j XRAY ``` После использования этого правила предыдущее правило `iptables -t mangle -A XRAY ! -s Диапазон LAN-адресов шлюза -j RETURN` становится лишним и его можно удалить. На этом второй этап завершен. Шлюз доступен, ssh не разрывается. ### Третий этап Обычно мы используем DNS, предоставляемый маршрутизатором, но это правило iptables проксирует только устройства в локальной сети, а не сам хост шлюза, поэтому возвращаемые результаты DNS-запросов могут быть неверными или загрязненными. iptables-tproxy не поддерживает работу с цепочкой `OUTPUT`, но мы можем настроить `маршрутизацию по политике`, чтобы перенаправлять соответствующие пакеты из цепочки `OUTPUT` обратно в цепочку `PREROUTING`. ```bash # Добавить маршрут по политике: пакеты с меткой 1 направляются в таблицу маршрутизации 100 ip rule add fwmark 1 table 100 # Добавить запись маршрута в таблицу маршрутизации 100: все пакеты направляются локально ip route add local 0.0.0.0/0 dev lo table 100 ``` Настроив `маршрутизацию по политике` выше, нам нужно только пометить пакеты, которые необходимо проксировать от хоста шлюза, меткой `1` в цепочке `OUTPUT`, и соответствующие пакеты будут направлены на сам хост шлюза, то есть в цепочку `PREROUTING`. Если мы хотим проксировать все запросы, отправленные хостом шлюза, это вызовет проблему: Xray работает на шлюзе, Xray отправляет запросы на сервер прокси, и эти запросы снова проксируются, образуя петлю. Поэтому, чтобы проксировать хост шлюза, необходимо избежать зацикливания, то есть исключить трафик запросов Xray из правил проксирования. **Существуют три распространенных метода:** 1. Прямое подключение трафика, адресованного VPS Перезагрузите шлюз, запустите Xray и выполните следующие команды: ```bash # Проксирование устройств локальной сети # Наследуем достижения предыдущего этапа ip rule add fwmark 1 table 100 ip route add local 0.0.0.0/0 dev lo table 100 iptables -t mangle -N XRAY iptables -t mangle -A XRAY -d Сегмент сети шлюза 1 -j RETURN iptables -t mangle -A XRAY -d Сегмент сети шлюза 2 -j RETURN ... iptables -t mangle -A XRAY -d 224.0.0.0/3 -j RETURN iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 iptables -t mangle -A PREROUTING -j XRAY # Проксирование хоста шлюза iptables -t mangle -N XRAY_MASK iptables -t mangle -A XRAY_MASK -d Сегмент сети шлюза 1 -j RETURN iptables -t mangle -A XRAY_MASK -d Сегмент сети шлюза 2 -j RETURN ... iptables -t mangle -A XRAY_MASK -d 224.0.0.0/3 -j RETURN iptables -t mangle -A XRAY_MASK -d Общедоступный IP-адрес VPS/32 -j RETURN iptables -t mangle -A XRAY_MASK -j MARK --set-mark 1 iptables -t mangle -A OUTPUT -p tcp -j XRAY_MASK iptables -t mangle -A OUTPUT -p udp -j XRAY_MASK ``` Однако у этого метода есть недостаток: если используется CDN или много VPS, то написание правил становится неудобным. 2. Исключение с помощью меток Три вышеупомянутых русскоязычных руководства используют этот метод исключения, обратитесь к ним, мы не будем повторяться здесь. 3. Исключение с помощью gid (рекомендуется) См. **[[Прозрачное проксирование] Исключение трафика Xray с помощью gid](../iptables_gid.md)** На этом третий этап проксирования, также известный как глобальное проксирование, завершен. Но не забудьте установить DNS-сервер шлюза на зарубежный DNS-сервер, иначе вы все равно можете получить загрязненные результаты. ### Четвертый этап На самом деле, не всем нужно реализовывать четвертый этап. Глобальное проксирование подходит для большинства случаев. Особенно для пограничных маршрутизаторов. При необходимости проксирования установите шлюз на IP-адрес пограничного маршрутизатора, при отсутствии необходимости проксирования - на IP-адрес основного маршрутизатора. Что касается конкретной реализации четвертого этапа, то об этом подробно рассказывается в трех вышеупомянутых русскоязычных руководствах. После того, как вы поймете вышеизложенное, вам будет легче понять эти руководства. ### Проксирование IPv6 Вышеуказанные правила действительны только для IPv4, если вы хотите проксировать запросы IPv6, используйте команду ip6tables, ее использование в основном такое же, как и у iptables. См. **[[Прозрачное проксирование] Исключение трафика Xray с помощью gid # 4-Настройка правил iptables](../iptables_gid # 4-Настройка правил iptables.md)** # Другие замечания по прозрачному проксированию с помощью iptables 1. Если шлюз, выступающий в качестве прокси, также является основным маршрутизатором, необходимо добавить правило `iptables -t mangle -A XRAY ! -s Диапазон LAN-адресов шлюза -j RETURN` в цепочку `PREROUTING`, то есть команду, использованную на первом этапе и удаленную на втором этапе. Если этого не сделать, другие люди в той же подсети, что и WAN-порт, смогут использовать ваш WAN_IP в качестве шлюза, чтобы злоупотреблять вашим прозрачным прокси, что может быть небезопасно. 2. В **[Новое руководство по V2Ray на русском языке - Прозрачное проксирование (TPROXY) # Настройка шлюза](https://guide.v2fly.org/app/tproxy.html # Настройка шлюза)** третий пункт гласит: `Настройте сеть ПК вручную, указав в качестве шлюза по умолчанию адрес Raspberry Pi, то есть 192.168.1.22. Теперь ПК должен иметь доступ к Интернету (поскольку проксирование еще не настроено, “доступ” означает возможность доступа к внутренним веб-сайтам)`. На самом деле, даже если включена переадресация IP, ПК под управлением Ubuntu, CentOS, Debian и других систем не смогут получить доступ к Интернету, это нормально. Фактически, только OpenWRT может сделать то, что описано в статье, как указал **[@BioniCosmos](https://github.com/BioniCosmos)**, это связано с тем, что в обычных системах Linux нет правил Masquerade. 3. **[Проблема too many open files](https://guide.v2fly.org/app/tproxy.html#решение-проблемы-too-many-open-files)**, см. решение в **[[Прозрачное проксирование] Исключение трафика Xray с помощью gid - Настройка максимального количества открытых файлов и запуск клиента Xray](../iptables_gid#3-настройка-максимального-количества-открытых-файлов-запуск-клиента-xray)** 4. Избегайте повторного прохождения пакетов с существующими подключениями через TPROXY, будет дополнено... 5. Основной маршрутизатор, однорукий маршрутизатор и пограничный маршрутизатор, будет дополнено...