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

What are the best socket option defaults? #72

Open
njsmith opened this Issue Mar 7, 2017 · 1 comment

Comments

Projects
None yet
1 participant
@njsmith
Member

njsmith commented Mar 7, 2017

Our default socket configuration is a little different than the classic BSD defaults. Are we making the right choices?

  • SO_REUSEADDR on non-Windows, SO_EXCLUSIVEADDR on Windows: almost certainly correct for listening sockets. More dubious but mostly harmless for client sockets. (See also #39)

    On Windows the other option would be to leave both SO_REUSEADDR and SO_EXCLUSIVEADDR unset, which gives (a) the preferred TIME_WAIT semantics (same as setting SO_REUSEADDR on a Unix system), but also (b) weird socket hijacking issues. (This is what libuv does, e.g.) For now our reasoning is "when in doubt, err on the side of security", but really it would be better to make an actual decision :-). And it's not clear what the best trade-off here is. On recent versions of Windows (including I think all the versions Python officially supports), you can only hijack sockets belonging to the same user, which under the traditional Unix security model would be no big deal – if the process belongs to the same user you could also ptrace it or whatever, and we already have countermeasures against anyone setting SO_REUSEADDR by accident. So maybe the security issue is not worth worrying about in practice. But Windows is not Unix, and even on Unix the traditional security model is not what it used to be (e.g. you probably can't ptrace random other processes these days!), so ... I'm not confident I understand the risks.

    There's also the option of pushing this into the higher-level networking interface (#73), where it knows whether or not it's dealing with a listening socket.

  • IPV6_V6ONLY unset: The important thing is to have a consistent default, because this varies across environments in practice. And I guess unset is a little better than set because it simplifies ipv6 support in simple cases?

  • TCP_NODELAY set: I'm not sure if this is a good idea or not. asyncio sets it by default as well. My suspicion is that having TCP_NODELAY set is a good idea for most serious protocols (latency is important, Nagle sucks for that, most protocols aren't telnet, and hopefully most serious implementations are not hitting the OS with lots of tiny writes and relying on it to fix things up). But Nagle also serves as a safety belt for low-effort implementations, which are the ones that are least likely to override defaults...

  • TCP_NOTSENT_LOWAT set to 16 KiB: well, it's... not obviously wrong? Here we're breaking new ground, so we'll have to see how it goes in practice. This is quite a complicated issue; see #76.

@njsmith

This comment has been minimized.

Member

njsmith commented Aug 11, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment