infra/.claude/skills/pfsense/SKILL.md
Viktor Barzin fd0f4a0365 fix: restore tree dropped by 6d224861; land stem95su gdrive-sync (10m) [ci skip]
6d224861 came from a --no-checkout worktree whose empty index made the
commit drop every file except two. This restores 05b50d2b's full tree and
correctly adds stacks/stem95su/gdrive-sync.tf + the service-catalog stem95su
entry. Forward-only (parent=6d224861, no force-push); [ci skip] since the
live infra was never applied from the broken commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 08:45:33 +00:00

7.5 KiB

name description author version date
pfsense Manage the pfSense firewall at 10.0.20.1 via SSH. Use when: (1) User asks about firewall rules, NAT, port forwarding, (2) User asks about network diagnostics (ARP, routing, DNS, ping), (3) User asks about DHCP leases or static mappings, (4) User asks about VPN status (WireGuard, Tailscale), (5) User asks about pfSense services (Snort, FRR/BGP/OSPF, etc.), (6) User asks about firewall states, connections, or traffic, (7) User mentions "pfsense", "firewall", "gateway", or network troubleshooting, (8) User wants to check system health (CPU, memory, disk, temp) of pfSense. pfSense CE 2.7.2 on FreeBSD 14.0, VMID 101 on Proxmox. Claude Code 1.0.0 2026-02-14

pfSense Firewall Management

Overview

  • Host: 10.0.20.1 (Kubernetes VLAN gateway)
  • SSH: ssh admin@10.0.20.1
  • Version: pfSense CE 2.7.2, FreeBSD 14.0
  • Proxmox VMID: 101 (8 CPU, 16GB RAM, 32G disk)
  • Web UI: https://pfsense.viktorbarzin.me (via reverse proxy) or https://10.0.20.1
  • Installed packages: FRR (BGP/OSPF), Tailscale, Snort, WireGuard, REST API, FreeRADIUS

Interfaces

Name Description Physical IP Network
wan WAN vtnet0 192.168.1.2/24 Physical network
lan Management VMs vtnet1 10.0.10.1/24 VLAN 10
opt1 Kubernetes vtnet2 10.0.20.1/24 VLAN 20
opt2 WireGuard tun_wg0 10.3.2.1/24 VPN tunnel
tailscale0 Tailscale tailscale0 100.64.0.x Headscale mesh

CLI Script

Script: .claude/pfsense.py

Execution Pattern

cd ~/code/infra && python3 .claude/pfsense.py <command> [options]

Available Commands

System Information

python3 .claude/pfsense.py status          # Full system overview
python3 .claude/pfsense.py uptime          # Uptime
python3 .claude/pfsense.py cpu             # CPU info and load
python3 .claude/pfsense.py memory          # Memory breakdown
python3 .claude/pfsense.py disk            # Disk usage
python3 .claude/pfsense.py temp            # CPU temperature
python3 .claude/pfsense.py pkg-list        # Installed packages

Network & Interfaces

python3 .claude/pfsense.py interfaces      # Interface list with IPs
python3 .claude/pfsense.py gateways        # Gateway status
python3 .claude/pfsense.py arp             # ARP table
python3 .claude/pfsense.py routes          # Routing table
python3 .claude/pfsense.py dns-resolve <host>  # DNS lookup via pfSense
python3 .claude/pfsense.py diag <host>     # Ping test

Firewall

python3 .claude/pfsense.py rules           # All firewall rules
python3 .claude/pfsense.py rules opt1      # Rules for Kubernetes interface
python3 .claude/pfsense.py nat             # NAT / port forwarding rules
python3 .claude/pfsense.py aliases         # List all aliases
python3 .claude/pfsense.py alias <name>    # Show alias members
python3 .claude/pfsense.py states          # State table summary
python3 .claude/pfsense.py states-top 20   # Top 20 IPs by connection count

DHCP

python3 .claude/pfsense.py dhcp-leases         # All DHCP leases
python3 .claude/pfsense.py dhcp-leases opt1    # Kubernetes network leases only

Services

python3 .claude/pfsense.py services                    # List all services + status
python3 .claude/pfsense.py service restart snort        # Restart a service
python3 .claude/pfsense.py service stop wireguard       # Stop a service
python3 .claude/pfsense.py service start wireguard      # Start a service

VPN & Routing

