added pf support

This commit is contained in:
Thomas von Dein
2020-12-03 19:01:05 +01:00
parent 615939bccd
commit 8f10788e55
2 changed files with 208 additions and 3 deletions

126
README.md
View File

@@ -418,6 +418,132 @@ which uses custom ipfw rules:
`exec.prestart = "/jail/bin/jaildk ipfw $name"` `exec.prestart = "/jail/bin/jaildk ipfw $name"`
Be aware, that the ipfw module will only be executed if the jail is
running so that we can properly determine the ip addresses of the
running jail. **Note**: this might change in the future.
### Using pf
Beside ipfw, Free supports
[pf](https://www.freebsd.org/doc/de_DE.ISO8859-1/books/handbook/firewalls-pf.html)
as well. You can use pf with `jaildk`. Unlike the ipfw module (see
above) it is a normal `install` module. That is it can be installed or
reloaded before the jail is running (i.e. like the mount module).
In order to use `pf` with a jail, enable and configure it according to
the FreeBSD handbook linked above. It is recommended to include
general block, scrup, state rules, communication to and fro localhost
etc and just leave everything which is related to your jail.
Just so that you know how such a global `/etc/pf.conf` file might look
like, here's a simple one:
```shell
# variables
ext = "em0"
me = "your ipv4 address here"
me5 = "your ipv6 address here/64"
loginports = "{ 22, 5222, 443 }"
icmp_types = "echoreq"
# tables. look at the contents of a table:
# pfctl -t bad_hosts -T show
# remove an entry from a table:
# pfctl -t bad_hosts -T delete $ip
table <bad_hosts> persist
# default policy
set block-policy drop
# optimize according to rfc's
set optimization aggressive
# normalisation
scrub in all
antispoof for $ext
# allow localhost
pass quick on $local
# additional default block rules w/ logging. to view the log:
# tcpdump -n -e -ttt -r /var/log/pflog
# to view live log:
# tcpdump -n -e -ttt -i pflog0
block in log on $ext
block in log on $ext inet6
# whoever makes it into those tables: you loose
block quick from <bad_hosts>
# allow outgoing established sessions
pass out keep state
pass out inet6 keep state
# allow troubleshooting
pass in on $ext inet proto icmp all icmp-type $icmp_types keep state
pass in on $ext inet proto udp from any to any port 33433 >< 33626 keep state
# allow all icmpv6
pass in quick inet6 proto icmp6 all keep state
# allow login but punish offenders
block quick from <bad*hosts>
pass in quick on $ext inet proto tcp from any to $me port $loginports \
flags S/SAFR keep state \
(max-src-conn-rate 10/60, \
overload <bad*hosts> flush global) label ServicesTCP
pass in quick on $ext inet6 proto tcp from any to $me6 port $loginports \
flags S/SAFR keep state \
(max-src-conn-rate 10/60, \
overload <bad_hosts> flush global) label ServicesTCP
```
Install the ruleset with `service pf start`.
Now that everything is prepared you can create a pf.conf file for your
jail. Here's an example I use for a webserver jail, which includes a
git server:
```shell
ip = "jail ip4 addr"
ip6 = "jail ip6 addr"
loginports = "{ 22 }"
prodports = "{ 80, 443 }"
ext = "em0"
# dynamic block list
table <blocked>
# restrict foreigners
block quick from <blocked>
pass in quick on $ext inet proto tcp from any to $ip port $loginports \
flags S/SAFR keep state \
(max-src-conn-rate 10/60, \
overload <blocked> flush global) label ServicesTCP
# allow production traffic v4
pass in quick on $ext proto tcp from any to $ip port $prodports keep state
# allow production traffic v6
pass in quick inet6 proto tcp from any to $ip6 port $prodports keep state
```
That's it already. Now install the jail as usual. You can also install
the pf ruleset for the jail separately:
`jaildk install myjail start -r pf`
To take look at the rules, execute:
`jaildk install myjail status -r pf`
You can of course manipulate the ruleset manually. `jaildk` installs
rulesets into a jail specific anchor using the following naming
scheme: `/jail/<jail name>`. So, for example to view the rules, execute:
`pfctl -a /jail/myjail -s rules`
Manipulate a jail specific table:
`pfctl -a /jail/myjail -t blocked -T show`
## Getting help ## Getting help

85
jaildk
View File

@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
version=1.08 version=1.09
usage_jaildk() { usage_jaildk() {
beg=`tput -T ${TERM:-cons25} md` beg=`tput -T ${TERM:-cons25} md`
@@ -119,6 +119,58 @@ die_if_not_exist() {
fi fi
} }
parse_jail_conf() {
#
# just in case we want or have to fetch variables out of
# /etc/jail.conf, this is the way to go. Call it like this:
#
# ip=`parse_jail_conf $jail ip4.addr`
#
# Output may be empty, so check before using. Multiple variables
# of the same type (like multiple ip addresses) will be returned
# comma separated.
jail=$1
search=$2
JAIL=''
list=''
# fetch 20 lines after "^$jail {", ignore comments
egrep -A20 "^$jail" jail.conf | egrep -v "^ *#" | \
# turn each line into an evaluable shell expression \
sed -e 's/ *{//g' -e 's/}//g' -e 's/ *= */=/g' -e 's/;$//' | \
# ignore empty lines \
egrep -v '^$' | while read LINE; do
if echo "$LINE" | egrep -q "="; then
case $JAIL in
$jail)
var=`echo "$LINE" | cut -d= -f1`
opt=`echo "$LINE" | cut -d= -f2 | sed -e 's/^"//' -e 's/"$//'`
case $var in
$search)
if test -z "$list"; then
list="$opt"
else
list="$list,$opt"
fi
;;
esac
;;
*)
echo $list
return
;;
esac
else
case $LINE in
\*) JAIL=any;;
*) JAIL="$LINE";;
esac
fi
done
}
usage_build() { usage_build() {
fin "Usage: $0 build <jail> [<start|stop|status>] [-b <base>] [-v <version>] fin "Usage: $0 build <jail> [<start|stop|status>] [-b <base>] [-v <version>]
Mount <jail> to $j/build read-writable for maintenance. Options: Mount <jail> to $j/build read-writable for maintenance. Options:
@@ -171,6 +223,33 @@ jaildk_build() {
esac esac
} }
jaildk_rc_pf() {
jail=$1
mode=$2
conf=$j/etc/$jail/pf.conf
# FIXME: maybe we use parse_jail_conf() to fetch ip addresses,
# generate a config file containing pf macros, which the user
# needs to include in the jails pf.conf? On the other hand,
# there's not that much duplication in the config. So, maybe not.
if test -f $conf; then
case $mode in
start)
bold "Installing PF rules for jail $jail:"
pfctl -a /jail/$jail -f $conf -v
;;
status)
bold "PF rules for jail $jail:"
pfctl -a /jail/$jail -s rules -v
;;
stop)
bold "Removing PF rules for jail $jail:"
pfctl -a /jail/$jail -f $conf -v -F all
;;
esac
fi
}
jaildk_rc_mtree() { jaildk_rc_mtree() {
jail=$1 jail=$1
mode=$2 mode=$2
@@ -1540,8 +1619,8 @@ jaildk_ipfw_delete() {
JAILDIR=/jail JAILDIR=/jail
# install modules # install modules
RCSCRIPTS_START="jaildk_rc_mount jaildk_rc_rcoff jaildk_rc_ports jaildk_rc_mtree" RCSCRIPTS_START="jaildk_rc_mount jaildk_rc_rcoff jaildk_rc_ports jaildk_rc_mtree jaildk_rc_pf"
RCSCRIPTS_STOP="jaildk_rc_rcoff jaildk_rc_mount jaildk_rc_ports" RCSCRIPTS_STOP="jaildk_rc_pf jaildk_rc_rcoff jaildk_rc_mount jaildk_rc_ports"
# globals # globals
j=$JAILDIR j=$JAILDIR