我正在用 Rust 编写一个 UDP 透明代理,我使用了几个板条箱
- 插座2=> 访问 RAW 套接字的创建
- nix::sys::套接字=> 访问所有低级套接字 API 调用
- std::net::套接字=> 访问标准套接字
应该充当代理的机器已被设置为目标机器的网关。
代理机器已启用 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
...
当谈到我所尝试过的事情时,我必须说我已经尝试了很多规则和代码的可能组合,包括变化和不同的结构。
我将发布一个简短的链接列表,这些链接我已经访问过并读过多次
- 使用 Rust 实现异步套接字 recvmsg 用于 RX 和 TX 时间戳
- 获取收到的 UDP 数据包的目标地址
- 使用 iptables 将系统范围的流量重定向到本地代理服务器
- 使用 iptables TPROXY 代替 REDIRECT
- 透明代理的 IPTables 配置
至于我的期望,我希望获取所有传入流量并将其重定向TPROXY
到端口 35。
我也在 stackoverflow 上发布了类似的问题,但我突然想到这不仅是一个编程问题,也可能是一个网络/linux 问题。
我想再指出一件事,在昨天的测试中,我发现即使我禁用了ICMP redirection
(参见第一个片段),我仍然看到机器正在发送 ICMP 重定向消息,无论如何通过 wireshark 读取它们,这让我非常困惑。