Więc w twojej konfiguracji wszystkie pakiety, które próbujesz wysłać do sieci, początkowo pochodzące 10.0.0.1
(ponieważ przechodzą przez tun0
interfejs, a jego lokalny adres to 10.0.0.1
). Przechwytujesz pakiety, na razie wszystko jest w porządku.
Teraz tun0
wysyła pakiety dalej. Adres źródłowy to 10.0.0.1
i chcesz, aby pakiety wychodziły przez inny interfejs ( wlp2s0
w twoim przypadku). To jest routing, więc najpierw włączmy routing:
sysctl -w net.ipv4.ip_forward=1
Po tym, jeśli będziesz patrzeć tcpdump
na wlp2s0
można zauważyć pakiety wyjechać z adresu źródłowego 10.0.0.1
, a nie z adresem źródłowym wlan interfejsu (czego można się spodziewać chyba). Musimy więc zmienić adres źródłowy, który nazywa się źródłowym NAT . W Linuksie jest to łatwe przy pomocy netfilter / iptables :
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.1 -j MASQUERADE
Sprawdź także, czy Twój FORWARD
łańcuch ma ACCEPT
zasady, czy też musisz zezwolić na przekazywanie z następującymi elementami:
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
Wszystko powinno działać teraz: jądro linuksa wykonuje routing, przenosi pakiety z tun0
interfejsu do wlp2s0
. netfilter powinien zmienić źródłowy adres IP 10.0.0.1
na wlp2s0
adres przypisany interfejsowi dla pakietów wyjściowych. Zapamiętuje wszystkie połączenia, a kiedy pakiety odpowiedzi wracają (jeśli są), zmienia adres docelowy wlp2s0
interfejsu przypisanego do adresu 10.0.0.1
(funkcja „conntrack”).
Powinno, ale tak nie jest. Wygląda na to, że netfilter myli się z tą skomplikowaną konfiguracją routingu i faktem, że ten sam pakiet najpierw przechodzi przez OUTPUT
łańcuch, a następnie jest kierowany i dochodzi do PREROUTING
łańcucha. Przynajmniej w przypadku Debiana 8 nie działa.
Najlepszym sposobem na rozwiązanie problemu z filtrem sieciowym jest TRACE
funkcja:
modprobe ipt_LOG
iptables -t raw -A OUTPUT -p icmp -j TRACE
iptables -t raw -A PREROUTING -p icmp -j TRACE
Włączam śledzenie tylko pakietów ICMP, możesz użyć innego filtra do debugowania.
Pokaże, przez jakie tabele i łańcuchy przechodzi pakiet. Widzę, że pakiet nie przechodzi dalej przez FORWARD
łańcuch (i nie jest przechwytywany przez nat/POSTROUTING
łańcuch, który faktycznie działa SNAT
).
Poniżej znajduje się kilka podejść, aby to zadziałało.
PODEJŚCIE 1
Najlepszym sposobem na dezorientację netfiltra jest zmiana źródłowego adresu IP pakietów w tun0.c
aplikacji. To także najbardziej naturalny sposób. Musimy zmienić 10.0.0.1 na 10.0.0.2 w drodze powrotnej i 10.0.0.2 na 10.0.0.1 w drodze powrotnej.
Zmodyfikowałem za tun0.c
pomocą kodu zmiany adresu źródłowego. Oto nowy plik i tutaj jest plik poprawek dla twojego tun0.c
. Zmiany w nagłówku IP również wymagają korekty sumy kontrolnej , więc wziąłem trochę kodu z projektu OpenVPN . Oto pełna lista poleceń, które wykonuję po czystym ponownym uruchomieniu i tun0_changeip.c
uruchomieniu:
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
Pamiętaj, że w takim przypadku nie musisz wyłączać filtrowania ścieżki zwrotnej , ponieważ wszystko jest legalne - tun0
odbiera i wysyła tylko pakiety należące do jego podsieci. Możesz także wykonać routing oparty na źródłach zamiast na interfejsie.
PODEJŚCIE 2
Jest to możliwe, SNAT
zanim pakiet osiągnie tun0
interfejs. Nie jest to jednak poprawne. W takim przypadku zdecydowanie musisz wyłączyć filtrowanie ścieżki zwrotnej :
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
Teraz zrób SNAT
: iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT - do źródła ip.address.of.your.wlan.interface
Tutaj zmieniamy adres źródłowy tuż przed dotarciem pakietów do tun0
urządzenia. tun0.c
kod ponownie wysyła te pakiety „tak jak są” (ze zmienionym adresem źródłowym) i są one pomyślnie kierowane przez interfejs sieci WLAN. Ale możesz mieć dynamiczny adres IP na interfejsie WLAN i chcesz go użyć MASQUERADE
(aby nie podawać jawnie adresu interfejsu). Oto jak możesz wykorzystać 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
Zwróć uwagę na 10.0.55.1
adres IP „ ” - jest inny. Możesz tutaj użyć dowolnego adresu IP, to nie ma znaczenia. Pakiety osiągają nat/POSTROUTING
łańcuch wlp2s0
interfejsu, jeśli wcześniej zmienimy źródłowy adres IP. A teraz nie jest zależny od statycznego adresu IP interfejsu wlan.
PODEJŚCIE 3
Możesz także użyć fwmark
. W ten sposób nie trzeba SNAT
ale można uchwycić tylko wychodzące pakiety:
Najpierw trzeba wyłączyć kanał zwrotny filtrowania dla tun0
ponieważ będzie przekazywał pakiety, które należą do innej sieci:
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
To kolejny „hack” do routingu i netfiltra, który działa na moim pudełku Debiana 8, ale nadal zalecam pierwsze podejście, ponieważ jest bardziej naturalne i nie używa żadnych hacków.
Możesz również rozważyć zbudowanie aplikacji jako przejrzystego serwera proxy . Myślę, że byłoby to znacznie łatwiejsze niż analizowanie pakietów z urządzenia tun.
-j SNAT
, nie-s SNAT
sudo ip rule add iif tun0 lookup main priority 500
to, ale nadal nie działało. Podoba mi się to podejście, szkoda, że nie mogę go odtworzyć.