Cadangkan koneksi internet untuk proses tertentu

Aug 17 2020

Saya ingin menambahkan koneksi internet cadangan sekunder ke server Linux saya. Saya berencana menggunakan modem USB LTE untuk tujuan ini.

Karena koneksi seluler ini akan diukur, saya ingin membatasi jumlah data yang dapat dikonsumsi seminimal mungkin.

Saya memiliki aplikasi server khusus yang dapat saya ubah. Ini memiliki beberapa tugas di mana konektivitas tanpa gangguan sangat penting, dan tugas lain di mana waktu henti tidak terlalu penting.

Saya membayangkan sesuatu seperti ini:

  • Server perlu membuat permintaan API HTTP eksternal. Upaya pertama dilakukan melalui rute default sistem (yaitu eth0, koneksi internet utama).
  • Jika permintaan gagal atau waktu habis, coba lagi permintaan melalui antarmuka LTE.

Hanya lalu lintas yang secara eksplisit ingin dikirim oleh proses server saya melalui LTE yang harus dikirim melalui LTE. Tidak boleh ada lalu lintas lain dari bagian sistem mana pun yang melewati LTE.

  • Secara khusus, saya akan menggunakan opsi soket node localAddressuntuk menentukan bahwa permintaan harus dilakukan melalui LTE.
  • Bagaimana saya memastikan bahwa lalu lintas lain tidak berakhir dengan perutean melalui antarmuka LTE (bahkan jika eth0 tidak aktif)?
  • Bagaimana dengan resolusi DNS?

Jawaban

josh3736 Sep 01 2020 at 03:53

Saya akhirnya mencapai ini dengan mengonfigurasi tabel rute alternatif dan aturan kebijakan perutean untuk alamat sumber antarmuka cadangan.

Modem USB LTE yang saya berikan sebagai perangkat NDIS, jadi ini hanya muncul eth1dengan IP 192.168.0.190 dan melakukan perutean NAT secara internal. Saya telah mengonfigurasi eth1dengan IP statis dan rute yang dikonfigurasi secara manual.

  1. Konfigurasi default menggunakan DHCP, jadi turunkan antarmuka dan pastikan semua rute yang ditambahkan secara otomatis dihapus.

  2. Tambahkan konfigurasi IP statis untuk antarmuka dan tampilkan.

  3. Tambahkan entri ke tabel perutean alternatif (saya telah memilih 1) untuk subnet dan gateway default.

    # 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. Tetapkan aturan kebijakan perutean agar aplikasi yang secara eksplisit menggunakan 192.168.1.190 sebagai alamat sumbernya akan menggunakan tabel perutean 1, bukan default.

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

Pada titik ini, Anda harus dapat menguji konektivitas Anda.

$ 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

Jika semuanya terlihat bagus, buat konfigurasi permanen. saya menambahkan ke /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

Sekarang hanya aplikasi yang secara eksplisit mengikat ke 192.168.0.190 saat membuat koneksi keluar yang akan dirutekan melalui koneksi cadangan. Semua lalu lintas lainnya dialihkan eth0(atau apa pun yang dikonfigurasi di maintabel perutean [default]).

Ada kemungkinan bahwa Anda memiliki sesuatu yang menyebutkan semua IP yang tersedia dan mencoba mengirimkan lalu lintas darinya, yang dapat mengakibatkan lalu lintas yang tidak terduga melalui koneksi cadangan, tetapi kemungkinannya kecil. Saya tidak mengamati lalu lintas seperti itu.

Perhatikan bahwa ini tidak membahas resolusi DNS. Dalam situasi di mana koneksi utama sedang offline, Anda mungkin beruntung dan mendapatkan pencarian dari cache, tetapi itu tidak baik untuk diandalkan. Saya juga tidak akan mengonfigurasi penyelesai di seluruh sistem untuk mengirim permintaan melalui antarmuka LTE. Sebagai gantinya, aplikasi Anda dapat menangani resolusi DNS secara manual saat membuat permintaan pencadangan.


Dengan node, membuat permintaan HTTP (atau koneksi TCP apa pun) dari alamat sumber tertentu menjadi mudah. Cukup tentukan localAddresspilihannya , misal:

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

Memecahkan pencarian DNS sedikit lebih rumit. Opsi lookupjuga tersedia, yang memungkinkan Anda mengesampingkan proses resolusi DNS default. Anda dapat menggunakan kebiasaan dns.Resolveruntuk melakukan pencarian. Sayangnya, node tidak memiliki cara untuk menentukan alamat sumber untuk pencarian DNS, jadi saya menambahkannya . Dengan itu, Anda dapat menyatukan potongan-potongan itu:

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