Roteamento de políticas baseadas em origem e NAT (DNAT / SNAT) também conhecido como Multi WANs no CentOS 5

4

Originalmente postado no Unix e no Linux, mas ninguém conseguiu responder, então estou migrando a pergunta aqui:

Minha pergunta é sobre Roteamento de Política Baseada em Origem no CentOS 5 com 2 WANs mais uma porta LAN (NAT) com Balanceamento de Carga, mas antes de qualquer coisa algumas observações antes de começar a descrever o problema ...

Eu sei que este tópico foi trazido muitas vezes aqui na troca de pilha e parece que as 5 principais respostas estão (ordenadas do mais ao mínimo):

  1. Desativar rp_filter
  2. Roteamento de políticas com base no Mark / Connmark
  3. Roteamento de políticas com base em IP (adicionar mais IPs)
  4. Instalar pfSense, Shorewall, Ubuntu ?, Etc ...
  5. Compre um roteador caro da Cisco / 3com / Juniper / Etc ...

Na maioria das vezes, algumas dessas respostas estão corretas, mas para mim as soluções 1 & 2 não tem treino (não descarto pelo menos o ponto 2 porque posso ter alguns problemas com minha configuração), o ponto 3 é basicamente isolar um problema em vez de resolvê-lo (também adiciona complexidade às tabelas de roteamento) e soluções 4 & ; 5 estão fora do escopo, pois não tenho recursos para comprar hardware especializado nem posso colocar offline o servidor, pois ele está em produção, portanto, resumir a substituição do servidor CentOS por algo "melhor" está fora da tabela.

Ok, agora, de volta ao problema, vamos primeiro descrever a configuração atual ...

Interfaces :

eth1: IP: 10.0.0.1, GW: 10.0.0.1, NM: 255.255.255.0 (LAN)
eth0: IP: 10.0.1.1, GW: 10.0.1.254, NM: 255.255.255.0 (ISP1 - ADSL Router)
eth2: IP: 10.0.2.1, GW: 10.0.2.254, NM: 255.255.255.0 (ISP2 - ADSL Router)

/etc/sysctl.conf :

# Controls IP packet forwarding
net.ipv4.ip_forward = 1

# Controls source route verification
net.ipv4.conf.default.rp_filter = 0

# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0

# Controls the use of TCP syncookies
net.ipv4.tcp_syncookies = 1

# Ignoring broadcasts request
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_messages = 1

/ etc / iproute2 / rt_tables:

#
# reserved values
#
255     local
254     main
253     default
0       unspec
#
# local
#
#1      inr.ruhep
2 ISP1
3 ISP2

/ etc / sysconfig / scripts de rede / route-eth0 :

10.0.1.0/24 dev eth0 src 10.0.1.1 table ISP1
default via 10.0.1.254 dev eth0 table ISP1

/ etc / sysconfig / scripts de rede / route-eth2 :

10.0.2.0/24 dev eth2 src 10.0.2.1 table ISP2
default via 10.0.2.254 dev eth2 table ISP2

/ etc / sysconfig / scripts de rede / rule-eth0 :

fwmark 2 table ISP1
from 10.0.1.1 table ISP1

/ etc / sysconfig / scripts de rede / rule-eth2 :

fwmark 3 table ISP2
from 10.0.2.1 table ISP2

/ etc / sysconfig / iptables :

*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# Basic Rules
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth2 -m state --state RELATED,ESTABLISHED -j ACCEPT

# SSH
-A INPUT -i eth0 -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -i eth2 -m tcp -p tcp --dport 22 -j ACCEPT

# OpenVPN
-A INPUT -i eth0 -m udp -p udp --dport 1194 -j ACCEPT
-A INPUT -i eth2 -m udp -p udp --dport 1194 -j ACCEPT

# Allow everything from LAN
-A INPUT -i eth1 -j ACCEPT

# Allow everything from the VPN
-A INPUT -i tun0 -j ACCEPT

# Default Drop on everything else
-A INPUT -j DROP

