Skip to content

Commit 357b06b

Browse files
committed
More UDP hacking
1 parent 1723645 commit 357b06b

File tree

6 files changed

+168
-44
lines changed

6 files changed

+168
-44
lines changed

.vscode/settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"cSpell.words": [
33
"addrinfo",
44
"addrtype",
5+
"cmsg",
56
"dport",
67
"Errno",
78
"familys",
@@ -16,6 +17,7 @@
1617
"lport",
1718
"noncommercially",
1819
"PREROUTING",
20+
"recvmsg",
1921
"RECVORIGDSTADDR",
2022
"reprs",
2123
"rustfmt",

Cargo.lock

Lines changed: 36 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9-
nix = { version = "0.24.1", features = ["socket"] }
9+
nix = { version = "0.24.1", features = [
10+
"socket",
11+
"net",
12+
], path = "/home/brian/tree/3rdparty/nix" }
1013
clap = { version = "3.2.12", features = ["derive"] }
1114
regex = "1"
1215
dns-lookup = "1.0.8"

src/client.rs

Lines changed: 120 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
use std::io::IoSliceMut;
2-
use std::net::{IpAddr, UdpSocket};
2+
use std::net::IpAddr;
33
use std::os::unix::prelude::AsRawFd;
44
use std::sync::Arc;
55
use std::time::Duration;
66
use std::{error::Error, fmt::Display, net::SocketAddr};
77

88
use fast_socks5::client::Socks5Stream;
99

10-
use nix::sys::socket::{recvmsg, MsgFlags, RecvMsg};
11-
use tokio::io::copy_bidirectional;
12-
use tokio::net::{TcpListener, TcpStream};
10+
use nix::cmsg_space;
11+
use nix::errno::Errno;
12+
use nix::sys::socket::sockopt::IpTransparent;
13+
use nix::sys::socket::{
14+
bind, recvmsg, setsockopt, socket, AddressFamily, ControlMessageOwned, MsgFlags, RecvMsg,
15+
SockFlag, SockType, SockaddrIn,
16+
};
17+
use tokio::io::{copy_bidirectional, Interest};
18+
use tokio::net::{TcpListener, TcpStream, UdpSocket};
1319
use tokio::select;
1420
use tokio::sync::mpsc;
1521
use tokio::task::JoinError;
@@ -350,29 +356,120 @@ async fn listen_udp(
350356
l_addr: ListenerAddr,
351357
_socks_addr: SocketAddr,
352358
) -> Result<(), ClientError> {
359+
let _firewall = Arc::clone(firewall);
353360
let firewall = Arc::clone(firewall);
354-
tokio::task::spawn_blocking(move || {
355-
// let firewall = Arc::clone(firewall);
356-
let local = UdpSocket::bind(l_addr.addr)?;
357-
local.set_nonblocking(false)?;
358-
firewall.setup_udp_socket(&local)?;
359-
std::thread::spawn(move || loop {
361+
let local = UdpSocket::bind(l_addr.addr).await?;
362+
// local.set_nonblocking(false)?;
363+
firewall.setup_udp_socket(&local)?;
364+
365+
let _handle = tokio::spawn(async move {
366+
loop {
367+
// let firewall = Arc::clone(&firewall);
368+
// let mut buf = [0u8; 65535];
369+
370+
// let (len, addr) = local.recv_from(&mut buf).await.unwrap();
371+
// let l_addr = l_addr.clone();
372+
360373
let mut buf = vec![0u8; 1024];
361-
let ioslice = IoSliceMut::new(&mut buf);
362-
let mut cmsg_buffer = vec![0u8; 24];
363-
println!("{l_addr} UDP waiting");
364-
let cmsg: RecvMsg<nix::sys::socket::SockAddr> = recvmsg(
374+
let mut iov = [IoSliceMut::new(&mut buf)];
375+
376+
let mut cmsg = cmsg_space!(libc::in6_addr);
377+
378+
log::debug!("udp readable?");
379+
local.readable().await.unwrap();
380+
381+
log::debug!("recvmesg");
382+
let msg: Result<RecvMsg<()>, _> = recvmsg(
365383
local.as_raw_fd(),
366-
&mut [ioslice],
367-
Some(&mut cmsg_buffer),
384+
&mut iov,
385+
Some(&mut cmsg),
368386
MsgFlags::empty(),
369-
)
370-
.unwrap();
371-
println!("{l_addr} UDP {cmsg:?}");
372-
});
373-
Ok(())
374-
})
375-
.await?
387+
);
388+
log::debug!("recvmsg: {msg:?}", msg = msg);
389+
390+
let msg = match msg {
391+
Ok(msg) => msg,
392+
Err(Errno::EAGAIN) => {
393+
continue;
394+
}
395+
Err(err) => {
396+
log::error!("recvmsg failed: {err}");
397+
continue;
398+
}
399+
};
400+
401+
for cmsg in msg.cmsgs() {
402+
match cmsg {
403+
ControlMessageOwned::Ipv4RecvOrigDstAddr(addr) => {
404+
println!("IPv4 {addr:?}");
405+
}
406+
ControlMessageOwned::Ipv6RecvOrigDstAddr(addr) => {
407+
println!("IPv6 {addr:?}");
408+
}
409+
_ => panic!("unexpected additional control msg"),
410+
}
411+
}
412+
}
413+
});
414+
Ok(())
415+
416+
// use nix::sys::socket::sockopt::Ipv4RecvOrigDstAddr;
417+
// let s: SockaddrIn = "127.0.0.1:12300".parse().unwrap();
418+
// let receive = socket(
419+
// AddressFamily::Inet,
420+
// SockType::Datagram,
421+
// SockFlag::empty(),
422+
// None,
423+
// )
424+
// .expect("receive socket failed");
425+
// setsockopt(receive, IpTransparent, &true).unwrap();
426+
// bind(receive, &s).expect("bind failed");
427+
// // let sa: SockaddrIn = getsockname(receive).expect("getsockname failed");
428+
// setsockopt(receive, Ipv4RecvOrigDstAddr, &true).expect("setsockopt IP_RECVDSTADDR failed");
429+
// // let value = 1u8;
430+
// // let value_ptr: *const libc::c_void = &value as *const u8 as *const libc::c_void;
431+
// // unsafe {
432+
// // libc::setsockopt(
433+
// // receive,
434+
// // libc::IPPROTO_IP,
435+
// // libc::IP_RECVORIGDSTADDR,
436+
// // value_ptr,
437+
// // std::mem::size_of::<u8>() as u32,
438+
// // )
439+
// // };
440+
441+
// tokio::spawn(async move {
442+
// loop {
443+
// // let iov = IoSliceMut::new(&mut buf);
444+
// // let mut cmsg = vec![0u8; 48];
445+
// let l_addr = l_addr.clone();
446+
// println!("{l_addr} UDP waiting");
447+
// let _: Result<_, ClientError> = tokio::task::spawn_blocking(move || {
448+
// let mut buf = vec![0u8; 1024];
449+
// let mut iov = [IoSliceMut::new(&mut buf)];
450+
451+
// let mut cmsg = cmsg_space!(libc::in_addr);
452+
// let msg: RecvMsg<()> =
453+
// recvmsg(receive, &mut iov, Some(&mut cmsg), MsgFlags::empty()).unwrap();
454+
// for cmsg in msg.cmsgs() {
455+
// match cmsg {
456+
// ControlMessageOwned::Ipv4RecvOrigDstAddr(addr) => {
457+
// println!("{addr:?}");
458+
// }
459+
// _ => panic!("unexpected additional control msg"),
460+
// }
461+
// }
462+
// println!("{l_addr} UDP {msg:?}");
463+
// Ok(())
464+
// })
465+
// .await
466+
// .unwrap();
467+
// }
468+
// });
469+
// // })
470+
// // .await
471+
// // .unwrap();
472+
// Ok(())
376473
}
377474

378475
async fn handle_tcp_client(

src/firewall.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{
22
error::Error,
33
fmt::Display,
4-
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, UdpSocket},
4+
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
55
os::unix::prelude::AsRawFd,
66
};
77

@@ -12,7 +12,7 @@ use nix::{
1212
sockopt::{Ip6tOriginalDst, OriginalDst},
1313
},
1414
};
15-
use tokio::net::{TcpListener, TcpStream};
15+
use tokio::net::{TcpListener, TcpStream, UdpSocket};
1616

1717
use crate::{
1818
commands::Commands,

src/firewall/tproxy.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use std::net::SocketAddr;
2-
use std::net::UdpSocket;
32
use std::os::unix::prelude::AsRawFd;
43

54
use nix::sys::socket::setsockopt;
65
use nix::sys::socket::sockopt::IpTransparent;
76
use tokio::net::TcpListener;
87
use tokio::net::TcpStream;
8+
use tokio::net::UdpSocket;
99

1010
use crate::network::ListenerAddr;
1111
use crate::network::Ports;
@@ -79,8 +79,8 @@ impl TProxyFirewall {
7979
ipm!("-I", "PREROUTING", "1", "-j", &tproxy_chain);
8080
}
8181

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

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

192192
let value = 1u8;
193193
let value_ptr: *const libc::c_void = &value as *const u8 as *const libc::c_void;

0 commit comments

Comments
 (0)