How to swap client and server
Situation: we have a server and we need to connect to it using a client. But here's the problem: for some reason we can't initiate a session from the client. This could be due to NAT, VPN client settings, or simply an ACL on the firewall.
What to do? Let's try swapping the client and server.
There are two subnets, External and Internal, the server is in the Internal network, but the firewall does not allow requests from the external network.
Assembling the stand:
curl client, on the “left” server
nginx web server, on the “right” server
Firewall, also known as ME, OPNsense (it’s like PfSense, only open).
Let's check. It works =))
So, to solve our problem we will use the socat utility. Socat is a mechanism for connecting two data streams. Useful links on the tool:
https://linux.die.net/man/1/socat
https://www.redhat.com/sysadmin/getting-started-socat
https://bitsanddragons.wordpress.com/2020/06/05/address-already-in-use-socat-not-working-on-osx/
On the “left” node (the client that should become the server), run the following command:
sudo socat -d -d TCP4-LISTEN:81,reuseaddr TCP4-LISTEN:82,fork,reuseaddr
Where -d -d
– these are debug flags, extended output.
TCP4-LISTEN
means that socat should listen via TCP and IPv4, then the address and port are specified via the “:” sign. However, in our case the address can be omitted, then it will listen on all addresses.
reuseaddr
– allows other sockets to bind to the same address, even if it is in use
fork
— after the connection is established, the channel is processed in a child process; that is, many child processes are created for different connections.
What's happened sudo
I guess I don't need to explain =))
So what socat does is it will first wait for a connection to be made to it on port 81, and then it will wait for a connection to be made to it on port 82. And when that happens, it will redirect traffic between those two connections.
So, let's launch it. We see the following output:
socat[150853] N listening on AF=2 0.0.0.0:81
Waits for the “right” server (the server that should become a client) to connect to it. If anything, N is notify, the logging level (W – warning, E – error). In order to see such records, we turned on debugging.
We go to the “Right” server and execute the command:
sudo socat -d -d TCP4:192.168.200.129:81 TCP4:127.0.0.1:80
Here we see that instead of TCP4-LISTEN, simply TCP4 is specified. This means that in this case, socat itself initiates the connection.
The first address is a connection through the firewall from the “right” server to the “left”, along the permitted green arrow.
The second address is a connection to a local web server.
Why is there no fork, reuseaddr here? Because these connections will be unique and permanent. Once connected to the remote server and web server – and we work.
In fact, I added these parameters there as an experiment. Child processes constantly appear, constantly initiate new connections to the web server and the remote server, clog all possibilities and the client can no longer reconnect. So it is better to leave them as is, without child processes.
So, we launched it. In the log we see that it established a connection to the “left” server on port 81, and also connected to the web server on the local machine on port 80:
socat[620719] N successfully connected from local address AF=2 192.168.100.168:58118
socat[620719] N opening connection to AF=2 127.0.0.1:80
socat[620719] N successfully connected from local address AF=2 127.0.0.1:35176
We return to the “left” server and see what’s there.
socat[150853] N accepting connection from AF=2 192.168.100.168:39974 on AF=2 192.168.200.129:81
socat[150853] N listening on AF=2 0.0.0.0:82
The first line – he waited for the connection to the first address.
The second line – he started listening to the second address.
Great, the servers see each other. Now let's try to access the web server from the client. On ME we see blocked attempts to go directly from the client to the server, as well as a successful connection in the opposite direction (from the server to the client) on port 81, as we specified in the socat command.
And directly on the client… it doesn’t work directly, but it does connect via localhost.
Control check: we execute a request on the server (to ourselves). We make sure that the request is identical, pay attention to Content-Length.
Conclusion
So, everything works. We swapped the client and server in order to initiate connections to the client from the server side and used the socat utility for this.
Command on the client: sudo socat -d -d TCP4-LISTEN:81,reuseaddr TCP4-LISTEN:82,fork,reuseaddr
Server command: sudo socat -d -d TCP4:192.168.200.129:81 TCP4:127.0.0.1:80
This is what it looks like:
That's all, thank you for your attention!