relay_core_lib/capture/
original_dst.rs1use std::net::SocketAddr;
2use tokio::net::TcpStream;
3use std::collections::BTreeSet;
4use std::io;
5use async_trait::async_trait;
6
7#[async_trait]
9pub trait OriginalDstProvider: Send + Sync {
10 fn get_original_dst(&self, stream: &TcpStream) -> io::Result<Option<SocketAddr>>;
12
13 fn get_listen_addrs(&self) -> BTreeSet<SocketAddr>;
15}
16
17#[cfg(all(target_os = "macos", feature = "transparent-macos"))]
18pub use crate::capture::macos_pf::MacOsOriginalDstProvider;
19
20#[cfg(target_os = "windows")]
21pub use crate::capture::windows::WindowsOriginalDstProvider;
22
23#[cfg(all(target_os = "linux", feature = "transparent-linux"))]
25pub struct LinuxOriginalDstProvider {
26 listen_addrs: BTreeSet<SocketAddr>,
27}
28
29#[cfg(all(target_os = "linux", feature = "transparent-linux"))]
30impl LinuxOriginalDstProvider {
31 pub fn new(listen_addrs: BTreeSet<SocketAddr>) -> Self {
32 Self { listen_addrs }
33 }
34}
35
36#[cfg(all(target_os = "linux", feature = "transparent-linux"))]
37#[async_trait]
38impl OriginalDstProvider for LinuxOriginalDstProvider {
39 fn get_original_dst(&self, stream: &TcpStream) -> io::Result<Option<SocketAddr>> {
40 use std::os::unix::io::AsRawFd;
41 let fd = stream.as_raw_fd();
42
43 unsafe {
44 let mut addr: libc::sockaddr_storage = std::mem::zeroed();
45 let mut len = std::mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
46
47 if libc::getsockopt(
50 fd,
51 libc::SOL_IP,
52 80,
53 &mut addr as *mut _ as *mut libc::c_void,
54 &mut len,
55 ) != 0 {
56 return Ok(None);
58 }
59
60 if addr.ss_family as i32 == libc::AF_INET {
61 let addr_in = *(&addr as *const _ as *const libc::sockaddr_in);
62 let ip = std::net::Ipv4Addr::from(u32::from_be(addr_in.sin_addr.s_addr));
67 let port = u16::from_be(addr_in.sin_port);
68 Ok(Some(SocketAddr::new(std::net::IpAddr::V4(ip), port)))
69 } else {
70 Err(io::Error::new(io::ErrorKind::Unsupported, "IPv6 transparent proxy not implemented"))
73 }
74 }
75 }
76
77 fn get_listen_addrs(&self) -> BTreeSet<SocketAddr> {
78 self.listen_addrs.clone()
79 }
80}
81
82pub struct NoOpOriginalDstProvider {
84 listen_addrs: BTreeSet<SocketAddr>,
85}
86
87impl NoOpOriginalDstProvider {
88 pub fn new(listen_addrs: BTreeSet<SocketAddr>) -> Self {
89 Self { listen_addrs }
90 }
91}
92
93#[async_trait]
94impl OriginalDstProvider for NoOpOriginalDstProvider {
95 fn get_original_dst(&self, _stream: &TcpStream) -> io::Result<Option<SocketAddr>> {
96 Ok(None)
97 }
98
99 fn get_listen_addrs(&self) -> BTreeSet<SocketAddr> {
100 self.listen_addrs.clone()
101 }
102}