Skip to content

Commit

Permalink
More UDP hacking
Browse files Browse the repository at this point in the history
  • Loading branch information
brianmay committed Jul 24, 2022
1 parent 1723645 commit 357b06b
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"cSpell.words": [
"addrinfo",
"addrtype",
"cmsg",
"dport",
"Errno",
"familys",
Expand All @@ -16,6 +17,7 @@
"lport",
"noncommercially",
"PREROUTING",
"recvmsg",
"RECVORIGDSTADDR",
"reprs",
"rustfmt",
Expand Down
50 changes: 36 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
nix = { version = "0.24.1", features = ["socket"] }
nix = { version = "0.24.1", features = [
"socket",
"net",
], path = "/home/brian/tree/3rdparty/nix" }
clap = { version = "3.2.12", features = ["derive"] }
regex = "1"
dns-lookup = "1.0.8"
Expand Down
143 changes: 120 additions & 23 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
use std::io::IoSliceMut;
use std::net::{IpAddr, UdpSocket};
use std::net::IpAddr;
use std::os::unix::prelude::AsRawFd;
use std::sync::Arc;
use std::time::Duration;
use std::{error::Error, fmt::Display, net::SocketAddr};

use fast_socks5::client::Socks5Stream;

use nix::sys::socket::{recvmsg, MsgFlags, RecvMsg};
use tokio::io::copy_bidirectional;
use tokio::net::{TcpListener, TcpStream};
use nix::cmsg_space;
use nix::errno::Errno;
use nix::sys::socket::sockopt::IpTransparent;
use nix::sys::socket::{
bind, recvmsg, setsockopt, socket, AddressFamily, ControlMessageOwned, MsgFlags, RecvMsg,
SockFlag, SockType, SockaddrIn,
};
use tokio::io::{copy_bidirectional, Interest};
use tokio::net::{TcpListener, TcpStream, UdpSocket};
use tokio::select;
use tokio::sync::mpsc;
use tokio::task::JoinError;
Expand Down Expand Up @@ -350,29 +356,120 @@ async fn listen_udp(
l_addr: ListenerAddr,
_socks_addr: SocketAddr,
) -> Result<(), ClientError> {
let _firewall = Arc::clone(firewall);
let firewall = Arc::clone(firewall);
tokio::task::spawn_blocking(move || {
// let firewall = Arc::clone(firewall);
let local = UdpSocket::bind(l_addr.addr)?;
local.set_nonblocking(false)?;
firewall.setup_udp_socket(&local)?;
std::thread::spawn(move || loop {
let local = UdpSocket::bind(l_addr.addr).await?;
// local.set_nonblocking(false)?;
firewall.setup_udp_socket(&local)?;

let _handle = tokio::spawn(async move {
loop {
// let firewall = Arc::clone(&firewall);
// let mut buf = [0u8; 65535];

// let (len, addr) = local.recv_from(&mut buf).await.unwrap();
// let l_addr = l_addr.clone();

let mut buf = vec![0u8; 1024];
let ioslice = IoSliceMut::new(&mut buf);
let mut cmsg_buffer = vec![0u8; 24];
println!("{l_addr} UDP waiting");
let cmsg: RecvMsg<nix::sys::socket::SockAddr> = recvmsg(
let mut iov = [IoSliceMut::new(&mut buf)];

let mut cmsg = cmsg_space!(libc::in6_addr);

log::debug!("udp readable?");
local.readable().await.unwrap();

log::debug!("recvmesg");
let msg: Result<RecvMsg<()>, _> = recvmsg(
local.as_raw_fd(),
&mut [ioslice],
Some(&mut cmsg_buffer),
&mut iov,
Some(&mut cmsg),
MsgFlags::empty(),
)
.unwrap();
println!("{l_addr} UDP {cmsg:?}");
});
Ok(())
})
.await?
);
log::debug!("recvmsg: {msg:?}", msg = msg);

let msg = match msg {
Ok(msg) => msg,
Err(Errno::EAGAIN) => {
continue;
}
Err(err) => {
log::error!("recvmsg failed: {err}");
continue;
}
};

for cmsg in msg.cmsgs() {
match cmsg {
ControlMessageOwned::Ipv4RecvOrigDstAddr(addr) => {
println!("IPv4 {addr:?}");
}
ControlMessageOwned::Ipv6RecvOrigDstAddr(addr) => {
println!("IPv6 {addr:?}");
}
_ => panic!("unexpected additional control msg"),
}
}
}
});
Ok(())

// use nix::sys::socket::sockopt::Ipv4RecvOrigDstAddr;
// let s: SockaddrIn = "127.0.0.1:12300".parse().unwrap();
// let receive = socket(
// AddressFamily::Inet,
// SockType::Datagram,
// SockFlag::empty(),
// None,
// )
// .expect("receive socket failed");
// setsockopt(receive, IpTransparent, &true).unwrap();
// bind(receive, &s).expect("bind failed");
// // let sa: SockaddrIn = getsockname(receive).expect("getsockname failed");
// setsockopt(receive, Ipv4RecvOrigDstAddr, &true).expect("setsockopt IP_RECVDSTADDR failed");
// // let value = 1u8;
// // let value_ptr: *const libc::c_void = &value as *const u8 as *const libc::c_void;
// // unsafe {
// // libc::setsockopt(
// // receive,
// // libc::IPPROTO_IP,
// // libc::IP_RECVORIGDSTADDR,
// // value_ptr,
// // std::mem::size_of::<u8>() as u32,
// // )
// // };

// tokio::spawn(async move {
// loop {
// // let iov = IoSliceMut::new(&mut buf);
// // let mut cmsg = vec![0u8; 48];
// let l_addr = l_addr.clone();
// println!("{l_addr} UDP waiting");
// let _: Result<_, ClientError> = tokio::task::spawn_blocking(move || {
// let mut buf = vec![0u8; 1024];
// let mut iov = [IoSliceMut::new(&mut buf)];

// let mut cmsg = cmsg_space!(libc::in_addr);
// let msg: RecvMsg<()> =
// recvmsg(receive, &mut iov, Some(&mut cmsg), MsgFlags::empty()).unwrap();
// for cmsg in msg.cmsgs() {
// match cmsg {
// ControlMessageOwned::Ipv4RecvOrigDstAddr(addr) => {
// println!("{addr:?}");
// }
// _ => panic!("unexpected additional control msg"),
// }
// }
// println!("{l_addr} UDP {msg:?}");
// Ok(())
// })
// .await
// .unwrap();
// }
// });
// // })
// // .await
// // .unwrap();
// Ok(())
}

async fn handle_tcp_client(
Expand Down
4 changes: 2 additions & 2 deletions src/firewall.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{
error::Error,
fmt::Display,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, UdpSocket},
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
os::unix::prelude::AsRawFd,
};

Expand All @@ -12,7 +12,7 @@ use nix::{
sockopt::{Ip6tOriginalDst, OriginalDst},
},
};
use tokio::net::{TcpListener, TcpStream};
use tokio::net::{TcpListener, TcpStream, UdpSocket};

use crate::{
commands::Commands,
Expand Down
8 changes: 4 additions & 4 deletions src/firewall/tproxy.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::net::SocketAddr;
use std::net::UdpSocket;
use std::os::unix::prelude::AsRawFd;

use nix::sys::socket::setsockopt;
use nix::sys::socket::sockopt::IpTransparent;
use tokio::net::TcpListener;
use tokio::net::TcpStream;
use tokio::net::UdpSocket;

use crate::network::ListenerAddr;
use crate::network::Ports;
Expand Down Expand Up @@ -79,8 +79,8 @@ impl TProxyFirewall {
ipm!("-I", "PREROUTING", "1", "-j", &tproxy_chain);
}

ipm!("-A", &mark_chain, "-j", "RETURN", "-m", "addrtype", "--dst-type", "LOCAL");
ipm!("-A", &tproxy_chain, "-j", "RETURN", "-m", "addrtype", "--dst-type", "LOCAL");
ipm!("-A", &mark_chain, "-j", "RETURN", "-m", "addrtype", "--dst-type", "LOCAL", "-m", protocol, "-p", protocol);
ipm!("-A", &tproxy_chain, "-j", "RETURN", "-m", "addrtype", "--dst-type", "LOCAL", "-m", protocol, "-p", protocol);

ipm!("-A", &divert_chain, "-j", "MARK", "--set-mark", tmark);
ipm!("-A", &divert_chain, "-j", "ACCEPT");
Expand Down Expand Up @@ -187,7 +187,7 @@ impl Firewall for TProxyFirewall {
fn setup_udp_socket(&self, l: &UdpSocket) -> Result<(), FirewallError> {
let fd = l.as_raw_fd();
setsockopt(fd, IpTransparent, &true)?;
l.set_nonblocking(true)?;
// l.set_nonblocking(true)?;

let value = 1u8;
let value_ptr: *const libc::c_void = &value as *const u8 as *const libc::c_void;
Expand Down

0 comments on commit 357b06b

Please sign in to comment.