Come proteggere Linux con Knockd (Port Knocking)

In questo articolo spiegherò come proteggere i servizi di un server con l’utilizzo di knockd, un software che permette di bloccare (chiudere) con il firewall (iptables) le porte per servizi come SSH (porta 22) e altro ancora, per sbloccarle in caso di necessità e soprattutto aprirle solo per noi, autorizzando temporaneamente il nostro indirizzo IP ad effettuare l’accesso a quel determinato servizio.

In sostanza, knockd si occupa di analizzare il file di log del firewall e se nota che, entro un tempo limite, qualcuno si collega su una serie di porte prefissate, nel corretto ordine, esegue una determinata azione (come ad esempio lo sblocco della porta 22 per collegarsi via SSH al server, abilitando però solo il nostro IP).

I requisiti sono i seguenti:

  1. Una distribuzione Linux (in questa guida tratteremo Debian e derivate);
  2. Accesso come root/super-user alla macchina con sopra la distribuzione Linux in questione (nel caso in cui non usiate l’account di root, togliete la parola chiave sudo da ogni comando di seguito descritto).

 

Iniziamo subito creando le regole necessarie a configurare il firewall. Il primo comando da impartire è quello che ci permetterà di abilitare il traffico locale (quello che rimane confinato all’interno del sistema, il loopback):

sudo iptables -A INPUT -i lo -j ACCEPT

Dopodiché abilitiamo il traffico per le connessioni già stabilite, come ad esempio quella che stiamo usando adesso (se vi siete collegati via SSH alla vostra macchina remota), grazie al comando:

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Ora è arrivato il momento di decidere quali porte aprire al pubblico, ad esempio quelle per il webserver:

sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

La prima permette ad un eventuale webserver (come Apache2) di rispondervi tramite protocollo HTTP, sulla porta di default per tale protocollo (la porta 80). La seconda, invece, abilita le connessioni HTTPS (connessioni HTTP sicure), ma ovviamente, per funzionare, dovete aver configurato correttamente il webserver, non basta aprire una porta!

Dopo aver aggiunto le porte di eventuali servizi che vogliamo garantire agli utenti (ad esempio per IRC bisogna aprire la 6667, per FTP la 21, per Minecraft la 25565 e così via, in base a quale servizio offrite sul vostro server), bisognerà applicare la regola che bloccherà tutto il resto del traffico, ovvero:

sudo iptables -A INPUT -j DROP

Nel caso in cui perdiate la connessione al server, sarà necessario o spostarsi localmente (se avete accesso fisico alla macchina) oppure dall’apposito pannello per l’accesso, offerto dal provider (ad esempio nei VPS di OVH, sotto la modalità Esperto c’è lo strumento KVM, che permette di aprire una shell bypassando il firewall).

Facciamo in modo tale che le regole impostate rimangano tali anche dopo un eventuale riavvio della macchina. Per fare ciò bisognerà installare un apposito pacchetto, così:

sudo apt-get install iptables-persistent -y

E dopodiché avviare il servizio:

sudo service iptables-persistent start

Arrivati a questo punto, sarà necessario installare knockd, con l’apposito comando:

sudo apt-get install knockd -y

E configurarlo, sfruttando l’editor nano:

sudo nano /etc/knockd.conf

Il file di configurazione predefinito ha solitamente questo contenuto:

[options]
        UseSyslog

[openSSH]
        sequence    = 7000,8000,9000
        seq_timeout = 5
        command     = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
        tcpflags    = syn

[closeSSH]
        sequence    = 9000,8000,7000
        seq_timeout = 5
        command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
        tcpflags    = syn

Non dovrebbe essere difficile modificarlo, la sequenza delle porte si imposta nella voce “sequence”, il tempo limite durante il quale eseguire la connessione a tali porte è “seq_timeout”, il comando da eseguire si trova invece in “command” e potete lasciare tranquillamente quello che c’è già, poiché sblocca la porta 22 solo per il vostro IP (da notare che %IP% è una variabile), nel caso specifico di questa guida è bene utilizzare il comando /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT piuttosto che quello di default. Il campo “tcpflags” serve invece per impostare i flags TCP da tenere in considerazione durante la vostra connessione sulle porte indicate nella sequenza.
Da notare che il file di log di knockd, così come specificato, è quello di sistema (/var/log/messages). Per cambiarlo bisogna specificare il parametro:

LogFile = /percorso/al/file/di/log

