web-dev-qa-db-ja.com

ポートを外部IPに透過的に転送するIptables(リモートエンドは実際のソースIPを確認する必要があります)

質問は簡単ですが、具体的な回答がなく、関連するトピックを無数に調べたので、答えは違うかもしれません。

ポート1234x.x.x.xからy.y.y.yに転送したい(インターネット上のさまざまな場所、つまりy.y.y.y10.a.b.cなどの内部IPではない) y.y.y.yx.x.x.xに接続している元のソースIPを取得できる方法。

現在、通常のSNATまたはMASQUERADEルールを使用してx.x.x.xをソースIPとして認識しています。 y.y.y.yが内部IP(x.x.x.xで実行されているlxcコンテナーなど)の場合、同じルールが機能し、コンテナーは実際のソースIPを認識できますが、y.y.y.yが外部の場合は認識できません。

これは何らかの方法で達成できますか?

4
Sam

NAT –いいえ。IPパケットには「ソース」フィールドが1つだけあります。

  • Iptablesに元のクライアントアドレス(DNATのみ)を保持させると、yyyyはその元のクライアント(通信していると思う)に直接応答を送信しようとしますxxxxであり、yyyyからのパケットを予期していません)。

  • Iptablesに自分のアドレスを新しいソース(DNAT + SNAT)として配置させると、y.y.y.yは元のソースアドレスを認識しなくなります。

(これは実際にはLANから同じLANにポート転送しようとする場合と同じ問題であり、2番目の方法は「NATヘアピニング」または「NATリフレクション」と呼ばれます。)


これを機能させるには、xxxxとyyyyの間にトンネル/ VPNが必要です。受信した元のパケットを変更せずに別のIPパケット内にラップします。はyyyyに送信されます(これにより、トンネリングされたパケットがアンラップされ、元のソースが表示されます)。

もちろん、これは、トンネルを構成するためにルート権限が必要であることを意味します両方のシステムで。さらに、宛先(y.y.y.y)は「ポリシールーティング」をサポートする必要があります–LinuxおよびFreeBSDpfはこれに対応しています。すべてをVPN経由でルーティングするルールが必要ですif送信元アドレスがVPNアドレスです。

Iptables DNATルールは引き続き必要ですが、その「宛先」はyのVPNアドレスであり、パブリックアドレスではありません。これには、基本的な「IP-in-IP」からGRE、OpenVPN、WireGuardまで、任意のトンネル/ VPNタイプを使用できます。例えば:

  • x.x.x.x

    トンネルを立ち上げる:

    ip link add gre-y type gre local x.x.x.x remote y.y.y.y ttl 64
    ip link set gre-y up
    ip addr add 192.168.47.1/24 dev gre-y
    

    LANの場合と同様に、ポート転送ルールを追加します。

    iptables -t nat -I PREROUTING -p tcp --dport 1234 -j DNAT --to-destination 192.168.47.2
    
  • y.y.y.y

    トンネルを立ち上げる:

    ip link add gre-x type gre local y.y.y.y remote x.x.x.x ttl 64
    ip link set gre-x up
    ip addr add 192.168.47.2/24 dev gre-x
    

    それが機能することを確認してください:

    ping 192.168.47.1
    

    ポリシールーティングを設定して、応答(および応答のみ)がトンネルを通過するようにします。

    ip route add default via 192.168.47.1 dev gre-x table 1111
    ip rule add pref 1000 from 192.168.47.2 lookup 1111
    

(別のトンネル/ VPNタイプを使用するには、「トンネルの起動」部分のみを置き換えます。)

4
user1686

いいえ、それを達成することはできません。問題は、ルーティングが機能しないことです。

ホストE(外部)はパケットをホストF(フォワーダー)に送信します。 Fは、同じ送信元のパケットをホストD(宛先)に送信します。この部分は、Dが内部か外部かに関係なく機能します。

ここで、Dは回答を返す必要があり、それをパケット内の送信元アドレスEに送信します。

  • Dが内部ホストであり、FDのデフォルトゲートウェイである場合、パケットはFを通過します。ここで、ソースはD応答パケットのFに変更されます。ホストEFからのパケットを確認し、すべてが正常です。
  • Dが外部ホストの場合、FDのデフォルトゲートウェイではないため、Dは回答をE。ホストEDから回答を取得しますが、Fからの回答を期待しているため、Dからのパケットを破棄します。ホストEは数回再試行し、間違った送信元アドレスからの回答を再度破棄し、最終的にタイムアウトします。
3
RalfFriedl

送信元アドレスがリターンパケットに使用されるため、おそらくこれを達成することはできません。したがって、送信元アドレスがNATの背後にある場合、より広いインターネットから到達することはできません。

一般的に使用されている回避策は少なくとも2つあります(追加のソフトウェアと構成が必要です)。1つは、VPNを使用してルーターをバイパスするか、ルーターと宛先の間で使用して、宛先が送信元に到達する方法を認識できるようにすることです。

HTTPおよびHTTPSの場合、IPTABLESファイアウォールルールを使用せず、代わりにルーターで(透過的または通常の)プロキシを使用し、プロキシサーバーに外部アプリケーションがアクセスして処理できるX-FORWARDED-FORヘッダーを追加させます。 。

正確なアプリケーションとファイアウォールによっては、リクエストの送信元の送信元ポートを変更することで、「相対的な」内部IPアドレスをマークすることもできる場合があります(ルーターのアドレスから送信されますが、取得できる場合があります。ルーターの背後にあるどのシステムが送信元ポートに基づいて送信したかのヒント)。私はこれが実際に使われるのを見たことがありません。

2
davidgo