cbsd / cbsd

Yet one more wrapper around jail, bhyve, QEMU and XEN
https://bsdstore.ru
BSD 2-Clause "Simplified" License
671 stars 76 forks source link

cbsd expose clears host's existing pf rules #761

Open n-connect opened 7 months ago

n-connect commented 7 months ago

Mandatory info for bug reports:

FreeBSD version ( uname -a ): FreeBSD host 13.2-RELEASE-p4 FreeBSD 13.2-RELEASE-p4 GENERIC amd64

CBSD version ( cbsd version ): 14.0.6

After adding port forward rules to a cbsd jail with

I've checked the following files:

After checking the [expose](https://github.com/cbsd/cbsd/blob/55f486932726df331b87c26b13bc667395c69d75/tools script/expose#L9) I did not see, if CBSD wants to take care about the eixsting rules at all. Please fix me.

Temporary solution:

With these steps I can have the exsiting host's pf config and the cbsd jail's ones both. I know there is an additional possible source of problem outside of CBSD - having wrong pf rules on the hosts, but a pfctt -nf check could potentially help during cbsd apply - at least syntax level.

olevole commented 7 months ago

Firewall management in CBSD is quite limited and creates very simple rules. This control is suitable if you do not use your own rules because, as you can see, it is quite difficult to mix/combine them together. As a rule, if you use your own rules, you should turn off the firewall in the cbsd ( cbsd natcfg + cbsd natoff ) for better control.

However, there are several ways to combine:

1) Checkout https://github.com/cbsd/cbsd/blob/develop/etc/defaults/pf.conf.tpl template. It regulates the sequence/order of includes and you can use it to include your rules. For example:

/storage/cbsd/etc/pf.conf:

## include CBSD NAT rules
include "/storage/cbsd/etc/pfnat.conf"

## include system pf RULES
include "/etc/pf.conf"

## include CBSD RDR rules
include "/storage/cbsd/etc/pfrdr.conf"

In this case, you should also change default config path for /etc/rc.d/pf service:

sysrc pf_rules="/storage/cbsd/etc/pf.conf"

/storage/cbsd/etc/pf.conf is static while "/storage/cbsd/etc/{pfnat,pfrdr}.conf is dynamic and managed by CBSD.

2) Use CBSD hooks for integration with your firewall rules management. By placing your own scripts in different directories in *~cbsd/jails-system/ENV/master_.d**, you can perform the actions you need in different states of the virtual environment. In these scripts you can use internal CBSD facts (you only need $jname and $ip4_addr)

For example for jail named dnsmasq create executable file ~cbsd/jails-system/dnsmasq/master_poststart.d/0_set_rules.sh:

#!/bin/sh

cat > /tmp/0_set_rules.txt <<EOF
My jail name: ${jname}
My Full IP address list: ${ip4_addr}

Other useful facrts:

ipv4_first_public="${ipv4_first_public}"
ipv4_first_private="${ipv4_first_private}"
ipv4_first="${ipv4_first}"
ipv6_first_public="${ipv6_first_public}"
ipv6_first_private="${ipv6_first_private}"
ipv6_first="${ipv6_first}"
nic_address="${nic_address}"

nic_hwaddr0="${nic_hwaddr0}"
nic_address0="${nic_address0}"
nic_parent0="${nic_parent0}"
interface="${interface}"
EOF
chmod +x ~cbsd/jails-system/dnsmasq/master_poststart.d/0_set_rules.sh

after the container (or VM) starts, look at the /tmp/0_set_rules.txt. Instead of saving facts to a log file, you can create and delete ( via master_poststop.d hooks directory ) corresponding rules at runtime.

if you want hook scripts to be created by default along with the new environment, put these files in the appropriate skeleton directory ( ~cbsd/share/jail-system-default ) or create your own profile.

less /storage/cbsd/etc/pfnat.conf-> contains all the private network ranges' nat pf rules, not just those IP ranges the jails using

you can adjust this, see: https://github.com/cbsd/cbsd/blob/develop/etc/defaults/cbsd-pf.conf

