mirror of
https://github.com/lgcosta/pf-linux-port.git
synced 2026-11-15 14:34:45 -03:00
Compare commits
3
Commits
7014628e8d
...
da1f678125
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da1f678125 | ||
|
|
fd0be917fe | ||
|
|
4994c577cd |
No files matched your search
@@ -95,6 +95,18 @@ pfk_divert_pkt_free(struct pfk_divert_pkt *dp)
|
||||
}
|
||||
|
||||
/* PF engine entry points (called from the ported pf.c) */
|
||||
static struct pfk_divert_sock *
|
||||
pfk_divert_lookup(u_int16_t port)
|
||||
{
|
||||
struct pfk_divert_sock *ds;
|
||||
|
||||
list_for_each_entry(ds, &pfk_divert_list, link) {
|
||||
if (ds->port == port)
|
||||
return ds;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
pfk_divert_queue(struct sk_buff *skb, int dir, int type, u16 port)
|
||||
{
|
||||
@@ -114,12 +126,8 @@ pfk_divert_queue(struct sk_buff *skb, int dir, int type, u16 port)
|
||||
dp->ifindex = skb->dev ? skb->dev->ifindex : 0;
|
||||
|
||||
spin_lock_irqsave(&pfk_divert_lock, flags);
|
||||
ds = NULL;
|
||||
list_for_each_entry(ds, &pfk_divert_list, link) {
|
||||
if (ds->port == port)
|
||||
break;
|
||||
}
|
||||
if (&ds->link == &pfk_divert_list) {
|
||||
ds = pfk_divert_lookup(port);
|
||||
if (ds == NULL) {
|
||||
pfk_divert_global.divs_noport++;
|
||||
spin_unlock_irqrestore(&pfk_divert_lock, flags);
|
||||
pr_info_ratelimited("pfk: divert port %u: no socket bound\n",
|
||||
|
||||
@@ -42,7 +42,9 @@ pf_disable_pf0() {
|
||||
>/dev/null 2>&1 || true
|
||||
}
|
||||
trap pf_disable_pf0 EXIT INT TERM
|
||||
ONLY="${1:-}"
|
||||
for t in "$REPO"/tests/vm/[0-9]*.sh; do
|
||||
[ -n "$ONLY" ] && case "$t" in *"$ONLY"*) ;; *) continue ;; esac
|
||||
[ -e "$t" ] || continue
|
||||
name="$(basename "$t")"
|
||||
echo "=== $name ==="
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
# M3 gate: nat-to — source NAT of transit traffic to the egress address.
|
||||
#
|
||||
# Scenario: cli (10.0.1.10) -> srv (10.0.2.20) through pf0, rule:
|
||||
# nat on egress proto icmp from 10.0.1.0/24 to any -> (egress)
|
||||
# Expected: srv sees src 192.168.122.8 (pf0 egress IP) instead of 10.0.1.10;
|
||||
# the reply is de-NATed and delivered back to cli; `pfctl -s nat`,
|
||||
# `pfctl -s states` show the translation.
|
||||
set -uo pipefail; cd "$(dirname "$0")"; . ./lib.sh
|
||||
|
||||
FAILED=0
|
||||
pf0 "insmod /tmp/pf.ko 2>/dev/null || insmod /opt/pf/pf.ko; true"
|
||||
pf0 '/opt/pf/pfctl -e; /opt/pf/pfctl -f /dev/null' >/dev/null
|
||||
|
||||
cat > /tmp/g05.conf <<C
|
||||
nat on egress proto icmp from 10.0.1.0/24 to any -> (egress)
|
||||
pass in quick on ingress proto icmp keep state
|
||||
pass out quick proto icmp keep state
|
||||
C
|
||||
pfload /tmp/g05.conf || { bad "nat rule load"; finish; }
|
||||
|
||||
pf0 '/opt/pf/pfctl -sn' | grep -q 'nat on egress' && ok "nat rule listed" || bad "nat not listed"
|
||||
|
||||
# capture on pf0's egress while cli pings srv
|
||||
pf0 'tcpdump -ni egress -c 4 -e icmp > /tmp/nat.td 2>&1 &'
|
||||
sleep 1
|
||||
cli "ping -c 2 -W 2 $SRV_IP >/dev/null 2>&1" && ok "transit ping through NAT" || bad "transit ping"
|
||||
sleep 2
|
||||
TD=$(pf0 'cat /tmp/nat.td')
|
||||
echo "$TD" | grep -q "$CLI_IP" && bad "cli source address leaked to egress" || ok "source rewritten (no $CLI_IP on egress)"
|
||||
echo "$TD" | grep -q '192.168.122.8' && ok "nat applied to $(pf0 'ip -4 addr show egress | grep -o "192[0-9.]*"' | head -1)" || bad "egress src ip not seen"
|
||||
|
||||
pf0 '/opt/pf/pfctl -s states' | grep -q "$SRV_IP" && ok "state present" || bad "no state"
|
||||
pf0 '/opt/pf/pfctl -d' >/dev/null
|
||||
finish
|
||||
@@ -16,9 +16,11 @@ FAILED=0
|
||||
|
||||
pf0 "insmod /tmp/pf.ko 2>/dev/null || insmod /opt/pf/pf.ko; true"
|
||||
pf0 '/opt/pf/pfctl -e; /opt/pf/pfctl -f /dev/null' >/dev/null
|
||||
pfput ../../tools/out/pdivert /opt/pf/pdivert || bad "pdivert deploy"
|
||||
pf0 'chmod +x /opt/pf/pdivert' >/dev/null
|
||||
|
||||
cat > /tmp/g11.conf <<C
|
||||
pass in quick proto icmp from $CLI_IP to $PFLAN divert-to $PFLAN $PORT keep state
|
||||
pass in quick proto icmp from $CLI_IP to $PFLAN divert-to "$PFLAN" port $PORT keep state
|
||||
pass out quick
|
||||
C
|
||||
pfload /tmp/g11.conf || { bad "divert rule load"; finish; }
|
||||
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
# M6 gate: soak + unload/leak discipline.
|
||||
#
|
||||
# 1) load pf, ruleset with states/tables/anchors, drive mixed traffic ~20s
|
||||
# 2) assert no BUG/WARNING/Oops in dmesg
|
||||
# 3) disable, rmmod; assert module unloads cleanly (no refcount hang)
|
||||
# 4) insmod/rmmod cycle x2; assert slab objects for pf caches return to the
|
||||
# pre-load baseline (no leak), and that a reload works (timer/notifier
|
||||
# re-registration is idempotent)
|
||||
set -uo pipefail; cd "$(dirname "$0")"; . ./lib.sh
|
||||
|
||||
FAILED=0
|
||||
slab_snapshot() {
|
||||
pf0 'grep -E "^(pf|pfk)[^ ]* " /proc/slabinfo | awk "{print \$1, \$3}"' \
|
||||
| sort
|
||||
}
|
||||
|
||||
pf0 'insmod /tmp/pf.ko 2>/dev/null || insmod /opt/pf/pf.ko; true'
|
||||
pf0 '/opt/pf/pfctl -e; /opt/pf/pfctl -f /dev/null' >/dev/null
|
||||
BEFORE=$(slab_snapshot)
|
||||
|
||||
cat > /tmp/g14.conf <<C
|
||||
table <peers> { $CLI_IP }
|
||||
anchor "s"
|
||||
pass in quick on ingress proto icmp from <peers> keep state
|
||||
pass out quick proto icmp keep state
|
||||
pass out quick proto tcp from any to any port 22 keep state
|
||||
C
|
||||
pfload /tmp/g14.conf || { bad soak ruleset; finish; }
|
||||
|
||||
# mixed traffic: ICMP + TCP handshakes, 20s
|
||||
cli "ping -q -c 30 -i 0.2 $SRV_IP >/dev/null 2>&1 &" 2>/dev/null
|
||||
cli "for i in 1 2 3 4 5; do nc -w1 -z $SRV_IP 22; done" 2>/dev/null
|
||||
sleep 22
|
||||
ST=$(pf0 '/opt/pf/pfctl -s states | wc -l')
|
||||
[ "${ST:-0}" -ge 1 ] && ok "states under load ($ST)" || bad "no states under load"
|
||||
|
||||
DMESG=$(pf0 'dmesg | grep -cE "BUG:|WARNING:|Oops|general protection"')
|
||||
[ "${DMESG:-1}" = 0 ] && ok "no kernel BUG/WARN/Oops" || bad "dmesg anomalies ($DMESG)"
|
||||
|
||||
pf0 '/opt/pf/pfctl -d; /opt/pf/pfctl -f /dev/null' >/dev/null
|
||||
pf0 'rmmod pf && echo UNLOAD_OK' | grep -q UNLOAD_OK && ok "clean unload (refcounts released)" || bad "rmmod failed"
|
||||
sleep 1
|
||||
pf0 'insmod /tmp/pf.ko 2>/dev/null || insmod /opt/pf/pf.ko; true; (/opt/pf/pfctl -s info >/dev/null && echo RELOAD_OK)' | grep -q RELOAD_OK && ok "reload after unload" || bad "reload failed"
|
||||
pf0 'rmmod pf && echo UNLOAD_OK2' | grep -q UNLOAD_OK2 && ok "second unload" || bad "second rmmod"
|
||||
sleep 1
|
||||
AFTER=$(slab_snapshot)
|
||||
# compare per-cache object counts if they exist on both sides
|
||||
LEAK=$(join <(echo "$BEFORE") <(echo "$AFTER") 2>/dev/null | awk '$3-$2 > 0 {print $1, $3-$2}')
|
||||
if [ -n "$LEAK" ]; then bad "slab growth after cycles: $LEAK"; else ok "no slab growth after unload cycles"; fi
|
||||
finish
|
||||
Reference in new issue
Block a user