Forwarding workststation nginx to gateway and host

Hi!

I do not want to do something really complex but in Whonix maybe it is not easy. I want to expose the port of my nginx (running inside of Workstation) into my host machine, so basically if I do curl 127.0.0.1:80 in my host machine I can get the output of the nginx running in Workstation.

I already read the documentation about how to SSH into Whonix Workstation an I understood that it is not an option adding a NAT interface to Whonix Workstation. So the schema I am looking for should be:
host → Whonix-Gateway ™ → Whonix-Workstation ™ (nginx)

Accessing Whonix Gateway’s ports from Host is not a problem following this tutorial:
Access Gateway Port From Host

I tested the example provided and everything worked fine. I want to do the same with the nginx port but before forwarding the port I must be able to access the nginx port from the Gateway, which currently is not possible because the gateway is not listening in that port (according with the output from netstat and when trying to curl it I get curl: (7) Failed to connect to 127.0.0.1 port 80: Connection refused)

So, unless that I am missing something what I need would be to redirect the traffic between Workstation and Gateway. If so, adding the following iptables route inside Whonix Gateway should be enough to have access the traffic from nginx inside the gateway?

sudo iptables -t nat -I PREROUTING -i eth0 -d 10.152.152.11 (the assigned ip of the workstation) -p tcp --dport 80 -j DNAT --to 127.0.0.1:80

I am new to iptables so any advice I really appreciate it @Patrick

Thanks!

Prerequisite knowledge:

  1. i.e. don’t use plain curl for this. Disabling or circumventing stream isolation for curl required.
  1. Open port in Whonix-Workstation firewall:
  1. Open port in Whonix-Gatway firewall:
  1. Options:
  • systemd-socket-proxyd
  • socat
  • ssh port forwarding

Not what you’re looking for but you might be able to figure out the systemd-socket-proxyd / socat of by reading and then looking how it’s done in the source code:

Or perhaps easier, duplicate/modify/emulate based on the following files:

  • /lib/systemd/system/anon-ws-disable-stacked-tor_autogen_port_9050.service
  • /lib/systemd/system/anon-ws-disable-stacked-tor_autogen_port_9050.socket

Something similar to this would have to run on Whonix-Gateway.

Or different method based on that: tunnel nginx through SSH.


related:

Thanks for your reply! I will carefully review all the information that you have sent me and the different options that you have presented to me. I hope I can implement it!

@Patrick After checking all resources, I decided to try socat to forward it. I think that I am missing something important because I have my nginx listening on port 8083 (nginx is working fine and I can access the hidden service in tor). So I am using the following command in the Workstation:

socat TCP-LISTEN:8083,fork TCP:10.152.152.10:80

And it is giving me the following output:

socat[145032] E bind(5, {AF=2 0.0.0.0:8083}, 16): Address already in use

Which makes sense for me, because nginx is listening in that port and I can check it through netstat too, but how can I forward that nginx port if I am listening in that port too? (Probably I am asking something really basic but I swear that I do not see it)

Has to be done on Whonix-Gateway. Accept the connection and forward to host.

Hi @Patrick , it seems that I am really close to what I am looking for but I still need one more step.

I decided to circumvent stream isolation (I do not want to disable it, just test if I can access nginx inside the Gateway). So I executed:

UWT_DEV_PASSTHROUGH=1 curl --output - 10.152.152.11:8083

And it is giving me the nginx’s output inside the Whonix Gateway!

To do port forwarding between my host and Whonix Gateway I followed next steps:

In Whonix Gateway I went to Settings > Network > Adapter 1 > Advanced > Port Forwarding and added

Name: Nginx
Protocol: TCP
Host IP: 127.0.0.1
Host Port: 80
Guest IP: 10.152.152.10
Guest Port: 8083

And now I execute socat inside Whonix Gateway:

socat TCP-LISTEN:8083,fork TCP:10.152.152.10:80

In another terminal I try to curl the forwarded ip but it does not work:

UWT_DEV_PASSTHROUGH=1 curl --output - 10.152.152.10:80
curl: (7) Failed to connect to 10.152.152.10 port 80: Connection refused

(Same result if I replace the gateway ip with localhost)

And if I curl localhost in my host:

curl --output - 127.0.0.1:80
curl: (56) Recv failure: Connection reset by peer

So it seems the port forwarding is not being done between whonix gateway and the host, probably because I am not executing properly the socat command

socat IP might be wrong. Listen on Whonix-Gateway and forward to Whonix-Workstation IP.

I do not understand it, if I already have access to Whonix-Workstation IP where nginx is running ( 10.152.152.11:8083) Why do I have to forward it to Whonix-Workstation IP? I thought that I needed to forward it from Whonix-Workstation IP ( 10.152.152.11:8083) to Whonix-Gateway IP (127.0.0.1:80)

recommended pre exercise: using Access Whonix-Gateway Ports from the Host as is

socat TCP-LISTEN:8083,fork TCP:10.152.152.10:80

Listens on gateway 8083 and forwards to gateway internal interface IP 10.152.152.10 port 80. And then? I don’t see how it would connect to the workstation.