For example, override this settings via ~cbsd/etc/cbsd-pf.conf:

# misc settings. Default RFC1918 network for NAT net/rules
cbsd_nat_networks="10.0.0.0/8 172.16.0.0/12"

# don't create (when '1') NAT rules for SAME network as NATIP
cbsd_nat_skip_natip_network=0

^^ exclude 192.168.x.x from NAT networks.

to apply:

cbsd natoff
cbsd naton
n-connect commented 7 months ago

Thank you for the details, and possible workarounds really helpful!

I have not checked the MyBee or ClonOS yet: how is this whole host pf.conf area handled in their case? If I understand well MyBee more cli and provides APIs, ClonOS has the "built-in" web-ui like Proxmox.

  1. For host pf rules - I'll test out the second version you wrote and write back the working way, eg. what could be a host pf.conf template which always works - only the allowed service/application ports need to be varied. In other words - providing a skeleton for host rules. It gives two directions:
    • if someone starts a new host with CBSD -> CBSD provide the host rules from the first step
    • if someone already has rules with a configured/running host and starts CBSD later -> can help how to strip down their original /etc/pf.conf with the CBSD host pf template/sample.

It could be a base of a tui or cli based import portion during cbsd expose apply... command. In general, I found the best base for populating a pf.conf ruleset at DigitalOcena pf FB12.1, It controls outbound as well (not a bad thing either, if I run multiple VMs/Jail even better, like myBee ), but missing nat/rdr samples for CBSD purposes.

  1. So for handling the RFC1918, editing/crop-to-target A/B/C network range is the simplest way in /path_to/cbsd/etc/defaults/cbsd-pf.conf OK

For including there are multiple ways, for first sight I would opt for including the host's /etc/pf.conf into

/etc/pf.conf into the /path/to/cbsd/etc/pf.conf:

## include system pf RULES
include "/etc/pf.conf"
  1. Last thing, as of now the expose command's rdr rules does not includes the ability to add rdr rules allowed for specific IPs only /path_to/cbsd/etc/pfrdr.conf rdr pass proto tcp from any to x.x.x.x port 111 -> y.y.y.y port 1110 # // Setup by CBSD expose: tcp-1110-jailname

I've learned by trial, that skipping to specify the source ip in rdr rules makes the packet filtering block useless in the pf.conf (host based or not) - the minute I opened a desired application port, got some bots connecting already. A desired version of that sample would be: rdr pass proto tcp from 8.8.8.8 to x.x.x.x port 111 -> y.y.y.y port 1110 # // Setup by CBSD expose: tcp-1110-jailname Here let only Google's DNS ip (8.8.8.8) to connec to the port 111.

Would you consider adding this "from-ip" capability into the expose command, as optional parameter?

n-connect commented 7 months ago

@olevole

After some quick tests, host /etc/pf.conf content can't be aded as just one file into the CBSD working directory structure into a special pf configuration file. One can make his/her system wide /etc/pf.conf relevant part duplicated into CBSD -> It need to parsed, cut in two (half or depends on the actual host's pf.conf )

I think less people will or should go in this direction, this is basically duplicates a forsen version of original pf.conf into an another place belongs to a non-base application, while CBSD's nat ad rdr will be dynamic via cbsd naton/natof & cbsd expose


My proposition is following the reverse logic, as the simplest & best solution: right after CBSD install, as a post-process hook just include CBSD's pfnat & pfrdr files automatically - before the filtering block of any /etc/pf.conf -> Include statement existing since FreeBSD 9.0 Release: man pf.conf I did that now manually, which solves the original issue for me.

Other, more fine-graned possibility post-process hooks placements: Include the CBSD's _/pathto/cbsd/etc/pfnat.conf after cbsd naton command (and remove if natoff has ran). Then include the _/pathto/cbsd/etc/pfrdr.conf into the host's /etc/pf.conf after expose apply (and remove if with expose clear|flush)


Details on pf.conf parsing and possible post-process hook scripting:

The /etc/pf.conf parsing:

A script needs to do: On install:

On uninstall: