Skip to content

Instantly share code, notes, and snippets.

@Sherlock-Holo
Created May 18, 2020 05:24
Show Gist options
  • Save Sherlock-Holo/a2b83d388edfcb9132a1b583593e7430 to your computer and use it in GitHub Desktop.
Save Sherlock-Holo/a2b83d388edfcb9132a1b583593e7430 to your computer and use it in GitHub Desktop.
get original dst addr
use std::io::{Error, Result};
use std::mem::{MaybeUninit, size_of};
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::os::unix::io::AsRawFd;
use async_std::net::TcpListener;
use futures::StreamExt;
#[async_std::main]
async fn main() {
let listener = TcpListener::bind("[::]:9876").await.unwrap();
let mut incoming = listener.incoming();
while let Some(stream) = incoming.next().await {
let stream = stream.unwrap();
let addr = get_original_addr(&stream).unwrap();
println!("{}", addr);
}
}
fn get_original_addr<T: AsRawFd>(fd: &T) -> Result<SocketAddr> {
let mut ipv6_addr = MaybeUninit::<libc::sockaddr_in6>::zeroed();
let mut size = size_of::<libc::sockaddr_in6>() as u32;
unsafe {
if libc::getsockopt(fd.as_raw_fd(), libc::SOL_IPV6, libc::IP6T_SO_ORIGINAL_DST, ipv6_addr.as_mut_ptr() as _, &mut size as _) == 0 {
let ipv6_addr = ipv6_addr.assume_init();
return Ok(SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(ipv6_addr.sin6_addr.s6_addr), ipv6_addr.sin6_port.to_be(), ipv6_addr.sin6_flowinfo, ipv6_addr.sin6_scope_id)));
}
}
let mut ipv4_addr = MaybeUninit::<libc::sockaddr_in>::zeroed();
let mut size = size_of::<libc::sockaddr_in>() as u32;
unsafe {
if libc::getsockopt(fd.as_raw_fd(), libc::SOL_IP, libc::SO_ORIGINAL_DST, ipv4_addr.as_mut_ptr() as _, &mut size as _) < 0 {
Err(Error::last_os_error())
} else {
let ipv4_addr = ipv4_addr.assume_init();
Ok(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(ipv4_addr.sin_addr.s_addr.to_be()), ipv4_addr.sin_port.to_be())))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment