저는 Rust로 UDP 투명 프록시를 작성하고 있습니다. 여러 상자를 사용하고 있습니다.
- 소켓2=> RAW 소켓 생성에 대한 액세스
- nix::sys::소켓=> 모든 하위 수준 소켓 API 호출에 대한 액세스
- 표준::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 (내가 원하지 않는). 그러나 대신 I를 사용하면 TPROXY
들어오는 트래픽을 모두 얻지 못하고 내 컴퓨터에서 볼 수 있다고 "가정"한 것만 얻을 수 있습니다. 예를 들어 브로드캐스트 트래픽과 프록시 컴퓨터의 mac 주소가 대상으로 있는 트래픽은 다음을 수행할 수 있음을 의미합니다. 연결된 클라이언트의 모든 트래픽이 표시되지 않습니다.
내가 set 을 수행한다는 점에 유의해야 합니다 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에서 RX 및 TX 타임스탬프를 위한 비동기 소켓 recvmsg 구현
- 수신된 UDP 패킷의 대상 주소를 가져옵니다.
- iptables를 사용하여 시스템 전체 트래픽을 로컬 프록시 서버로 리디렉션
- REDIRECT 대신 iptables TPROXY 사용
- 투명 프록시에 대한 IPTables 구성
제가 기대하는 바는 들어오는 모든 트래픽을 수신하고 이를 TPROXY
포트 35로 리디렉션할 것으로 예상합니다.
나는 또한 stackoverflow에 비슷한 질문을 게시했지만 이것이 프로그래밍 질문일 뿐만 아니라 네트워크/리눅스 질문일 수도 있다는 생각이 들었습니다.
한 가지 더 언급하고 싶습니다. 어제 테스트하는 동안 비활성화했음에도 불구하고 ICMP redirection
(첫 번째 스니펫 참조) 기계가 어쨌든 Wireshark를 통해 읽는 ICMP 리디렉션 메시지를 보내는 것을 보았고 그것이 나를 꽤 당황하게 만들었습니다. .