Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Itsusinn committed Mar 30, 2024
1 parent e926959 commit 1594cc2
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 24 deletions.
1 change: 1 addition & 0 deletions clash/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ fn main() {
}
}
}
std::env::set_var("RUST_BACKTRACE", "1");
match clash::start(clash::Options {
config: clash::Config::File(file),
cwd: cli.directory.map(|x| x.to_string_lossy().to_string()),
Expand Down
6 changes: 6 additions & 0 deletions clash_lib/src/config/internal/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ pub struct TunConfig {
/// default: 198.18.0.0/16
pub network: Option<String>,
pub gateway: Option<IpAddr>,
/// auto manage route
pub auto_route: Option<bool>,
/// fwmark for preveting loop
pub mark: Option<u32>,
/// ip rule table name
pub table: Option<String>
}

#[derive(Clone, Default)]
Expand Down
4 changes: 2 additions & 2 deletions clash_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ async fn start_async(opts: Options) -> Result<(), Error> {
let inbound_runner = inbound_manager.lock().await.get_runner()?;
let inbound_listener_handle = tokio::spawn(inbound_runner);

let tun_runner = get_tun_runner(config.tun, dispatcher.clone(), dns_resolver.clone())?;
let tun_runner = get_tun_runner(config.tun, dispatcher.clone(), dns_resolver.clone()).await?;
let tun_runner_handle = tun_runner.map(tokio::spawn);

debug!("initializing dns listener");
Expand Down Expand Up @@ -419,7 +419,7 @@ async fn start_async(opts: Options) -> Result<(), Error> {
.map(tokio::spawn)?;

let tun_runner_handle =
get_tun_runner(config.tun, dispatcher.clone(), dns_resolver.clone())?
get_tun_runner(config.tun, dispatcher.clone(), dns_resolver.clone()).await?
.map(tokio::spawn);

debug!("reloading dns listener");
Expand Down
18 changes: 6 additions & 12 deletions clash_lib/src/proxy/direct/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ impl OutboundHandler for Handler {
sess.destination.host().as_str(),
sess.destination.port(),
None,
#[cfg(any(target_os = "linux", target_os = "android"))]
None,
sess.packet_mark,
)
.await?;

Expand All @@ -66,8 +65,8 @@ impl OutboundHandler for Handler {
async fn proxy_stream(
&self,
s: AnyStream,
#[allow(unused_variables)] sess: &Session,
#[allow(unused_variables)] _resolver: ThreadSafeDNSResolver,
_sess: &Session,
_resolver: ThreadSafeDNSResolver,
) -> std::io::Result<AnyStream> {
Ok(s)
}
Expand All @@ -77,14 +76,9 @@ impl OutboundHandler for Handler {
sess: &Session,
resolver: ThreadSafeDNSResolver,
) -> std::io::Result<BoxedChainedDatagram> {
let d = new_udp_socket(
None,
sess.iface.as_ref(),
#[cfg(any(target_os = "linux", target_os = "android"))]
None,
)
.await
.map(|x| OutboundDatagramImpl::new(x, resolver))?;
let d = new_udp_socket(None, sess.iface.as_ref(), sess.packet_mark)
.await
.map(|x| OutboundDatagramImpl::new(x, resolver))?;

let d = ChainedDatagramWrapper::new(d);
d.append_to_chain(self.name()).await;
Expand Down
20 changes: 20 additions & 0 deletions clash_lib/src/proxy/tun/auto_route.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::config::internal::config::TunConfig;

#[cfg(target_os = "linux")]
pub async fn setup(cfg: &mut TunConfig, tun_name: &str) -> anyhow::Result<()>{
if !cfg.auto_route.unwrap_or(false) {
return Ok(());
}
let mark = cfg.mark.unwrap_or(6969);
cfg.mark = Some(mark);
let table = cfg.table.take().unwrap_or("2233".into());
cfg.table = Some(table);
// TODO
Ok(())
}

#[cfg(not(target_os = "linux"))]
pub fn setup(cfg: &mut TunConfig, tun_name: &str) -> anyhow::Result<()>{
tracing::error!("Auto route not impl!");
Ok(())
}
30 changes: 24 additions & 6 deletions clash_lib/src/proxy/tun/inbound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
app::{dispatcher::Dispatcher, dns::ThreadSafeDNSResolver},
common::errors::map_io_error,
config::internal::config::TunConfig,
proxy::datagram::UdpPacket,
proxy::{datagram::UdpPacket, tun::auto_route},
session::{Network, Session, SocksAddr, Type},
Error, Runner,
};
Expand All @@ -20,12 +20,14 @@ async fn handle_inbound_stream(
local_addr: SocketAddr,
remote_addr: SocketAddr,
dispatcher: Arc<Dispatcher>,
packet_mark: Option<u32>,
) {
let sess = Session {
network: Network::Tcp,
typ: Type::Tun,
source: local_addr,
destination: remote_addr.into(),
packet_mark,
..Default::default()
};

Expand All @@ -36,6 +38,7 @@ async fn handle_inbound_datagram(
socket: Box<netstack::UdpSocket>,
dispatcher: Arc<Dispatcher>,
resolver: ThreadSafeDNSResolver,
packet_mark: Option<u32>,
) {
let local_addr = socket.local_addr();
// tun i/o
Expand All @@ -56,6 +59,7 @@ async fn handle_inbound_datagram(
let sess = Session {
network: Network::Udp,
typ: Type::Tun,
packet_mark,
..Default::default()
};

Expand Down Expand Up @@ -117,8 +121,8 @@ async fn handle_inbound_datagram(
let _ = futures::future::join(fut1, fut2).await;
}

pub fn get_runner(
cfg: TunConfig,
pub async fn get_runner(
mut cfg: TunConfig,
dispatcher: Arc<Dispatcher>,
resolver: ThreadSafeDNSResolver,
) -> Result<Option<Runner>, Error> {
Expand All @@ -127,10 +131,10 @@ pub fn get_runner(
return Ok(None);
}

let device_id = cfg.device_id;
let device_id = &cfg.device_id;

let u =
Url::parse(&device_id).map_err(|x| Error::InvalidConfig(format!("tun device {}", x)))?;
Url::parse(device_id).map_err(|x| Error::InvalidConfig(format!("tun device {}", x)))?;

let mut tun_cfg = tun::Configuration::default();

Expand Down Expand Up @@ -163,6 +167,11 @@ pub fn get_runner(
let tun_name = tun.get_ref().name().map_err(map_io_error)?;
info!("tun started at {}", tun_name);

// Configuare auto-route when tun is ready
if cfg.auto_route.unwrap_or(false) {
auto_route::setup(&mut cfg, &tun_name).await.map_err(|e| Error::Operation(e.to_string()))?;
}

let (stack, mut tcp_listener, udp_socket) =
netstack::NetStack::with_buffer_size(512, 256).map_err(map_io_error)?;

Expand Down Expand Up @@ -215,21 +224,30 @@ pub fn get_runner(
}));

let dsp = dispatcher.clone();

let mark = if cfg.auto_route.unwrap_or(false)
&& cfg!(any(target_os = "android", target_os = "linux"))
{
cfg.mark
} else {
None
};
futs.push(Box::pin(async move {
while let Some((stream, local_addr, remote_addr)) = tcp_listener.next().await {
tokio::spawn(handle_inbound_stream(
stream,
local_addr,
remote_addr,
dsp.clone(),
mark,
));
}

Err(Error::Operation("tun stopped unexpectedly 2".to_string()))
}));

futs.push(Box::pin(async move {
handle_inbound_datagram(udp_socket, dispatcher, resolver).await;
handle_inbound_datagram(udp_socket, dispatcher, resolver, mark).await;
Err(Error::Operation("tun stopped unexpectedly 3".to_string()))
}));

Expand Down
1 change: 1 addition & 0 deletions clash_lib/src/proxy/tun/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod inbound;
pub mod auto_route;
pub use netstack_lwip as netstack;
mod datagram;
pub use inbound::get_runner as get_tun_runner;
8 changes: 4 additions & 4 deletions clash_lib/src/proxy/utils/socket_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub async fn new_tcp_stream<'a>(
address: &'a str,
port: u16,
iface: Option<&'a Interface>,
#[cfg(any(target_os = "linux", target_os = "android"))] packet_mark: Option<u32>,
packet_mark: Option<u32>,
) -> io::Result<AnyStream> {
let dial_addr = resolver
.resolve(address, false)
Expand Down Expand Up @@ -125,7 +125,7 @@ pub async fn new_tcp_stream<'a>(
pub async fn new_udp_socket(
src: Option<&SocketAddr>,
iface: Option<&Interface>,
#[cfg(any(target_os = "linux", target_os = "android"))] packet_mark: Option<u32>,
packet_mark: Option<u32>,
) -> io::Result<UdpSocket> {
let socket = match src {
Some(src) => {
Expand Down Expand Up @@ -172,9 +172,9 @@ impl StdSocketExt for std::net::TcpStream {
}

fn set_mark<'a>(socket: socket2::SockRef<'a>, mark: u32) -> io::Result<()> {
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux"))]
return socket.set_mark(mark);
#[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
#[cfg(not(any(target_os = "android", target_os = "linux")))]
return Ok(());
}

Expand Down

0 comments on commit 1594cc2

Please sign in to comment.