Bloccare gli HELO/EHLO con falso DNS

16 agosto 2023 by Roberto Puzzanghera 0 commenti

Changelog

  • Aug 17, 2023
    - C++ version
  • Aug 13, 2023
    - v. 8.2.0 bug fix: segfault in case of no result in DNS record
    - default action changed to GNLR
  • 27 luglio 2023
    P lascia passare il client e ignora tutti i filtri. E' necessario rimuovere o rivedere questa opzione se già si usa il programma.
    - aggiunto il filtro G, ovvero HELO/EHLO con una sintassi non valida sono bloccati (stringhe casuali ma anche errori di digitazione come sagredo..eu). Compilare con -lpcre
    - ampia revisione del codice. Per favore riportare ogni problema nei commenti.

La Sezione 3.5 del documento RFC-821 afferma che

The sender-SMTP MUST ensure that the <domain> parameter in a HELO command is a valid principal host domain name for the client host. As a result, the receiver-SMTP will not have to perform MX resolution on this name in order to validate the HELO parameter.

The HELO receiver MAY verify that the HELO parameter really corresponds to the IP address of the sender. However, the receiver MUST NOT refuse to accept a message, even if the sender's HELO command fails verification.

Ammettere i client con un record DNS bacato nel proprio HELO/EHLO può essere sensato non solo perché suggerito dalla RFC di cui sopra, ma anche una cosa conveniente per l'amministratore, che non dovrà perdere il suo tempo ad aggiungere continuamente record alla whitelist per colpa dei client regolari che non hanno settato bene il proprio record DNS.

Ma d'altra parte, è un dato di fatto che praticamente tutti gli spammers utilizzino nel loro HELO domini che non appartengono loro -spesso addirittura uno dei nostri stessi domini (cosa ovviamente intollerabile)-, oppure delle stringhe random o domini che non sono riconducibili ad alcun IP.

Per esempio, consideriamo le seguenti righe del mio log (ne ho sempre moltissime):

2022-02-01 10:19:53.142643500 helo-dns-check: HELO [yq3H9cDKgS] from [109.237.103.41] doesn't solve
2022-02-01 09:53:05.772497500 helo-dns-check: HELO [sagredo.eu] is a local domain but IP [183.240.55.119] is not a RELAYCLIENT

Penso che, a prescindere da cosa dica l'RFC sopra menzionato, non si commetta un peccato mortale se si respingono almeno i client che riportano gli errori di cui sopra.

Spiegherò quindi qui sotto come settare un filtro che respinga i seguenti problemi a livello DNS:

  1. HELO/EHLO con una sintassi non valida. Stringhe casuali ma anche domini non validi a causa di una errata digitazione come ad esempio sagredo..eu non verranno ammessi.
  2. falsi HELO/EHLO contenenti addirittura uno dei nostri domini, riconoscibili dal fatto che il record DNS non corrisponde a uno dei nostri IP mentre la variabile RELAYCLIENT non è stata definita;
  3. HELO/EHLO contenenti un dominio non riconducibile con alcun record A. In questo caso si otterranno alcuni falsi positivi, ad esempio i client il cui amministratore ha dimenticato di creare il record A nel proprio DNS verranno bannati.
  4. client il cui A record non corrisponde all'indirizzo IP remoto. Ciò è palesemente contro la RFC-821, pertanto la mia configurazione non rifiuterà queste connessioni, che però saranno loggate.

Faremo uso di un plugin "helodnscheck" di qmail-spp che ho derivato da un vecchio lavoro di  Perolo Silantico, Jason Frisvold con modifiche di Ren Bing. Ecco il programma da me modificato:

La logica del plugin originale è di bloccare i client del tipo 3, che ovviamente includono quelli del tipo 1 2 e 3, ma senza poter all'occorrenza selezionare solo quelli di tipo 1 2 o 3, cosa che invece fa la mia versione modificata, che comunque può -se si vuole- funzionare come il programma originario.

Installazione e configurazione

Assumo qui che si abbia già patchato qmail con qmail-spp. Se si sta usando la mia patch combinata si è a posto.

Scarichiamo, compiliamo e installiamo:

cd /usr/local/src
wget https://raw.githubusercontent.com/sagredo-dev/helodnscheck/main/helodnscheck.cpp
g++ -o /var/qmail/plugins/helodnscheck helodnscheck.cpp -lpcre

Ora abilitiamo il plugin, aggiungiamolo a /var/qmail/control/smtpplugins nella sezione [helo]:

[helo] 
plugins/helodnscheck