# Allow forwarding from LAN and VPN
-A FORWARD -i eth1 -j ACCEPT
-A FORWARD -i tun0 -j ACCEPT

# Allow all outbound traffic
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -o eth1 -j ACCEPT
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# DNAT to Developer Box (SSH Server)
-A PREROUTING -i eth0 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 10.0.0.200:2222
-A PREROUTING -i eth2 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 10.0.0.200:2222

# SNAT
-A POSTROUTING -o eth0 -j SNAT --to-source 10.0.1.1
-A POSTROUTING -o eth2 -j SNAT --to-source 10.0.2.1
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# Mark Based Routing? (based on NerdBoys site)
-A PREROUTING -j CONNMARK --restore-mark
-A PREROUTING --match mark --mark 2 -j ACCEPT
-A PREROUTING -i eth0 -j MARK --set-mark 2
-A PREROUTING --match mark --mark 3 -j ACCEPT
-A PREROUTING -i eth2 -j MARK --set-mark 3
-A PREROUTING -j CONNMARK --save-mark
COMMIT

O Balanceamento de Carga está sendo possível com o script bash de gwping, que basicamente monitora as duas wans (eth0 e eth2) e configura as rotas e pesos padrão no servidor como este (enquanto no balanceamento de carga ou os 2 wans ativos e em execução) :

ip route replace default scope global nexthop via 10.0.1.1 dev eth0 weight 1 nexthop via 10.0.2.1 dev eth1 weight 1

O problema que tenho é que mesmo com essa configuração que muitas pessoas parecem concordar ser a correta, eu ainda tenho problemas em acessar serviços dentro da rede do lado de fora (especificamente a caixa do desenvolvedor ssh e a do OpenVPN) mesmo que os pacotes estão sendo "marcados" e roteados de acordo, a resposta da caixa dev vai sempre para o caminho errado. Eu não sei se estou perdendo algo na área do mangle ou nat ou estou entendendo mal o roteamento baseado na fonte, de qualquer forma, se alguém souber como fazer esse trabalho de acordo, será gentilmente apreciado.

Minhas fontes para essa configuração são:

lartc.org/lartc.html#LARTC.RPDB.MULTIPLE-LINKS
fatalsite.net/?p=90
nerdboys.com/2006/05/05/conning-the-mark-multiwan-connections-using-iptables-mark-connmark-and-iproute2/
policyrouting.org/PolicyRoutingBook/ONLINE/CH08.web.html
unix.stackexchange.com/questions/58635/iptables-set-mark-route-diferent-ports-through-different-interfaces
unix.stackexchange.com/questions/22770/two-interfaces-two-addresses-two-gateways
bulma.net/body.phtml?nIdNoticia=2145

Com os melhores cumprimentos

PS1: Encontrei um site dizendo que as marcas na tabela de roteamento devem ser + 1 diferentes das marcas do iptables (kim.attr.ee/2010/08/source-based-policy-routing-on-centos .html) isso é verdade? ou este site está super-incorreto.

Atualização 15/08/2013 22:15

Depois de pesquisar e depurar mais, encontrei um site que diz que esqueci de adicionar a parte SNAT na tabela de pós-roteamento, então adiciono essas regras à configuração do iptables:

-A POSTROUTING --match mark --mark 2 -j SNAT --to-source 10.0.1.1
-A POSTROUTING --match mark --mark 3 -j SNAT --to-source 10.0.2.1

Mas ainda não consigo me conectar ao devbox do lado de fora da rede. Do lado bom, um iptables -t nat -nvL POSTROUTING dá uma dica sobre o funcionamento do roteamento de política baseado em connmark, então talvez seja algo relacionado à borda do roteador ISP1 e ISP2:

