feat: allow_fragmentation in UdpSocketOptions

This commit is contained in:
zonyitoo
2024-12-01 10:27:05 +08:00
12 changed files with 644 additions and 3428 deletions

View File

@@ -142,6 +142,7 @@ impl Server {
connect_opts.tcp.keepalive = config.keep_alive.or(Some(LOCAL_DEFAULT_KEEPALIVE_TIMEOUT));
connect_opts.tcp.mptcp = config.mptcp;
connect_opts.udp.mtu = config.udp_mtu;
connect_opts.udp.allow_fragmentation = config.outbound_udp_allow_fragmentation;
context.set_connect_opts(connect_opts);
let mut accept_opts = AcceptOpts {

View File

@@ -106,7 +106,7 @@ impl TcpStreamRedirExt for TcpStream {
PF.natlook(&bind_addr, &peer_addr, Protocol::TCP)
}
#[cfg(target_os = "openbsd")] //in OpenBSD, we can get TCP destination address with getsockname()
#[cfg(target_os = "openbsd")] // in OpenBSD, we can get TCP destination address with getsockname()
RedirType::PacketFilter => self.local_addr(),
#[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios"))]
RedirType::IpFirewall => {

View File

@@ -20,8 +20,8 @@ use crate::{
sys::set_ipv6_only,
},
};
const IP_RECVDSTPORT: i32 = 33; //Temporary workaround until libc supports this
const IPV6_RECVDSTPORT: i32 = 64; //Temporary workaround until libc supports this
const IP_RECVDSTPORT: i32 = 33; // Temporary workaround until libc supports this
const IPV6_RECVDSTPORT: i32 = 64; // Temporary workaround until libc supports this
pub struct UdpRedirSocket {
io: AsyncFd<UdpSocket>,
@@ -240,7 +240,7 @@ fn get_destination_addr(msg: &libc::msghdr) -> io::Result<SocketAddr> {
unsafe {
let (_, addr) = SockAddr::try_init(|dst_addr, dst_addr_len| {
let mut cmsg: *mut libc::cmsghdr = libc::CMSG_FIRSTHDR(msg);
let mut addr_or_port_received = false; //The address should come first and then the port, but we use a flag just in case. https://github.com/openbsd/src/blob/3d310523b415eeee9db46a5b67eecf8f9fdd5c8f/sys/netinet/udp_usrreq.c#L662-L687
let mut addr_or_port_received = false; // The address should come first and then the port, but we use a flag just in case. https://github.com/openbsd/src/blob/3d310523b415eeee9db46a5b67eecf8f9fdd5c8f/sys/netinet/udp_usrreq.c#L662-L687
while !cmsg.is_null() {
let rcmsg = &*cmsg;
match (rcmsg.cmsg_level, rcmsg.cmsg_type) {

View File

@@ -53,6 +53,7 @@ pub async fn run(config: Config) -> io::Result<()> {
connect_opts.tcp.keepalive = config.keep_alive.or(Some(SERVER_DEFAULT_KEEPALIVE_TIMEOUT));
connect_opts.tcp.mptcp = config.mptcp;
connect_opts.udp.mtu = config.udp_mtu;
connect_opts.udp.allow_fragmentation = config.outbound_udp_allow_fragmentation;
let mut accept_opts = AcceptOpts {
ipv6_only: config.ipv6_only,

View File

@@ -4,7 +4,7 @@ use std::{io, net::SocketAddr, sync::Arc, time::Duration};
use futures::future;
use log::trace;
use shadowsocks::net::{AcceptOpts, ConnectOpts};
use shadowsocks::net::{AcceptOpts, ConnectOpts, UdpSocketOpts};
use crate::{
config::{Config, ConfigType},
@@ -66,7 +66,12 @@ pub async fn run(config: Config) -> io::Result<()> {
bind_local_addr: config.outbound_bind_addr.map(|ip| SocketAddr::new(ip, 0)),
bind_interface: config.outbound_bind_interface,
udp_allow_fragmentation: config.outbound_udp_allow_fragmentation,
udp: UdpSocketOpts {
allow_fragmentation: config.outbound_udp_allow_fragmentation,
..Default::default()
},
..Default::default()
};
@@ -122,7 +127,7 @@ pub async fn run(config: Config) -> io::Result<()> {
}
if let Some(udp_allow_fragmentation) = inst.outbound_udp_allow_fragmentation {
connect_opts.udp_allow_fragmentation = udp_allow_fragmentation;
connect_opts.udp.allow_fragmentation = udp_allow_fragmentation;
}
server_builder.set_connect_opts(connect_opts);

View File

@@ -5,7 +5,7 @@ use std::net::SocketAddr;
#[cfg(unix)]
pub use self::sys::uds::{UnixListener, UnixStream};
pub use self::{
option::{AcceptOpts, ConnectOpts, TcpSocketOpts},
option::{AcceptOpts, ConnectOpts, TcpSocketOpts, UdpSocketOpts},
sys::{get_ip_stack_capabilities, set_tcp_fastopen, socket_bind_dual_stack, IpStackCapabilities},
tcp::{TcpListener, TcpStream},
udp::UdpSocket,

View File

@@ -37,6 +37,9 @@ pub struct UdpSocketOpts {
///
/// NOTE: MTU includes IP header, UDP header, UDP payload
pub mtu: Option<usize>,
/// Outbound UDP socket allows IP fragmentation
pub allow_fragmentation: bool,
}
/// Options for connecting to remote server
@@ -65,9 +68,6 @@ pub struct ConnectOpts {
/// Outbound socket binds to interface
pub bind_interface: Option<String>,
/// Outbound UDP socket allows IP fragmentation
pub udp_allow_fragmentation: bool,
/// TCP options
pub tcp: TcpSocketOpts,

View File

@@ -251,7 +251,7 @@ pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, _config: &ConnectO
UdpSocket::from_std(socket.into())?
};
if ! config.udp_allow_fragmentation {
if !config.udp.allow_fragmentation {
if let Err(err) = set_disable_ip_fragmentation(af, &socket) {
warn!("failed to disable IP fragmentation, error: {}", err);
}

View File

@@ -379,7 +379,7 @@ pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOp
UdpSocket::from_std(socket.into())?
};
if ! config.udp_allow_fragmentation {
if !config.udp.allow_fragmentation {
if let Err(err) = set_disable_ip_fragmentation(af, &socket) {
warn!("failed to disable IP fragmentation, error: {}", err);
}

View File

@@ -310,7 +310,7 @@ pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOp
UdpSocket::from_std(socket.into())?
};
if ! config.udp_allow_fragmentation {
if !config.udp_allow_fragmentation {
if let Err(err) = set_disable_ip_fragmentation(af, &socket) {
warn!("failed to disable IP fragmentation, error: {}", err);
}

View File

@@ -498,12 +498,11 @@ pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, opts: &ConnectOpts
socket.set_nonblocking(true)?;
let socket = UdpSocket::from_std(socket.into())?;
if ! opts.udp_allow_fragmentation {
if !opts.udp.allow_fragmentation {
if let Err(err) = set_disable_ip_fragmentation(af, &socket) {
warn!("failed to disable IP fragmentation, error: {}", err);
}
}
disable_connection_reset(&socket)?;
Ok(socket)