web-dev-qa-db-ja.com

ソースベースのポリシールーティング&NAT(DNAT / SNAT)別名CentOS5のマルチWAN

もともとはUnixとLinuxに投稿されましたが、誰もそれに答えることができなかったので、ここで質問を移行します。

私の質問は、2つのWANとロードバランシングを備えたLAN(NAT)ポートを備えたCentOS 5でのソースベースのポリシールーティングに関するものですが、問題の説明を始める前に、まずいくつかのコメントがあります...

私はこのトピックがスタック交換で何度もここに持ち込まれたことを知っており、上位5つの答えは(最も多いものから最も低いものへと)次のようです:

  1. Rp_filterを無効にする
  2. マーク/コメントベースのポリシールーティング
  3. IPベースのポリシールーティング(IPを追加)
  4. PfSense、Shorewall、Ubuntu?などをインストールします...
  5. 高価なCisco/3com/Juniper/Etc ...ルーターを購入する

ほとんどの場合、この答えのいくつかは正しいですが、私にとっては解決策1と2がうまくいきません(セットアップに問題がある可能性があるため、少なくともポイント2を破棄しません)、ポイント3は基本的に問題を切り分けていますそれを解決するのではなく(ルーティングテーブルに複雑さを追加します)、ソリューション4と5は、専用のハードウェアを購入するためのリソースがないため、またサーバーをオフラインにすることができないため、範囲外です。 「より良い」何かを備えたCentOSサーバーはテーブルから外れています。

さて、問題に戻りましょう。最初に現在の設定について説明しましょう...

インターフェース

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-eth

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-eth

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

負荷分散は、基本的に2つのWAN(eth0とeth2)を監視し、次のようにサーバーにデフォルトルートと重みを設定するgwping bashスクリプトで可能です(負荷分散中または2つのWANが稼働中)。

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

私が抱えている問題は、多くの人が同意しているように見えるこの設定でも正しいものであり、パケットであっても外部からネットワーク内のサービス(特にssh開発者ボックスとOpenVPNボックス)にアクセスする際に問題が発生することです「マーク」が付けられ、それに応じてルーティングされます。開発ボックスからの回答は常に間違ったパスに送られます。マングルまたはNAT領域で何かが欠落しているのか、ソースベースのルーティングを誤解しているのかはわかりません。とにかく、誰かがこれを適切に機能させる方法を知っていれば、親切に感謝します。

この設定のソースは次のとおりです。

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

よろしくお願いします

PS1:ルーティングテーブルのマークはiptablesのマークと+1異なる必要があるというWebサイトを見つけました(kim.attr.ee/2010/08/source-based-policy-routing-on-centos.html)これは本当ですか?またはこのウェブサイトは非常に間違っています。


更新15/08/201322:15

さらに調査とデバッグを行った後、ルーティング後のテーブルにSNAT部分を追加するのを忘れたというウェブサイトを見つけたので、このルールを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

しかし、mはまだネットワークの外部からdevboxに接続できません。良い面として、a iptables -t nat -nvL POSTROUTINGは、connmarkベースのポリシールーティングの動作に関するヒントを提供するため、ISP1および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

また、セットアップからさらに情報を追加します。アイデアが不足し始めたので、誰かが私に命の恩人を投げてください...>。<

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

ip rule show:

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

新しい情報源:

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

よろしくお願いします

4
CentOS_noob

上手...

数千時間のデバッグ、さまざまなセットアップの試行、および72時間の本番環境での徹底的なテストの後、正しい解決策/セットアップを見つけることができました。問題はiptablesルール(マングルセクション)にあり、パケットが入ったときに正しくマークされたようです。しかし、それらが出てきたとき、dnat'tedパケットには何もありませんでした、とにかくここでそれは私の問題に対する私の最終的な解決策です:

/ 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

明らかに、iprouteとgwping(リンクの負荷分散とフェイルオーバー用)に関連する以前のすべてのセットアップに加えて、ソース[1]と[2]のおかげでソリューションが可能になり、どちらも別の部分を示しました(Luca Gibelli forソリューションのPREROUTING部分とKarlBowden(OUTPUT部分)もここにあり、他のWebサイトのソースがいくつかあり、私が正しい方向を探していることを示しています。これが将来別のシステム管理者に役立つことを願っています。

よろしくお願いします

出典:

[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

2013年10月10日更新

OpenVPNは(前のもののように)複数のWANセットアップで動作するために追加の構成ディレクティブを必要とするので、server.confにmultihomeオプションを追加するだけです(OpenVPN> = 2.1、より低いバージョンの場合はローカルディレクティブを変更して特定のIP)そしてあなたは行ってもいいです。

5
CentOS_noob

あなたへのヒント私は負荷分散と3つのWANリンクなしで同じタイプのことをします、そして私はそれすべてにiptablesさえ使用しません。単純なポリシーベースのルーティングとsocatを使用する方がはるかに効果的だと思います

私のrt_tables:

100     lan
102     wireless
103     wan1
104     wan2
105     wan3

各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

各WANリンクのダウンインターフェイスで:

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

lANクライアントに特定のリンクを強制的に送信するには:これをインターフェイスアップスクリプトに配置します。

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

そしてこれはダウンスクリプトで:

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

着信接続を特定のマシン(Webサーバーなど)に送信するには、次のようなものをrc.localに追加します(これは、リンクがアップしているかどうかに関係なく実行できます)

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

次に、IP転送とマスカレード、および必要なその他のファイアウォールルールをオンにします。

ubuntuでは、socatの起動ジョブを作成することもできます。これは私の/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

まず、素晴らしい仕事と共有してくれてありがとう、どうもありがとう!私は何年もそれと格闘していました。 :)

選択したリンクを介して指定されたサービスを送信したい場合は、現在のマーキングルールの前でこのように行うことができます。

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

どこ:

br1 - is LAN interface
10.1.1.2 - is LAN's IP of some Host.
0