Porty dla NFS

Krótko i na temat. Dodałem kiedyś wpis o aktówce w Linuksie, ale nie doprecyzowałem w nim wszystkich portów, jakich potrzebuje do komunikacji. Ostatnio potrzebowałem uruchomić sobie NFS na CentOSie i okazało się, że 111 oraz 2049 nie wystarczy. Mam sobie taki plik /etc/sysconfig/nfs, do którego należy dopisać pewne wartości, które chcę mieć na stałe:

MOUNTD_PORT=22222
STATD_PORT=22223
LOCKD_TCPPORT=22224
LOCKD_UDPPORT=22225

Przed wybraniem portu należy oczywiście upewnić się, że nic w systemie tego nie używa. Dla mnie najwygodniej użyć do tego netstat -atpn. Do czego są te porty:

  • MOUNT_PORT jest używany przez rpc.mountd za każdym razem, kiedy klient zamontuje dowolny eksport nfsa,
  • STATD_PORT dla rpc.statd, którego serwer używa do kontroli stanu podłączonych klientów,
  • lockd kontroluje coś związanego z kernelem; jeszcze nie wiem co, ale kiedy się dowiem, to napiszę 🙂 .

W pliki /etc/sysconfig/iptables piszemy więc coś takiego:

# nfs
-A INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 111 -j ACCEPT
-A INPUT -s 192.168.1.0/24 -p udp -m udp --dport 111 -j ACCEPT
-A INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 2049 -j ACCEPT
-A INPUT -s 192.168.1.0/24 -p udp -m udp --dport 2049 -j ACCEPT

# nfs-mountd
-A INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 22222 -j ACCEPT
-A INPUT -s 192.168.1.0/24 -p udp -m udp --dport 22222 -j ACCEPT

# nfs-statd
-A INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 22223 -j ACCEPT
-A INPUT -s 192.168.1.0/24 -p udp -m udp --dport 22223 -j ACCEPT

# nfs-lockd
-A INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 22224 -j ACCEPT
-A INPUT -s 192.168.1.0/24 -p udp -m udp --dport 22225 -j ACCEPT

I mamy łączność. 192.168.1.0/24 można poprawić, biorąc pod uwagę, w jakiej podsieci jesteśmy. Można też w ogóle zrezygnować z parametru -s ip.ip.ip.ip, jeżeli mamy dodatkowy firewall na routerze. Ja dla pewności zawsze go dopisuję.

Ograniczanie ruchu na SSH

Otwarcie portu 22 na serwerze jest z jednej strony koniecznością, ale z drugiej po każdorazowym zalogowaniu jako root widzimy nieprzyjemny komunikat o setkach i tysiącach prób zalogowania na nasz serwer, typu

There were 4011 failed login attempts since the last successful login.

(a taki komunikat właśnie otrzymałem, na długo po zaaplikowaniu przedstawianej procedury, wyobrażacie sobie jakieś 30000 prób bez tego zabezpieczenia?)
Zwykle owe próby niewiele dają, gdyż a) wyłączyłem zdalne logowanie jako root i b) uważam, że hasło jest naprawdę niezłe 🙂 , ale generują tylko dodatkowy, niepotrzebny ruch. Czy jedynym wyjściem jest zmiana portu i powiadamianie wszystkich zainteresowanych o konieczności przestawiania ustawień w putty, czy wklepywaniu portu za każdym razem? Na krótką metę zadziała, ale boty są cwane i się prędzej czy później zorientują.
Rozwiązanie, którego mnie nauczyli, a teraz piszę wam, polega na ograniczeniu ruchu na porcie 22 z poziomu firewalla. W dystrybucjach CentOS, RHEL i Fedora jest zainstalowany firewalld i mimo kilku zalet (typu wsparcia dla dockera) jest mi zbędny, używam starego, dobrego skryptu z regułkami iptables. W tym celu wyłączam firewalld i instaluję usługi iptables:

yum install iptables-services
systemctl disable firewalld.service
systemctl mask firewalld.service
systemctl enable iptables.service

Po tej wstępnej konfiguracji czas zająć się plikiem /etc/sysconfig/iptables, którego domyślną zawartość można usunąć, lub skomentować za pomocą dopisania znaku # na początku każdej linijki. Potem dopisujemy poniżej takie oto zaklęcia:

*filter
-F
-X
-P INPUT DROP
-A INPUT -s 0/0 -m state --state RELATED,ESTABLISHED -j ACCEPT

# localhost
-A INPUT -i lo -j ACCEPT

# ping
-A INPUT -p icmp -j ACCEPT

Są to podstawowe opcje, które warto mieć na każdym serwerze. Pewną wariacją może być znak komentarza przed linijką dopuszczającą pinga, ale jeszcze nigdy nie zapingowano mi serwera na śmierć, więc ta lekcja jest jeszcze przede mną. 🙂 No fajnie, ale nie mamy tu jeszcze niczego na temat SSH. Dopisujemy więc poniżej:

# SSH
# sprawdzanie, czy ktos nie laczy sie zbyt czesto
-N trap
-A INPUT -s 0/0 -p tcp --dport 22 --syn -j trap
-A trap -m recent --name its_trap --rcheck --seconds 50 --hitcount 3 --rttl -j DROP
-A trap -m recent --name its_trap --set -j RETURN

# sprawdzanie, czy ktos nie laczy sie z tego samego miejsca
-N stoper
-A INPUT -s 0/0 -p tcp --dport 22 --syn -j stoper
-A stoper -m connlimit --connlimit-above 4 -j DROP
-A stoper -m limit --limit 2/m --limit-burst 1 -j ACCEPT

# commit na koniec
COMMIT

Co to wszystko znaczy? Zamiast standardowo wpuszczać każdy pakiet na porcie 22 licząc na to, że może to być połączenie z naszym terminalem (lub putty), co nie zdarza się przecież zbyt często, wprowadzamy pewne ograniczenia. Łańcuch trap sprawdza, czy w ciągu 50 sekund nie próbowano się połączyć więcej niż 3 razy. Oznacza to, że jeżeli trzy razy wpiszę złe hasło, będę musiał poczekać do następnych 50 sekund, by próbować ponownie. Stoper sprawdza zaś, czy w ciągu ostatnich 2 minut nie próbowano się dostać więcej niż 4 razy z tego samego komputera. W obydwu przypadkach kolejne połączenia są blokowane.

Wiąże się z tym kilka niedogodności. Po pierwsze nie otworzę sobie 10 kart terminala, żeby połączyć się 10 razy z serwerem (ale od czago jest screen, czy podobne programy). Po drugie jeżeli zapomni mi się hasła, to proces jego zgadywania będzie trwał nieco dłużej. Warto więc używać kluczy ssh i nie bawić się w hasła.

Zdaję sobie sprawę, że nie jest to może specjalnie elegancko rozpisane, nie mam się za żadnego mega specjalistę od iptables, ale daje radę i zdecydowanie zmniejsza liczbę prób logowania. Na koniec trzeba powiadomić systemd o naszym zamiarach:

systemctl stop firewalld.service
systemctl disable firewalld.service
systemctl mask firewalld.service
systemctl enable iptables.service
systemctl start iptables.service
systemctl status iptables.service

Uwaga! Bardzo starałem się nie zrobić żadnej głupiej literówki kopiując te regułki, ale z iptables nigdy nic nie wiadomo. Wklejasz na własne ryzyko. Mam nadzieję, że masz jakieś zapasowe wejście do serwera.