Instradamento delle politiche basato sulla fonte e NAT (DNAT / SNAT) aka Multi WAN su CentOS 5


4

Originariamente pubblicato su Unix e Linux, ma nessuno è stato in grado di rispondere, quindi m migrando la domanda qui:

La mia domanda riguarda il routing basato su criteri di origine su CentOS 5 con 2 WAN più una porta LAN (NAT) con bilanciamento del carico, ma prima di tutto alcune osservazioni prima di iniziare a descrivere il problema ...

So che questo argomento è stato portato molte volte qui allo scambio di stack e sembra che le prime 5 risposte siano (ordinate dal più al minimo):

  1. Disabilita rp_filter
  2. Instradamento delle politiche basato su Mark / Connmark
  3. Instradamento dei criteri basato su IP (aggiungi più IP)
  4. Installa pfSense, Shorewall, Ubuntu ?, Etc ...
  5. Acquista router Cisco / 3com / Juniper / Etc ... costoso

La maggior parte delle volte, alcune di queste risposte sono corrette ma per me le soluzioni 1 e 2 non hanno allenamento (non scarto almeno il punto 2 perché potrei avere alcuni problemi con la mia configurazione), il punto 3 sostanzialmente sta isolando un problema piuttosto che risolverlo (aggiunge anche complessità alle tabelle di routing) e le soluzioni 4 e 5 sono appena fuori dall'ambito in quanto non ho risorse per acquistare hardware specializzato né posso portare offline il server poiché è in produzione, quindi per riassumere la sostituzione il server CentOS con qualcosa di "migliore" è fuori dal tavolo.

Ok ora torniamo al problema, per prima cosa descriviamo la configurazione corrente ...

Interfacce :

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 / network-scripts / 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 / network-scripts / 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 / network-scripts / rule-eth0 :

fwmark 2 table ISP1
from 10.0.1.1 table ISP1

/ etc / sysconfig / network-scripts / 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

Il bilanciamento del carico è possibile con lo script bash gwping che in pratica monitora i 2 wan (eth0 ed eth2) e imposta le rotte e i pesi predefiniti nel server in questo modo (mentre in bilanciamento del carico o i 2 wan sono attivi e funzionanti):

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

Il problema che ho è che anche con questa configurazione che molte persone sembrano concordare è quella corretta, ho ancora problemi con l'accesso ai servizi all'interno della rete dall'esterno (in particolare la scatola degli sviluppatori ssh e quella OpenVPN) anche che i pacchetti vengono "contrassegnati" e indirizzati di conseguenza la risposta dalla casella dev va sempre nel percorso sbagliato. Non so se mi manchi qualcosa nella zona di mangle o nat o se non installo affatto il routing basato su sorgenti, comunque se qualcuno sa come fare questo lavoro di conseguenza, sarà apprezzato.

Le mie fonti per questa configurazione sono:

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

Cordiali saluti

PS1: ho trovato un sito Web che dice che i segni nella tabella di routing dovrebbero essere + 1 diversi dai segni iptables (kim.attr.ee/2010/08/source-based-policy-routing-on-centos.html) è vero? o questo sito Web è super-errato.


Aggiornamento 15/08/2013 alle 22:15

Dopo ulteriori ricerche e debug, ho trovato un sito Web che dice che ho dimenticato di aggiungere la parte SNAT alla tabella di post-routing, quindi aggiungo queste regole alla configurazione di 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

Ma non riesco ancora a collegarmi al devbox dall'esterno della rete. Sul lato positivo un a iptables -t nat -nvL POSTROUTING fornisce un suggerimento sul funzionamento del routing delle politiche basato su connmark, quindi forse è qualcosa di correlato al bordo del router 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

Inoltre aggiungo ulteriori informazioni dal mio setup, per favore qualcuno mi metta in salvo la vita da quando ho iniziato a rimanere senza idee ...>. <

mostra percorso ip :

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

mostra regole 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

Nuove fonti:

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

Cordiali saluti


Potresti forse cambiare il titolo e rimuovere i centos, sostituendolo con Linux? Ho usato l'esatto per configurare su Debian / Devuan
Hvisage

Risposte:


5

Bene...

Dopo migliaia di ore di debug, tentando diverse configurazioni e 72 ore di pesanti test in produzione, sono stato in grado di trovare la soluzione / impostazione corretta, il problema era nelle regole di iptables (sezione mangle) i pacchetti apparentemente erano contrassegnati proprio quando arrivano ma quando escono non ce n'era per pacchetti non traditi, comunque qui è la mia soluzione di lavoro finale al mio 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

Ovviamente, oltre a tutte le impostazioni precedenti relative a iproute e gwping (per il bilanciamento del carico dei collegamenti e il fail-over), le soluzioni sono state rese possibili grazie alle fonti [1] e [2], entrambe che mi hanno indicato una parte diversa (Luca Gibelli per la parte PREROUTING e Karl Bowden per la parte OUTPUT) della soluzione, sto vivendo anche qui alcune altre fonti per altri siti Web che mi hanno indicato la giusta direzione per andare a cercare. Spero che questo aiuti un altro amministratore di sistema in futuro.

Cordiali saluti

fonti:

[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

Aggiornamento 10/10/2013

OpenVPN richiede una direttiva di configurazione aggiuntiva per funzionare con una configurazione con più wan (come la precedente), quindi basta aggiungere l'opzione multihome in server.conf (OpenVPN> = 2.1, per le versioni inferiori basta cambiare la direttiva locale per ascoltare solo in un IP particolare) e sei a posto.


Grazie, -t mangle -A OUTPUT ... -j CONNMARK --restore-mark era qualcosa che mi mancava nella mia installazione :)
Hvisage

0

solo un consiglio per te Faccio lo stesso esatto tipo di cose solo senza il bilanciamento del carico e 3 collegamenti deboli e non uso nemmeno iptables per tutto. Trovo che l'uso di semplici percorsi basati su policy e socat sia molto più efficace

my rt_tables:

100     lan
102     wireless
103     wan1
104     wan2
105     wan3

nelle interfacce in su per ogni collegamento 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

nelle interfacce verso il basso per ogni collegamento wan:

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

per forzare un client lan fuori un link specifico: inseriscilo nella tua interfaccia up script:

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

e questo nello script down:

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

per inviare una connessione in entrata a una macchina specifica (es. un server web) aggiungere qualcosa di simile a rc.local (questo può essere eseguito sia che il collegamento sia attivo o meno)

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

quindi attiva l'ip forwarding e il travestimento e tutte le altre regole del firewall di cui hai bisogno e che sei pronto

su Ubuntu puoi persino creare un lavoro di avvio per la socat, questo è il mio /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

0

@CentOS_noob

Innanzitutto, ottimo lavoro e molte grazie per la condivisione, grazie mille! Ci stavo battendo da anni. :)

Se desideri indirizzare servizi specifici attraverso il link selezionato, puoi farlo in questo modo davanti alle tue attuali regole di MARKING.

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

Dove:

br1 - is LAN interface
10.1.1.2 - is LAN's IP of some host.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.