relay_core_lib/capture/
original_dst.rs1use async_trait::async_trait;
2use std::collections::BTreeSet;
3use std::io;
4use std::net::SocketAddr;
5use tokio::net::TcpStream;
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 {
57 return Ok(None);
59 }
60
61 if addr.ss_family as i32 == libc::AF_INET {
62 let addr_in = *(&addr as *const _ as *const libc::sockaddr_in);
63 let ip = std::net::Ipv4Addr::from(u32::from_be(addr_in.sin_addr.s_addr));
68 let port = u16::from_be(addr_in.sin_port);
69 Ok(Some(SocketAddr::new(std::net::IpAddr::V4(ip), port)))
70 } else {
71 Err(io::Error::new(
74 io::ErrorKind::Unsupported,
75 "IPv6 transparent proxy not implemented",
76 ))
77 }
78 }
79 }
80
81 fn get_listen_addrs(&self) -> BTreeSet<SocketAddr> {
82 self.listen_addrs.clone()
83 }
84}
85
86pub struct NoOpOriginalDstProvider {
88 listen_addrs: BTreeSet<SocketAddr>,
89}
90
91impl NoOpOriginalDstProvider {
92 pub fn new(listen_addrs: BTreeSet<SocketAddr>) -> Self {
93 Self { listen_addrs }
94 }
95}
96
97#[async_trait]
98impl OriginalDstProvider for NoOpOriginalDstProvider {
99 fn get_original_dst(&self, _stream: &TcpStream) -> io::Result<Option<SocketAddr>> {
100 Ok(None)
101 }
102
103 fn get_listen_addrs(&self) -> BTreeSet<SocketAddr> {
104 self.listen_addrs.clone()
105 }
106}