The idea is:

  1. listen on workstation all interfaces using nginx
  2. test: make sure gateway curl can connect to above (uwt circumvention required)
  3. listen on gateway external interface and connect it to the workstation (same IP/port as for 2)) using socat or similar mention tool
  4. test: make sure gateway uwt circumventing curl can connect to above
  5. Access Whonix-Gateway Ports from the Host

Thanks for your reply and your time @Patrick now I see the error on my socat command and once I specified the same ip it worked! :smiley:

Just one last question @Patrick ! What is the best practice to execute always my socat command each time I restart the Gateway? Using nohup will work but if it is executed automatically once the system is restarted would be perfect

A systemd unit file.

If you’re up for it, would be nice if you could document the whole thing.

Sure, I do not think today I can do it but tomorrow or during the weekend I will do it. Do I post in this thread or in other place?

Reproduce following steps if you want to forward nginx (or any other service) from Whonix Workstation to your Whonix Gateway and Host

In this example, I am also configuring a hidden service for Nginx (although you can skip this)

  1. Editing Tor Configuration in Whonix Gateway:

sudo nano /usr/local/etc/torrc.d/50_user.conf

HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 10.152.152.11:8083 # IP assigned in Workstation

Restarted tor and get the generated onion domain (my_onion_domain)

  1. Opening external port in Whonix Gateway:

sudo mkdir -p /usr/local/etc/whonix_firewall.d
nano /usr/local/etc/whonix_firewall.d/50_user.conf

EXTERNAL_OPEN_PORTS+=" 80 "

sudo whonix_firewall

  1. Prepare Nginx in Whonix Workstation

In Nginx config add:

server {
server_name my_onion_domain;
listen 8083;
…

I restarted nginx and at that point I could access my onion domain in Tor Browser

  1. At this point we can test using curl if we can connect to Nginx directly from inside Whonix Gateway

To test that the connection is working we must circumvent stream isolation in the Gateway using the following command:

UWT_DEV_PASSTHROUGH=1 curl --output - 10.152.152.11:8083

Curl’s output must be the same than you get in your Workstation or accessing your hidden service in Tor Browser, in case not double check that Nginx is working and that you are using the proper ports

  1. Port Forwarding from Workstation to Gateway

Once we can access our nginx directly from our Gateway we need to forward the IP and Port from our Whonix Workstation to our Whonix Gateway. Patrick suggested systemd-socket-proxyd, socat or ssh port forwarding (maybe it is possible to use sshuttle and faster than traditional openssh’s port forwarding but it is untested as mentioned before footnotes here: Connecting to Tor before SSH). In my case I decided to use socat because it seemed easier to me, it was a personal choice

socat TCP-LISTEN:80,fork,bind=10.152.152.10 TCP:10.152.152.11:8083

10.152.152.10 assigned to eth1 Gateway internal interface
10.152.152.11 assigned to my Workstation

Before continuing we must test if the port forwarding is working. We repeat the process as the previous step
UWT_DEV_PASSTHROUGH=1 curl --output - 10.152.152.10:80

  1. Port forwarding from Gateway to Host

In Whonix Gateway we go to Settings > Network > Adapter 1 > Advanced > Port Forwarding and added

Name: Nginx
Protocol: TCP
Host IP: 127.0.0.1
Host Port: 80
Guest IP: 10.152.152.10
Guest Port: 8083

In case you want to do it from the command line check it here: Access Whonix-Gateway Ports from the Host

After restarting Whonix Gateway we can test from our host if we have direct access to our Nginx running in the Workstation

curl 127.0.0.1:80

  1. Use systemd to start automatically socat at boot

If you want to start automatically your socat command follow next steps to create a new service and start it automatically at boot using systemd

sudo nano /lib/systemd/system/socat_autostart.service

[Unit]
Description=Start at boot socat command
After=network.target

[Service]
ExecStart=socat TCP-LISTEN:80,fork,bind=10.152.152.10 TCP:10.152.152.11:8083

[Install]
WantedBy=multi-user.target

chmod 644 /lib/systemd/system/socat_autostart.service

sudo systemctl enable socat_autostart

sudo systemctl start socat_autostart

You can check if your service is working fine with

sudo systemctl status socat_autostart

@Patrick feel to free to move this post or modify it if you see some typo.

P.S. I am facing a small issue with systemd when booting the system
My service is working fine if I start/stops when Whonix Gateway is on but after restarting the Gateway, my service is executed but socat is failing with the following output (from systemctl status socat_autostart):

E bind(5, {AF=2 10.152.152.10:80}, 16): Cannot assign requested address

Any idea about how maybe delay the execution of my service after the reboot? (Edited: now it is fixed in my edit)

Thank you!

systemd is parallelized and starts that service before even networking is up.

After=network.target

Other files in folder After=network.target use it too. See these for proper syntax. Has to be in the [Unit] block.

fork should likely be avoided for Type=simple.
(“Type=forking style” is outdated.)


Ok perfect, I updated my post with the proper syntax

Perfect! I am happy to contribute to this project :raised_hands: :grinning_face_with_smiling_eyes:

1 Like