web-dev-qa-db-ja.com

DNATedIPで着信するのと同じインターフェースで返信する

サーバーには3つのifaceがあり、2つは異なるパブリックネットワークの内部(eth1/2)、1つは外部(eth0)です。

一部のIP/ifaceにバインドできず、すべてまたは1つにしかバインドできないサービス(openvpn)がありますが、内部ifaceでのみ接続(UDP)を受け入れるために必要です。デフォルトのgwは外部のものを経由します。

各内部ifaceのIPにバインドされたサービスの2つのインスタンスと、iproute2(ip route add xxx table xip rule add from <IP> table x)で設定されたルーティングを使用した作業セットアップがあります。

2番目の内部iface(eth2)の着信接続を最初の内部iface(eth1)のIPにDNATし、同じインターフェイス(eth2)を介して応答させることは可能ですか?この場合、サービスの2番目のインスタンスを実行し、リッスンするIPの違いだけで2つの同一の構成を維持する必要はありません。

問題は、(DNATを使用して)eth2の着信接続の宛先IPをeth1のIPに変更すると、from <IP>に基づくIPルールが機能しないことです。または、より適切に言うと、eth1のデフォルトのgwを使用して、eth2ではなくeth1を介してサービスに応答します。

DNATed「セッション」(UDP)のすべての発信パケットに効率的にマークを設定して、IPルールでfwmarkを使用できるようにすることは可能ですか?主な問題に対する他の解決策はありますか?

3
Anatoli

解決策を見つけました。このソリューションは、特定のインターフェイスでリッスンできないLinuxサービスで機能するはずですが、MySQL、OpenVPNなどのすべて(0.0.0.0)または特定の1つでのみリッスンします。そのため、サービスを1つのifaceでリッスンさせ、netfilter/iproute2ルールを追加して、同じプロトコルとポートのすべてのリクエストを別のifaceのサービスにリダイレクトします。

「セッション」(OpenVPNの場合はUDPであるにもかかわらず)は実際にはnetfilterによって維持され、特定のセッションからのパケットを参照できるようにするモジュールconntrackがあります。この場合、マングルテーブルにOUTPUTのルールを追加して、DNATedセッションからのすべてのパケットにマークを付けました。そして、このマークを使用してパケットをルーティングします。


つまり、コマンドは次のとおりです。

変数を定義する

iface_int2=eth2         # the second internal iface
ip_int2=xx.xx.xx.xx     # the IP of the second internal iface
proto=udp               # the protocol of the connection
service_port=1194       # the incoming service port
ip_int1=yy.yy.yy.yy     # the IP of the first internal iface
ip_gw2=xx.xx.xx.1       # the IP of the default gateway for the second internal iface



このコマンドは、2番目のifaceで着信接続の宛先IPを上書きするようにnetfilterに指示します。

iptables -t nat -A PREROUTING -i $iface_int2 -d $ip_int2 -p $proto --dport \
$service_port -j DNAT --to $ip_int1



このコマンドは、上書きされた(DNATされた)着信接続の発信パケット(サービスの応答)にマークを付けるようにnetfilterに指示します。 --ctorigdstは、着信接続の元の(事前にDNATされた)宛先IPです

iptables -t mangle -A OUTPUT -p $proto --sport $service_port -m conntrack \
--ctstate DNAT --ctorigdst $ip_int2 -j MARK --set-mark 0x75



このコマンドは、テーブル100のルート定義を介してセットマークされたパケットをルーティングするようにiproute2に指示します。このルールは非常に具体的で他のルールに干渉しないため、Prioはこのルールの最高の優先度を設定する必要があります。 prioが指定されていない場合、最初の内部ifaceのルーティングルールの優先度が高くなる可能性があります。

ip rule add prio 10 fwmark 0x75 table 100



このコマンドは、デフォルトゲートウェイをテーブル100に追加します

ip route add default via $ip_gw2 table 100



これがすべて機能するためには、2番目の内部ifaceのリターンパスフィルターのグリップを弱める必要があります。

# rp_filter - INTEGER
#   0 - No source validation.
#   1 - Strict mode as defined in RFC3704 Strict Reverse Path
#       Each incoming packet is tested against the FIB and if the interface
#       is not the best reverse path the packet check will fail.
#       By default failed packets are discarded.
#   2 - Loose mode as defined in RFC3704 Loose Reverse Path
#       Each incoming packet's source address is also tested against the FIB
#       and if the source address is not reachable via any interface
#       the packet check will fail.

echo 2 > /proc/sys/net/ipv4/conf/$iface_int2/rp_filter
# -OR-
sysctl -w "net.ipv4.conf.$iface_int2.rp_filter=2"
# -OR-
echo "net.ipv4.conf.$iface_int2.rp_filter=2" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
1
Anatoli