From af65069fd15bbfca5c93b6099a9cc1d5b8de30bc Mon Sep 17 00:00:00 2001 From: Hodlinator <172445034+hodlinator@users.noreply.github.com> Date: Fri, 4 Sep 2026 21:51:32 +0200 Subject: [PATCH] windows: Use SO_EXCLUSIVEADDRUSE over SO_REUSEADDR The latter allows other processes to bind to the same socket and intercept traffic on this platform. --- src/httpserver.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 9bb89863afc..6e186d151d3 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -722,6 +722,17 @@ util::Expected HTTPServer::BindAndStartListening(const CServi NetworkErrorString(WSAGetLastError()))}; } +#ifdef WIN32 + // Prevent another application from binding to the same address and port and + // intercepting RPC credentials. + // SO_REUSEADDR on Windows is non-exclusive so another process could bind to + // the same port. + if (sock->SetSockOpt(SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &SOCKET_OPTION_TRUE, sizeof(SOCKET_OPTION_TRUE)) == SOCKET_ERROR) { + return util::Unexpected{strprintf("Cannot set SO_EXCLUSIVEADDRUSE on %s listen socket: %s", + to.ToStringAddrPort(), + NetworkErrorString(WSAGetLastError()))}; + } +#else // Allow binding if the port is still in TIME_WAIT state after // the program was closed and restarted. if (sock->SetSockOpt(SOL_SOCKET, SO_REUSEADDR, &SOCKET_OPTION_TRUE, sizeof(SOCKET_OPTION_TRUE)) == SOCKET_ERROR) { @@ -730,6 +741,7 @@ util::Expected HTTPServer::BindAndStartListening(const CServi to.ToStringAddrPort(), NetworkErrorString(WSAGetLastError())); } +#endif // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option // and enable it by default or not. Try to enable it, if possible.