Connexion Internet de sauvegarde pour un processus spécifique

Aug 17 2020

Je voudrais ajouter une connexion Internet de secours secondaire à mon serveur Linux. Je prévois d'utiliser un modem USB LTE à cet effet.

Étant donné que cette connexion cellulaire sera mesurée, je souhaite limiter la quantité de données pouvant être consommées au minimum absolu nécessaire.

J'ai une application serveur personnalisée sur laquelle je peux apporter des modifications. Il comporte quelques tâches pour lesquelles une connectivité ininterrompue est essentielle et d'autres tâches pour lesquelles les temps d'arrêt n'ont pas vraiment d'importance.

J'imagine quelque chose comme ça:

  • Le serveur doit effectuer une requête d'API HTTP externe. La première tentative est effectuée sur la route par défaut du système (c'est-à-dire eth0, la connexion Internet principale).
  • Si la demande échoue ou expire, réessayez la demande via l'interface LTE.

Seul le trafic que mon processus serveur souhaite explicitement envoyer via LTE doit être envoyé via LTE. Aucun autre trafic provenant d'aucune partie du système ne doit passer par LTE.

  • Plus précisément, j'utiliserai l' localAddressoption socket du nœud pour spécifier que la demande doit être effectuée via LTE.
  • Comment puis-je m'assurer que tout autre trafic ne finit pas par être acheminé via l'interface LTE (même si eth0 est en panne)?
  • Qu'en est-il de la résolution DNS?

Réponses

josh3736 Sep 01 2020 at 03:53

J'ai fini par y parvenir en configurant une table de routage alternative et une règle de politique de routage pour l'adresse source de l'interface de sauvegarde.

Le modem USB LTE que j'ai se présente comme un périphérique NDIS, il apparaît donc simplement comme eth1avec une IP de 192.168.0.190 et il effectue le routage NAT en interne. J'ai configuré eth1avec une adresse IP statique et des routes configurées manuellement.

  1. La configuration par défaut utilise DHCP, alors désactivez l'interface et assurez-vous que toutes les routes ajoutées automatiquement sont supprimées.

  2. Ajoutez une configuration IP statique pour l'interface et faites-la apparaître.

  3. Ajoutez des entrées à une table de routage alternative (que j'ai choisie 1) pour le sous-réseau et la passerelle par défaut.

    # 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
    
  4. Définissez des règles de stratégie de routage afin que les applications qui utilisent explicitement 192.168.1.190 comme adresse source utilisent la table de routage 1 au lieu de la table par défaut.

    # ip rule add from 192.168.0.190/32 table 1
    # ip rule add to 192.168.0.190/32 table 1
    

À ce stade, vous devriez pouvoir tester votre connectivité.

$ 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

Si tout semble bon, rendez la configuration permanente. J'ai ajouté à /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

Désormais, seules les applications qui se lient explicitement à 192.168.0.190 lors de l'établissement de connexions sortantes seront acheminées via la connexion de sauvegarde. Tout le reste du trafic est acheminé eth0(ou ce qui est configuré dans la maintable de routage [par défaut]).

Il est possible que vous ayez quelque chose qui énumère toutes les adresses IP disponibles et tente d'envoyer du trafic à partir d'elles, ce qui pourrait entraîner un trafic inattendu sur la connexion de sauvegarde, mais c'est peu probable. Je n'ai observé aucun trafic de ce type.

Notez que cela ne concerne pas la résolution DNS. Dans une situation où la connexion principale est hors ligne, vous pouvez avoir de la chance et avoir une recherche dans le cache, mais il n'est pas bon de s'y fier. Je ne configurerais pas non plus le résolveur à l'échelle du système pour envoyer des demandes via l'interface LTE. Au lieu de cela, votre application peut gérer manuellement la résolution DNS lors des demandes de sauvegarde.


Avec node, il est facile de faire des requêtes HTTP (ou toute connexion TCP) à partir d'une adresse source spécifique. Spécifiez simplement l' localAddressoption , par exemple:

https.get('https://wtfismyip.com/text', { localAddress: '192.168.0.190' }, …);

La résolution de la recherche DNS est légèrement plus délicate. Une lookupoption est également disponible, qui vous permet de remplacer le processus de résolution DNS par défaut. Vous pouvez utiliser une personnalisation dns.Resolverpour effectuer des recherches. Malheureusement, le nœud n'avait pas de moyen de spécifier l'adresse source pour les recherches DNS, je l'ai donc ajouté . Avec cela en place, vous pouvez assembler les pièces:

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) { … });