> ## Content Index
> Fetch the complete content index at: https://blog.firenetwork.it/llms.txt
> Use this file to discover other available public pages before exploring further.

# NGINX - Creare un Load Balancer per server DNS
- URL: https://blog.firenetwork.it/nginx-creare-un-load-balancer-per-server-dns-2/
- Published: 2025-06-05T22:20:10.000Z
- Updated: 2025-06-19T20:31:39.000Z
- Description: NGINX è -tra le altre cose- un ottimo load Balancer. In questa guida vedremo come usarlo per mettere più server DNS in Load Balancing.
- Author: Samuele Gabbrielli
- Tags: Guide, NGINX, DNS, #Import 2026-03-12 20:23

## Introduzione

[NGINX](https://nginx.org/?ref=blog.firenetwork.it) (pronunciato Engine-X) è

> "un HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, e mail proxy server"

utilizzato dalla maggioranza degli HomeLabber.  
Permette di fare Reverse Proxy con poche righe di configurazione ed offre prestazioni spaventose con un minimo di risorse a disposizione.

In questa guida vedremo come usarlo per mettere più server DNS in Load Balancing. Nello specifico, gli faremo gestire due server [AdGuard Home](https://adguard.com/it/adguard-home/overview.html?ref=blog.firenetwork.it) per avere un DNS bilanciato, che gestisca il fault di uno dei server, e soprattutto per non avere più quella fastidiosissima pubblicità **in tutta la rete di casa**.

## Prerequisiti

Prima di seguire i passaggi indicati di seguito, è necessario avere **almeno un nodo con NGINX installato**, ed almeno **due server DNS**. Poco importa di quale server DNS si tratti, **la configurazione è universale**.

Dettaglio molto importante: per ovvi motivi (due software non posso usare la stessa porta in ascolto) **non potete effettuare questa configurazione se sulla macchina dove risiede NGINX avete anche un DNS Server**.

❗

[NGINX](https://nginx.org/?ref=blog.firenetwork.it) è compatibile con la maggior parte dei sistemi operativi Linux, ma in questa guida userò i comandi che ho usato su Ubuntu Server 24.04

## Installazione delle dipendenze

Il modulo di NGINX che ci permette di gestire questo tipo di load balancing è il modulo **stream**, che non è fornito di default nelle nuove installazioni di NGINX.

Installarlo è semplice, infatti è disponibile su apt:

```
sudo apt install -y libnginx-mod-stream
```

Controllare che sia stato creato il file *50-mod-stream.conf*

```
nano /etc/nginx/modules-available/50-mod-stream.conf
```

❗

L'editor di testo potrebbe mostrare un file vuoto, ma ****non dovrebbe segnalare che il file non sia esistente**. In tal caso controllare di aver effettivamente installato il modulo.

Se il file è vuoto, compilarlo con la seguente direttiva per indicare ad NGINX come caricare il modulo stream:

```
load_module modules/ngx_stream_module.so;
```

Ricaricare NGINX per fargli caricare il modulo appena installato

```
systemctl reload nginx
```

## Configurazione su NGINX

Una volta caricato il modulo stream, è necessario configurarlo. La configurazione può essere fatta direttamente sul file /etc/nginx/nginx.conf , anche se usare il meccanismo degli include e dei symlink sarebbe la *best practice*. In questo esempio inseriamo la configurazione direttamente in nginx.conf

```
nano /etc/nginx/nginx.conf
```

### La sezione *stream*

Prima di tutto, va creata la sezione stream, nel primo livello del file di configurazione. Consiglio di crearla sopra alla sezione http (mi raccomando, **non al suo interno**)

```
stream {

}
```

Dentro alla sezione *stream*, creiamo una sezione *upstream* dove andiamo ad elencare una lista di **server DNS**. Questa lista deve avere un nome (a cui faremo riferimento successivamente, nella sezione *server*)

```
stream {
  upstream dns_servers {
    server 192.168.0.27:53;
    server 192.168.0.28:53;
    server 192.168.0.1:53;
  }
}
```

In questa configurazione, la lista contiene tre server DNS che NGINX tratterà in modo equo. Per esempio, in **round robin**, a turno verrà interrogato ciascuno dei tre server indicati.

Nel mio caso, 192.168.0.1 è il mio Gateway, che però non è un DNS AdGuard. Voglio che venga utilizzato solamente se gli altri server DNS vanno offline.  
Per fare questo, lo indico come server di Backup.

```
stream {
  upstream dns_servers {
    server 192.168.0.27:53;
    server 192.168.0.28:53;
    server 192.168.0.1:53 backup;
  }
}
```

Infine, per indicare con quale criterio decidere quando un server DNS non va più usato perchè offline, uso i seguenti parametri:

- **max\_fails** per indicare quante richieste senza risposta mi servono per giudicarlo offline.
- **fail\_timeout** per indicare dopo quanto tempo decretare che una richiesta non ha ricevuto risposta.

```
stream {
  upstream dns_servers {
    server 192.168.0.27:53 max_fails=3 fail_timeout=5s;
    server 192.168.0.28:53 max_fails=3 fail_timeout=5s;
    server 192.168.0.1:53 backup;
  }
}
```

In questo modo, se per tre volte di fila un server DNS non risponde entro 5 secondi, viene contato come offline.

Se entrambi i server DNS AdGuard sono offline, viene utilizzato il Gateway (che non bloccherà certo le pubblicità, ma è meglio di niente!)

### Altre modalità di load balancing

La configurazione mostrata sopra utilizzerà un algoritmo **round robin** per smistare le richieste, cioè **utilizzerà a turno ciascuno dei server**. Altre modalità possibili con NGINX sono:

- **least connections**, cioè la richiesta verrà passata al server DNS che al momento **sta gestendo meno connessioni** (ma nel caso di un server DNS, spesso entrambi saranno molto scarichi)

```
stream {
  upstream dns_servers {
    least_conn;
    server 192.168.0.27:53 max_fails=3 fail_timeout=5s;
    server 192.168.0.28:53 max_fails=3 fail_timeout=5s;
    server 192.168.0.1:53 backup;
  }
}
```

- **max connections**, cioè l'algoritmo Round Robin, ma escludendo temporaneamente uno dei server quando raggiunge il **numero massimo di connessioni** indicato (in questo esempio, 3 per il primo e 5 per il secondo)

```
stream {
  upstream dns_servers {
    server 192.168.0.27:53 max_fails=3 fail_timeout=5s max_conns=3;
    server 192.168.0.28:53 max_fails=3 fail_timeout=5s max_conns=5;
    server 192.168.0.1:53 backup;
  }
}
```

- **weighted**, cioè bilanciando in maniera *pesata* le richieste. Nell'esempio sotto, se devono essere gestite 300 richieste, 200 verranno mandate al primo, 100 al secondo. Questo parametro è molto utile se i vostri DNS **non hanno le stesse risorse a disposizione**.

```
stream {
  upstream dns_servers {
    server 192.168.0.27:53 max_fails=3 fail_timeout=5s weight=2;
    server 192.168.0.28:53 max_fails=3 fail_timeout=5s weight=1;
    server 192.168.0.1:53 backup;
  }
}
```

- **IP Hashing** (o più comunemente chiamata **connessione persistente**) che ha molto poco senso per i DNS, ma utile negli scenari in cui serve che lo stesso client venga gestito **sempre dallo stesso server**.  
Ovviamente, se il server a cui è stato associato uno specifico client diventa offline, le richieste vengono inoltrate ad uno dei restanti.

```
stream {
  upstream dns_servers {
    ip_hash;
    server 192.168.0.27:53 max_fails=3 fail_timeout=5s;
    server 192.168.0.28:53 max_fails=3 fail_timeout=5s;
    server 192.168.0.1:53 backup;
  }
}
```

### La sezione *server*

Infine, ci serve una sezione *server* per dire ad NGINX che cosa deve fare, su quali porte, e dove loggare eventuali errori.

```
stream {
  upstream dns_servers {
    server 192.168.0.27:53 max_fails=3 fail_timeout=5s;
    server 192.168.0.28:53 max_fails=3 fail_timeout=5s;
    server 192.168.0.1:53 backup;
  }

  server {
    listen 53 udp;
    listen 53;

    proxy_responses 1;
    proxy_pass dns_servers;
    error_log /var/log/nginx/dns.log error;
  }
}
```

Analizziamo la sezione *server* riga per riga:

- **listen 53 udp** dice ad NGINX di rimanere in ascolto sulla porta 53 UDP, dove arriveranno la maggior parte delle richieste DNS.
- **listen 53** dice ad NGINX di rimanere in ascolto sulla 53 anche in TCP, dove in casi limite possono arrivare alcune richieste DNS.
- **proxy\_responses** impostato ad 1 fa sì che NGINX chiuda il socket quando riceve una risposta dal server DNS. Sappiamo per certo che in una richiesta DNS questo è il limite di risposte, ed in questo modo liberiamo subito il processo che è stato aperto al momento della richiesta del client.  
**Questo parametro non è strettamente necessario**, ma ho notato che migliora notevolmente le performance.
- **proxy\_pass dns\_servers** indica ad NGINX di far riferimento, per i server a cui inoltrare la richiesta, a quelli che abbiamo indicato in *dns\_servers*, con le regole che abbiamo indicato.
- infine, **error\_log /var/log/nginx/dns.log error** fa sì che NGINX scriva i log di errore relativi a questa regola in un file dns.log . **Anche questo parametro non è strettamente necessario**, ma se ci dovesse essere bisogno di fare troubleshooting, sarà sicuramente meglio avere un file dedicato alle richieste DNS (e lo dico per esperienza).

Adesso non rimane che far caricare ad NGINX le ultime modifiche al file di configurazione, e goderci lo spettacolo.

```
systemctl reload nginx
```

Controllate subito dopo che il servizio si sia ricaricato senza errori

```
systemctl status nginx
```

❗

Se un simpatico messaggio relativo alla porta 53 già in uso da un altro processo vi accoglie, si tratta di quel mascalzone di ****systemd-resolved** che se l'è presa tutta per sè. Dando per scontato che non abbiate installato un server DNS sulla stessa macchina dove avete installato NGINX, questo binding non ci serve e potete disattivarlo seguenti [questi passaggi](https://blog.firenetwork.it/errore-port-53-already-in-use/).

## Conclusioni

Ora che avete messo in load balancing i vostri DNS, potrete finalmente dormire sonni tranquilli. La maggior parte dei problemi di rete è imputabile a problemi con la risoluzione dei nomi, e ridondando questo servizio vi siete risparmiati un sacco di problemi.

Se avete messo in load balancing delle istanze di AdGuard, perchè adesso non le monitorate tramite [Telegraf](https://blog.firenetwork.it/telegraf-installazione/), [Prometheus](https://blog.firenetwork.it/installazione-di-prometheus/) e Grafana?

---

![](https://blog.firenetwork.it/content/images/2025/06/Written-By-Human-Not-By-AI-Badge-white@2x-4.png)