Как сделать так, чтобы весь трафик проходил через один интерфейс в Linux

Как сделать так, чтобы весь трафик проходил через один интерфейс в Linux

у меня естьсамописный интерфейс tun0(ТУН/ТАПна основе), который выводит то, что получает.
Мне нужно, чтобы весь трафик системы проходил через этот интерфейс.
Роль интерфейса:

  1. Выявить пакеты, которые с большой вероятностью будут подвергнуты цензуре, и туннелировать их.
  2. Пропускайте весь остальной транспорт нетронутым.

Как вы догадываетесь, я пытаюсь создать антицензурный инструмент.
Решение о туннелировании должно быть принято внутри процесса tun0,
потому что только там мы можем использовать доверенный DNS.

Мне нужна ваша помощь, чтобы показать, как заставить весь трафик проходить через самописный интерфейс tun0. Если tun0 нуждается в изменениях, прошу вас предоставить такие изменения.

Ниже показано, как я попытался заставить весь трафик проходить через tun0, но это не удалось (пинги не проходят).

Компиляция

  1. gcc tun0.c
  2. sudo ./a.out

Настройка

  1. sudo ip addr add 10.0.0.1/24 dev tun0
  2. создать таблицу Джон

    $ cat /etc/iproute2/rt_tables 
    #
    # reserved values
    #
    255     local
    254     main
    253     default
    0       unspec
    #
    # local
    #
    #1      inr.ruhep
    
    200 John
    

Порядок важен:

  1. sudo ip rule add from all lookup John
  2. sudo ip route add default dev tun0 table John
  3. sudo ip rule add iif tun0 lookup main priority 500

    $ ip rule
    0:      from all lookup local 
    500:    from all iif tun0 lookup main 
    32765:  from all lookup John 
    32766:  from all lookup main 
    35000:  from all lookup default 
    

Поиск неисправностей

  1. sudo tcpdump -i wlp2s0 -qtln icmpа затем ping -I tun0 8.8.8.8показывает, что пакеты не захвачены, это означает, что пакеты не передаются из tun0 в wlp2s0 через iif tun0 lookup mainправило.

  2. Когда я заменил tun0везде lo, то у меня все заработало.

Также пробовал

  1. Отключение фильтрации обратного пути, rp_filter=0в/etc/sysctl.conf

Ответ на вопрос «Устранение неполадок»

iptables -I FORWARD -j LOG --log-prefix "filter/FORWARD " 
iptables -t nat -I OUTPUT -j LOG --log-prefix "nat/OUTPUT " 
iptables -t nat -I PREROUTING -j LOG --log-prefix "nat/PREROUTING " 
iptables -t nat -I POSTROUTING -j LOG --log-prefix "nat/POSTROUTNG "
tail -f /var/log/syslog

Измененные источники из ответа такжездесь.

решение1

Итак, в вашей конфигурации все пакеты, которые вы пытаетесь отправить в сеть, изначально исходят из 10.0.0.1(потому что они проходят через tun0интерфейс и его локальный адрес 10.0.0.1). Вы перехватываете пакеты, пока все в порядке.
Теперь,tun0 отправляет пакеты дальше.Адрес источникаи 10.0.0.1вы хотите, чтобы пакеты уходили через другой интерфейс (wlp2s0 в вашем случае).маршрутизацияИтак, давайте сначала включим маршрутизацию:

sysctl -w net.ipv4.ip_forward=1

После этого, если вы посмотрите, tcpdumpто wlp2s0заметите, что пакеты уходят с исходным адресом10.0.0.1 , а не с исходным адресом интерфейса WLAN (что вы, я полагаю, и ожидали). Поэтому нам нужно изменить исходный адрес, и он называетсяисточник NAT. В linux это легко с помощьюсетевой фильтр/iptables:

iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.1 -j MASQUERADE

Пожалуйста, также проверьте, что в вашей FORWARDсети естьACCEPT политика, иначе вам придетсяразрешить пересылкучто-то вроде:

iptables -A FORWARD -i tun0 -o wlp2s0 -s 10.0.0.1 -j ACCEPT
iptables -A FORWARD -i wlp2s0 -o tun0 -d 10.0.0.1 -j ACCEPT

