TCP simultaneous open and self connect prevention

2019-01-17 17:09发布

TCP standard has "simultaneous open" feature.

The implication of the feature, client trying to connect to local port, when the port is from ephemeral range, can occasionally connect to itself (see here).

So client think it's connected to server, while it actually connected to itself. From other side, server can not open its server port, since it's occupied/stolen by client.

I'm using RHEL 5.3 and my clients constantly tries to connect to local server. Eventually client connects to itself.

I want to prevent the situation. I see two possible solutions to the problem:

  1. Don't use ephemeral ports for server ports. Agree ephemeral port range and configure it on your machines (see ephemeral range)
  2. Check connect() as somebody propose here.

What do you thinks? How do you handle the issue?

P.S. 1

Except of the solution, which I obviously looking for, I'd like you to share your real life experience with the problem.

When I found the cause of the problem, I was "astonished" on my work place people are not familiar with it. Polling server by connecting it periodically is IMHO common practice, so how it's that the problem is not commonly known.

9条回答
劫难
2楼-- · 2019-01-17 18:01

For server you need to bind() socket to port. Once addr:port pair had socket bound, it will no longer be used for implicit binding in connect().

No problem, no trouble.

查看更多
Deceive 欺骗
3楼-- · 2019-01-17 18:01

The actual problem you are having seems to be that while the server is down, something else can use the ephemeral port you expect for your server as the source port for an outgoing connection. The detail of how that happens is separate to the actual problem, and it can happen in ways other than the way you describe.

The solution to that problem is to set SO_REUSEADDR on the socket. That will let you create a server on a port that has a current outgoing connection.

If you really care about that port number, you can use operating specific methods to stop it being allocated as an ephemeral port.

查看更多
beautiful°
4楼-- · 2019-01-17 18:02

Note that this solution is theoretical and I have not tested it on my own. I've not experienced it before (or did not realize) and hopefully I won't experience it anymore.

I'm assuming that you cannot edit neither the client source code nor the server source. Additionally I'm assuming the real problem is the server which cannot start.

Launch the server with a starter application. If the target port that the server will bind is being used by any process, create an RST (reset packet) by using raw sockets.

The post below briefly describes what an RST packet is (taken from http://forum.soft32.com/linux/killing-socket-connection-cmdline-ftopict473059.html)

You have to look at a "raw socket" packet generator.
And you have to be superuser.
You probably need a network sniffer as well.

http://en.wikipedia.org/wiki/Raw_socket
http://kerneltrap.org/node/3072 - TCP RST attacks
http://search.cpan.org/dist/Net-RawIP/lib/Net/RawIP.pm - a Perl module
http://mixter.void.ru/rawip.html - raw IP in C

In the C version, you want a TH_RST packet.

RST is designed to handle the following case.

A and B establish a connection.
B reboots, and forgets about this.
A sends a packet to B to port X from port Y.

B sends a RST packet back, saying "what are you talking about? I don't
have a connection with you. Please close this connection down."

So you have to know/fake the IP address of B, and know both ports X
and Y. One of the ports will be the well known port number. The other
you have to find out. I thnk you also need to know the sequence
number.

Typically people do this with a sniffer. You could use a switch with a
packet mirroring function, or run a sniffer on either host A or B.

As a note, Comcast did this to disable P2P traffic.
http://www.eff.org/wp/packet-forgery-isps-report-comcast-affair

In our case we don't need to use a sniffer since we know the information below:

So you have to know/fake the IP address of B, and know both ports X and Y

X = Y and B's IP address is localhost

Tutorial on http://mixter.void.ru/rawip.html describes how to use Raw Sockets.

NOTE that any other process on the system might also steal our target port from ephemeral pool. (e.g. Mozilla Firefox) This solution will not work on this type of connections since X != Y B's IP address is not localhost but something like 192.168.1.43 on eth0. In this case you might use netstat to retrieve X, Y and B's IP address and then create a RST packet accordingly.

查看更多
登录 后发表回答