Skip to content

Commit 1d3325b

Browse files
authored
feat(tun)!: replace netstack with smoltcp based impl (#886)
1 parent 3bbfc09 commit 1d3325b

File tree

37 files changed

+1922
-220
lines changed

37 files changed

+1922
-220
lines changed

.github/workflows/release.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ on:
44
workflow_dispatch:
55
inputs:
66
version_type:
7-
description: 'Version bump type'
7+
description: "Version bump type"
88
required: true
9-
default: 'minor'
9+
default: "minor"
1010
type: choice
1111
options:
1212
- patch
@@ -48,7 +48,7 @@ jobs:
4848
4949
- name: Commit version bump
5050
run: |
51-
git add Cargo.toml clash/Cargo.toml clash_lib/Cargo.toml clash_doc/Cargo.toml clash_ffi/Cargo.toml Cargo.lock
51+
git add Cargo.toml clash-bin/Cargo.toml clash-dns/Cargo.toml clash-doc/Cargo.toml clash-ffi/Cargo.toml clash-lib/Cargo.toml Cargo.lock
5252
git commit -m "chore: bump version to ${{ steps.version.outputs.version }}"
5353
5454
- name: Create tag

Cargo.lock

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

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
[workspace]
2-
resolver = "2"
2+
resolver = "3"
33

44
members = [
55
"clash-bin",
66
"clash-lib",
77
"clash-doc",
88
"clash-ffi",
9-
"clash-dns"
9+
"clash-dns",
10+
"clash-netstack"
1011
]
1112

1213

clash-bin/tests/data/config/tun.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
port: 8888
33

4-
log-level: trace
4+
log-level: warn
55

66
ipv6: true
77

clash-lib/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ wireguard = ["dep:boringtun", "dep:smoltcp"]
3232
tproxy = ["tun"]
3333
tun = [
3434
"dep:tun-rs",
35-
"dep:netstack-smoltcp",
35+
"dep:watfaq-netstack",
3636
"dep:smoltcp",
3737
]
3838
redir = []
@@ -121,7 +121,7 @@ chrono = { version = "0.4", features = ["serde"] }
121121

122122
# TUN
123123
tun-rs = { version = "2", features = ["async", "async_framed"], optional = true }
124-
netstack-smoltcp = { git = "https://github.com/automesh-network/netstack-smoltcp", rev = "ab06bc3de566fc6485a238dd4c746bb3e4f79484", optional = true }
124+
watfaq-netstack = { path = "../clash-netstack", optional = true }
125125
smoltcp = { version = "0.12", default-features = false, features = ["std", "log", "medium-ip", "proto-ipv4", "proto-ipv6", "socket-udp", "socket-tcp"], optional = true }
126126

127127
# WireGuard

clash-lib/src/app/dns/dns_client.rs

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,35 @@
1-
use std::{
2-
fmt::{Debug, Display, Formatter},
3-
net,
4-
str::FromStr,
5-
sync::Arc,
6-
time::Duration,
7-
};
8-
9-
use async_trait::async_trait;
10-
11-
use futures::{TryFutureExt, future::BoxFuture};
12-
use hickory_client::client;
13-
use hickory_proto::{
14-
ProtoError, runtime::iocompat::AsyncIoTokioAsStd,
15-
rustls::tls_client_stream::tls_client_connect_with_future, tcp::TcpClientStream,
16-
udp::UdpClientStream,
17-
};
18-
use rustls::ClientConfig;
19-
use tokio::{sync::RwLock, task::JoinHandle};
20-
use tracing::{info, instrument, trace, warn};
21-
1+
use super::{ClashResolver, Client, runtime::DnsRuntimeProvider};
222
use crate::{
233
Error,
244
app::net::{OutboundInterface, TUN_SOMARK},
255
common::tls::{self, GLOBAL_ROOT_STORE},
266
dns::{ThreadSafeDNSClient, dhcp::DhcpClient},
277
proxy::utils::new_tcp_stream,
288
};
9+
use anyhow::anyhow;
10+
use async_trait::async_trait;
11+
use futures::{TryFutureExt, future::BoxFuture};
12+
use hickory_client::client;
2913
use hickory_proto::{
30-
DnsHandle,
14+
DnsHandle, ProtoError,
3115
h2::HttpsClientStreamBuilder,
3216
op::Message,
17+
runtime::iocompat::AsyncIoTokioAsStd,
18+
rustls::tls_client_stream::tls_client_connect_with_future,
19+
tcp::TcpClientStream,
20+
udp::UdpClientStream,
3321
xfer::{DnsRequest, DnsRequestOptions, FirstAnswer},
3422
};
35-
use tokio::net::TcpStream as TokioTcpStream;
36-
37-
use super::{ClashResolver, Client, runtime::DnsRuntimeProvider};
23+
use rustls::ClientConfig;
24+
use std::{
25+
fmt::{Debug, Display, Formatter},
26+
net,
27+
str::FromStr,
28+
sync::Arc,
29+
time::Duration,
30+
};
31+
use tokio::{net::TcpStream as TokioTcpStream, sync::RwLock, task::JoinHandle};
32+
use tracing::{info, instrument, trace, warn};
3833

3934
#[derive(Clone, Debug, PartialEq)]
4035
pub enum DNSNetMode {

clash-lib/src/app/dns/helper.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
dns_client::{DNSNetMode, DnsClient, Opts},
66
},
77
};
8+
use hickory_proto::rr::rdata::opt::EdnsCode;
89
use std::sync::Arc;
910
use tracing::{debug, warn};
1011

