Skip to content

Commit 1baecd0

Browse files
committed
More UDP hacking
1 parent 1723645 commit 1baecd0

File tree

6 files changed

+150
-42
lines changed

6 files changed

+150
-42
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: 102 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
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::sys::socket::sockopt::IpTransparent;
12+
use nix::sys::socket::{
13+
bind, recvmsg, setsockopt, socket, AddressFamily, ControlMessageOwned, MsgFlags, RecvMsg,
14+
SockFlag, SockType, SockaddrIn,
15+
};
16+
use tokio::io::{copy_bidirectional, Interest};
17+
use tokio::net::{TcpListener, TcpStream, UdpSocket};
1318
use tokio::select;
1419
use tokio::sync::mpsc;
1520
use tokio::task::JoinError;
@@ -350,29 +355,105 @@ async fn listen_udp(
350355
l_addr: ListenerAddr,
351356
_socks_addr: SocketAddr,
352357
) -> Result<(), ClientError> {
358+
let _firewall = Arc::clone(firewall);
353359
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 {
360+
let local = UdpSocket::bind(l_addr.addr).await?;
361+
// local.set_nonblocking(false)?;
362+
firewall.setup_udp_socket(&local)?;
363+
364+
let _handle = tokio::spawn(async move {
365+
loop {
366+
// let firewall = Arc::clone(&firewall);
367+
// let mut buf = [0u8; 65535];
368+
369+
// let (len, addr) = local.recv_from(&mut buf).await.unwrap();
370+
// let l_addr = l_addr.clone();
371+
360372
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(
373+
let mut iov = [IoSliceMut::new(&mut buf)];
374+
375+
let mut cmsg = cmsg_space!(libc::in_addr);
376+
377+
local.readable().await.unwrap();
378+
let msg: RecvMsg<()> = recvmsg(
365379
local.as_raw_fd(),
366-
&mut [ioslice],
367-
Some(&mut cmsg_buffer),
380+
&mut iov,
381+
Some(&mut cmsg),
368382
MsgFlags::empty(),
369383
)
370384
.unwrap();
371-
println!("{l_addr} UDP {cmsg:?}");
372-
});
373-
Ok(())
374-
})
375-
.await?
385+
for cmsg in msg.cmsgs() {
386+
match cmsg {
387+
ControlMessageOwned::Ipv4RecvOrigDstAddr(addr) => {
388+
println!("IPv4 {addr:?}");
389+
}
390+
ControlMessageOwned::Ipv6RecvOrigDstAddr(addr) => {
391+
println!("IPv6 {addr:?}");
392+
}
393+
_ => panic!("unexpected additional control msg"),
394+
}
395+
}
396+
}
397+
});
398+
Ok(())
399+
400+
// use nix::sys::socket::sockopt::Ipv4RecvOrigDstAddr;
401+
// let s: SockaddrIn = "127.0.0.1:12300".parse().unwrap();
402+
// let receive = socket(
403+
// AddressFamily::Inet,
404+
// SockType::Datagram,
405+
// SockFlag::empty(),
406+
// None,
407+
// )
408+
// .expect("receive socket failed");
409+
// setsockopt(receive, IpTransparent, &true).unwrap();
410+
// bind(receive, &s).expect("bind failed");
411+
// // let sa: SockaddrIn = getsockname(receive).expect("getsockname failed");
412+
// setsockopt(receive, Ipv4RecvOrigDstAddr, &true).expect("setsockopt IP_RECVDSTADDR failed");
413+
// // let value = 1u8;
414+
// // let value_ptr: *const libc::c_void = &value as *const u8 as *const libc::c_void;
415+
// // unsafe {
416+
// // libc::setsockopt(
417+
// // receive,
418+
// // libc::IPPROTO_IP,
419+
// // libc::IP_RECVORIGDSTADDR,
420+
// // value_ptr,
421+
// // std::mem::size_of::<u8>() as u32,
422+
// // )
423+
// // };
424+
425+
// tokio::spawn(async move {
426+
// loop {
427+
// // let iov = IoSliceMut::new(&mut buf);
428+
// // let mut cmsg = vec![0u8; 48];
429+
// let l_addr = l_addr.clone();
430+
// println!("{l_addr} UDP waiting");
431+
// let _: Result<_, ClientError> = tokio::task::spawn_blocking(move || {
432+
// let mut buf = vec![0u8; 1024];
433+
// let mut iov = [IoSliceMut::new(&mut buf)];
434+
435+
// let mut cmsg = cmsg_space!(libc::in_addr);
436+
// let msg: RecvMsg<()> =
437+
// recvmsg(receive, &mut iov, Some(&mut cmsg), MsgFlags::empty()).unwrap();
438+
// for cmsg in msg.cmsgs() {
439+
// match cmsg {
440+
// ControlMessageOwned::Ipv4RecvOrigDstAddr(addr) => {
441+
// println!("{addr:?}");
442+
// }
443+
// _ => panic!("unexpected additional control msg"),
444+
// }
445+
// }
446+
// println!("{l_addr} UDP {msg:?}");
447+
// Ok(())
448+
// })
449+
// .await
450+
// .unwrap();
451+
// }
452+
// });
453+
// // })
454+
// // .await
455+
// // .unwrap();
456+
// Ok(())
376457
}
377458

378459
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)