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 <lee.smet@hotmail.com>
This commit is contained in:
Lee Smet
2025-10-07 17:19:12 +02:00
parent 2f8b74bc63
commit c2ba181d5d
2 changed files with 17 additions and 1 deletions
+3
View File
@@ -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
+14 -1
View File
@@ -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;