How to setup a VM Gateway like Whonix but for a generic VPN

Hi
I created a linux VM with 3 interfaces: a NAT interface for internet access (eth0 with ip 192.168.84.0/24), a Host-only interface for communication with other VMs (eth1 with ip 192.168.10.10) and a VPN interface (tun0 that’s up when connected to a VPN server and with ip 10.182.0.0/16, this may change at every connection into that range).

My goal is to set up all the necessary instructions on how to route only the incoming and outgoing internet traffic from eth1 to go through tun0 and leave internet access to the other applications on the gateway (if necessary). I would like to create something similar to the Whonix Gateway (where connections are routed through TOR from the outside connected VM Workstation) but instead of using TOR I would like to use a generic VPN service, that would be accessed with OpenVPN or Wireguard.

So I thought of some steps to do:

(1) Enable IP forwarding on the Linux virtual machine by editing the /etc/sysctl.conf file and setting net.ipv4.ip_forward = 1

(2) Add a new route for the host-only interface to route all traffic through the VPN interface with the following command:

sudo route add -net 192.168.10.0 netmask 255.255.255.0 gw 10.182.4.2 dev tun0

Here I’m not sure how to manage it if the IP of the tun0 changes. And if this is correct.

(3) Set up iptables rules to redirect all incoming and outgoing traffic from the eth1 interface to the VPN interface, except for traffic coming from the gateway itself with the following commands:

sudo iptables -A FORWARD -i eth1 -o tun0 -j ACCEPT
sudo iptables -A FORWARD -i tun0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o tun0 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -s 192.168.84.131 -o eth0 -j MASQUERADE

(4) Make iptables rules persistent so install the iptables-persistent package by running the command:

sudo apt-get install iptables-persistent
sudo iptables-save > /etc/iptables/rules.v4

(5) Configure the other virtual machine connected to the host-only network to use the Linux virtual machine as its default gateway and DNS server. So set the IP address to a unique address on the same subnet as the host-only network interface of the Linux virtual machine then set the default gateway to the IP address of the host-only network interface of the Linux virtual machine and finally set the DNS server to the IP address of the host-only network interface of the Linux virtual machine.

But something is not working properly and from the other VM connected to the gateway through the host-only network I can’t connect to the internet (when the VPN is connected on the GW).

I’m no expert and I know I’m doing something wrong so can someone help me on simplify and adjust (remove or add instructions) this steps on how to create a linux VM gateway that connect to the internet through a VPN and share this and only this connection with another VM connected through a private network of the 2 VMs (so when the VPN is off the other VM connected to the gateway have no Internet connection).

If all of this make sense :slight_smile: Thanks you so much

bump

Hi,

So what you’re doing is totally valid, but it feels a little like trying to write a website in assembly language … :slight_smile:

Many (many) years ago I spent a lot of time playing with “iptables” and related tools, but I ended up with two problems;

  • Making it work in the first place can be problematic or difficult (at best)
  • Once you’ve done it (assuming a reasonable degree of complexity), you can’t verify it “by eye”, so essentially it’s un-readable and/or unmaintainable

(apologies to the 8 iptables experts out there, but for us mere mortals who do other things too, iptables is not user-friendly)

As an “alternative”, I use something called “firehol”. I’m not saying it’s perfect or even the best solution, but at the time I switched it did the job and I can still come back to years-old scripts and modify them without breaking everything or re-testing everything from scratch. To summarise;

  • It can do everything raw “iptables” can do (and a lot more)
  • It’s pretty much “english” rather than raw unix tools
  • It has “try before you buy” option with an automatic revert if you render your machine unusable
    (edit: it’s totally open source, when I say “try before you buy” I mean it lets you try a new configuration before you commit your machine to it)
  • It adds loads of “other” stuff that you didn’t know you needed
  • It’s written by one of the aforementioned “8”

Maybe worth a look-see, but I can’t help thinking that if you’re working with raw “iptables”, the number of places you can get help might be a little limited once you stray beyond the basics.

https://firehol.org/

Example firehol script (from the website) which is doing the sorts of things you’re talking about;

interface eth0 mylan
    policy accept

interface ppp+ internet
    server smtp accept
    server http accept
    server ftp  accept
    server ssh  accept src example.firehol.org

    client all  accept

router mylan2internet inface eth0 outface ppp+
    masquerade
    route all accept

Hi,

I have used several VMs as gateways the last one was ClearOS.

Just a word of warning using a VM as a gateway; especially if it runs services like NTP, DNS, and/or DHCP… if you turn off your host-server or reboot to patch, you will essentially loose your entire network!

Currently I use a RPI3b as a gateway/dns/dhcp/ntp (using dnsmasq). Yes with IP tables… You can find a number of IPTable generators; I start there and butcher the output to suit.

eg: http://mista.nu/iptables/

The RPI boots quicker than most things so will be ready to accept requests as your other devices begin to start up.

if you want to setup an RPI (3bs are ~£40) there are many online howto for that too.

Hi,

So what you’re doing is totally valid, but it feels a little like trying to write a website in assembly language … :slight_smile:

Many (many) years ago I spent a lot of time playing with “iptables” and related tools, but I ended up with two problems;

  • Making it work in the first place can be problematic or difficult (at best)
  • Once you’ve done it (assuming a reasonable degree of complexity), you can’t verify it “by eye”, so essentially it’s un-readable and/or unmaintainable

(apologies to the 8 iptables experts out there, but for us mere mortals who do other things too, iptables is not user-friendly)

As an “alternative”, I use something called “firehol”. I’m not saying it’s perfect or even the best solution, but at the time I switched it did the job and I can still come back to years-old scripts and modify them without breaking everything or re-testing everything from scratch. To summarise;

  • It can do everything raw “iptables” can do (and a lot more)
  • It’s pretty much “english” rather than raw unix tools
  • It has “try before you buy” option with an automatic revert if you render your machine unusable
    (edit: it’s totally open source, when I say “try before you buy” I mean it lets you try a new configuration before you commit your machine to it)
  • It adds loads of “other” stuff that you didn’t know you needed
  • It’s written by one of the aforementioned “8”

Maybe worth a look-see, but I can’t help thinking that if you’re working with raw “iptables”, the number of places you can get help might be a little limited once you stray beyond the basics.

https://firehol.org/

Example firehol script (from the website) which is doing the sorts of things you’re talking about;

interface eth0 mylan
    policy accept

interface ppp+ internet
    server smtp accept
    server http accept
    server ftp  accept
    server ssh  accept src example.firehol.org

    client all  accept

router mylan2internet inface eth0 outface ppp+
    masquerade
    route all accept

Thanks for the reply and for the new possible solution using that software. I have to learn how to use it tho :slightly_smiling_face:
Maybe not so easy or there is some kind of gui where you can set up things?

Hi,

I have used several VMs as gateways the last one was ClearOS.

Just a word of warning using a VM as a gateway; especially if it runs services like NTP, DNS, and/or DHCP… if you turn off your host-server or reboot to patch, you will essentially loose your entire network!

Currently I use a RPI3b as a gateway/dns/dhcp/ntp (using dnsmasq). Yes with IP tables… You can find a number of IPTable generators; I start there and butcher the output to suit.

eg: http://mista.nu/iptables/

The RPI boots quicker than most things so will be ready to accept requests as your other devices begin to start up.

if you want to setup an RPI (3bs are ~£40) there are many online howto for that too.

Actually I don’t understand much of this, of what you are suggesting.
As I said I just want to replicate the Whonix gateway behavior with a common VPN as substitute of the TOR used there.
I think the instruction I stated in the first post should in theory work but for some reason is not working and I was asking where it could be an error or maybe how can I implement it better :wink:
I just want to create a VM that do this, I don’t care about the system on where such VM runs, if I understood correctly.

I have to learn how to use it tho
Yes, but this is the same for everything, including GUI's .. the point of firehol is that it's more English than config so it's not really any harder than a GUI, either way you still need to understand what you're doing before you use it. The problem with firewall GUI's typically is that the GUI needs to live on the box the firewall will live on, and given such boxes are typically servers and don't run X servers, it's often not practical. I've been configuring and maintaining Firewalls on the Internet for the last 30 years, firehol is the best solution I've come across to date (including a number of GUI options). I'd always look at new GUI options, however thus far, they all seem "limited" and never encompass all the features that are available .. which means you can develop infrastructure over time, then one day get a requirement that the GUI can't meet, at which point you have to change everything.
I have to learn how to use it tho
Yes, but this is the same for everything, including GUI's .. the point of firehol is that it's more English than config so it's not really any harder than a GUI, either way you still need to understand what you're doing before you use it. The problem with firewall GUI's typically is that the GUI needs to live on the box the firewall will live on, and given such boxes are typically servers and don't run X servers, it's often not practical. I've been configuring and maintaining Firewalls on the Internet for the last 30 years, firehol is the best solution I've come across to date (including a number of GUI options). I'd always look at new GUI options, however thus far, they all seem "limited" and never encompass all the features that are available .. which means you can develop infrastructure over time, then one day get a requirement that the GUI can't meet, at which point you have to change everything.

Yes I agree.
FireHOL seems to be an interesting way of doing this sort of routing/firewalling. I tried some configurations but I can’t manage to make the system work as wanted.
Any advice on where I can set up it as I need?

Ok, so it’s difficult to get “exactly” what you need from what you’ve written, but it sounds like you’re using your machine as a gateway for machines on a private IP range, and you want the gateway to retain normal internet access and you want to provide NAT access to the private range through the gateway … in which case you would want (in principle) something like this;

version 6

# create a new table
# set the default route for the table to be eth0
# set the source for the table to be eth1
# completely untested, but in principle as something to play with

iptables4 -t mytable
ipv4 rule add from eth1 table mytable  # may need ip instead of interface
ipv4 route add default via vpn0 table mytable  # may need ip instead of interface

interface eth0 public
  policy accept

interface vpn0 vpn
    policy accept

interface eth1 private
    policy accept

router natme inface private outface vpn0
    masquerade
    route all accept

# then add whatever restrictions you want per interface / per router instead of "policy accept"

Note if you have “other” things trying to set up routes etc on your box in addition to firehol, the two won’t get along … so any other routing needs to get removed and inserted into your firehol config. Use “firehol try” to experiment, this should always offer the option to back out if things go wrong.

Essentially there are two things here;
a. Route traffic originating on the private interface via the VPN (ipv4 rule)
b. Add NAT to traffic going out of the VPN when coming from the private interace (router natme)

hth

Caveat: I have actually done exactly this in the past, but it was a long time ago … so from memory something “like” this should do what you want, but it may take a little tweaking (assuming I understand what it is you’re trying to do)

Ok, so it's difficult to get "exactly" what you need from what you've written, but it sounds like you're using your machine as a gateway for machines on a private IP range, and you want the gateway to retain normal internet access and you want to provide NAT access to the private range through the gateway .. in which case you would want (in principle) something like this;
version 6

# create a new table
# set the default route for the table to be eth0
# set the source for the table to be eth1
# completely untested, but in principle as something to play with

iptables4 -t mytable
ipv4 rule add from eth1 table mytable  # may need ip instead of interface
ipv4 route add default via vpn0 table mytable  # may need ip instead of interface

interface eth0 public
  policy accept

interface vpn0 vpn
    policy accept

interface eth1 private
    policy accept

router natme inface private outface vpn0
    masquerade
    route all accept

# then add whatever restrictions you want per interface / per router instead of "policy accept"

Note if you have “other” things trying to set up routes etc on your box in addition to firehol, the two won’t get along … so any other routing needs to get removed and inserted into your firehol config. Use “firehol try” to experiment, this should always offer the option to back out if things go wrong.

Essentially there are two things here;
a. Route traffic originating on the private interface via the VPN (ipv4 rule)
b. Add NAT to traffic going out of the VPN when coming from the private interace (router natme)

hth

Caveat: I have actually done exactly this in the past, but it was a long time ago … so from memory something “like” this should do what you want, but it may take a little tweaking (assuming I understand what it is you’re trying to do)

I know that is kinda hard to explain exactly what I would like to do but I try to sum up:

  • I have 2 vmware Virtual Machine: a linux VM1 (Kali or Ubuntu) that will work as the Internet gateway for the other one VM2, with Windows 11 installed.
  • The VM1 Linux Gateway have 3 interfaces: a NAT interface for internet access (eth0 with ip in this range 192.168.84.0/24), a Host-only interface for communication with VM2 (eth1 with ip 192.168.10.10) and a VPN interface (tun0 that’s up when connected to a VPN server and with ip into this range 10.182.0.0/16, this may change at every connection
  • The VM2 Windows have just one interface: the same Host-only for communication with VM1 (with ip 192.168.10.11)

What I would like to accomplish is the following:

  • Have Windows 11 on VM2 have internet connection only when the VPN is connected inside the VM1 Linux Gateway so to not have internet connection when the VPN on VM1 is disconnected.
    In other words, I would like to isolate the Windows 11 VM from the internet except when I connect successfully to the VPN provider inside the VM1 Linux Gateway, either with OpenVPN or Wireguard protocols
  • Inside the VM1 Linux Gateway there should always be internet connection, to be able to connect to the VPN service correctly

This is the same behavior that Whoinix does with the TOR connection instead of a generic VPN connection.
This ensure that VM2 will never have leaks outside the VPN connection and the VPN connection is transparent to the applications inside the Windows VM2.

I hope to have explained a little bit better what I would like to accomplish. I did took a look at the FireHOL configuration you kindly proposed and I really have to test it out and conceptually understand it
But after the explanation, those fireHOL instruction will do what I need to do? :slight_smile:
Thank you very much

Ok, so you’ll need to adapt the config a little to suit your interfaces and addresses, but essentially it should do what you want, or at least all the bits are there.

The config should be “firehol.conf” and needs to go in /etc/firehol/ , then you need to tweak to suit. Then “firehol try” will give it a go, make sure you’ve disabled any other firewalls or custom routes first.
There are two things at play in the config, the iptables routing, and the “firehol” masquerading (nat).

So iptables -t mytable should create a new iptables table.
“rule add from” is then used to direct all traffic from your desired ip range (the windows box) to the table “mytable”
“route add default” is then used to set a default route out via the vpn for any traffic entering “mytable”.

  • which should set the routing up.
    Then the “router natme” statement is used to specify where nat happens and on what traffic, i.e. all traffic coming in to the interface connected to the windows box, and going out of the vpn interface.

Make sense?
(note; this is completely untested / off the top of my head, there may be some syntax issues in there somewhere)

Ok, so you'll need to adapt the config a little to suit your interfaces and addresses, but essentially it should do what you want, or at least all the bits are there.

The config should be “firehol.conf” and needs to go in /etc/firehol/ , then you need to tweak to suit. Then “firehol try” will give it a go, make sure you’ve disabled any other firewalls or custom routes first.
There are two things at play in the config, the iptables routing, and the “firehol” masquerading (nat).

So iptables -t mytable should create a new iptables table.
“rule add from” is then used to direct all traffic from your desired ip range (the windows box) to the table “mytable”
“route add default” is then used to set a default route out via the vpn for any traffic entering “mytable”.

  • which should set the routing up.
    Then the “router natme” statement is used to specify where nat happens and on what traffic, i.e. all traffic coming in to the interface connected to the windows box, and going out of the vpn interface.

Make sense?
(note; this is completely untested / off the top of my head, there may be some syntax issues in there somewhere)

Yeah it make sense but I’m no expert on FireHOL so I don’t know. I will try and tweak a little bit to make things works.
Do you suggest using Kali or Ubuntu?

And in the iptable part should I put the address in which form: 192.168.10.0/24 or other form? the interface would not work as a bypass on put exact ip ranges?

You added a comment into the configuration that say: # set the default route for the table to be eth0 but there is no instruction regarding eth0, or I can’t see it?

Ubuntu, Kali is for pen testers.
Address formats are flexible, anything iptables would take should work.
Set default route for table mytable to vpn0;

ipv4 route add default via vpn0 table mytable