サーバーには3つのifaceがあり、2つは異なるパブリックネットワークの内部(eth1/2)、1つは外部(eth0)です。
一部のIP/ifaceにバインドできず、すべてまたは1つにしかバインドできないサービス(openvpn)がありますが、内部ifaceでのみ接続(UDP)を受け入れるために必要です。デフォルトのgwは外部のものを経由します。
各内部ifaceのIPにバインドされたサービスの2つのインスタンスと、iproute2(ip route add xxx table x
、ip 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を使用できるようにすることは可能ですか?主な問題に対する他の解決策はありますか?
解決策を見つけました。このソリューションは、特定のインターフェイスでリッスンできない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