Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tunnel fails to close after Linux system resumes from sleep #342

Open
VITEK-THE-BEST opened this issue Dec 6, 2024 · 1 comment
Open
Labels

Comments

@VITEK-THE-BEST
Copy link

On a Linux-based system, after resuming from sleep, it is impossible to close the tunnel without killing the process.

Here’s the normal behavior when closing the tunnel:

sudo go run github.com/Jigsaw-Code/outline-sdk/x/examples/outline-cli@latest -transport "ss://token"
OutlineVPN CLI (experimental)
[INFO] 2024/12/06 16:00:09 updated global IPv6 support: false
[INFO] 2024/12/06 16:00:09 remote server supports UDP, we will delegate all UDP packets to it
[INFO] 2024/12/06 16:00:09 routing traffic configured...
^C[INFO] 2024/12/06 16:47:43 received interrupt, terminating...
[INFO] 2024/12/06 16:47:43 routing table cleaned up
[INFO] 2024/12/06 16:47:43 DNS config restored
[INFO] 2024/12/06 16:47:43 OutlineDevice -> tun stopped: 274279765 <nil>
[INFO] 2024/12/06 16:47:43 tun -> OutlineDevice stopped: 27566484 read tun: file already closed

However, after resuming from sleep, attempting to close the tunnel results in infinite waiting:

OutlineVPN CLI (experimental)
[INFO] 2024/12/06 00:23:58 updated global IPv6 support: false
[INFO] 2024/12/06 00:23:58 remote server supports UDP, we will delegate all UDP packets to it
[INFO] 2024/12/06 00:23:58 routing traffic configured...
^C[INFO] 2024/12/06 10:21:42 received interrupt, terminating...
[INFO] 2024/12/06 10:21:42 routing table cleaned up
[INFO] 2024/12/06 10:21:42 DNS config restored
[INFO] 2024/12/06 10:21:42 OutlineDevice -> tun stopped: 264549559 <nil>
signal: killed

The only way to close the tunnel in this case is to kill the outline-cli process manually.

The issue occurs in app_linux.go, specifically here:

go func() {
    defer trafficCopyWg.Done()
    written, err := io.Copy(ss, tun)
    logging.Info.Printf("tun -> OutlineDevice stopped: %v %v\n", written, err)
}()

This section does not receive an EOF, preventing the connection from closing.

I believe the issue lies in how io.Copy blocks indefinitely while waiting for data from the TUN device. This behavior becomes problematic after the system wakes up from sleep, as the TUN device does not signal EOF or return from the Read call.

@jyyi1
Copy link
Contributor

jyyi1 commented Dec 10, 2024

Thanks for reporting the issue. Though the root cause here seems to be that we are not able to Close the tun device:

https://github.com/Jigsaw-Code/outline-sdk/blob/v0.0.17/x/examples/outline-cli/app_linux.go#L36

Because in the normal case, once the tun device has been Closed, the traffic copy go-routine will terminate:

[INFO] 2024/12/06 16:47:43 tun -> OutlineDevice stopped: 27566484 read tun: file already closed

io.Copy should respect that and return immediately when one of the IO objects has been closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants