Jak zrobić cały ruch, aby przejść przez jeden interfejs w systemie Linux

12

Mam własny interfejs tun0 ( oparty na TUN / TAP ), który wyświetla to, co otrzymuje.
Potrzebuję całego ruchu systemu, aby przepłynąć przez ten interfejs.
Rola interfejsu to:

  1. Aby dowiedzieć się, które pakiety będą cenzurowane, i tuneluj je.
  2. Przekaż cały pozostały ruch nietknięty.

Jak się domyślacie, staram się zbudować narzędzie antykluczowe.
Decyzję o tunelowaniu należy podjąć w ramach procesu tun0,
ponieważ tylko tam możemy używać zaufanego DNS.

Potrzebuję twojej pomocy, aby pokazać mi, jak sprawić, by cały ruch przepływał przez napisany przez siebie interfejs tun0. Jeśli tun0 wymaga zmian, proszę o podanie takich zmian.

Poniżej pokazano, jak próbowałem sprawić, aby cały ruch przechodził przez tun0 i nie powiódł się (ping nie działa).

Kompilacja

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

Konfiguracja

  1. sudo ip addr add 10.0.0.1/24 dev tun0
  2. stwórz stół John

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

Kolejność jest ważna:

  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 
    

Rozwiązywanie problemów

  1. sudo tcpdump -i wlp2s0 -qtln icmpa następnie ping -I tun0 8.8.8.8pokazuje brak przechwyconych pakietów, oznacza to, że żadne pakiety nie są przesyłane z tun0 do wlp2s0 za pomocą iif tun0 lookup mainreguły.

  2. Kiedy otrzymuje tun0się lowszędzie następnie pracował dla mnie.

Próbowałem także

  1. Wyłączanie filtrowania odwrotnej ścieżki, rp_filter=0w/etc/sysctl.conf

Odpowiedz Rozwiązywanie problemów

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

Zmodyfikowane źródła z odpowiedzi są również tutaj .

ilyaigpetrov
źródło

Odpowiedzi:

10

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 tun0interfejs, a jego lokalny adres to 10.0.0.1). Przechwytujesz pakiety, na razie wszystko jest w porządku.
Teraz tun0wysyła pakiety dalej. Adres źródłowy to 10.0.0.1i chcesz, aby pakiety wychodziły przez inny interfejs ( wlp2s0w 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ć tcpdumpna wlp2s0moż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 ACCEPTzasady, 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 tun0interfejsu do wlp2s0. netfilter powinien zmienić źródłowy adres IP 10.0.0.1na wlp2s0adres przypisany interfejsowi dla pakietów wyjściowych. Zapamiętuje wszystkie połączenia, a kiedy pakiety odpowiedzi wracają (jeśli są), zmienia adres docelowy wlp2s0interfejsu 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 TRACEfunkcja:

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.caplikacji. 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.cpomocą 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.curuchomieniu:

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 - tun0odbiera 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, SNATzanim pakiet osiągnie tun0interfejs. 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 tun0urządzenia. tun0.ckod 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.1adres IP „ ” - jest inny. Możesz tutaj użyć dowolnego adresu IP, to nie ma znaczenia. Pakiety osiągają nat/POSTROUTINGłańcuch wlp2s0interfejsu, 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 SNATale można uchwycić tylko wychodzące pakiety:
Najpierw trzeba wyłączyć kanał zwrotny filtrowania dla tun0ponieważ 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.

tifssoft
źródło
Musiałem użyć -j SNAT, nie-s SNAT
ilyaigpetrov
Działa, ale wydajność jest bardzo przerywana (może utknąć na 10 sekund, a następnie kontynuować pracę). Zastanowię się, dlaczego tak się dzieje i jak to naprawić.
ilyaigpetrov
1
Przepraszam, to była moja literówka. Dodałem inne podejście do mojej odpowiedzi. Nie masz pojęcia o problemie z wydajnością. Nawiasem mówiąc, dlaczego nie użyć przezroczystego proxy z iptables DNAT do filtrowania i przekierowywania ruchu?
tifssoft,
Nie jestem w stanie odtworzyć twojego podejścia do oceny, dodałem tylko sudo ip rule add iif tun0 lookup main priority 500to, ale nadal nie działało. Podoba mi się to podejście, szkoda, że ​​nie mogę go odtworzyć.
ilyaigpetrov
1
Dziękuję za twoje nowe podejście, śledziłem je krok po kroku i działało idealnie. Jednak nie rozumiem, dlaczego musimy zmienić IP, co najważniejsze, działa. W przypadku niepowodzenia moich planów z proxy proxy TCP będę mógł wrócić do twojej odpowiedzi. Pokazałeś tutaj wiele umiejętności sieciowych i nie wątpię, że twoje umiejętności będą pożądane. Powodzenia!
ilyaigpetrov,