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.

The stand scheme. You need to contact the server on the right, but ME won't let you in. But it lets you back in

The stand scheme. You need to contact the server on the right, but ME won't let you in. But it lets you back in

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 =))

Magazine on ME. Blocks from left to right, lets through from right to left.

Magazine on ME. Blocks from left to right, lets through from right to left.

LAN Interface Rules. Default settings, allow all

LAN Interface Rules. Default settings, allow all

Rules for WAN interface. By default, all are denied

Rules for WAN interface. By default, all are denied

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 sudoI 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.

In the ME log we see that the server initiates a connection to the client

In the ME log we see that the server initiates a connection to the client

And directly on the client… it doesn’t work directly, but it does connect via localhost.

Requests from the client. Doesn't work directly, but the connection is made via localhost

Requests from the client. Doesn't work directly, but the connection is made 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.

Requests from the server to your address. The responses match what the client sees

Requests from the server to your address. The responses match what the client sees

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:

And here's how it works

And here's how it works

That's all, thank you for your attention!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *