Backup della connessione Internet per un processo specifico
Vorrei aggiungere una connessione Internet di backup secondaria al mio server Linux. Ho intenzione di utilizzare un modem USB LTE per questo scopo.
Poiché questa connessione cellulare verrà misurata, voglio limitare la quantità di dati che possono essere consumati al minimo indispensabile.
Ho un'applicazione server personalizzata a cui posso apportare modifiche. Ha alcune attività in cui la connettività ininterrotta è fondamentale e altre attività in cui i tempi di inattività non contano davvero.
Sto immaginando qualcosa del genere:
- Il server deve effettuare una richiesta API HTTP esterna. Il primo tentativo viene effettuato sulla route predefinita del sistema (es. Eth0, la connessione Internet primaria).
- Se la richiesta non riesce o va in timeout, riprovare a eseguire la richiesta tramite l'interfaccia LTE.
Solo il traffico che il processo del mio server vuole esplicitamente inviare tramite LTE deve essere inviato tramite LTE. Nessun altro traffico proveniente da nessuna parte del sistema deve passare su LTE.
- In particolare, userò l' localAddressopzione socket del nodo per specificare che la richiesta deve essere effettuata su LTE.
- Come posso assicurarmi che altro traffico non finisca per essere instradato sull'interfaccia LTE (anche se eth0 non è attivo)?
- E la risoluzione DNS?
Risposte
Ho finito per ottenere questo risultato configurando una tabella di route alternativa e una regola dei criteri di routing per l'indirizzo di origine dell'interfaccia di backup.
Il modem USB LTE che ho si presenta come un dispositivo NDIS, quindi si presenta semplicemente come eth1
con un IP di 192.168.0.190 e fa internamente il routing NAT. Ho configurato eth1
con un IP statico e percorsi configurati manualmente.
La configurazione predefinita utilizza DHCP, quindi chiudere l'interfaccia e assicurarsi che tutti i percorsi aggiunti automaticamente vengano eliminati.
Aggiungi una configurazione IP statica per l'interfaccia e aprila.
Aggiungi voci a una tabella di routing alternativa (che ho scelto
1
) per la sottorete e il gateway predefinito.# ip route add 192.168.0.0/24 dev eth1 src 192.168.1.190 table 1 # ip route add default via 192.168.0.1 table 1
Imposta le regole dei criteri di routing in modo che le app che utilizzano esplicitamente 192.168.1.190 come indirizzo di origine utilizzino la tabella di routing 1 invece del valore predefinito.
# ip rule add from 192.168.0.190/32 table 1 # ip rule add to 192.168.0.190/32 table 1
A questo punto dovresti essere in grado di testare la tua connettività.
$ curl https://wtfismyip.com/text 1.2.3.4 # primary ISP external IP $ curl --interface 192.168.0.190 https://wtfismyip.com/text
5.6.7.8 # backup LTE external IP
Se tutto sembra a posto, rendi la configurazione permanente. Ho aggiunto a /etc/network/interfaces
:
iface eth1 inet static
address 192.168.0.190
netmask 255.255.255.0
post-up ip route add 192.168.0.0/24 dev eth1 src 192.168.0.190 table 1
post-up ip route add default via 192.168.0.1 table 1
post-up ip rule add from 192.168.0.190/32 table 1
post-up ip rule add to 192.168.0.190/32 table 1
Ora solo le app che si legano esplicitamente a 192.168.0.190 quando si effettuano connessioni in uscita verranno instradate sulla connessione di backup. Tutto il resto del traffico viene instradato eth0
(o qualsiasi cosa sia configurata nella main
tabella di instradamento [predefinita]).
È possibile che tu abbia qualcosa che enumeri tutti gli IP disponibili e tenti di inviare traffico da loro, il che potrebbe causare un traffico imprevisto sulla connessione di backup, ma è improbabile. Non ho osservato tale traffico.
Notare che questo non riguarda la risoluzione DNS. In una situazione in cui la connessione principale è offline, potresti essere fortunato e avere una ricerca dalla cache, ma non è bene fare affidamento. Non configurerei nemmeno il resolver a livello di sistema per inviare richieste tramite l'interfaccia LTE. La tua app potrebbe invece gestire manualmente la risoluzione DNS durante le richieste di backup.
Con node, è facile effettuare richieste HTTP (o qualsiasi connessione TCP) da uno specifico indirizzo sorgente. Specificare semplicemente l' localAddressopzione , ad esempio:
https.get('https://wtfismyip.com/text', { localAddress: '192.168.0.190' }, …);
Risolvere la ricerca DNS è leggermente più complicato. È lookup
disponibile anche un'opzione che consente di ignorare il processo di risoluzione DNS predefinito. È possibile utilizzare una personalizzazione dns.Resolverper effettuare ricerche. Sfortunatamente, il nodo non aveva un modo per specificare l'indirizzo di origine per le ricerche DNS, quindi l'ho aggiunto . Con quello a posto, puoi mettere insieme i pezzi:
const resolver = new dns.Resolver();
resolver.setServers(['8.8.8.8']);
resolver.setLocalAddress('192.168.0.190'); // requires node > v15.0.0
https.get('https://wtfismyip.com/text', {
localAddress: '192.168.0.190',
lookup: function(hostname, opts, cb) {
resolver.resolve(hostname, function(err, records) {
if (err) cb(err);
else if (!records[0]) cb(new Error('Missing DNS record'));
else cb(null, records[0], 4);
});
}
}, function(res) { … });