Ochrana SSH démona proti útokům (3)

Kromě vypnutí autentizace na základě jména a hesla v konfiguraci ssh démona a povolení autentizace na základě klíčů (viz 2. díl) a kromě použití programu sshdfilter nebo podobného na blokování portu 22 (s využitím iptables) při detekci většího počtu neúspěšných pokusů o přihlášení (viz 1. díl) můžeme využít ještě další možnost jak ochánit ssh démona před útoky a přitom si nijak výrazně neomezit vzdálený přístup. Jedná se o ochranu pomocí tzv. port knockingu. Výhodou této metody je, že si vystačíme pouze se stavovým filtrem, tedy s iptables.

Jak to funguje?

Pomocí iptables a především modulu recent můžeme firewall nastavit tak, že se port 22 otevře (obvykle pouze na pár vteřin) na základě "zaťukání" (port knockingu) na námi stanovené porty (například: 250 100 150 200). Není to sice nejpohodlnější metoda, ale když si napíšeme jednoduchý skript, který za nás například pomocí programu telnet nebo nmap dané porty kontaktuje a poté se přes otevřený ssh port připojí k ssh serveru, tak to zase nijak pracné nebude.

Nastavení

#!/bin/bash

# smazeme predchozi nastaveni pravidel a nami nadefinovanych retezcu
/sbin/iptables -F
/sbin/iptables -X

# nastavime defaultni politiky
/sbin/iptables -P INPUT DROP
/sbin/iptables -P FORWARD DROP
/sbin/iptables -P OUTPUT ACCEPT

/sbin/iptables -N MYKNOCK2
/sbin/iptables -A MYKNOCK2 -m recent --name KNOCK1 --remove
/sbin/iptables -A MYKNOCK2 -m recent --name KNOCK2 --set
/sbin/iptables -A MYKNOCK2 -j LOG --log-prefix "MYKNOCK2: "

/sbin/iptables -N MYKNOCK3
/sbin/iptables -A MYKNOCK3 -m recent --name KNOCK2 --remove
/sbin/iptables -A MYKNOCK3 -m recent --name KNOCK3 --set
/sbin/iptables -A MYKNOCK3 -j LOG --log-prefix "MYKNOCK3: "

/sbin/iptables -N MYKNOCK4
/sbin/iptables -A MYKNOCK4 -m recent --name KNOCK3 --remove
/sbin/iptables -A MYKNOCK4 -m recent --name KNOCK4 --set
/sbin/iptables -A MYKNOCK4 -j LOG --log-prefix "MYKNOCK4: "

/sbin/iptables -A INPUT -m recent --update --name KNOCK1

/sbin/iptables -A INPUT -m tcp -p tcp --dport 250 -m recent --set --name KNOCK1
/sbin/iptables -A INPUT -m tcp -p tcp --dport 100 -m recent --rcheck --name KNOCK1 -j MYKNOCK2
/sbin/iptables -A INPUT -m tcp -p tcp --dport 150 -m recent --rcheck --name KNOCK2 -j MYKNOCK3
/sbin/iptables -A INPUT -m tcp -p tcp --dport 200 -m recent --rcheck --name KNOCK3 -j MYKNOCK4

/sbin/iptables -A INPUT -p tcp --dport 22 -m recent --rcheck --seconds 5 --name KNOCK4 -j ACCEPT

/sbin/iptables -A INPUT -i lo -j ACCEPT
/sbin/iptables -A INPUT -m icmp -p icmp --icmp-type any -j ACCEPT 
/sbin/iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
/sbin/iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited 

Případný výstup z programu iptables-save bude vypadat následovně:

# Generated by iptables-save v1.3.5 on Thu Oct 19 16:26:20 2006
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:MYKNOCK2 - [0:0]
:MYKNOCK3 - [0:0]
:MYKNOCK4 - [0:0]
-A INPUT -m recent --update --name KNOCK1 --rsource
-A INPUT -p tcp -m tcp --dport 250 -m recent --set --name KNOCK1 --rsource
-A INPUT -p tcp -m tcp --dport 100 -m recent --rcheck --name KNOCK1 --rsource -j MYKNOCK2 
-A INPUT -p tcp -m tcp --dport 150 -m recent --rcheck --name KNOCK2 --rsource -j MYKNOCK3 
-A INPUT -p tcp -m tcp --dport 200 -m recent --rcheck --name KNOCK3 --rsource -j MYKNOCK4 
-A INPUT -p tcp -m tcp --dport 22 -m recent --rcheck --seconds 5 --name KNOCK4 --rsource -j ACCEPT 
-A INPUT -i lo -j ACCEPT 
-A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT 
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A MYKNOCK2 -m recent --remove --name KNOCK1 --rsource
-A MYKNOCK2 -m recent --set --name KNOCK2 --rsource
-A MYKNOCK2 -j LOG --log-prefix "MYKNOCK2: "
-A MYKNOCK3 -m recent --remove --name KNOCK2 --rsource
-A MYKNOCK3 -m recent --set --name KNOCK3 --rsource
-A MYKNOCK3 -j LOG --log-prefix "MYKNOCK3: "
-A MYKNOCK4 -m recent --remove --name KNOCK3 --rsource
-A MYKNOCK4 -m recent --set --name KNOCK4 --rsource
-A MYKNOCK4 -j LOG --log-prefix "MYKNOCK4: "
COMMIT
# Completed on Thu Oct 19 16:26:20 2006

Skript pro port knocking pomocí telnetu a následné připojení pomocí ssh klienta na danou IP adresu. Tento skript je jen jako názorný příklad, samozřejmě by se dal podstatně vylepšit a parametrizovat.

#!/bin/bash

for port in 250 100 150 200 
do 
    telnet 192.168.2.100 $port > /dev/null 2>&1; 
done

ssh ondra@192.168.2.100

Druhý skript se stejnou funkčností, ale využívající místo telnetu program nmap.

for port in 250 100 150 200
do
    nmap -P0 -sT -p $port --host_timeout 250 192.168.2.100 > /dev/null 2>&1;
done

ssh ondra@192.168.2.100
Naposledy změněno: 19.10.2006 17:01