5

Can and will an operating system reuse a source port number for a connection to a different destination address/port combination?

If I connect() to enough hosts, and keep those connections open, eventually I'll run out of unique source ports, exhausting the ephemeral range, the non-root range (1025-65,535; assuming non-root) or the absolute range (0-65,535). I want to know if those represent real limits to the number of hosts I can simultaneously have a connection to. I'm interested in what the standards promise (or don't), as well as the reality on Linux (Windows would be a bonus).

I know that opening that many connections will likely run into a number of other limits; that's a different issue and question. If it matters, this massive number of connections would be divided among a similarly large number of processes. I'm interested in the case where I'm requesting an ephemeral port, not manually bind()ing one. If under "normal" circumstances ports won't be reused, are there ways of changing that behavior from user-space (at which point bind()ing to a specific point becomes an option)?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Alan De Smet
  • 1,699
  • 1
  • 16
  • 20
  • If you're going to have roughly the same number of processes as you do connections, try (under Linux) doing the shell command `ps -ef`. You'll find that the process numbers range from 1 to 32767 or so. You'll run out of processes way sooner than you run out of ephemeral ports. – Bill Evans at Mariposa Apr 25 '14 at 21:48
  • Why should a process only open a single port? It's easy for a process to keep 1000s of connections open, servers like nginx do it all the time and even browsers often have multiple connections open. – Steffen Ullrich Apr 25 '14 at 21:58
  • @Steffen: There is no reason a process should open only a single port. I was concerned, though, about OP's statement: "If it matters, this massive number of connections would be divided among a similarly large number of processes." – Bill Evans at Mariposa Apr 26 '14 at 01:19
  • 1
    @Bill: max_pid is adjustable on Linux: http://stackoverflow.com/a/12152304/16672 I intended for such things to fall until "will likely run into a number of other limits," but I wasn't clear. – Alan De Smet Apr 26 '14 at 22:39
  • @Steffen and Bill: I certainly appreciate that this may be a terrible idea for a host of reasons. To paraphrase Donald Rumseld, you go to war with the code you have, not the code you might want or wish to have at a later time. – Alan De Smet Apr 26 '14 at 22:41
  • 1
    There's a delightfully apropos ambiguity here. In reference to the code you're using, does "go to war with" mean "go to war using", or does it mean "go to war against"? ;) – Bill Evans at Mariposa Apr 27 '14 at 07:49

2 Answers2

5

By default, the kernel will not reuse any in-use port for an ephemeral port, which may result in failures if you have 64K+ simultaneous ports in use.

You can explicitly reuse a port by using the SO_REUSEADDR socket option and explicitly binding to the same port. This only works if none of the ports are listening (you can't reuse a listening port), and if you connect each socket to a different remote address.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • 1
    And this works because the combination that must be unique is 'source IP address:source port:destination IP address:destination port' for a completed connection, but listeners must be unique based on 'listening IP address:listening port' only. – Jonathan Leffler Apr 25 '14 at 22:35
  • How does it know in advance that you're going to connect to a different address? – user207421 Apr 25 '14 at 23:28
  • 1
    @EJP: it doesn't. If you use REUSEADDR to bind the same port then attempt to connect to the same address, the connect will fail. This is a corner case that probably isn't well tested, so I wouldn't be suprised if doing this had other bad effects, such as crashing the machine... – Chris Dodd Apr 26 '14 at 00:50
  • Yep I just tested it myself on Windows 2k, it works as you describe, but no crash. My answer dates from about 1983 ;-) – user207421 Apr 26 '14 at 01:58
1

In theory yes. In practice no, because bind precedes connect, and so it can't see what you're connecting to, so can't see that the 4-tuple would be unique, so won't let you reuse an ephemeral port.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Are you referring to the bind that the kernel and/or C library is doing as part of my connect() call? If I don't explicitly bind() prior to connect(), it seems like kernel/library has the information it needs. Of course there may be good reasons to not be that clever and to behave as though I'd called bind(). – Alan De Smet Apr 26 '14 at 22:51
  • @AlanDeSmet If the bind() is implicit, as part of connect(), it isn't reusing anything. It finds a free port. The only way you can reuse any port at any time is via an explicit bind(). – user207421 Apr 26 '14 at 23:30