feat: support macOS Network Extension (#1902)

* feat: support macOS Network Extension
* fix: disable macOS NE feature in cargo hack check
This commit is contained in:
Chenx Dust
2026-02-14 14:54:36 +08:00
committed by GitHub
parent 5a777959e3
commit 7a26640c26
15 changed files with 180 additions and 42 deletions
@@ -464,7 +464,7 @@ fn get_system_config(
return Ok(Some(Box::new(WindowsDNSManager::new(tun_name)?)));
}
#[cfg(target_os = "macos")]
#[cfg(all(target_os = "macos", not(feature = "macos-ne")))]
{
use super::system_config::darwin::DarwinConfigurator;
return Ok(Some(Box::new(DarwinConfigurator::new())));
@@ -4,7 +4,7 @@ pub mod linux;
#[cfg(target_os = "windows")]
pub mod windows;
#[cfg(target_os = "macos")]
#[cfg(all(target_os = "macos", not(feature = "macos-ne")))]
pub mod darwin;
#[derive(Default, Debug)]
+21 -5
View File
@@ -114,7 +114,7 @@ impl IpProxy {
tracing::error!("start icmp proxy failed: {:?}", e);
if cfg!(not(any(
target_os = "android",
target_os = "ios",
any(target_os = "ios", feature = "macos-ne"),
target_env = "ohos"
))) {
// android, ios and ohos not support icmp proxy
@@ -802,7 +802,11 @@ impl Instance {
}
#[cfg(all(
not(any(target_os = "android", target_os = "ios", target_env = "ohos")),
not(any(
target_os = "android",
any(target_os = "ios", feature = "macos-ne"),
target_env = "ohos"
)),
feature = "tun"
))]
{
@@ -846,7 +850,11 @@ impl Instance {
}
#[cfg(all(
not(any(target_os = "android", target_os = "ios", target_env = "ohos")),
not(any(
target_os = "android",
any(target_os = "ios", feature = "macos-ne"),
target_env = "ohos"
)),
feature = "tun"
))]
fn check_for_static_ip(&self, first_round_output: oneshot::Sender<Result<(), Error>>) {
@@ -936,7 +944,11 @@ impl Instance {
{
Self::clear_nic_ctx(self.nic_ctx.clone(), self.peer_packet_receiver.clone()).await;
#[cfg(not(any(target_os = "android", target_os = "ios", target_env = "ohos")))]
#[cfg(not(any(
target_os = "android",
any(target_os = "ios", feature = "macos-ne"),
target_env = "ohos"
)))]
if !self.global_ctx.config.get_flags().no_tun {
let (output_tx, output_rx) = oneshot::channel();
self.check_for_static_ip(output_tx);
@@ -1440,7 +1452,11 @@ impl Instance {
self.peer_packet_receiver.clone()
}
#[cfg(any(target_os = "android", target_os = "ios", target_env = "ohos"))]
#[cfg(any(
target_os = "android",
any(target_os = "ios", feature = "macos-ne"),
target_env = "ohos"
))]
pub async fn setup_nic_ctx_for_mobile(
nic_ctx: ArcNicCtx,
global_ctx: ArcGlobalCtx,
+26 -9
View File
@@ -523,7 +523,7 @@ impl VirtualNic {
}
}
#[cfg(target_os = "macos")]
#[cfg(all(target_os = "macos", not(feature = "macos-ne")))]
config.platform_config(|config| {
// disable packet information so we can process the header by ourselves, see tun2 impl for more details
config.packet_information(false);
@@ -583,7 +583,11 @@ impl VirtualNic {
Ok(tun::create(&config)?)
}
#[cfg(any(target_os = "android", target_os = "ios", target_env = "ohos"))]
#[cfg(any(
target_os = "android",
any(target_os = "ios", feature = "macos-ne"),
target_env = "ohos"
))]
pub async fn create_dev_for_mobile(
&mut self,
tun_fd: std::os::fd::RawFd,
@@ -592,7 +596,7 @@ impl VirtualNic {
let mut config = Configuration::default();
config.layer(Layer::L3);
#[cfg(target_os = "ios")]
#[cfg(any(target_os = "ios", feature = "macos-ne"))]
config.platform_config(|config| {
// disable packet information so we can process the header by ourselves, see tun2 impl for more details
config.packet_information(false);
@@ -602,7 +606,7 @@ impl VirtualNic {
config.close_fd_on_drop(false);
config.up();
let has_packet_info = cfg!(target_os = "ios");
let has_packet_info = cfg!(any(target_os = "ios", feature = "macos-ne"));
let dev = tun::create(&config)?;
let dev = AsyncDevice::new(dev)?;
let (a, b) = BiLock::new(dev);
@@ -680,7 +684,7 @@ impl VirtualNic {
self.ifcfg.set_mtu(ifname.as_str(), mtu_in_config).await?;
}
let has_packet_info = cfg!(target_os = "macos");
let has_packet_info = cfg!(all(target_os = "macos", not(feature = "macos-ne")));
let (a, b) = BiLock::new(dev);
let ft = TunnelWrapper::new(
TunStream::new(a, has_packet_info),
@@ -827,7 +831,10 @@ impl NicCtx {
nic.remove_ip(None).await?;
nic.add_ip(ipv4_addr.address(), ipv4_addr.network_length() as i32)
.await?;
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
#[cfg(any(
all(target_os = "macos", not(feature = "macos-ne")),
target_os = "freebsd"
))]
{
nic.add_route(ipv4_addr.first_address(), ipv4_addr.network_length())
.await?;
@@ -841,7 +848,10 @@ impl NicCtx {
nic.remove_ipv6(None).await?;
nic.add_ipv6(ipv6_addr.address(), ipv6_addr.network_length() as i32)
.await?;
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
#[cfg(any(
all(target_os = "macos", not(feature = "macos-ne")),
target_os = "freebsd"
))]
{
nic.add_ipv6_route(ipv6_addr.first_address(), ipv6_addr.network_length())
.await?;
@@ -1134,7 +1144,10 @@ impl NicCtx {
let _ = RegistryManager::reg_change_catrgory_in_profile(&dev_name);
}
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
#[cfg(any(
all(target_os = "macos", not(feature = "macos-ne")),
target_os = "freebsd"
))]
{
// remove the 10.0.0.0/24 route (which is added by rust-tun by default)
let _ = nic
@@ -1175,7 +1188,11 @@ impl NicCtx {
Ok(())
}
#[cfg(any(target_os = "android", target_os = "ios", target_env = "ohos"))]
#[cfg(any(
target_os = "android",
any(target_os = "ios", feature = "macos-ne"),
target_env = "ohos"
))]
pub async fn run_for_mobile(&mut self, tun_fd: std::os::fd::RawFd) -> Result<(), Error> {
let tunnel = {
let mut nic = self.nic.lock().await;