TPROXY はすべてのトラフィックを指定されたポートにリダイレクトしません

TPROXY はすべてのトラフィックを指定されたポートにリダイレクトしません

私はRustでUDP透過プロキシを書いています。いくつかのクレートを使用しています。

プロキシとして機能するはずのマシンが、ターゲット マシンのゲートウェイとして設定されています。

プロキシマシンでは Linux カーネルのリダイレクト機能が有効になっています。以下のスニペットを参照してください。

#!/bin/sh

# Redirect packets coming to the computer
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1

# Disable ICMP redirection
sysctl -w net.ipv4.conf.all.send_redirects=0

マシンには、NFTABLESすべての着信トラフィックをプロキシプログラムにリダイレクトするルールも設定されています。以下のスニペットを参照してください。

#!/bin/sh

# Setting up NFTABLES

nft add table filter
nft add chain filter divert "{ type filter hook prerouting priority -150; }"
nft add rule filter divert meta l4proto udp socket transparent 1 meta mark set 1 accept

#nft add table ip nat
#nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; }

# Creating a new rule that redirects UDP traffic from P1-P2 to port 35

nft add rule filter divert udp dport 80-65525 tproxy to :35 meta mark set 1 accept

#nft add rule ip nat prerouting udp dport 80-65525 redirect to :35

コメントアウトされた部分からわかるように、私はNAT PREROUTINGとの両方を試しましたTPROXY。 広範囲にわたる調査とテストの結果、NAT PREROUTINGプロキシ (ポート 35 でリッスンしている) を使用すると、クライアントからの着信トラフィックがすべて取得されますが、ソケットからパケットを読み取ると、元の宛先アドレスがプロキシ マシンの IP で上書きされる (これは望ましくありません) ことがわかりました。 しかし、代わりに を使用すると、着信TPROXYトラフィックがすべて取得されるわけではなく、マシンが「認識するはず」のもの (たとえば、ブロードキャスト トラフィックや、プロキシ マシンの MAC アドレスを宛先とするトラフィック) のみが取得されます。つまり、接続されたクライアントからのトラフィックがすべて認識されるわけではありません。

私は、Linux カーネルの tproxy マニュアル

私が設定していることに注意する必要がありますIP_TRANSPARENT

これらは私がプログラムで設定したものです

use socket2::{Socket, Domain, Type, Protocol};
use std::os::fd::{OwnedFd, RawFd, AsRawFd};
use nix::sys::socket::{
    ...
    sockopt::{IpTransparent, Ipv4OrigDstAddr, Ipv4PacketInfo},
    setsockopt,
    ...
};
...
let client_to_proxy_socket = match Socket::new(Domain::IPV4, Type::RAW, Some(Protocol::UDP)) { ... };
let socket_ref: OwnedFd = client_to_proxy_socket.into();
let active: bool = true;
match setsockopt(&socket_ref, IpTransparent, &active) { ... };   // IP_TRANSPARENT
match setsockopt(&socket_ref, Ipv4OrigDstAddr, &active) { ... }; // SO_ORIGINAL_DST
match setsockopt(&socket_ref, Ipv4PacketInfo, &active) { ... };  // IP_PKTINFO
...

私が試したことに関して言えば、バリエーションや異なる構造を持つルールとコードのさまざまな組み合わせを試したと言わざるを得ません。

すでに何度も訪れて読んだリンクの短いリストを投稿します

私が期待していることとしては、すべての着信トラフィックを取得し、それをTPROXYポート 35 にリダイレクトすることを期待しています。

私も stackoverflow に同様の質問を投稿しましたが、これはプログラミングに関する質問だけでなく、ネットワーク/Linux に関する質問でもある可能性があることに気づきました。

もう 1 つ注意したいのは、昨日のテスト中に、無効にしたにもかかわらずICMP redirection(最初のスニペットを参照)、マシンが ICMP リダイレクト メッセージを送信し、Wireshark で読み取っているのがわかり、かなり困惑したことです。

関連情報