1

Consider the following situation, on Windows:

  1. listen socket 1 has the SO_EXCLUSIVEADDRUSE option set, and binds to a port
  2. listen socket 1 receives an incoming connection, which it accepts to create a connected socket
  3. listen socket 1 is closed, but the connected socket remains open (in some sense, perhaps ESTABLISHED or TIME_WAIT)
  4. listen socket 2 has the SO_EXCLUSIVEADDRUSE option set, and attempts to bind to the same port as the first listen socket. Does it succeed?

There isn't a ton of information about this available on the web, but what there is mostly agrees that in the last step, bind will always raise an error, because SO_EXCLUSIVEADDRUSE prevents having listen socket 2 and the connected socket sharing the port. This is important because SO_EXCLUSIVEADDRUSE provides some non-trivial security benefits, but if it breaks port rebinding then it's difficult to decide whether to use it or not.

The current MSDN docs are clear that in at least some cases a lingering connection can make the second bind fail, though they're vague about what exactly counts as an "active connection":

Conversely, a socket with the SO_EXCLUSIVEADDRUSE set cannot necessarily be reused immediately after socket closure. For example, if a listening socket with SO_EXCLUSIVEADDRUSE set accepts a connection and is then subsequently closed, another socket (also with SO_EXCLUSIVEADDRUSE) cannot bind to the same port as the first socket until the original connection becomes inactive.

libuv explicitly chooses not to use SO_EXCLUSIVEADDRUSE – despite the security benefits – because they say it interferes with TIME_WAIT handling.

And this microsoft.com blog post from 2005 provides some more details, claiming that a connected socket can prevent SO_EXCLUSIVEADDRUSE rebinding in at least some cases (though not TIME_WAIT):

While the SO_EXCLUSIVEADDRUSE option is extremely useful, there is an important caveat. If at least one connection which originated from or was accepted on a port bound with exclusive access is active then all binds to this port will fail. In this case, a “connection” is defined as a socket which is explicitly connected to a peer via connect, WSAConnect, or ConnectEx with the exclusive flag set or a connection returned from a listening socket (such as from accept, WSAAccept, or AcceptEx) which has the exclusive option set (on the listening socket). An active port for TCP is defined as in the ESTABLISHED, FIN_WAIT, FIN_WAIT_2, or LAST_ACK states

So I wrote little script to try for myself:

https://gist.github.com/njsmith/8770bed5bbf2154940e8e3e7762e4ac3

and indeed, when I run it on Windows 10, I get:

rebind with existing listening socket: failed
    details: OSError(10048, 'Only one usage of each socket address (protocol/network address/port) is normally permitted', None, 10048, None)
rebind with live connected sockets: succeeded
rebind with TIME_WAIT socket: succeeded

So my tentative conclusion is that MSDN and everyone else are wrong: so long as the original listening socket is closed, SO_EXCLUSIVEADDRUSE actually does allow rebinding a port that has remaining connected sockets associated with it, whether in ESTABLISHED or TIME_WAIT state or what. Which is what everyone wants, so that's great. Presumably this was not true back in 2005, but sometime between then and now they fixed it.

Questions:

  • Is my interpretation of these results correct?
  • Is there another case I'm missing where a previous connection could cause a SO_EXCLUSIVEADDRUSE bind to fail where a regular bind would succeed? (I would expect that if ESTABLISHED sockets don't cause a problem, then nothing does, but I could be missing something.)
  • Most importantly: when did they make the change? For example, I tested on Windows 10, but if my code needed to target Windows Vista for some reason, would this work or not? Or did it always work like this and the docs were always wrong?
Nathaniel J. Smith
  • 11,613
  • 4
  • 41
  • 49

1 Answers1

1

On which versions of Windows (if any) does SO_EXCLUSIVEADDRUSE prevent rebinding a port that has lingering TIME_WAIT connections?

None.

Is my interpretation of these results correct?

No. Your results show that an ESTABLISHED socket doesn't block a rebind. They also show that a TIME_WAIT socket doesn't either, but that's what all your quotations already say. According to the documentation you quoted, TIME_WAIT never prevents rebinding of the port. Only an 'active port' as defined in the documentation ( ESTABLISHED, FIN_WAIT, FIN_WAIT_2, or LAST_ACK) is supposed to do that, and what your script shows is that that is not, or no longer, the case.

The post that you claim disagrees doesn't disagree at all.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Ah, good point -- I misread the list of TCP states in the blog post (which I only found a few minutes before posting...). MSDN unfortunately doesn't define "active connection", and everyone else seems to have interpreted it's vague warning as referring to TIME_WAIT, so I got swept up with the crowd. I'll edit the question to remove the explicit TIME_WAIT aspect, so that it remains meaningful. – Nathaniel J. Smith Aug 11 '17 at 00:23