Теперь все должно работать:ядро linuxвыполняет маршрутизацию, перемещает пакеты с tun0интерфейса наwlp2s0 .сетевой фильтрследует изменить исходный IP 10.0.0.1на ваш wlp2s0назначенный адрес интерфейса для исходящих пакетов. Он запоминает все соединения и когда ответные пакеты возвращаются (если они возвращаются), он меняет адрес назначения wlp2s0назначенного адреса интерфейса на 10.0.0.1(функция "conntrack").
Ну, должен, но не делает. Кажется,сетевой фильтрпутается с этой сложной конфигурацией маршрутизации и тем фактом, что один и тот же пакет сначала проходит через OUTPUTцепочку, а затем маршрутизируется и попадает в PREROUTINGцепочку. По крайней мере на Debian 8 box это не работает.
Лучший способ устранения неполадоксетевой фильтрэто TRACEособенность:

modprobe ipt_LOG
iptables -t raw -A OUTPUT -p icmp -j TRACE
iptables -t raw -A PREROUTING -p icmp -j TRACE

Я включаю трассировку только для пакетов ICMP, вы можете использовать другой фильтр для отладки.
Он покажет, через какие таблицы и цепочки проходит пакет. И я вижу, что пакет не идет дальше цепочки FORWARD(и он не перехватывается цепочкой nat/POSTROUTING, которая на самом деле это делает SNAT).
Ниже приведено несколько подходов, чтобы это работало.

ПОДХОД №1

Лучший способ разобратьсясетевой фильтрэто изменить исходный IP-адрес пакетов в tun0.cприложении. Это также самый естественный способ. Нам нужноизменить 10.0.0.1 на 10.0.0.2на пути наружу и10.0.0.2 по 10.0.0.1на обратном пути.
Я модифицировал tun0.cс исходным адресом кода изменения.Вот новый файливот файл исправлениядля вашего tun0.c. Изменения в заголовке IP также включаюткоррекция контрольной суммы, поэтому я взял код изПроект OpenVPN. Вот полный список команд, которые я выполняю после чистой перезагрузки и tun0_changeip.cзапуска:

ifconfig tun0 inet 10.0.0.1/30 up
sysctl -w net.ipv4.ip_forward=1
ip route add default dev tun0 table John
ip rule add from all lookup John
ip rule add from 10.0.0.2 lookup main priority 500
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.2 -j MASQUERADE

Обратите внимание, что вам не нужно выключатьфильтрация обратного путив этом случае, потому что все законно - tun0только получает и отправляет пакеты, которые принадлежат его подсети. Также вы можете сделать маршрутизацию на основе источника вместо маршрутизации на основе интерфейса.

ПОДХОД №2

Это возможно сделать SNATдо того, как пакет достигнет tun0интерфейса. Это не очень правильно, хотя. Вам определенно нужно будет отключитьфильтрация обратного путив этом случае:

sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0

Теперь выполните SNAT: iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source ip.адрес.вашего.беспроводного.интерфейса

Здесь мы просто меняем исходный адресдопакеты достигают tun0устройства. tun0.cкод пересылает эти пакеты "как есть" (с измененным исходным адресом), и они успешно маршрутизируются через интерфейс wlan. Но у вас может быть динамический IP на интерфейсе wlan и вы хотите использовать MASQUERADE(чтобы не указывать адрес интерфейса явно). Вот как вы можете использовать MASQUERADE:

iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source 10.0.55.1
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.55.1 -j MASQUERADE

Обратите внимание на 10.0.55.1IP-адрес " " - он другой. Вы можете использовать любой IP, это не имеет значения. Пакеты достигают nat/POSTROUTINGцепочки на wlp2s0интерфейсе, если мы изменили исходный IP ранее. И теперь он не зависит от статического IP для интерфейса wlan.

ПОДХОД №3

Вы также можете использовать fwmark. Таким образом, вам не нужно SNAT, но вы будете захватывать только исходящие пакеты:
Сначала нам нужно отключитьфильтрация обратного путипотому tun0что он будет пересылать пакеты, принадлежащие другой сети:

sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0

Now let's alter the routing rules a bit:
# Delete old rules
ip rule del iif tun0 lookup main
ip rule del from all lookup John

# Packets will start going from wlan interface so they will have source address of it
iptables -t mangle -A OUTPUT -o wlp2s0 -j MARK --set-mark 1
ip rule add fwmark 0x1 lookup John

Это еще один "хак" длямаршрутизацияисетевой фильтрэто работает на моем компьютере с Debian 8, но я все же рекомендую использовать первый подход, так как он более естественный и не требует никаких ухищрений.


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

Связанный контент