feat(udp): set SO_MARK for udp cnx

This commit is contained in:
Σrebe - Romain GERARD 2024-07-20 15:55:08 +02:00
parent 2c5cc95c52
commit 97251804dd
No known key found for this signature in database
GPG key ID: 7A42B4B97E0332F4
4 changed files with 20 additions and 4 deletions

View file

@ -1,4 +1,4 @@
use crate::{tcp}; use crate::tcp;
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use futures_util::{FutureExt, TryFutureExt}; use futures_util::{FutureExt, TryFutureExt};
use hickory_resolver::config::{LookupIpStrategy, NameServerConfig, Protocol, ResolverConfig, ResolverOpts}; use hickory_resolver::config::{LookupIpStrategy, NameServerConfig, Protocol, ResolverConfig, ResolverOpts};

View file

@ -991,8 +991,14 @@ async fn main() {
port, port,
}; };
let connect_to_dest = |_| async { let connect_to_dest = |_| async {
udp::connect(&tunnel.remote.0, tunnel.remote.1, cfg.timeout_connect, &cfg.dns_resolver) udp::connect(
.await &tunnel.remote.0,
tunnel.remote.1,
cfg.timeout_connect,
cfg.socket_so_mark,
&cfg.dns_resolver,
)
.await
}; };
if let Err(err) = if let Err(err) =
@ -1033,7 +1039,7 @@ async fn main() {
.map(|s| Box::new(s) as Box<dyn T>) .map(|s| Box::new(s) as Box<dyn T>)
} }
LocalProtocol::Udp { .. } => { LocalProtocol::Udp { .. } => {
udp::connect(&remote.host, remote.port, timeout, dns_resolver) udp::connect(&remote.host, remote.port, timeout, so_mark, dns_resolver)
.await .await
.map(|s| Box::new(s) as Box<dyn T>) .map(|s| Box::new(s) as Box<dyn T>)
} }

View file

@ -60,6 +60,7 @@ async fn run_tunnel(
&remote.host, &remote.host,
remote.port, remote.port,
timeout.unwrap_or(Duration::from_secs(10)), timeout.unwrap_or(Duration::from_secs(10)),
server_config.socket_so_mark,
&server_config.dns_resolver, &server_config.dns_resolver,
) )
.await?; .await?;

View file

@ -11,6 +11,7 @@ use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use tokio::task::JoinSet; use tokio::task::JoinSet;
use log::warn; use log::warn;
use socket2::SockRef;
use std::pin::{pin, Pin}; use std::pin::{pin, Pin};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::task::{ready, Poll}; use std::task::{ready, Poll};
@ -323,6 +324,7 @@ pub async fn connect(
host: &Host<String>, host: &Host<String>,
port: u16, port: u16,
connect_timeout: Duration, connect_timeout: Duration,
so_mark: Option<u32>,
dns_resolver: &DnsResolver, dns_resolver: &DnsResolver,
) -> anyhow::Result<MyUdpSocket> { ) -> anyhow::Result<MyUdpSocket> {
info!("Opening UDP connection to {}:{}", host, port); info!("Opening UDP connection to {}:{}", host, port);
@ -354,6 +356,13 @@ pub async fn connect(
} }
}; };
#[cfg(target_os = "linux")]
if let Some(so_mark) = so_mark {
SockRef::from(&socket)
.set_mark(so_mark)
.with_context(|| format!("cannot set SO_MARK on socket: {:?}", io::Error::last_os_error()))?;
}
// Spawn the connection attempt in the join set. // Spawn the connection attempt in the join set.
// We include a delay of ix * 250 milliseconds, as per RFC8305. // We include a delay of ix * 250 milliseconds, as per RFC8305.
// See https://datatracker.ietf.org/doc/html/rfc8305#section-5 // See https://datatracker.ietf.org/doc/html/rfc8305#section-5