Gostaria de adicionar uma conexão secundária de backup à Internet ao meu servidor Linux. Pretendo usar um modem USB LTE para essa finalidade.
Como esta conexão celular será medida, quero limitar a quantidade de dados que podem ser consumidos ao mínimo necessário.
Eu tenho um aplicativo de servidor personalizado no qual posso fazer alterações. Possui algumas tarefas onde a conectividade ininterrupta é crítica e outras tarefas onde o tempo de inatividade realmente não importa.
Estou imaginando algo assim:
- O servidor precisa fazer uma solicitação de API HTTP externa. A primeira tentativa é feita pela rota padrão do sistema (ou seja, eth0, a conexão primária com a Internet).
- Se a solicitação falhar ou expirar, tente novamente pela interface LTE.
Somente o tráfego que meu processo de servidor deseja enviar explicitamente por LTE deve ser enviado por LTE. Nenhum outro tráfego de qualquer parte do sistema deve passar por LTE.
- Especificamente, usarei node's
localAddress
opção de soquete para especificar que a solicitação deve ser feita por LTE. - Como posso garantir que outro tráfego não acabe sendo roteado pela interface LTE (mesmo que a eth0 esteja inativa)?
- E quanto à resolução DNS?
Responder1
Acabei conseguindo isso configurando umtabela de rotas alternativase umregra de política de roteamentopara o endereço de origem da interface de backup.
O modem USB LTE que tenho apresenta-se como um dispositivo NDIS, então ele simplesmente aparece eth1
com um IP de 192.168.0.190 e faz roteamento NAT internamente. Configurei eth1
com um IP estático e configurei rotas manualmente.
A configuração padrão usa DHCP, portanto, desative a interface e certifique-se de que todas as rotas adicionadas automaticamente sejam excluídas.
Adicione uma configuração de IP estático para a interface e abra-a.
Adicione entradas a uma tabela de roteamento alternativa (eu escolhi
1
) para a sub-rede e o gateway padrão.# 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
Defina regras de política de roteamento para que os aplicativos que usam explicitamente 192.168.1.190 como endereço de origem usem a tabela de roteamento 1 em vez do padrão.
# ip rule add from 192.168.0.190/32 table 1 # ip rule add to 192.168.0.190/32 table 1
Neste ponto, você poderá testar sua conectividade.
$ 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 tudo parecer bem, torne a configuração permanente. Eu adicionei 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
Agora, apenas os aplicativos que se vinculam explicitamente a 192.168.0.190 ao fazer conexões de saída serão roteados pela conexão de backup. Todo o outro tráfego é roteado eth0
(ou o que estiver configurado na main
tabela de roteamento [padrão]).
Isso épossívelque você tem algo que enumera todos os IPs disponíveis e tenta enviar tráfego deles, o que pode resultar em tráfego inesperado na conexão de backup, mas isso é improvável. Não observei esse tipo de tráfego.
Observe que isso não aborda a resolução de DNS. Em uma situação em que a conexão principal está offline, você pode ter sorte e conseguir uma pesquisa no cache, mas não é bom confiar nisso. Eu também não configuraria o resolvedor de todo o sistema para enviar solicitações pela interface LTE. Em vez disso, seu aplicativo poderia lidar manualmente com a resolução de DNS ao fazer solicitações de backup.
Com o node, é fácil fazer solicitações HTTP (ou qualquer conexão TCP) a partir de um endereço de origem específico. Basta especificar olocalAddress
opção, por exemplo:
https.get('https://wtfismyip.com/text', { localAddress: '192.168.0.190' }, …);
Resolver a pesquisa de DNS é um pouco mais complicado. Também está disponível uma lookup
opção que permite substituir o processo de resolução de DNS padrão. Você pode usar um personalizadodns.Resolver
para fazer pesquisas. Infelizmente, o nó não tinha como especificar o endereço de origem para pesquisas de DNS,então eu adicionei. Com isso pronto, você pode juntar as peças:
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) { … });