Nasłuch na wszystkich adresach IP i wszystkich portach
Napisał: Patryk Krawaczyński
29/06/2018 w Administracja Brak komentarzy. (artykuł nr 661, ilość słów: 490)
A
ny-IP w Linuksie to możliwość odbierania pakietów i nawiązywania połączeń przychodzących na adresy IP, które nie są jeszcze skonfigurowane na hoście. Umożliwia to skonfigurowanie serwera, aby odpowiadał w określonym zakresie adresacji sieciowej jakby była ona lokalną – bez konieczności konfigurowania adresów na interfejsie. Dla przykładu: chcemy, aby nasza maszyna odpowiadała dla całej adresacji 192.168.0.0/24 bez konieczności konfiguracji każdego adresu IP na interfejsie/sach.
Dla osiągnięcia tego celu musimy skonfigurować routing naszego serwera, aby odpowiadał na dowolnym adresie z zakresu CIDR: 192.168.0.0/24 – tak jakby był lokalnym:
ip -4 route add local 192.168.0.0/24 dev lo
Potwierdzenie, że od teraz możemy nasłuchiwać na w/w adresacji możemy sprawdzić poprzez polecenie:
ip route show table local
lub
nmap -sP -oG - 192.168.0.0/24
lub
nc -l 192.168.0.1 8080
Do wykorzystania Any-IP w programach wymagane jest tworzenie gniazd sieciowych z opcją IP_TRANSPARENT
:
#!/usr/bin/python3 import socket IP_TRANSPARENT = 19 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.setsockopt(socket.IPPROTO_IP, IP_TRANSPARENT, 1) s.bind(('192.168.0.1', 1234)) s.listen(32) print("[+] Bound to tcp://192.168.0.1:1234") while True: c, (r_ip, r_port) = s.accept() l_ip, l_port = c.getsockname() print("[ ] Connection from tcp://%s:%d to tcp://%s:%d" % (r_ip, r_port, l_ip, l_port)) c.send(b"hello world\n") c.close()
Działanie tego prostego serwera w języku Python możemy przetestować za pomocą netcata. Od strony klienta powinniśmy zobaczyć:
root@darkstar:~# nc -v 192.168.0.1 1234 Connection to 192.168.0.1 1234 port [tcp/*] succeeded! hello world
a od strony serwera:
root@darkstar:~# ./server.py [+] Bound to tcp://192.168.0.1:1234 [ ] Connection from tcp://192.168.0.1:63436 to tcp://192.168.0.1:1234
Skoro już posiadamy w swoim władaniu całą sieć 192.168.0.1-255 to sprawmy, że jakiekolwiek połączenie TCP przychodzące do tej sieci będzie zawsze łączyło się na port 1234 lokalnego hosta. Umożliwi to nam moduł TPROXY dla iptables:
ip -4 route add local 192.168.0.0/24 dev lo src 127.0.0.1 iptables -t mangle -I PREROUTING -d 192.168.0.0/24 -p tcp -j TPROXY \ --on-port=1234 --on-ip=127.0.0.1
W pierwszej linii ponownie używamy Any-IP do lokalnego trasowania sieci 192.168.0.0/24 jasno definiując, że źródłowy adres IP dla tej sieci w przypadku lokalnych połączeń powinien być w zakresie 127.0.0.0/8. Jest to wymagane dla użytej poniżej reguły iptables, która by mogła dopasować zarówno ruch przekazywany, jak i zwrotny. Nam zależy tylko na złapaniu ruchu przekazywanego. Modyfikując linie w poprzednim skrypcie:
s.bind(('127.0.0.1', 1234)) s.listen(32) print("[+] Bound to tcp://127.0.0.1:1234")
możemy sprawdzić, czy wszystko działa tak, jak zakładaliśmy. Od strony klienta powinniśmy zobaczyć:
root@darkstar:~# nc -v 192.168.0.15 9999 Connection to 192.168.0.15 9999 port [tcp/*] succeeded! hello world
a od strony serwera:
root@darkstar:~# ./server.py [+] Bound to tcp://127.0.0.1:1234 [ ] Connection from tcp://127.0.0.1:44920 to tcp://192.168.0.15:9999
Jak widać: mimo, że nasz serwer nasłuchiwał na lokalnym hoście i porcie 1234 to doszło do niego połączenie z adresu 192.168.0.15 i portu 9999. Dzięki Any-IP oraz TPROXY nie musieliśmy:
– definiować każdego adresu na interfejsach,
– używać problematycznych conntracków iptables,
– zmuszać aplikację, aby prowadziła nasłuch na wielu portach.
Więcej informacji: Abusing Linux’s firewall: the hack that allowed us to build Spectrum