@@ -76,5 +77,10 @@ pub fn build_dns_response_message(
7677
res.set_edns(edns);
7778
}
7879

80+
if let Some(edns) = res.extensions_mut() {
81+
// Remove only padding options, keep everything else
82+
edns.options_mut().remove(EdnsCode::Padding);
83+
}
84+
7985
res
8086
}

clash-lib/src/app/dns/resolver/enhanced.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,3 @@
1-
use async_trait::async_trait;
2-
use futures::{FutureExt, TryFutureExt};
3-
use rand::seq::IndexedRandom;
4-
use std::{
5-
net,
6-
sync::{
7-
Arc,
8-
atomic::{AtomicBool, Ordering::Relaxed},
9-
},
10-
time::{Duration, Instant},
11-
};
12-
use tokio::sync::RwLock;
13-
use tracing::{debug, error, instrument, trace, warn};
14-
15-
use hickory_proto::{op, rr};
16-
171
use crate::{
182
Error,
193
app::{dns::helper::build_dns_response_message, profile::ThreadSafeCacheFile},
@@ -29,6 +13,21 @@ use crate::{
2913
helper::make_clients,
3014
},
3115
};
16+
use anyhow::anyhow;
17+
use async_trait::async_trait;
18+
use futures::{FutureExt, TryFutureExt};
19+
use hickory_proto::{op, rr};
20+
use rand::seq::IndexedRandom;
21+
use std::{
22+
net,
23+
sync::{
24+
Arc,
25+
atomic::{AtomicBool, Ordering::Relaxed},
26+
},
27+
time::{Duration, Instant},
28+
};
29+
use tokio::sync::RwLock;
30+
use tracing::{debug, error, instrument, trace, warn};
3231

3332
pub struct EnhancedResolver {
3433
ipv6: AtomicBool,
@@ -314,7 +313,13 @@ impl EnhancedResolver {
314313
}
315314
}
316315
trace!(q = q.to_string(), "querying resolver");
317-
let res = self.exchange_no_cache(message).await;
316+
let res = self.exchange_no_cache(message).await.map(|mut r| {
317+
if let Some(edns) = r.extensions_mut() {
318+
// Remove only padding options, keep everything else
319+
edns.options_mut().remove(rr::rdata::opt::EdnsCode::Padding);
320+
}
321+
r
322+
});
318323
trace!(q = q.to_string(), "query completed");
319324
res
320325
} else {

clash-lib/src/app/dns/server/handler.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1+
use super::DEFAULT_DNS_SERVER_TTL;
2+
use crate::app::dns::{ThreadSafeDNSResolver, helper::build_dns_response_message};
13
use hickory_proto::{
24
op::{Message, ResponseCode},
35
rr::{RData, Record, rdata::A},
46
};
57
use tracing::debug;
68

7-
use crate::app::dns::{ThreadSafeDNSResolver, helper::build_dns_response_message};
8-
9-
use super::DEFAULT_DNS_SERVER_TTL;
10-
119
pub async fn exchange_with_resolver<'a>(
1210
resolver: &'a ThreadSafeDNSResolver,
1311
req: &'a Message,

clash-lib/src/app/logging.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::def::LogLevel;
2-
use std::{io::IsTerminal, sync::Once};
3-
2+
use anyhow::anyhow;
43
#[cfg(feature = "tracing")]
54
use opentelemetry::trace::TracerProvider;
65
#[cfg(feature = "tracing")]
@@ -11,6 +10,7 @@ use opentelemetry_semantic_conventions::{
1110
attribute::{DEPLOYMENT_ENVIRONMENT_NAME, SERVICE_VERSION},
1211
};
1312
use serde::Serialize;
13+
use std::{io::IsTerminal, sync::Once};
1414
use tokio::sync::broadcast::Sender;
1515
use tracing::level_filters::LevelFilter;
1616
#[cfg(feature = "tracing")]

0 commit comments

Comments
 (0)