Force all network traffic through one server via NAT and PF

I have 3 virtualbox FreeBSD vm servers running inside a pcbsd host:


..............Public IP Address..............
.....................|.......................
...................gateway/modem...................
................192.168.1.254................
.....................|.......................
...................pc-bsd....................
..............(virtualbox host)..............
................192.168.1.10.................
.....................|.......................
............192.168.1.20 (nic le0)...........
..............reverse proxy (vm1)............
.............192.168.1.30 (nic le1)..........
.....................|.......................
...........--------------------..............
..........|.....................|............
.....web server (vm2)....email server (vm3)..
......192.168.1.140.......192.168.1.150......


Currently - the reverse proxy vm isn't a gateway - only nginx is redirecting traffic - and just port 80 traffic to the web server and port 443 traffic to the email server. I ssh directly to each vm from the host pcbsd or another box in the same subnet 192.168.1.0/24.

Now - I want to tighten security and force all network traffic to go through the reverse proxy server so that the web and email servers are behind it. But I don't want this to be 'transparent' - I want pf rules to decide what goes through nic 2 (le1) to the email and web servers.
The nginx reverse proxy will still listen on port 80 and nic 1 (elo0) and redirect traffic to the web server - but now through nic 2 (le1).
And now all ssh to the web and email servers should be through the reverse proxy, using pf to ssh portforward/tunnel to them.


In /etc/rc.conf

Code:
ifconfig_le0="inet 192.168.1.20 netmask 0xffffff00"
ifconfig_le1="inet 192.168.1.30 netmask 0xffffff00"
defaultrouter="192.168.1.254"
gateway_enable="YES"

My Questions:

1 - If I want to redirect traffic in pf between 2 nics, do I need to use NAT in /etc/pf.conf?

2 - And if so, in /etc/rc.conf do I need to use:

Code:
gateway_enable="YES"

and in /etc/syctl.conf use:

Code:
sysctl net.inet.ip.forwarding=1

but have /etc/pf.conf 'intercept' this traffic forwarding from nic 1 (le0) to nic 2 (le1)?


3 - If I have to use NAT, how may this affect the nginx reverse proxy that current listens on port 80 and redirects to the web server?

4 - How is traffic passed/forwarded back from the web and email servers through nic 2 to nic 1 on the reverse proxy and then to the gateway? I would prefer it did this because at some point in the future I want to set up a firewall vm and have all outbound traffic from vm servers go through this to the internet (not through the reverse proxy).

Sorry for all the noob questions - but I feel I'm making progress ;)
 
nx said:
2 - And if so, in /etc/rc.conf do I need to use:

Code:
gateway_enable="YES"

and in /etc/syctl.conf use:

Code:
sysctl net.inet.ip.forwarding=1
gateway_enable sets that sysctl(8), there's no need to set it explicitly.
 
  • Thanks
Reactions: nx
Ok.. ty,

am I on the right track?

Do I have to enable gateway and NAT to use pf to redirect/forward traffic based on protocol and port from one interface to the other?

Can anyone give me an example of a pf redirect rule for ssh that goes from external to internal interface? Or do I only need to redirect from ssh port to the web server and let the NAT rule that is before this rule 'intervene' and handle redirection between interfaces?

I'm trying to get NAT right and a rule for ssh but no luck so far - probably because I'm not sure if I need NAT and how to write the redirect rule based on whether I have to use NAT or not.
 
You are on the wrong track. Don't use the same network with 2 different NIC's. There is no point in doing this.

Instead, separate your networks and put the reverse proxy and the email server in the front side and the web server behind.

The NAT should take place in your router ideally.
 
Thanks gkontos,

I understand your suggestion, but for now I must use the reverse proxy as the firewall. So the email and web servers (and any more I add later) should be behind it.

In future I will replace some of the pf rules on the reverse proxy with a dedicated pf firewall in front of it, perhaps pfsense. Then the email server and reverse proxy can go directly behind the firewall, with the web server behind the reverse proxy. That is my end goal. I cannot do it because of resource restrictions at this time.

At present I cannot change anything on the gateway/modem other than simple portwarding. I'm in a tricky position because if I have to use NAT, I could easily change the internal interface and the web server to class b, but changing all IPs in the email server would be painful.

These are 3 typical scenarios/rules I need:

1. TCP traffic comes in via ext_if, nginx 'catches' port 80 TCP traffic and redirects to web server, and pf rule lets this traffic go through int_if to the web server.

I'm not sure if I need NAT for this, but it appears I would need a pf rule to redirect nginx's redirect to int_if so it would then go to the web server (and right port - nginx listens for port 80 and sends to port 8083 on IP address 192.168.1.140).

I'm really struggling to write a pf rule for this as I'm not sure which interface the nginx redirect traffic comes from - because TCP traffic has already come into the reverse proxy server via ext_if and redirected by nginx to 192.168.1.140:8083. Somehow I need pf to 'know' that traffic going to the web server (192.168.1.140) goes through int_if - and only after it has been redirected there by nginx.


2. SSH traffic comes in via ext_if and NAT/pf redirects this to int_if and it gets to web or email server based on the IP address in the ssh command.

Again I'm not sure if I need NAT and/or pf rule for redirecting ssh to int_if then to the server referenced in the ssh command.

3. Decide whether all traffic leaving the web and email servers should pass through the reverse proxy's int_if and ext_if via pf rules - for added security - or just rely on the pf rules I have on web and email servers to do this. Again, the reason for forcing them through the reverse proxy is because I will eventually replace this with the firewall as explained above.

These are really simple - basic - needs. I'm sure many people have set this up. Please give me your advice.

Thanks
 
For testing (and to learn the pf syntax) I am trying to bypass nginx (reverse proxy) by using pf to redirect TCP port 80 received on the external interface to the web server on port 8083 via the internal interface.

The relevant bit of my /etc/rc.conf is

Code:
# External Interface - Connected To Gateway (& Internet)
ext_if = "le0"
# Internal Interface - Connected To Servers on LAN
int_if = "le1"
# Servers By Name
reverse_proxy_ext = "192.168.1.20"
reverse_proxy_int = "192.168.1.30"
web_server = "192.168.1.140"
email_server = "192.168.1.150"

# Redirect all TCP packets arriving on reverse proxy server's external interface from any source address and destined to the web server listening on port 80 to the internal interface on port 8083.

rdr on $ext_if proto tcp from any to $web_server port 80 -> $reverse_proxy_int port 8083

I guess this isn't working because I don't know where to reference the internal interface?

If I can get his going, perhaps I can work out how to take TCP port 80 traffic redirected from nginx to the web server on port 8083.

Again, the reason I have to do this is... the web server (and email server) are sharing a virtualbox internal network adapter so that they are not connected to the virtualbox host via the other adapter types (not used) - bridged and host-only adapters.
The reverse proxy has 2 interfaces (adapters) - bridged (le0) for gateway/internet and le1 - the same internal network adapter as the web and email servers.
 
Back
Top