aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jan@jantuomi.fi>2025-11-13 18:45:10 +0200
committerJan Tuomi <jan@jantuomi.fi>2025-11-13 18:45:10 +0200
commit28379e016d4ab80a0d0529d6ca08083c75a0be4d (patch)
treeadf5c7edbf5903de6d7023db200bbd74172a41c4
parent1df3d09ae131bf4709820205b562a04c22bdd85b (diff)
WIP
-rw-r--r--playbook.yml1
-rw-r--r--templates/etc_devfs.rules.j211
-rw-r--r--templates/etc_jail.conf.d_[jailname].conf.j22
-rw-r--r--templates/etc_pf.conf.j215
-rw-r--r--templates/ingress/etc_pf.conf.j213
-rw-r--r--templates/usr_local_bin_safepf.sh36
6 files changed, 58 insertions, 20 deletions
diff --git a/playbook.yml b/playbook.yml
index 8a038ba..23d3b3b 100644
--- a/playbook.yml
+++ b/playbook.yml
@@ -16,6 +16,7 @@
- secrets.yml
vars:
lan_ipv4_cidr: 192.168.0.10/16
+ lan_ipv4_network: 192.168.0.0/16
lan_ipv4_gateway: 192.168.0.1
lan_search_domain: local.jan.systems
jail_userland_version: 14.3-RELEASE
diff --git a/templates/etc_devfs.rules.j2 b/templates/etc_devfs.rules.j2
index 7145400..4f0e186 100644
--- a/templates/etc_devfs.rules.j2
+++ b/templates/etc_devfs.rules.j2
@@ -70,9 +70,6 @@ add path stderr unhide
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
-add path pf unhide
-#add path fuse unhide
-#add path zfs unhide
[devfsrules_jail_postgres=5]
add include $devfsrules_hide_all
@@ -80,3 +77,11 @@ add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_jail
add path 'bpf*' unhide
+
+[devfsrules_jail_ingress=5]
+add include $devfsrules_hide_all
+add include $devfsrules_unhide_basic
+add include $devfsrules_unhide_login
+add include $devfsrules_jail
+add path 'bpf*' unhide
+add path 'pf*' unhide
diff --git a/templates/etc_jail.conf.d_[jailname].conf.j2 b/templates/etc_jail.conf.d_[jailname].conf.j2
index ce0e7ba..a12226d 100644
--- a/templates/etc_jail.conf.d_[jailname].conf.j2
+++ b/templates/etc_jail.conf.d_[jailname].conf.j2
@@ -50,6 +50,8 @@
{%if jail.name == "postgres" -%}
allow.sysvipc;
devfs_ruleset = 5;
+ {% elif jail.name == "ingress" -%}
+ devfs_ruleset = 6;
{% else %}
devfs_ruleset = 4;
{% endif %}
diff --git a/templates/etc_pf.conf.j2 b/templates/etc_pf.conf.j2
index ceae731..87ae43a 100644
--- a/templates/etc_pf.conf.j2
+++ b/templates/etc_pf.conf.j2
@@ -1,8 +1,10 @@
lan_if = "lan0"
-wan_if = "wan0"
+wan_if = "brwan0"
# Default policy
set skip on lo
+# Allow all traffic on $wan_if. Proper firewall rules are implemented in the ingress jail.
+set skip on $wan_if
set block-policy return
scrub in
@@ -12,21 +14,12 @@ block in all
# Allow all outbound traffic
pass out all keep state
-# Allow inbound HTTP/HTTPS on both interfaces
-pass in on $wan_if proto tcp from any to any port { 80, 443 } keep state
+# Allow inbound HTTP/HTTPS on lan0
pass in on $lan_if proto tcp from any to ($lan_if) port { 80, 443 } keep state
# Allow SSH only on lan0
pass in on $lan_if proto tcp from any to ($lan_if) port 22 keep state
-# Allow DHCPv4 (client side): from server port 67 to client port 68
-pass in quick on $lan_if proto udp from any port 67 to any port 68 keep state
-pass in quick on $wan_if proto udp from any port 67 to any port 68 keep state
-
-# Allow DHCPv6 (client side): from server port 547 to client port 546
-pass in quick on $lan_if proto udp from any port 547 to any port 546 keep state
-pass in quick on $wan_if proto udp from any port 547 to any port 546 keep state
-
# Allow all ICMPv6 (required for IPv6 to function correctly)
pass inet6 proto ipv6-icmp from any to any keep state
diff --git a/templates/ingress/etc_pf.conf.j2 b/templates/ingress/etc_pf.conf.j2
index c8045fd..3cdad6e 100644
--- a/templates/ingress/etc_pf.conf.j2
+++ b/templates/ingress/etc_pf.conf.j2
@@ -3,17 +3,18 @@
# Interfaces & nets
lan = "epl{{ jail.num }}b"
wan = "epw{{ jail.num }}b"
-lan_net = "{{ lan_ipv4_cidr }}"
+lan_net = "{{ lan_ipv4_network }}"
# Keep PF out of loopback, drop by default if you add blocks later
set skip on lo0
set block-policy drop
-# NAT: translate LAN traffic to the WAN interface address, and log it
-nat log on $wan from $lan_net to any -> ($wan)
+# NAT: translate LAN traffic to the WAN interface address
+nat on $wan from $lan_net to any -> ($wan)
-# Allow and log the LAN traffic so NAT can happen
-pass in on $lan inet from $lan_net to any keep state
-pass out on $wan inet from $lan_net to any keep state
+# Allow all outbound traffic from the jail and LAN via both interfaces
+# NAT will be applied automatically when source is in $lan_net and going out $wan
+pass out on $wan all keep state
+pass out on $lan all keep state
{% endif %}
{% endfor %}
diff --git a/templates/usr_local_bin_safepf.sh b/templates/usr_local_bin_safepf.sh
new file mode 100644
index 0000000..1b6efee
--- /dev/null
+++ b/templates/usr_local_bin_safepf.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+set -eu
+
+cmd="pfctl -f /etc/pf.conf"
+read -p "Run this command (y/n)? $cmd " answer
+if [ "$answer" = "y" ]; then
+ (set -x; $cmd)
+else
+ exit 0
+fi
+
+cmd="service pf restart"
+read -p "Run this command (y/n)? $cmd " answer
+if [ "$answer" = "y" ]; then
+ (set -x; $cmd)
+else
+ exit 0
+fi
+
+timeout=60
+echo "Running safety timeout ($timeout seconds). Press CTRL-C if everything is working."
+while [ $timeout -gt 0 ]
+do
+ sleep 1
+ timeout=$((timeout - 1))
+ echo -n "."
+done
+
+echo "Timeout reached. Enabling empty pf rules"
+
+set -x
+mv /etc/pf.conf /etc/pf.conf.locked_out
+echo "" > /etc/pf.conf
+pfctl -f /etc/pf.conf
+service pf restart