у меня естьсамописный интерфейс tun0(ТУН/ТАПна основе), который выводит то, что получает.
Мне нужно, чтобы весь трафик системы проходил через этот интерфейс.
Роль интерфейса:
- Выявить пакеты, которые с большой вероятностью будут подвергнуты цензуре, и туннелировать их.
- Пропускайте весь остальной транспорт нетронутым.
Как вы догадываетесь, я пытаюсь создать антицензурный инструмент.
Решение о туннелировании должно быть принято внутри процесса tun0,
потому что только там мы можем использовать доверенный DNS.
Мне нужна ваша помощь, чтобы показать, как заставить весь трафик проходить через самописный интерфейс tun0. Если tun0 нуждается в изменениях, прошу вас предоставить такие изменения.
Ниже показано, как я попытался заставить весь трафик проходить через tun0, но это не удалось (пинги не проходят).
Компиляция
gcc tun0.c
sudo ./a.out
Настройка
sudo ip addr add 10.0.0.1/24 dev tun0
создать таблицу Джон
$ cat /etc/iproute2/rt_tables # # reserved values # 255 local 254 main 253 default 0 unspec # # local # #1 inr.ruhep 200 John
Порядок важен:
sudo ip rule add from all lookup John
sudo ip route add default dev tun0 table John
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
Поиск неисправностей
sudo tcpdump -i wlp2s0 -qtln icmp
а затемping -I tun0 8.8.8.8
показывает, что пакеты не захвачены, это означает, что пакеты не передаются из tun0 в wlp2s0 черезiif tun0 lookup main
правило.Когда я заменил
tun0
вездеlo
, то у меня все заработало.
Также пробовал
- Отключение фильтрации обратного пути,
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.1
IP-адрес " " - он другой. Вы можете использовать любой 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.