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

[WIP] Stop setting SO_REUSEADDR to fix Port Forwarding #654

Open
wants to merge 2 commits into
base: latestw_all
Choose a base branch
from

Conversation

vthiebaut10
Copy link
Collaborator

@vthiebaut10 vthiebaut10 commented Jan 17, 2023

Fix: PowerShell/Win32-OpenSSH#1968

PR Summary

SO_REUSEADDR socket option means different things on Windows and *nix systems.
On Windows, that option allows sockets to forcibly bind to ports in use by other sockets. The behavior for all sockets once the second socket is bound to the port is indeterminate. (See: https://learn.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse#using-so_reuseaddr)

On *nix systems, the SO_REUSEADDR is used to address edge cases that might occur after socket termination. It allows the socket to be reused while it is on TIME_WAIT state. It still returns "Address already in use" error if the socket is being used while in any other state. (See: https://stackoverflow.com/questions/3229860/what-is-the-meaning-of-so-reuseaddr-setsockopt-option-linux)

Supposedly, Windows doesn't have the issue of preventing the reutilization of sockets during TIME_WAIT (according to this discussion: warmcat/libwebsockets#65 (comment)), so there should be no value for us to use the SO_REUSEADDR when creating sockets.

@vthiebaut10 vthiebaut10 changed the title Stop setting SO_REUSEADDR to fix Port Forwarding [WIP] Stop setting SO_REUSEADDR to fix Port Forwarding Jan 23, 2023
@OAIUR
Copy link

OAIUR commented Sep 12, 2024

To ensure proper socket reuse on Windows without using SO_REUSEADDR, you can use the SO_EXCLUSIVEADDRUSE option instead. This option prevents multiple sockets from binding to the same port, which helps avoid the indeterminate behavior caused by SO_REUSEADDR. Here’s how you can approach it:

  1. Use SO_EXCLUSIVEADDRUSE: This option ensures that only one socket can bind to a specific port at a time, preventing conflicts.

    $socket = New-Object System.Net.Sockets.Socket(
        [System.Net.Sockets.AddressFamily]::InterNetwork,
        [System.Net.Sockets.SocketType]::Stream,
        [System.Net.Sockets.ProtocolType]::Tcp
    )
    $socket.SetSocketOption([System.Net.Sockets.SocketOptionLevel]::Socket, [System.Net.Sockets.SocketOptionName]::ExclusiveAddressUse, $true)
  2. Proper Socket Closure: Ensure that sockets are properly closed and disposed of when they are no longer needed. This helps release the port and avoid TIME_WAIT issues.

    $socket.Close()
    $socket.Dispose()
  3. Avoid Binding to In-Use Ports: Implement logic to check if a port is already in use before attempting to bind to it.

By using SO_EXCLUSIVEADDRUSE and ensuring proper socket management, you can achieve reliable socket reuse on Windows without relying on SO_REUSEADDR.

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