複数のデータセンターでホストされている複数の専用サーバーがあり、メールを移行したい(pop3、imap、smtpおよびそれらのTLS/SSLバリアント)サービスをあるサーバーから別のサーバーに。
そのために、DNS伝播の時間を処理するために、新しいサーバーから古いサーバーへの[〜#〜] nat [〜#〜]ルーティングを一時的にインストールする予定です。
そこで、次の[〜#〜] iptables [〜#〜]ルールを定義しました:
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 25 -j DNAT --to-destination <my_remote_ip>:8025
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 110 -j DNAT --to-destination <my_remote_ip>
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 143 -j DNAT --to-destination <my_remote_ip>
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 465 -j DNAT --to-destination <my_remote_ip>:8465
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 587 -j DNAT --to-destination <my_remote_ip>:8587
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 993 -j DNAT --to-destination <my_remote_ip>
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 995 -j DNAT --to-destination <my_remote_ip>
iptables -t nat -A POSTROUTING -d <my_remote_ip> -p tcp -m tcp --dport 110 -j SNAT --to-source <my_local_ip>
iptables -t nat -A POSTROUTING -d <my_remote_ip> -p tcp -m tcp --dport 143 -j SNAT --to-source <my_local_ip>
iptables -t nat -A POSTROUTING -d <my_remote_ip> -p tcp -m tcp --dport 993 -j SNAT --to-source <my_local_ip>
iptables -t nat -A POSTROUTING -d <my_remote_ip> -p tcp -m tcp --dport 995 -j SNAT --to-source <my_local_ip>
iptables -t nat -A POSTROUTING -d <my_remote_ip> -p tcp -m tcp --dport 8025 -j SNAT --to-source <my_local_ip>:25
iptables -t nat -A POSTROUTING -d <my_remote_ip> -p tcp -m tcp --dport 8465 -j SNAT --to-source <my_local_ip>:465
iptables -t nat -A POSTROUTING -d <my_remote_ip> -p tcp -m tcp --dport 8587 -j SNAT --to-source <my_local_ip>:587
iptables -A FORWARD -d <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --dport 110 -j ACCEPT
iptables -A FORWARD -d <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --dport 143 -j ACCEPT
iptables -A FORWARD -d <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --dport 993 -j ACCEPT
iptables -A FORWARD -d <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --dport 995 -j ACCEPT
iptables -A FORWARD -d <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --dport 8025 -j ACCEPT
iptables -A FORWARD -d <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --dport 8465 -j ACCEPT
iptables -A FORWARD -d <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --dport 8587 -j ACCEPT
iptables -A FORWARD -s <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --sport 110 -j ACCEPT
iptables -A FORWARD -s <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --sport 143 -j ACCEPT
iptables -A FORWARD -s <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --sport 993 -j ACCEPT
iptables -A FORWARD -s <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --sport 995 -j ACCEPT
iptables -A FORWARD -s <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --sport 8025 -j ACCEPT
iptables -A FORWARD -s <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --sport 8465 -j ACCEPT
iptables -A FORWARD -s <my_remote_ip> -i eth0 -o eth0 -p tcp -m tcp --sport 8587 -j ACCEPT
(実際には単純化されています。実際、これはIPv4とIPV6で重複しており、一部のサーバーではインターフェイスがeth0と異なる場合があります…そしてもちろん実際のIPアドレスを壊しました)
メールサービスはNATのみであることに注意してくださいが、SMTP関連サービスにはポート変換もあり、逆変換またはこれらのポートの特定のリスニングに関連付けられています。宛先サーバー。
それには説得力のある理由があります:私のホスティングプロバイダーは、それらによってホストされているすべてのサーバーでホストされているスパムを検出してブロックするために、発信SMTP接続を監視するために使用します。しかし、SMTPポートへの着信接続を別のサーバーに転送すると、着信スパムは発信スパム(fromデータセンターの観点)フィルタリングされる前に(宛先サーバー上)、その結果、ホスティングプロバイダーはすぐにNATサーバーをブロックします。
したがって、これらの接続を転送するには、ポート番号も変換する必要があります。
着信パケットと発信(NAT)パケットは同じインターフェースを使用します(これらのサーバーにはネットワークインターフェースが1つしかないため)。
実際には、これは多かれ少なかれ機能しますが、ポート転送接続(とこれらの接続のみ、ポート110、143などでは問題ありません)は奇妙な動作をします:最初に機能します使用している時間ですが、すぐに切断して再接続すると、転送が機能しなくなり、1〜3分待ってから再度接続できるようになります。
これは、ポート番号ではなくIPアドレスに関連しているようです。前の接続がポート110(pop3、ポート転送ではない)であったとしても、ポート25に接続できるようになるまで同じ遅延を待つ必要があります。
いくつかのサーバーで、すべてがLinux Debian Wheezy、Jessie、またはStretchであることを確認しました、およびIPv4とIPv6の両方で(NAT IPv6)。 ………はい、Wheezyが古くなったことを知っています。これが、私が移行する理由です。
すべてのIPアドレスは完全に静的です。
はい、/ proc/sys/net/ipv4/ip_forward(およびIPv6と同等)を1に設定しました。
接続のテストにはtelnetを使用し、tcpdumpを使用して転送を確認します。後者を使用すると、転送が実際に行われていないこと、および着信接続をブロックしているのはnot宛先サーバーであることを確認できます。
この1〜3分のブロック遅延の理由と、それを修正する方法を誰かが見つけてくれるでしょうか。
銀杏
あなたの問題は、Linux接続トラッカーの特殊性に関連しています。
簡単な答え:構成でこの遅延を回避することはできません。この問題を回避する唯一の方法は、-j SNAT
オプションでポート番号を指定せずに--to-source
を使用することです。
ちょっとしたトリックもありますが、それはほとんど役に立ちません-j SNAT
で、単一のポート番号の代わりにポートの範囲を使用してください。複数の接続を確立できます。同時接続数は、範囲内のポート数です。ルールは次のようになります。
iptables -t nat -A POSTROUTING -d <my_remote_ip> -p tcp -m tcp --dport 8025 -j SNAT --to-source <my_local_ip>:10025-10125
血まみれの詳細が必要な場合は、答えを拡張できます。
詳細を理解するには、いくつかの背景が必要です。ラミ・ローゼンの"Linux kernel networking: implementation and theory"
を読んでください。主に、この本の「第9章Netfilter。接続トラッカー」が必要です。
パケットがLinuxホストを通過すると、Linux接続トラッカー(conntrack
)がパケットを分析し、パケットフローに関する情報をテーブル(conntrack table
)に格納します。すべてのパケットフローは、conntrackエントリとして表示されます。 conntrackは、タプルを使用してパケットフローを識別します。タプルは、L(両端のIPアドレスとL4プロトコルの数)およびL4(TCPの場合)のポート番号情報です。両端)フローの情報。
Conntrackには、トランスポートプロトコル固有の接続状態をトレースするために、すべてのL4プロトコル用のモジュールがいくつかあります。 TCP conntrack部分は、TCP有限状態マシンを実装します。
ラボ(カーネル4.14)では、このTCP conntrack部分の奇妙な動作があります。これを単純な環境で示しましょう。
クライアント(192.0.2.2
)はLinuxホスト(192.0.2.1:22
)に接続し、この接続を他のホスト(192.0.2.6:22
)に転送します。 Linuxホストも、セットアップと同様にSNATルールを使用します。
Tcpdumpの出力:
14:47:32.036809 IP 192.0.2.2.40079 > 192.0.2.1.22: Flags [S], seq 2159011818, win 29200, length 0
14:47:32.037346 IP 192.0.2.1.22 > 192.0.2.2.40079: Flags [S.], seq 960236935, ack 2159011819, win 28960, options [mss 1460,sackOK,TS val 1415987649 ecr 3003498128,nop,wscale 5], length 0
14:47:32.037683 IP 192.0.2.2.40079 > 192.0.2.1.22: Flags [.], ack 1, win 913, options [nop,nop,TS val 3003498129 ecr 1415987649], length 0
14:47:32.041407 IP 192.0.2.1.22 > 192.0.2.2.40079: Flags [P.], seq 1:22, ack 1, win 905, options [nop,nop,TS val 1415987653 ecr 3003498129], length 21
14:47:32.041806 IP 192.0.2.2.40079 > 192.0.2.1.22: Flags [.], ack 22, win 913, options [nop,nop,TS val 3003498133 ecr 1415987653], length 0
14:47:35.826919 IP 192.0.2.2.40079 > 192.0.2.1.22: Flags [F.], seq 1, ack 22, win 913, options [nop,nop,TS val 3003501918 ecr 1415987653], length 0
14:47:35.827996 IP 192.0.2.1.22 > 192.0.2.2.40079: Flags [F.], seq 22, ack 2, win 905, options [nop,nop,TS val 1415991440 ecr 3003501918], length 0
14:47:35.828386 IP 192.0.2.2.40079 > 192.0.2.1.22: Flags [.], ack 23, win 913, options [nop,nop,TS val 3003501919 ecr 1415991440], length 0
Linuxホストのconntrackで、私はこれを見ます:
ipv4 2 tcp 6 431999 ESTABLISHED src=192.0.2.2 dst=192.0.2.1 sport=40079 dport=22 src=192.0.2.6 dst=192.0.2.5 sport=22 dport=22 [ASSURED] mark=0 zone=0 use=2
ipv4 2 tcp 6 431998 ESTABLISHED src=192.0.2.2 dst=192.0.2.1 sport=40079 dport=22 src=192.0.2.6 dst=192.0.2.5 sport=22 dport=22 [ASSURED] mark=0 zone=0 use=2
ipv4 2 tcp 6 431997 ESTABLISHED src=192.0.2.2 dst=192.0.2.1 sport=40079 dport=22 src=192.0.2.6 dst=192.0.2.5 sport=22 dport=22 [ASSURED] mark=0 zone=0 use=2
ipv4 2 tcp 6 431996 ESTABLISHED src=192.0.2.2 dst=192.0.2.1 sport=40079 dport=22 src=192.0.2.6 dst=192.0.2.5 sport=22 dport=22 [ASSURED] mark=0 zone=0 use=2
ipv4 2 tcp 6 119 TIME_WAIT src=192.0.2.2 dst=192.0.2.1 sport=40079 dport=22 src=192.0.2.6 dst=192.0.2.5 sport=22 dport=22 [ASSURED] mark=0 zone=0 use=2
...
ipv4 2 tcp 6 0 TIME_WAIT src=192.0.2.2 dst=192.0.2.1 sport=40079 dport=22 src=192.0.2.6 dst=192.0.2.5 sport=22 dport=22 [ASSURED] mark=0 zone=0 use=2
ご覧のとおり、接続が正しく閉じられているにもかかわらず、関連付けられたconntrackエントリは、TIME_WAIT
状態でconntrackテーブルに表示されます。また、SNATに使用できるポートは1つしかないため、すでにビジー状態であるため、新しい接続の試行は失敗します。なぜこのポートをもう一度使用しないのですか?システムは、192.0.2.6
状態の現在のフローと新しいフローの間でTIME_WAIT
からの応答パケットを区別できないためです。
Conntrackが接続をTIME_WAIT
状態に設定し、代わりに私が知らなかった接続を破棄する理由。