python3 .claude/pfsense.py wireguard       # WireGuard tunnel status
python3 .claude/pfsense.py tailscale       # Tailscale/Headscale status
python3 .claude/pfsense.py bgp             # BGP summary (FRR)
python3 .claude/pfsense.py ospf            # OSPF neighbors (FRR)

Security

python3 .claude/pfsense.py snort           # Snort IDS status + recent alerts
python3 .claude/pfsense.py logs            # Last 50 firewall log entries
python3 .claude/pfsense.py logs 200        # Last 200 entries
python3 .claude/pfsense.py logs-filter "blocked"  # Search logs

Advanced

python3 .claude/pfsense.py pfctl "-sr"     # Raw pfctl command
python3 .claude/pfsense.py php "echo phpversion();"  # Run PHP on pfSense
python3 .claude/pfsense.py raw "ls /tmp"   # Run arbitrary shell command
python3 .claude/pfsense.py backup          # Dump config.xml to stdout

Direct SSH Access

For tasks not covered by the script, SSH directly:

ssh admin@10.0.20.1 "<command>"

Useful Direct Commands

# pfSense PHP shell (interactive config access)
ssh admin@10.0.20.1 "php -r 'require_once(\"config.inc\"); \$cfg = parse_config(true); echo json_encode(\$cfg[\"nat\"], JSON_PRETTY_PRINT);'"

# pfSsh.php playback commands
ssh admin@10.0.20.1 "pfSsh.php playback gatewaystatus"
ssh admin@10.0.20.1 "pfSsh.php playback svc restart snort"
ssh admin@10.0.20.1 "pfSsh.php playback listpkg"

# Config sections via PHP
ssh admin@10.0.20.1 "php -r 'require_once(\"config.inc\"); \$cfg = parse_config(true); print_r(\$cfg[\"filter\"][\"rule\"][0]);'"

# FRR/vtysh for routing
ssh admin@10.0.20.1 "/usr/local/bin/vtysh -c 'show ip route'"
ssh admin@10.0.20.1 "/usr/local/bin/vtysh -c 'show bgp ipv4 unicast'"

REST API (pfSense-pkg-RESTAPI v2.2)

The REST API package is installed but no API keys are configured. To use it:

  1. Create an API key in pfSense Web UI: System > REST API > Settings > Keys
  2. Use Bearer token auth: curl -sk https://10.0.20.1/api/v2/status/system -H 'Authorization: Bearer <key>'

Until API keys are set up, use SSH for all operations.

Key Services

Service Status Notes
FRR (BGP/OSPF) Running Routing daemon
Snort Running IDS/IPS
WireGuard Running VPN tunnel (10.3.2.0/24)
Tailscale Running Mesh VPN via Headscale
FreeRADIUS Running RADIUS auth
DHCP (Kea) Running kea-dhcp4
SSH Running Admin access
NTP Running Time sync

Firewall Stats

  • 167 firewall rules (pfctl -sr)
  • 154 NAT rules (pfctl -sn)
  • ~784 active states (varies)
  • 10 aliases (LAN, OPT1, OPT2, WAN networks + custom)

NFS Backup

Config backups stored at NFS: /mnt/main/pfsense-backup

Troubleshooting

Issue Command
Can't reach internet from K8s python3 .claude/pfsense.py gateways + python3 .claude/pfsense.py diag 8.8.8.8
K8s pod can't reach external python3 .claude/pfsense.py rules opt1 + check NAT
DHCP not working python3 .claude/pfsense.py dhcp-leases opt1 + python3 .claude/pfsense.py service restart kea-dhcp4
High connection count python3 .claude/pfsense.py states-top 20
Snort blocking traffic python3 .claude/pfsense.py snort + check alerts
DNS resolution failing python3 .claude/pfsense.py dns-resolve <host>
BGP/OSPF routes missing python3 .claude/pfsense.py bgp or python3 .claude/pfsense.py ospf
WireGuard tunnel down python3 .claude/pfsense.py wireguard

Notes

  1. FreeBSD-based: Commands differ from Linux (no ip, use ifconfig, netstat, arp)
  2. pfctl is the firewall: Rules loaded from config.xml via PHP, managed by pfctl
  3. Config file: /cf/conf/config.xml — all pfSense config in one XML file
  4. PHP shell: pfSense uses PHP for all config management; config.inc loads the config
  5. Do NOT edit config.xml directly — use the Web UI or PHP functions that properly reload services
  6. Logs: Binary circular logs, read with clog -f /var/log/<logfile>