On Thu, 4 Jan 2018 14:09:50 +0100
Jon S <[email protected]> wrote:

> Hello misc!
> 
> My OpenBSD file server just became a router too (after getting a new
> internet connection where the provider does not include a router in
> the subscription).

If possible, I'd avoid combining file server and firewall services on
single box.

> This led to my first experieces with pf. After some work I came up
> with whats below. It works as I want it to work, but I wonder if
> there is a way to create a rule where incomming traffic to the
> internal NIC (re0) is passed if it is targeted for em0 (external,
> internet NIC)? The current solution would require an update of the
> "pass in on re0 to !re0:network"-rule if another NIC is added (lets
> say a DMZ).

All my pf rulesets start with defining interface macros so they are
more readable, and also more flexible (this way changing NIC with
different driver needs one line changed, instead of all lines in the
ruleset referencing that interface):

# INTERFACE MACROS
if_int = "re0"
if_ext = "em0"

> set skip on lo0
> 
> # Block everything everywhere by default
> block log all

I prefer to put "match" section above default "block log all" rule.
It's more logical to me, as something being "matched" has no impact if
it's not "passed" or "blocked" later on in the ruleset.

> # NAT local network to external
> match out on em0 inet from re0:network nat-to (em0)
> 
> # Allow all outgoing traffic
> pass out on {em0, re0}
> 
> # Allow only specific services on this machine to be accessed from
> # local network
> pass in on re0 inet proto tcp to port ssh # ssh
> pass in on re0 inet proto icmp            # icmp
> pass in on re0 inet proto tcp to port 445 # samba

Your description line does not describe accurately what next three
lines do - as destination IP is not present, "to any" is assumed, so
more accurate description would be "Allow specific services on any
machine be accessed from local network".

If you wanted your ruleset to match description line, and your
services listen on internal NIC, you would do something like:

pass in on $if_int inet proto tcp  from re0:network to re0 port ssh
pass in on $if_int inet proto icmp from re0:network to re0
pass in on $if_int inet proto tcp  from re0:network to re0 port 445

> 
> #pass in on re0 inet to em0:network # This does not work, since the
> #mask for this IF will only let traffic through to the limitied set of
> #IPs on the same C-segment as em0. That would probably be a set of
> #other customers at the nework operator...
> 
> # This works, but will require an update if any furter NIC is involved
> # later
> pass in on re0 to !re0:network

There are multiple ways to achieve this. One of them would be passing
everything on $if_int, and blocking what you don't want later (if
"quick" keyword is not used, last matching rule wins):

pass in on $if_int
block in on $if_int inet proto tcp from $if_int:network to \
  $if_int port { !=ssh !=445 }

The other one would be blocking unwanted stuff quickly early in the
ruleset, and passing what you want later on:

block in quick on $if_int inet proto tcp from $if_int:network to \
  $if_int port { !=ssh !=445 }
pass in on $if_int

Both examples block only TCP to internal NIC, so blocking other
protocols if there are any on the firewall also needs to be done.
> 
> # I would like something like this to work, so that future added NICs
> # wont open new unwanted paths
> #pass in on re0 to em0
> 
> # Allow only incomming SSH to external NIC
> pass in on em0 inet proto tcp to port ssh

In the end, your ruleset seems quite minimal. I suggest you start
worrying about new NIC once you add it. For now it would be better to
play around with pfctl -vvsr, systat states/rules, tcpdumping pflog etc.

Hope this helps,

-- 
Before enlightenment - chop wood, draw water.
After  enlightenment - chop wood, draw water.

Marko Cupać
https://www.mimar.rs/

Reply via email to