Zmiana adresu źródłowego dla połączeń wychodzących w linuksie

17 lipca, 2012 (08:24) | linux | By: konrad

Ostatnio na forum CentOSa pojawił się wątek dotyczący nawiązywania połączeń z hosta lokalnego, ale ze zmienionym adresem źródłowym. Warto by było w przejrzystej formie zebrać wszystko, co można w takiej sytuacji zrobić.

Zacznijmy od konfiguracji samego hosta. Zakładam, że mamy poprawnie skonfigurowany system z CentOSem z jednym interfejsem sieciowym (eth0), do którego „przypięliśmy” kilka adresów IP:

[root@honey1 ~]# ip addr
1: lo:  mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc mq state UNKNOWN qlen 1000
    link/ether 00:0c:29:19:94:72 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.168/26 brd 192.168.0.191 scope global eth0
    inet 192.168.0.169/26 brd 192.168.0.191 scope global secondary eth0:0
    inet 192.168.0.170/26 brd 192.168.0.191 scope global secondary eth0:1
    inet 192.168.0.171/26 brd 192.168.0.191 scope global secondary eth0:2
    inet 192.168.0.172/26 brd 192.168.0.191 scope global secondary eth0:3
    inet 192.168.0.173/26 brd 192.168.0.191 scope global secondary eth0:4
    inet 192.168.0.174/26 brd 192.168.0.191 scope global secondary eth0:5
    inet 192.168.0.175/26 brd 192.168.0.191 scope global secondary eth0:6
    inet6 fe80::20c:29ff:fe19:9472/64 scope link
       valid_lft forever preferred_lft forever
[root@honey1 ~]# ip route
192.168.0.128/26 dev eth0  proto kernel  scope link  src 192.168.0.168
169.254.0.0/16 dev eth0  scope link  metric 1002
default via 192.168.0.190 dev eth0
[root@honey1 ~]#

Standardowo, wszystkie połączenia, które zaczynają się na tej maszynie będą widoczne w świecie jako pakiety pochodzące od pierwszego adresu, czyli 192.168.0.168. Co możemy zrobić, żeby to zmienić? Kilka rzeczy.

Po pierwsze – najprostsze, ale czasami przydatne – możemy zmienić adres źródłowy dla wszystkich połączeń wychodzących. Albo za pomocą zmian w tablicy routingu (musimy oczywiście pamiętać, aby adres IP zgadzał się z oznaczeniem interfejsu :-)):

ip route replace default dev eth0:1 src 192.168.0.170

albo za pomocą narzędzia iptables:

iptables -t nat -A POSTROUTING -j SNAT --to-source 192.168.0.170

Oba powyższe rozwiązania mają swoje wady i zalety, chociaż w większości przypadków zastosowałbym raczej to pierwsze.

Po drugie – używając odpowiednich „filtrów” możemy zrobić to samo, ale tylko dla wybranych hostów w Sieci. Komendy, odpowiednio, będą wyglądały tak:

ip route add 10.0.0.0/16 dev eth0:1 src 192.168.0.170
iptables -t nat -A POSTROUTING -d 10.0.0.0/16 -j SNAT --to-source 192.168.0.170

Tak w zasadzie niewiele się zmieniło. Polecenia zostały te same, rozbudowałem je tylko o odpowiednie warunki ograniczające adresy docelowe.

Po trzecie – zrobić tak, żeby adres źródłowy ustawiany był w zależności od użytkownika (lub grupy) w systemie. Na kilku stronach znalazłem coś takiego:

iptables -t nat -A POSTROUTING -m owner --uid-owner kbechler -j SNAT --to-source 192.168.0.170
iptables -t nat -A POSTROUTING -m owner --gid-owner kbechler -j SNAT --to-source 192.168.0.170

Wydaje się być OK i działać poprawnie. Chociaż tutaj można się naciąć na pewien „problem”. Podczas pierwszych testów (przeprowadzanych za pomocą pinga na serwerze źródłowym i tcpdumpa na docelowym), zadziałała mi jedynie wersja z „–gid-owner”, czyli przypisanie adresu dla grupy. Pomimo próśb i zaklęć, wersja „per user” nie chciała zrobić tego, co bym chciał. Odpowiedź, po krótkim poszukiwaniu, znalazłem TUTAJ. Okazuje się, że generowanie ruchu ICMP wymaga tzw. raw socket, co z kolei wymusza działanie z prawami roota. I z tego powodu, narzędzie ‚ping’ ma ustawiony bit SUID – do tej pory nie zwróciłem na to uwagi.

Jeżeli chodzi o możliwości samego systemu, to właściwie tyle. Większość potrzeb można „załatwić” za pomocą jednej z opisanych wyżej metod. Jeżeli potrzebujemy czegoś bardziej skomplikowanego, to pewnie też da się zrobić, np. za pomocą dodatkowych tablic routingu.

Na koniec warto jeszcze zauważyć, że niektóre narzędzia same potrafią zmienić adres źródłowy, z którego nawiązują połączenie (jak choćby wget i jego opcja –bind-address). Jeżeli więc nie mamy zbyt dużych wymagań, to powinniśmy zacząć od przejrzenia dokumentacji narzędzia, którego używamy. Jest to metoda o tyle fajna, że działa w przestrzeni użytkownika i można z niej skorzystać w sytuacji, kiedy nie mamy uprawnień roota.

Trackback URL: http://konrad.bechler.pl/2012/07/linux-change-source-ip-address/trackback/

«

»

Comments

Pingback from my personal page » Ustawienia sieci w CentOSie
Time 14 marca 2013 at 12:33

[…] Kolejną fajną rzecz znalazłem na TEJ stronie. Opisano tam, jak w prosty sposób do jednego interfejsu przypisać kilka kolejnych adresów IP i nie rozpisywać się przy tym zbyt mocno. W przypadku takich konfiguracji mogą się przydać metody zmiany adresów pakietów wychodzących, które opisywałem TUTAJ. […]

Write a comment





*