From 0b898d982549eab1ba12bf743d001aee6c2e27f9 Mon Sep 17 00:00:00 2001 From: Andrew Guschin Date: Fri, 30 Oct 2026 13:20:18 +0400 Subject: Validate real TUN forwarding and fix firewall routing - Move the default-drop guard to POSTROUTING so it sees final TUN egress - Treat a missing TUN interface as absent and add acceptance coverage - Document successful real-subscription validation on ALT Xray 26.10.29 --- src/linux/firewall.rs | 5 ++++- src/linux/routes.rs | 13 ++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'src/linux') diff --git a/src/linux/firewall.rs b/src/linux/firewall.rs index 8a0dd43..bbde560 100644 --- a/src/linux/firewall.rs +++ b/src/linux/firewall.rs @@ -126,7 +126,10 @@ fn apply_policy(enabled: bool, xray_uid: u32, allow_tun: bool) -> Result<()> { batch.add(&mark, MsgType::Add); let mut guard = Chain::new(c"guard", &table); guard.set_type(ChainType::Filter); - guard.set_hook(Hook::Out, 100); + // OUTPUT's hook state still names the original interface after the + // route chain changes skb's route. POSTROUTING sees the final egress, + // so the guard can allow TUN traffic without allowing direct fallback. + guard.set_hook(Hook::PostRouting, 100); guard.set_policy(Policy::Drop); batch.add(&guard, MsgType::Add); exceptions(&mut batch, &guard, xray_uid); diff --git a/src/linux/routes.rs b/src/linux/routes.rs index 4212183..0380faf 100644 --- a/src/linux/routes.rs +++ b/src/linux/routes.rs @@ -178,12 +178,19 @@ pub async fn remove() -> Result<()> { pub async fn tun_index() -> Result> { let handle = connection()?; - Ok(handle + let result = handle .link() .get() .match_name("roentgen0") .execute() .try_next() - .await? - .map(|link| link.header.index)) + .await; + match result { + Ok(link) => Ok(link.map(|link| link.header.index)), + // A named RTM_GETLINK request reports ENODEV for an absent interface, + // including before Xray starts and while waiting for it to create TUN. + Err(rtnetlink::Error::NetlinkError(error)) + if error.raw_code() == -libc::ENODEV => Ok(None), + Err(error) => Err(error.into()), + } } -- cgit v1.2.3