Ich schreibe einen transparenten UDP-Proxy in Rust und verwende mehrere Kisten
- Buchse2=> Zugang zur Erstellung eines RAW-Sockets
- nix::sys::socket=> Zugriff auf alle Low-Level-Socket-API-Aufrufe
- std::net::socket=> Zugang zur Normsteckdose
Die Maschine, die als Proxy fungieren soll, wurde als Gateway für die Zielmaschinen festgelegt.
Auf dem Proxy-Rechner sind die Umleitungsfunktionen des Linux-Kernels aktiviert, siehe Snippet unten
#!/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
Auf dem Computer ist außerdem eine NFTABLES
Regel eingerichtet, die den gesamten eingehenden Datenverkehr an das Proxy-Programm umleitet (siehe unten).
#!/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
Wie Sie an den auskommentierten Teilen sehen können, habe ich sowohl mit NAT PREROUTING
als auch experimentiert TPROXY
. Nach umfangreichen Recherchen und Tests habe ich herausgefunden, dass bei Verwendung NAT PREROUTING
meines Proxys (der auf Port 35 lauscht) der GESAMTE eingehende Datenverkehr von den Clients empfangen wird, aber wenn ich die Pakete vom Socket lese, wird die ursprüngliche Zieladresse mit der IP des Proxy-Rechners überschrieben (was ich nicht will). Wenn ich stattdessen verwende, TPROXY
erhalte ich nicht den gesamten eingehenden Datenverkehr, sondern nur das, was mein Rechner „sehen soll“, z. B. Broadcast-Datenverkehr und Datenverkehr, der die Mac-Adresse des Proxy-Rechners als Ziel hat. Das bedeutet, dass ich nicht den gesamten Datenverkehr der verbundenen Clients sehen kann.
Ich habe die Anweisungen befolgt, die in dertproxy-Handbuch des Linux-Kernels.
Es muss beachtet werden, dass ich setze IP_TRANSPARENT
.
Dies sind die Dinge, die ich in meinem Programm einstelle
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
...
Zu dem, was ich versucht habe, muss ich sagen, dass ich viele mögliche Kombinationen von Regeln und Code mit Variationen und unterschiedlichen Strukturen ausprobiert habe.
Ich werde eine kurze Liste von Links veröffentlichen, die ich bereits besucht und mehrmals gelesen habe
- Implementieren Sie asynchrones Socket recvmsg für RX- und TX-Zeitstempel in Rust
- Zieladresse eines empfangenen UDP-Pakets abrufen
- Systemweite Umleitung des Datenverkehrs zum lokalen Proxyserver mithilfe von iptables
- Verwenden von iptables TPROXY anstelle von REDIRECT
- IPTables-Konfiguration für Transparent Proxy
Ich gehe davon aus, dass der gesamte eingehende Datenverkehr TPROXY
auf Port 35 umgeleitet wird.
Ich habe auch eine ähnliche Frage auf Stackoverflow gepostet, aber mir ist aufgefallen, dass dies nicht nur eine Programmierfrage ist, sondern auch eine Netzwerk-/Linux-Frage sein könnte.
Ich möchte noch auf eines hinweisen: Bei meinen Tests gestern habe ich festgestellt, dass ICMP redirection
die Maschine, obwohl ich sie deaktiviert hatte (siehe erstes Snippet), trotzdem ICMP-Umleitungsnachrichten sendete und sie über Wireshark las, und das hat mich ziemlich verwirrt.