From c2ba181d5d91a67cfe5e558ac918bf593f8bd046 Mon Sep 17 00:00:00 2001 From: Lee Smet Date: Tue, 7 Oct 2025 17:19:12 +0200 Subject: [PATCH] Improve handling of local TUN packets on MacOS On Mac, a packet originating on the system send to the TUN is not routed via the loopback interface, therefore we need to send it on the TUN inside the application for it to be properly handled by the system. Signed-off-by: Lee Smet --- CHANGELOG.md | 3 +++ mycelium/src/tun/darwin.rs | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b12b53..1f84eb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Return actuall amount of bytes sent to peers instead of the amount of bytes received from them. +- Improve handling of completely local packets on MacOS. This will allow the kernel + to reply to ping packets send from the local system to the TUN interface, among + other things. ## [0.6.2] - 2025-09-19 diff --git a/mycelium/src/tun/darwin.rs b/mycelium/src/tun/darwin.rs index 11b84f2..7414ff7 100644 --- a/mycelium/src/tun/darwin.rs +++ b/mycelium/src/tun/darwin.rs @@ -3,7 +3,7 @@ use std::{ ffi::CString, io::{self, IoSlice}, - net::IpAddr, + net::{IpAddr, Ipv6Addr}, os::fd::AsRawFd, str::FromStr, }; @@ -126,6 +126,19 @@ pub async fn new( }); + // On Mac, packets from the tun ip to the tun ip (e.g. ping tun ip) need to be + // passed explicitly to the TUN interface again for them to be picked up by the + // kernel, since they are not routed on the loopback interface. + if let Ok(ref buf) = rr { + if buf.len() >= 40 && tun_config.node_subnet.contains_ip(IpAddr::V6(Ipv6Addr::from(<[u8;16] as TryFrom<&[u8]>>::try_from(&buf[24..40]).expect("Valid 16 byte buffer; qed")))) { + if let Err(err) = tun.write_vectored(&[IoSlice::new(&HEADER), IoSlice::new(&buf)]).await { + error!(%err, "Failed to send data to tun interface"); + } + } + } + + + if tun_stream.send(rr).is_err() { error!("Could not forward data to tun stream, receiver is gone"); break;