Chain POSTROUTING (policy ACCEPT 520 packets, 56738 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 SNAT       all  --  *      *       0.0.0.0/0            0.0.0.0/0           MARK match 0x2 to:10.0.1.1
    6   312 SNAT       all  --  *      *       0.0.0.0/0            0.0.0.0/0           MARK match 0x3 to:10.0.2.1
  903 70490 SNAT       all  --  *      eth0    0.0.0.0/0            0.0.0.0/0           to:10.0.1.1
  931 78070 SNAT       all  --  *      eth2    0.0.0.0/0            0.0.0.0/0           to:10.0.2.1

Além disso, adiciono mais informações da minha configuração, por favor, alguém me dê um salva-vidas desde que comecei a ficar sem idéias ... <

ip route show :

10.8.0.2 dev tun0  proto kernel  scope link  src 10.8.0.1
10.0.2.0/24 dev eth2  proto kernel  scope link  src 10.0.2.1
10.0.0.0/24 dev eth1  proto kernel  scope link  src 10.0.0.1
10.8.0.0/24 via 10.8.0.2 dev tun0
10.0.1.0/24 dev eth0  proto kernel  scope link  src 10.0.1.1
169.254.0.0/16 dev eth2  scope link
default
        nexthop via 10.0.1.254  dev eth0 weight 1
        nexthop via 10.0.2.254  dev eth2 weight 1

show de regra de ip:

0:      from all lookup 255
1024:   from all fwmark 0x2 lookup ISP1
1025:   from all fwmark 0x3 lookup ISP2
2024:   from 10.0.1.1 lookup ISP1
2025:   from 10.0.2.1 lookup ISP2
32766:  from all lookup main
32767:  from all lookup default

Novas fontes:

sarcasmasaservice.com/2013/04/linux-routing-capabilities-my-abuse-thereof/

Com os melhores cumprimentos

    
por CentOS_noob 29.08.2013 / 06:38

3 respostas

4

Bem ...

Após milhares de horas de depuração, tentando configurações diferentes e 72 horas de testes pesados em produção, consegui encontrar a solução / configuração correta, o problema estava nas regras do iptables (seção mangle) que os pacotes aparentemente eram marcados quando eles entram, mas quando eles saem, não há nenhum para os pacotes abandonados, de qualquer forma aqui, é a minha solução final para o meu problema:

/ etc / sysconfig / iptables :

*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# Basic Rules
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth2 -m state --state RELATED,ESTABLISHED -j ACCEPT

# SSH
-A INPUT -i eth0 -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -i eth2 -m tcp -p tcp --dport 22 -j ACCEPT

# OpenVPN
-A INPUT -i eth0 -m udp -p udp --dport 1194 -j ACCEPT
-A INPUT -i eth2 -m udp -p udp --dport 1194 -j ACCEPT

# Allow everything from LAN
-A INPUT -i eth1 -j ACCEPT

# Allow everything from the VPN
-A INPUT -i tun0 -j ACCEPT

# Default Drop on everything else
-A INPUT -j DROP

# Allow forwarding from LAN and VPN
-A FORWARD -i eth1 -j ACCEPT
-A FORWARD -i tun0 -j ACCEPT

# Allow all outbound traffic
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -o eth1 -j ACCEPT
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# DNAT to Developer Box (SSH Server)
-A PREROUTING -i eth0 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 10.0.0.200:2222
-A PREROUTING -i eth2 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 10.0.0.200:2222

# SNAT
-A POSTROUTING -o eth0 -j SNAT --to-source 10.0.1.1
-A POSTROUTING -o eth2 -j SNAT --to-source 10.0.2.1
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# CONNMARK Source Based Routing
-A PREROUTING -i eth0 -m state --state NEW,RELATED,ESTABLISHED -d 10.0.1.1 -j CONNMARK --set-mark 0x2
-A PREROUTING -i eth2 -m state --state NEW,RELATED,ESTABLISHED -d 10.0.2.1 -j CONNMARK --set-mark 0x3
-A PREROUTING -i eth1 -m connmark --mark 0x2 -j CONNMARK --restore-mark
-A PREROUTING -i eth1 -m connmark --mark 0x3 -j CONNMARK --restore-mark
-A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNMARK --restore-mark
COMMIT

Obviamente, além de toda a configuração anterior relacionada a iproute e gwping (para balanceamento de carga de link e failover), as soluções foram possíveis graças às fontes [1] & [2], ambos os quais apontaram para uma parte diferente (Luca Gibelli para a parte PREROUTING e Karl Bowden para a parte OUTPUT) da solução, também estou vivendo aqui mais algumas fontes para outros sites que me apontaram na direção certa para ir olhando. Espero que isso ajude outro sysadmin no futuro.

Com os melhores cumprimentos

Fontes:

[1]www.nervous.it/2010/09/dnat-and-ip-source-routing-woes/
[2]blog.khax.net/2009/12/01/multi-gateway-balancing-with-iptables/
[3]home.regit.org/netfilter-en/links-load-balancing/
[4]mailman.ds9a.nl/pipermail/lartc/2006q2/018964.html
[5]web.archive.org/web/20120320115329/http://versa.net.au/index.php?option=com_content&task=view&id=21&Itemid=34

Atualização 10/10/2013

O OpenVPN requer uma diretiva de configuração extra para trabalhar com uma configuração múltipla wan (como a anterior), então apenas adicione a opção multihome em seu server.conf (OpenVPN > = 2.1, para versões inferiores apenas altere a diretiva local para só ouça em um ip particular) e você está pronto para ir.

    
por 25.09.2013 / 07:03
0

apenas uma dica para você Eu faço exatamente o mesmo tipo de coisa sem o balanceamento de carga e 3 links wan e nem uso o iptables para isso. Eu acho que usar roteamento baseado em políticas simples e socat é muito mais eficaz

minhas rt_tables:

100     lan
102     wireless
103     wan1
104     wan2
105     wan3

nas interfaces para cada link wan:

/bin/ip route add <wan network id> dev eth0 src <wan host ip> table wan1
/bin/ip route add default via <wan gateway address> table wan1
/bin/ip rule add from <wan host ip> table wan1

nas interfaces abaixo para cada link wan:

/bin/ip route del default via <wan gateway address> table wan1
/bin/ip rule del from <wan host ip> table wan1

para forçar um cliente de lan a sair de um link específico: coloque isso em seu script de interface:

/bin/ip rule add from <lan client ip> table <wan table number of link to force it through>

e isso no script abaixo:

/bin/ip rule del from <lan client ip> table <wan table number of link to force it through>

para enviar uma conexão de entrada para uma máquina específica (por exemplo, um servidor da web) adicione algo assim ao rc.local (isso pode ser executado se o link estiver ativo ou não)

exec socat -T15 tcp4-listen:80,reuseaddr,fork tcp:<lan host ip to send it to>:80 >> /var/log/socat-web.log 2>&1

em seguida, ligue o encaminhamento de ip e masquerade e quaisquer outras regras de firewall que você precisa e é bom ir

no ubuntu você pode até mesmo criar um trabalho iniciante para o socat, esse é o meu /etc/init/socat-web.conf:

description "socat web port tunnel"
author      "jacqueline"

start on started mountall
stop on shutdown
respawn
respawn limit 99 5

script
    export HOME="/root"
    exec socat -T15 tcp4-listen:80,reuseaddr,fork tcp:192.168.0.97:80 >> /var/log/socat-web.log 2>&1
end script

post-start script
   # Optionally put a script here that will notifiy you socat has (re)started
end script
    
por 20.11.2013 / 05:00
0

@CentOS_noob

Primeiramente, ótimo trabalho e muito obrigado por compartilhar, muito obrigado! Eu estava lutando com isso há anos. :)

Se você quiser direcionar os serviços especificados por meio do link selecionado, poderá fazê-lo na frente de suas regras de MARCAÇÃO atuais.

iptables -t mangle -A PREROUTING -i br1 -s 10.1.1.2 -p tcp --dport 80 -m state --state NEW,RELATED,ESTABLISHED -j CONNMARK --set-mark 0x3
iptables -t mangle -A PREROUTING -i br1 -s 10.1.1.2 -p icmp  -j CONNMARK --set-mark 0x4

Onde:

br1 - is LAN interface
10.1.1.2 - is LAN's IP of some host.
    
por 16.04.2014 / 02:34