Отже, у вашій конфігурації всі пакети, які ви намагаєтеся надіслати в мережу, спочатку походять 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 це легко за допомогою netfilter / 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
. netfilter повинен змінити IP-код джерела 10.0.0.1
на wlp2s0
призначений для вашого вихідного пакету інтерфейс. Він запам'ятовує всі з'єднання, і коли пакети відповідей повертаються назад (якщо вони є), він змінює адресу призначення wlp2s0
інтерфейсу, призначеного адресою 10.0.0.1
(функція "conntrack").
Ну, так, але це не так. Здається, netfilter плутається з цією складною конфігурацією маршрутизації і тим фактом, що той самий пакет спочатку проходить через OUTPUT
ланцюг, а потім направляється і надходить у PREROUTING
ланцюг. Принаймні у вікні Debian 8 це не працює.
Найкращий спосіб усунення несправностей netfilter - це 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
Найкращий спосіб відключити netfilter - це змінити вихідну 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.address.of.your.wlan.interface
Тут ми змінюємо адресу джерела безпосередньо перед тим, як пакети дістаються до 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
Це ще один "хак" для маршрутизації та netfilter, який працює на моєму вікні Debian 8, але все ж рекомендую скористатися першим підходом, оскільки він більш природний і не використовує жодних хаків.
Ви також можете створити свою програму як прозорий проксі . Я думаю, що це було б набагато простіше, а не аналізувати пакети з пристрою tun.
-j SNAT
, не-s SNAT