Creiamo ora una lista con tutti i nostri IP nel file control/moreipme (probabilmente ce l'abbiamo già se abbiamo installato la patch "moreipme"):

1.2.3.4
5.6.7.8

Poi abilitiamo qmail-spp e settiamo i parametri relativi al plugin. Io suggerisco i seguenti sia nel run file di qmail-smtpd che in quello di qmail-submission:

export ENABLE_SPP=1 
export HELO_DNS_CHECK=RLNG

In questo modo solo gli HELO cattivi del tipo 1 (G) e 2 (N) saranno bloccati a meno che RELAYCLIENT non sia stato definito (R). Tutti gli altri errori nel controllo del DNS verranno loggati (L).

Si tenga presente che il controllo dell'HELO non può funzionare bene con il servizio submission, poichè l'IP remoto non potrà risolvere l'HELO usato. Di conseguenza la variabile HELO_DNS_CHECK non dovrà essere definita nel run file di qmail-submission.

Naturalmente si può sempre definire HELO_DNS_CHECK nelle tcprules o porre un particolare IP in whitelist attraverso la variabile NOHELODNSCHECK come qui mostrato:

111.222.333.444:allow, NOHELODNSCHECK=""
:allow,HELO_DNS_CHECK="RNLG"

Il comportamento del programma è definito dalla variabile HELO_DNS_CHECK:

  • L - (default) Log
  • H - aggiunge un Header "X-Helo-Check"
  • D - Modalità debug
  • R - (default) se RELAYCLIENT è impostato non viene fatto nulla
  • P - modalità lasciapassare. Usare con L e/o H.

I filtri sono eseguiti nel seguente ordine:

  • G - (Garbage, default) HELO/EHLO con una sintassi non valida sono bloccati.
  • A - i domini in HELO/HELO che non possono essere risolti sono bloccati. Si tratta di hostname che non corrispondono ad alcun record A registrato. Usare G insieme ad A è ridondante (è sufficiente usare A).
  • I - Come A per compatibilità con le versioni precedenti. Obsoleto e sarà rimosso.
  • N - (Not me, default) blocca se l'IP remoto non è un RELAYCLIENT NON è impostato e se l'hostname in HELO/EHLO  viene risolto verso uno degli nostri IP contenuti in control/moreipme. Anche localhost sarà bloccato. Usare N insieme ad A è ridondante (usare semplicemente A).
  • V - Come N per compatibilità con le versioni precedenti. Obsoleto e sarà rimosso.
  • B - Blocca se l'IP remoto (TCPREMOTEIP) non è contenuto in uno degli indirizzi risolti. E' la modalità originale di funzionamento. Usare G e/o A e/o N insieme a B è ridondante  (usare semplicemente B).

I precedenti possono essere combinati, ovvero BL significa blocca & logga.

Se P è definito, allora tutti i filtri G, A, B e N vengono ignorati.

Nota: l'opzione di default è GNLR, usata se HELO_DNS_CHECK è vuoto, ovvero HELO_DNS_CHECK="".

Test

 E' possibile testare il buon fnzionamentodel programma in questo modo:

HELO_DNS_CHECK="BLRD" \
SMTPHELOHOST="test.tld" \
TCPREMOTEIP="111.222.333.444" \
./helodnscheck

helo-dns-check: dbg: action is BLRD 
helo-dns-check: dbg: no_helo_check is (null) 
helo-dns-check: dbg: helo_domain is test.tld 
helo-dns-check: dbg: remote_ip is 111.222.333.444 
helo-dns-check: dbg: G filter 'nomatch': [2] 
helo-dns-check: dbg: no result in A record 
helo-dns-check: HELO [test.tld] from [111.222.333.444] doesn't solve 
R553 sorry, invalid host name in HELO/EHLO command. (#5.7.1) 
helo-dns-check: blocked with: invalid host name in HELO/EHLO command. [111.222.333.444]

Esempi

Utilizzo con le tcprules

111.222.333.444:allow, NOHELODNSCHECK="" // lascia passare IP 
:allow,HELO_DNS_CHECK="LB" // blocca & logga gli altri

Utilizzo nel file run di qmail-smtpd

export HELO_DNS_CHECK=""     // default (GNLR)
export HELO_DNS_CHECK        // HELO_DNS_CHECK non attivo
#export HELO_DNS_CHECK       // HELO_DNS_CHECK non attivo
export HELO_DNS_CHECK=RLGN   // consenti i RELAYCLIENT, logga, blocca HELO con sintassi errata, blocca i client con i miei domini nell'HELO/EHLOs (scelta sicura)

Aggiungi un commento

Ultimi commenti
Vedi anche...
Articoli recenti

RSS feeds