Salviamo quindi il nostro file di configurazione e andiamo a prepararci per avviare knockd. Prima però, nel caso in cui desideriate impostare la chiusura automatica della porta, è necessario aggiungere dei campi:

cmd_timeout = 60
stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT

Da inserire ovviamente, sotto la regola che sblocca la porta 22 ([openSSH]). Questo ci garantirà di chiudere la porta automaticamente allo scadere del 60° secondo dal momento dell’apertura (in sostanza esegue il comando specificato in stop_command dopo i secondi definiti in cmd_timeout).
Sempre usando l’editor nano, apriamo il seguente file:

sudo nano /etc/default/knockd

E assicuriamoci di impostarlo così:

################################################
#
# knockd's default file, for generic sys config
#
################################################

# control if we start knockd at init or not
# 1 = start
# anything else = don't start
#
# PLEASE EDIT /etc/knockd.conf BEFORE ENABLING
START_KNOCKD=1

# command line options
KNOCKD_OPTS="-i venet0:0"

Da notare l’opzione che ho impostato (-i venet0:0). Essa ci assicura che nel caso in cui utilizzassimo un VPS, knockd analizzi i logs della scheda di rete giusta (che solitamente è quella che ho impostato sopra). Se no dovrebbe bastare eth0 / eth1 o wlan0 / wlan1, che tuttavia dovrebbero essere rilevate automaticamente nel caso di una macchina reale e non virtualizzata. In ogni caso tramite il comando:

ifconfig

È possibile visualizzare tutte le informazioni relative alle schede di rete e identificare quella giusta sulla quale mettere in ascolto knockd.
Se avete fatto modifiche al file di configurazione, ricordatevi di riavviare il demone, con il comando:

sudo service knockd restart

Per fare eseguire un’azione al server con knockd in esecuzione o utilizzate un apposito pacchetto (se state usando un PC con Linux):

sudo apt-get install knock

E poi date il comando:

knock IP_del_server sequenza

Ad esempio:

knock 192.168.0.8 7000 8000 9000

Oppure scaricate dal sito ufficiale l’archivio tar.gz, o lo zip con l’eseguibile per Windows o i binari per Mac OS X (sono disponibili anche app per smartphone, oltre che ulteriori esempi).
Nel caso in cui siate su Windows, vi allego il file batch che utilizzo per sbloccare la porta SSH del mio server e aprire PuTTY, da salvare come Connetti.bat con il blocco note:

@echo off
knock.exe IP-DEL-SERVER SEQUENZA-DI-APERTURA-PORTA-SSH
putty.exe -ssh IP-DEL-SERVER
EXIT /B

Da notare che i files “knock.exe” e “putty.exe” devono trovarsi nello stesso percorso del file Connetti.bat.

Vi garantisco che utilizzando knockd avrete un ottimo incremento in termini di sicurezza, non dovrete preoccuparvi di impostare chiavi RSA per il login via SSH o altre configurazioni per SSH di sicurezza, ma bisogna prestare comunque attenzione agli altri servizi in esecuzione sul server. Insomma, la sicurezza non è mai troppa, ricordatevi di tenere un’occhio di riguardo ai logs per prevenire eventuali attacchi.

Aggiornamento: a causa di un bug su Debian 9 con systemd non è possibile abilitare l’avvio al boot di knockd. Per ovviare a ciò basta aggiungere al file /lib/systemd/system/knockd.service queste righe:

[Install]
WantedBy=multi-user.target
Alias=knockd.service

E dopodiché eseguire:

sudo systemctl enable knockd.service

Così facendo knockd si avvierà all’avvio del sistema.
Se volete che knockd si avvii subito dopo che la rete è stata configurata e state usando systemd, assicuratevi che il servizio sia configurato come segue:

[Unit]
Description=Port-Knock Daemon
After=network.target
Documentation=man:knockd(1)

[Service]
EnvironmentFile=-/etc/default/knockd
ExecStart=/usr/sbin/knockd $KNOCKD_OPTS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
SuccessExitStatus=0 2 15
ProtectSystem=full
CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN

[Install]
WantedBy=multi-user.target
Alias=knockd.service

Questo dovrebbe garantire un corretto funzionamento di knockd su qualsiasi distro GNU/Linux. In alternativa, se knockd non dovesse partire correttamente dopo la rete, provate con le opzioni:

After=network-online.target
Wants=network-online.target

Da inserire sotto a [Unit].