From 1a60fc78ffd01024a9d39dd8717bc9754f1647cf Mon Sep 17 00:00:00 2001 From: Hossin Asaadi Date: Thu, 8 Oct 2026 06:14:14 +0100 Subject: [PATCH] TUN inbound: Duplicate the iOS tunnel file descriptor (#6883) https://github.com/XTLS/Xray-core/pull/6883#issuecomment-6008368575 --- proxy/tun/tun_darwin.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/proxy/tun/tun_darwin.go b/proxy/tun/tun_darwin.go index 1ae4d451f..bcca838db 100644 --- a/proxy/tun/tun_darwin.go +++ b/proxy/tun/tun_darwin.go @@ -155,12 +155,20 @@ func NewTun(options *Config) (Tun, error) { fdStr := platform.NewEnvFlag(platform.TunFdKey).GetValue(func() string { return "" }) if fdStr != "" { // iOS: use provided fd from NetworkExtension - fd, err := strconv.Atoi(fdStr) + providedFd, err := strconv.Atoi(fdStr) + if err != nil { + return nil, err + } + + // duplicate NetworkExtension fd so Xray can close its own handle + // without closing the original. + fd, err := unix.FcntlInt(uintptr(providedFd), unix.F_DUPFD_CLOEXEC, 0) if err != nil { return nil, err } if err = unix.SetNonblock(fd, true); err != nil { + _ = unix.Close(fd) return nil, err } @@ -232,11 +240,7 @@ func (t *DarwinTun) Close() error { t.waitKq.close() } routeErr := t.unsetSystemRoutes() - if t.ownsFd { - return xerrors.Combine(routeErr, t.tunFile.Close()) - } - // iOS: don't close the fd, it's owned by NetworkExtension - return routeErr + return xerrors.Combine(routeErr, t.tunFile.Close()) } func (t *DarwinTun) monitorRouteChanges() {