Krótka historia,
3 interfejsy, eth0 (LAN), eth1 (ADSL), eth2 (4G).
eth0 -> eth1: Działa
(porty 80, 443, 4070) eth0 -> eth2: Nie dzieje się
To jest graficzne przedstawienie pomysłu:
Port 80 i 443 przez eth2,
a reszta przez eth1
Netscheme:
eth0: -ip 10.0.0.1 -net 10.0.0.0/8 -gw 10.0.0.1 (the servers own intf)
eth1: -ip 192.168.1.74 -net 192.168.1.0/24 -gw 192.168.1.254
eth2: -ip 192.168.1.91 -net 192.168.0.0/24 -gw 192.168.0.1
Myślę, że ten nowy skrypt przekierowuje 22 i 4070 do odpowiedniej tabeli.
Jednak po przejściu do tej tabeli nie jest przekierowywana do eth2.
Ten skrypt działa, z wyjątkiem 22 i 4070!
(Port 80 nie został skomentowany i działa, ale przez eth1, co jest złe)
modprobe iptable_nat
modprobe ip_conntrack
echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -P INPUT ACCEPT
iptables -F INPUT
iptables -P OUTPUT ACCEPT
iptables -F OUTPUT
iptables -P FORWARD DROP
iptables -F FORWARD
iptables -F PREROUTING
iptables -t nat -F
iptables -t mangle -F
iptables -F
# This next line restores any issues trying to connect to something
# if you get weird ACK packets when trying to connect (at least i did)!
iptables -t mangle -A PREROUTING -p tcp -j CONNMARK --restore-mark
ip route flush table main
iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 22 -j MARK --set-mark 1
### iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 80 -j MARK --set-mark 1
iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 4070 -j MARK --set-mark 1
## Setup routes
# LAN
route add -net 10.0.0.0 netmask 255.0.0.0 dev eth0
# ADSL
route add -net 192.168.1.0 netmask 255.255.255.0 dev eth1
# 4G (Only accessible if marking packages with \x01
route add -net 192.168.0.0 netmask 255.255.255.0 dev eth2
# Default via ADSL
## -- Does the same as ip route below? route add default gw 192.168.1.254
echo "201 eth2.out" >> /etc/iproute2/rt_tables
ip rule add fwmark 1 table eth2.out
ip route add default via 192.168.0.1 dev eth2 table eth2.out
ip route add default via 192.168.1.254 dev eth1
## Setup forwards
# From 4G to LAN
iptables -A FORWARD -i eth2 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From ADSL to LAN
iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From LAN to ADSL (Default route out)
# - Note: If marked packages is sent to ADSL they will be mangled and rerouted to 4G
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE
Stary skrypt:
Ignore everything below unless you're interested in retracing my steps!!
Utworzyłem skrypt router.sh, aby skonfigurować moje środowisko na wypadek, gdyby zrobiłem coś złego. Mam 3 porty, które chcę wysłać do połączenia 4G, a pozostałe za pośrednictwem stacjonarnego połączenia ADSL. Aby to zrobić, poinstruowałem iptables, aby zmieniały paczki na domyślnej trasie i wysyłały je przez mój interfejs 4G, jeśli --dport == 443 | 80 | 4070
To jednak nie działa; Nadal jestem prowadzony przez mój telefon stacjonarny, bez względu na wszystko.
Tak wygląda mój skrypt:
#!/bin/bash
## routing tables
# wireless = 4G via eth2
# adsl = adsl via eth1
modprobe iptable_nat
modprobe ip_conntrack
echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -P INPUT ACCEPT
iptables -F INPUT
iptables -P OUTPUT ACCEPT
iptables -F OUTPUT
iptables -P FORWARD DROP
iptables -F FORWARD
iptables -t nat -F
ip route flush table main
ip route flush table wireless
ip route flush table adsl
## Setup routing tables
# ADSL
ip route add table adsl to 192.168.1.0/24 dev eth1
# 4G
ip route add table wireless to 192.168.0.0 dev eth2
ip rule add fwmark 0x1 table wireless
## Setup routes
# LAN
route add -net 10.0.0.0 netmask 255.0.0.0 dev eth0
# ADSL
route add -net 192.168.1.0 netmask 255.255.255.0 dev eth1
# 4G (Only accessible if marking packages with \x01
route add -net 192.168.0.0 netmask 255.255.255.0 dev eth2
# Default via ADSL
route add default gw 192.168.1.254
## Forward ports into the LAN
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j DNAT --to 10.0.0.3:80
## Lets mark all packets we want for 4G forward
# HTTPS
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 443 -j MARK --set-mark 1
# HTTP
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 80 -j MARK --set-mark 1
# Spotify
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 4070 -j MARK --set-mark 1
## Setup forwards
# From 4G to LAN
iptables -A FORWARD -i eth2 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From ADSL to LAN
iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
# From LAN to ADSL (Default route out)
# - Note: If marked packages is sent to ADSL they will be mangled and rerouted to 4G
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
iptables -A FORWARD -j LOG
#iptables --table nat --append POSTROUTING --out-interface eth2 --jump SNAT --to-source "192.168.1.74"
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
Próbowałem również dodać te 3 do dolnej części skryptu:
iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 80 -j SNAT --to "192.168.0.91"
iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 443 -j SNAT --to "192.168.0.91"
iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 4070 -j SNAT --to "192.168.0.91"
Próbowałem także bez powodzenia:
iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 80 -j MARK --set-mark 1
Na koniec wypróbowałem:
## Lets mark all packets we want for 4G forward
# HTTPS
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 443 -j MARK --set-mark 1
# HTTP
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 80 -j MARK --set-mark 1
# Spotify
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 4070 -j MARK --set-mark 1
Trasowanie działa, mogę przeglądać internet, słuchać muzyki i co nie, ale robię to za pomocą niewłaściwego interfejsu. Od dłuższego czasu googlowałem i znalazłem fragmenty, aby zrozumieć, co robię i dlaczego to robię. Mógłbym kształtować ruch poprzez tc, ale jeśli jest to możliwe poprzez oznaczanie pakietów w iptables, pomogłoby to mi na dłuższą metę.
Domyślam się, że źle wykonuję zamówienie na różnych zasadach, głównie w części MASQUERADE ? a jeśli to w ogóle powinno tam być?
Czy ktoś może wyjaśnić, w jaki sposób port DNAT może powiedzieć tcp: 80 z interfejsu zewnętrznego (jednego lub obu protokołów) do wewnętrznej przestrzeni adresowej 10.0.0.0?
Wyjścia:
root@Netbridge:~# route -n Kernel IP routing table Destination
Gateway Genmask Flags Metric Ref Use Iface<br>
0.0.0.0 192.168.1.254 0.0.0.0 UG 0 0 0 eth1<br>
10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 eth0<br>
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2<br>
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
root@Netbridge:~# ifconfig
eth0 Link encap:Ethernet HWaddr 00:0c:29:7e:9e:4e
inet addr:10.0.0.1 Bcast:10.255.255.255 Mask:255.0.0.0
eth1 Link encap:Ethernet HWaddr 00:0c:29:7e:9e:58
inet addr:192.168.1.74 Bcast:192.168.1.255 Mask:255.255.255.0
eth2 Link encap:Ethernet HWaddr 00:0c:29:7e:9e:62
inet addr:192.168.0.91 Bcast:192.168.0.255 Mask:255.255.255.0
Postępował zgodnie z tymi instrukcjami:
ruch wyjściowy na różnych interfejsach oparty na miejscu docelowym
iptables-forward-specific-port-to-specific-nic
Wśród kilku innych powiązanych wątków.
localhost
z adresem i adresemeth2
interfejsu?ethX
adresie IP uniemożliwi hostom w sieciethX
LAN dostęp do lokalnego serwera za pomocąethY
adresu IP i nie uniemożliwi hostomethY
dostępu do serwera za pomocąethX
adresu IP. Pamiętaj, że Linux używa słabego modelu hosta.Odpowiedzi:
BatchyX już bardzo dobrze wyjaśnia iptables i routing, więc wykorzystam swoje lenistwo i przejdę bezpośrednio do skryptu.
Powinien NAT cały ruch do portu 80,443,22,4070 do 192.168.0.91. Cała reszta będzie NAT przez 192.168.1.254.
Ponownie przeprowadzam testy i kończę zgodnie z tym przewodnikiem . W tym przewodniku brakuje 3 ostatnich wierszy mojego skryptu. O czym dowiedziałem się z innego portu, ale straciłem kontakt z tym linkiem.
Jest to sprawdzony skrypt roboczy.
Potrzebujesz domyślnej trasy
Jedną rzeczą, której nie umieściłem w skrypcie, jest ustawienie domyślnej trasy. Powinno być
Gdy to zrobisz
route -n
, powinna to być jedyna domyślna trasa (Dest: 0.0.0.0)fw-router.sh
PS1: Krótko mówiąc,
MASQUERADE
nie działa (w większości przypadków, a zdecydowanie w twoim przypadku) dla NAT z wieloma zewnętrznymi adresami IP, które wymagają pewnego rodzaju równoważenia obciążenia lub DNAT do obsługi ruchu przychodzącego. PotrzebujeszSNAT
kontroli kierunku.PS2: Czyste iptables nie są wystarczające.
źródło
Uwaga: Rozważyłem tylko pierwszy skrypt, ignorując stary.
route
iip route
. To jest czyste zło. Po prostu używajip
wszędzie i zapomnij oifconfig
iroute
/etc/iproute2/rt_tables
nie resetuje się po ponownym uruchomieniu. Ciągłe dołączanie tego samego wpisu nie jest dobrym pomysłem, wystarczy zrobić to tylko raz. Pamiętaj, żert_tables
wystarczy zdefiniować aliasy nazw na wartości liczbowe, nie zmieni to żadnej konfiguracji.Teraz dla
iptables
: W swoimFORWARD
łańcuchu upuszczasz pakiety przychodzące z sieci LAN do 4G. To jest złe.FORWARD
hak jest stosowany po routingu jest wykonywana. W tym momencie wszystkie routing zasad jest wykonywany i już wiadomo, czy pakiet powinien zostać wysłany do 4G czy ADSL. Zmiana trasy nie jest wykonywana wFORWARD
ani późniejFORWARD
(cóż, technicznie, zmiana trasy może być wykonanaPOSTROUTING
w ciężkich przypadkach, ale wracając do sedna).Teraz twój routing: pamiętaj, że Ubuntu domyślnie włącza filtrowanie ścieżek zwrotnych. Filtrowanie ścieżki zwrotnej działa w następujący sposób: Kiedy jądro odbierze pakiet (może być przekazany lub nie) z interfejsu A, odwróci adres źródłowy i adres docelowy oraz sprawdzi, czy wynikowy pakiet powinien zostać przekierowany przez interfejs A. Jeśli tak nie jest, pakiet jest odrzucany jako próba fałszowania adresu.
W przypadku pakietów otrzymanych od
eth0
nie stanowi to problemu. W przypadku pakietów otrzymanych zeth1
nie stanowi to również problemu, ponieważ podczas odwracania źródłowego adresu IP i docelowego adresu IP jądro będzie domyślną trasą w tabelimain
. W przypadku pakietów otrzymanych odeth2
, których nie zaznaczasz, jest to problem, ponieważ jądro uderzy w domyślną trasę w tabelimain
i uzna, że pakiety te powinny były zostać odebraneeth1
. Najłatwiejszym rozwiązaniem jest wyłączenie filtrowania ścieżki zwrotnej w eth1:źródło