I've done as much research as I could on this without digging right off in the kernel source. There seems to be a large amount of disinformation/incorrect info on the subject, so I hope this answers the question for me and others once and for all.
Strictly IPv4 speaking, is port exhaustion actually possible? Let me explain:
- Seemingly there are 65535 ports available for use. 0 isn't available.
- I have read that port exhaustion requires the (src ip, src port, dst ip, dst port) tuple to be unique.
- To be clear and assuming I can use 100% of ephemeral ports via sysctl net.ipv4.ip_local_port_range setting
And this is the question: Is this how it works?
- I could have 65k connections from 127.0.0.1:(x) to 127.0.0.1:80
- I could have 65k connections from 127.0.0.1:(x) to 127.0.0.1:555
- Basically once again, the question is (srcip,srcport,dstip,dstport) must be unique, correct?
- I could not open any more than 65k connections from ip "A" to IP "B", Port "N"
- Likewise, a single IP could not open more than 65k connections to my webserver at x.x.x.x:80, however I could support much more than 65k overall as long as they are from different source IPs?
Finally, I am a little confused about (outgoing) ephemeral ports and incoming ports which are listening. I realize once the connection is established each side of the connection is a peer and equal, but before that happens:
For example, if indeed the (srcip,srcport,dstip,dstport) tuple must be unique, why is it if I enable, for example
net.ipv4.ip_local_port_range = 1024 65535
Which allows the use of ephemeral ports from 1024-65535, that if I have services that bind on port 3306 (mySQL, for example), they will sometimes fail to start because the port is in use.
Is this relating the fact that: (And this is a statement I am asking to be validated):
- (srcip,srcport,dstip,dstport) are needed to be unique for each connection with the port range of 1-65535 (not paying attention to the OS's usage of ephemeral ports)
- However, for a socket to bind, it could be seen as (srcip,srcport, *, *). Or another way to put this, is the IP must not be using that port for any reason to bind to?
I can verify the above behavior, i.e. I use the exact sysctl line above, and because of it I moved mySQL to a port lower than 1024 because it would occasionally and very randomly fail to restart because assuming the OS was using that port (3306) for an ephemeral port.