I have a provider (A) that wants to send us data through an incoming TCP connection. Unfortunately the consuming service (B) cannot receive inbound TCP connections. Also it does not have a static IP, another requirement.
One way to solve this would be a service that connects the incoming TCP A port to another TCP port B, so that the consumer can make an outbound connection to B.
This is not a unique problem [1] [2], and with socat I can make something very close to what I want:
socat -d -d -d -u TCP4-LISTEN:PORT-A,reuseaddr TCP4-LISTEN:PORT-B,reuseaddr
However, this has the following problems:
- If B disconnects, it cannot re-connect. With
TCP4-LISTEN:PORT-B,reuseaddr,fork
, it can connect but does not receive data. - B cannot connect before A has established a connection (surmountable)
- Only one connection can be established to
PORT-B
(surmountable)
Is there a way to adjust the command so that is becomes "permament" and resistent to failures?
The important question is, how will A react to loss of connection, or to connection being refused? Anything that just assumes that a single TCP connection will stay up forever is going to be fragile; that's just the nature of internet.
How about setting up the
socat
as a[x]inetd
service?You would set
xinetd
to listen in PORT-B, and start thesocat -u TCP4-LISTEN:PORT-A,reuseaddr STDIO
as soon as the B-side connects.xinetd
will pass the incoming traffic from B-side to standard input ofsocat
, and catch the standard output ofsocat
and pass it to the B-side.If B disconnects, then the
socat
process can be allowed to end;xinetd
will start a new one as soon as B connects again. While B is disconnected, A will be getting "connection refused" errors.I once had to do something quite similar on an old HP-UX system.
The real world is messy.
In the real world sometimes TCP connections die, this may happen for example if a stateful firewall or NAT is rebooted, if the connection goes too long without traffic, if the underlying connection is down for too long.
Furthermore sometimes when connections die they don't die symmetrically. If a connection carrying a lot of data dies then it is likely that the sender will notice that it is dead long before the recipiant does so. This has a couple of side effects.
Furthermore TCP connections are a stream of bytes, NOT a stream of messages, so when your connection dies you may receive a partial message.
The net result of this leads me to conclude that a robust solution requires an understanding of the application protocol so that your solution can understand.