Em um projeto recente precisei fazer o balanceamento de links no linux, o cliente possuía saída por dois provedores, sendo o primeiro NET/Virtua e o segundo Embratel, seu link Embratel estava ocioso e ele queria acabar com essa ociosidade.
A solução foi usar o iproute2 para criar uma tabela com balanceamento de links para alguns pacotes, em conjunto usei o iptables para marcar os pacotes que deveriam sair por essa tabela.
Além disto o cliente usava o Embratel para alguns serviços, logo existia um redirecionamento DNAT para rede interna e isso precisava ser levado em conta.
Vamos a solução para essa necessidade.
Ambiente
Vamos descrever as configurações de rede do ambiente
Interface eth0 está com rede interna (10.1.x.x/xx)
Interface eth1 está conectado ao modem virtua (189.x.x.x)
Interface eth2 está conectado ao modem embratel (200.x.x.x)
Se isto está entendido, vamos continuar.
Procedimento manual
1. Criando tabelas no rt_tables
Primeiro edite o arquivo
vim /etc/iproute2/rt_tables
E adicione as seguintes tabelas ao final do arquivo
20 VIRTUA
30 EMBRATEL
40 BALANCEAMENTO
Ótimo, isso é suficiente, elas precisam existir para que possamos criar regras em cada uma destas tabelas.
2. Criando regras no iproute2
2.1 configurando tabela virtua
Antes de começar, vou colocar nomes ao invés de endereços IPs para facilitar o entendimento, veja o que significa cada coisa.
VIRTUA_NET é o endereço de rede
VIRTUA_NIC é a placa de rede (eth1)
VIRTUA_GAT é o endereço do GW virtua
VIRTUA_IPA é o ip da VIRTUA_NIC
Vamos a configuração básica da tabela virtua
ip route add VIRTUA_NET dev VIRTUA_NIC src VIRTUA_IPA table VIRTUA
Agora vamos especificar quem é o defautl gateway da virtua
ip route add default via VIRTUA_GAT table VIRTUA
2.2 configurando tabela embratel
Novamente eu vou colocar nomes ao invés de endereços IPs para facilitar o entendimento, veja o que significa cada coisa.
EMBRATEL_NET é o endereço de rede
EMBRATEL_NIC é a placa de rede (eth1)
EMBRATEL_GAT é o endereço do GW
EMBRATEL_IPA é o ip da EMBRATEL_NIC
Agora vamos configurar a tabela EMBRATEL
ip route add EMBRATEL_NET dev EMBRATEL_NIC src EMBRATEL_IPA table EMBRATEL
Defina o gateway padrão da tabela EMBRATEL
ip route add default via EMBRATEL_GAT table EMBRATEL
2.3 configurando tabela balanceamento
Agora vamos criar a tabela que fará o balanceamento entre os dois links
ip route add default scope global table BALANCEAMENTO nexthop via VIRTUA_GAT dev VIRTUA_NIC weight 2 nexthop via EMBRATEL_GAT dev EMBRATEL_NIC weight 1
Pronto, configuramos a tabela BALANCEAMENTO.
Veja que o peso do VIRTUA é maior que o EMBRATEL, fiz isso pois o link VIRTUA é mais parrudo e por isso seu peso no balanceamento será maior (analogia: 2 conexões vão para o virtua e 1 para a Embratel).
2.4 Definido regras de roteamento
Definindo que pacotes vindos do IP do VIRTUAL usarão a tabela VIRTUA
ip rule add from VIRTUA_IPA table VIRTUA
Definindo que pacotes vindos do IP da EMBRATEL usarão a tabela embratel
ip rule add from EMBRATEL_IPA table EMBRATEL
Definindo que pacotes com a marca 2 usarão a tabela de balanceamento
ip rule add fwmark 2 table BALANCEAMENTO
Definindo que pacotes coma marca 1 usarão a tabela Embratel
ip rule add fwmark 1 table EMBRATEL
Essa última regra estou criando pois existe um redirect para para rede interna, e portanto preciso tratar a ida e a volta para que não saia pelo balanceamento, e sim pela interface de origem do redirect que é a EMBRATEL.
2.5 Configurando rota padrao
Preciso configurar qual será a rota padrão
ip route add default via EMBRATEL_GAT
É possível fazer o balanceamento usando a tabela default, no final darei um exemplo disto.
2.6 Limpando cache de tabelas
Necessário para fazer a limpeza de informação que não é útil, como por exemplo tabelas que foram deletadas.
ip route flush cache
3. Criando regras no netfilter/iptables
3.1 Regras de redirecionamento
Primeiro redireciono para rede interna
iptables -t nat -A PREROUTING -i eth2 -d 200.252.xx.xxx -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.1.0.xxx:80
Depois marco o pacote de retorno para ele usar a tabela embratel.
iptables -t mangle -A PREROUTING -i eth0 -s 10.1.xx.xx -p tcp --sport 22 -j MARK --set-mark 1
3.2 Regras para balanceamento
Aqui eu marco os pacotes que desejo que usem a tabela de balanceamento.
iptables -t mangle -A PREROUTING -s 10.1.x.x/24 -d 0/0 -j MARK --set-mark 2
3.3 Mascarando pacotes
Aqui vamos mascarar os pacotes da rede interna, necessário para que as máquinas consigam sair para internet e para o redirect.
iptables -t nat -A POSTROUTING -s 10.1.x.x/24 -j MASQUERADE
3.4 Ativando ip forward
Precisamos ativar o encaminhamento de pacotes para que tudo funcione.
echo 1 > /proc/sys/net/ipv4/ip_forward
Pronto, balanceamento feito, você pode usar o comando IPTRAF no servidor para avaliar se os dois links estão sendo utilizados.
Nas estações recomendo que use o mtr-tiny para ver por onde seus pacotes estão saindo.
mtr terra.com.br
Se preferir use o traceroute
traceroute uol.com.br
Automatizado
Não dá para executar todas as regras toda a vez que a máquina inciar, seria cansativo e poderíamos esquecer algo, logo criei um script para me ajudar com isto.
4. Script de roteamento
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
|
5. Script de firewall
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
|
6. Colocando scripts para rodar durante a inicialização
Você pode simplesmente chamar os scripts no arquivo /etc/rc.local, vamos supor que os scripts estejam dentro de /root/rules e tenham o nome de rc.routes e rc.firewall.
Edite o arquivo
vim /etc/rc.local
Adicione
/root/rules/rc.routes
/root/rules/rc.firewall
Salve
:wq!
Pronto, desde que eles tenham permissão de execução tudo está pronto para funcionar, se quiser testar para valer dê um reboot.
Outras dicas
7. Usando Proxy Transparente na mesma máquina
Se quiser configurar um proxy transparente a regra abaixo resolve.
$IPTABLES -t nat -A PREROUTING -i eth0 -p tcp -s $LAN_NET --dport 80 -j REDIRECT --to-port 3128
Você precisa ter o SQUID na mesma máquina.
8. Saída por link específico para destino específico
Se quiser acessar um site sempre por uma das saídas, por exemplo embratel, basta marcar assim:
$IPTABLES -A PREROUTING -t mangle -s 10.1.xxx.xxx/xx -d 186.202.xxx.xxx -j MARK --set-mark 1
Como estou marcando com 2, ele sairia para embratel toda a vez que o destino fosse 186.202.xxx.xxx
8.1 Serviço específico saindo por link específico
Podemos especificar que toda o envio de e-mail (SMTP) será feito pelo link EMBRATEL que é mais estável, seguro e tem menos chances se estar em um lista de bloqueio.
$IPTABLES -A PREROUTING -t mangle -s 10.1.xxx.xxx/xx -d 0/0 --dport 25 -j MARK --set-mark 1
9. SQUID usando Balanceamento
Se tiver um squid na mesma máquina e desejar que ele use a tabela de balanceamento ao invés da rota padrão, defina a configuração abaixo no squid.conf
tcp_outgoing_tos 0x2 redelocal
0x1 é referente a marcação no iptables para saída pela tabela de balanceamento e rede local seria relativa a uma ACL que tem como conteúdo o endereço da rede local.
7.1 Exemplo de squid.conf
Aqui um exemplo de conf de squid3 que só faz cache na porta 80.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
|
7.2 Exemplo de balanceamento usando tabela default
Ao invés de criar uma tabela específica para balanceamento, podemos definir o balanceamento na tabela default.
ip route add default scope global nexthop via 189.xxx.xxx.xxx \
dev eth1 weight 1 nexthop via 200.xxx.xxx.xxx dev eth2 weight 1
É apenas uma outra forma de fazê-lo, mais direta.
Amarrando as pontas
8. Conclusão
O Netfilter/iptables e Iproute2 possuem juntos um universo de funcionalidades e comandos para te ajudar a resolver os mais diversos problemas.
O exemplo deste post é bem básico e simples, espero que sirva de referência para aqueles que necessitem balancear dois ou mais links.
8.2 Cuidado com testes MEUIP
Se estiver tentando ver se o balanceamento funciona usando sites MEUIP, você está fazendo errado. O balanceamento possui um cache, e no caso do mesmo site ele vai analisar por qual link voce acessou aquele site e vai sair sempre por ele, isso ocorre para evitar problemas ao acessar sites que precisam de persistência de sessão.
O balanceamento vai funcionar, mas acesse sites diferentes para testar e use o MTR no console para avaliar por onde você está saindo, isso será mais eficiente.
9. Referências de pesquisa
9.1 Principais
- https://www.policyrouting.org/iproute2.doc.html
- https://netfilter.org/documentation/
9.2 Secundários
- https://lartc.org/howto/lartc.rpdb.multiple-links.html
- https://www.debian-administration.org/articles/377
- https://www.enterprisenetworkingplanet.com/netos/article.php/3512836/Tunnels-Routes-and-Rules-Theyre-Easier-with-iproute2.htm
- https://blog.nielshorn.net/2008/09/load-balancing-two-isps/