PfChat is an API-driven operational and security workflow for pfSense plus ntopng.
It talks directly to:
- the pfSense REST API for authoritative firewall state, rules, interfaces, gateways, logs, device inventory, and controlled administrative changes
- the ntopng API for host-level traffic visibility, top talkers, alerts, applications, and network-activity context
In practice, PfChat is meant to answer questions like:
- what is this client doing right now?
- what traffic is a host generating?
- what was blocked recently?
- what are the top talkers?
- what applications is this device using?
- is anything suspicious happening on the firewall?
- can I block this host or restrict its outbound traffic safely?
PfChat is model-agnostic: it fetches live data from pfSense and ntopng, then lets the current OpenClaw agent analyze it conversationally.
PfChat is not just a pfSense reader and not just an ntopng wrapper.
It combines:
- pfSense for firewall truth and administration
- ntopng for network intelligence and host behavior
- OpenClaw for investigation workflows, summaries, and operator-friendly interactions
Think of it like this:
- pfSense tells you what the firewall knows and enforces
- ntopng tells you what hosts are doing on the network
- PfChat brings both together into one operational interface
+---------------------------+
| OpenClaw / CLI / Operator |
+-------------+-------------+
|
v
+---------------------------+
| PfChat |
| query / correlate / act |
+-------------+-------------+
|
+-------+-------+ +--------+--------+
| pfSense REST | | ntopng API |
| API | | (host traffic, |
| | | alerts, apps) |
+-------+-------+ +--------+--------+
| |
v v
firewall state / rules / host activity / top talkers /
logs / interfaces / apply apps / alerts / traffic context
Use PfChat to inspect live network and firewall state:
- connected devices
- active firewall states
- recent blocked or passed events
- interface and gateway health
- WAN/public IP visibility
- firewall rules
- top talkers
- active ntopng hosts
- per-host application/protocol summaries
- recent alerts and traffic summaries
Use PfChat for security-focused questions such as:
- what is
example-clientdoing right now? - which client is generating the most traffic?
- what did the firewall block in the last hour?
- does ntopng show anything suspicious for this host?
- what apps is this client using?
- is this host talking to unusual destinations or ports?
- is the firewall healthy, overloaded, or dropping something important?
PfChat is also an operational control surface for pfSense.
It can perform controlled administrative actions such as:
- build block drafts for IPs or devices
- apply block drafts with confirmation
- roll back managed changes
- list and clean up PfChat-managed objects
- perform quick host-specific egress blocks/unblocks
Administrative actions are intentionally guarded through preview / confirm / rollback workflows instead of blind mutation.
pfSense and ntopng solve different parts of the problem.
- rules
- enforcement
- interfaces and gateways
- firewall logs
- device discovery through ARP/DHCP when exposed
- controlled writes such as rule or alias changes
- top talkers
- host traffic behavior
- host application/protocol summaries
- recent alerts and network-activity context
- answering “what is this client actually doing?”
Typical workflow:
- use pfSense to confirm the host, interface, rules, states, and blocked activity
- use ntopng to understand traffic volume, applications, peer behavior, and alerts
- use PfChat to summarize findings or perform a safe administrative action
Examples:
- identify the host in pfSense inventory
- inspect current firewall states for that host
- inspect recent firewall log entries
- pivot into ntopng host details
- review top applications and alerts
- decide whether to monitor, block, or constrain egress
Examples:
- use ntopng top-talker views when supported
- fall back cleanly when some ntopng endpoints are unavailable
- correlate top talkers with pfSense device identity and interface context
Examples:
- inspect recent filterlog activity from pfSense
- isolate repeated blocks from one source
- compare with ntopng alerts or host behavior
- determine whether it is noise, misconfiguration, or suspicious activity
Examples:
- draft a host block
- preview the rule/alias plan
- confirm the change
- verify impact
- roll back if needed
PfChat intentionally uses different backends for different classes of answers.
- firewall rules
- live state-table data
- filterlog / recent firewall events
- interfaces, gateways, WAN status, and system health
- device inventory exposed through ARP/DHCP endpoints
- firewall writes such as aliases, rules, apply, rollback-related cleanup, and state deletion
- top talkers and traffic ranking
- per-host traffic profile
- application / protocol visibility
- network alerts and host alert context
- higher-level traffic summaries when raw state-table output is too low-level
If the question is about policy, enforcement, or firewall truth, PfChat should lean on pfSense first. If the question is about behavior, traffic shape, host activity, or application visibility, PfChat should lean on ntopng first.
PfChat is most useful when it correlates both sides instead of treating them as isolated tools.
Typical correlation fields include:
- IP address
- hostname / FQDN
- local inventory name
- interface / VLAN context
- host identity normalized from pfSense inventory plus ntopng host records
This is why PfChat can answer operator questions more cleanly than using pfSense or ntopng alone.
Goal: understand current activity for one LAN client with both firewall and traffic context.
Suggested sequence:
python3 pfchat/scripts/pfchat_query.py devices
python3 pfchat/scripts/pfchat_query.py connections --host 192.168.0.95 --limit 100
python3 pfchat/scripts/pfchat_query.py logs --host 192.168.0.95 --limit 100
python3 pfchat/scripts/pfchat_query.py ntop-host --host 192.168.0.95 --ifid 0
python3 pfchat/scripts/pfchat_query.py ntop-host-apps --host 192.168.0.95 --ifid 0
python3 pfchat/scripts/pfchat_query.py ntop-alerts --host 192.168.0.95 --ifid 0 --hours 24What each step answers:
devicesconfirms host identity and local interface contextconnectionsshows live state-table activity from the firewall point of viewlogsshows recent blocked or notable eventsntop-hostshows host-level traffic profilentop-host-appsshows application/protocol mixntop-alertsshows whether the host triggered recent attention-worthy events
Goal: decide whether recent blocked activity is harmless noise, misconfiguration, or something worth containment.
Suggested sequence:
python3 pfchat/scripts/pfchat_query.py snapshot --limit 150
python3 pfchat/scripts/pfchat_query.py logs --limit 200
python3 pfchat/scripts/pfchat_query.py ntop-alerts --ifid 0 --hours 24
python3 pfchat/scripts/pfchat_query.py ntop-top-talkers --ifid 0 --direction localWhat to look for:
- repeated blocks from one source
- unusual outbound destinations
- one host dominating traffic unexpectedly
- alert concentration around one client or service
- mismatch between firewall policy intent and observed traffic
Goal: explain why one host is currently dominant on the network.
Suggested sequence:
python3 pfchat/scripts/pfchat_query.py ntop-top-talkers --ifid 0 --direction local
python3 pfchat/scripts/pfchat_query.py ntop-host --host <host-or-ip> --ifid 0
python3 pfchat/scripts/pfchat_query.py ntop-host-apps --host <host-or-ip> --ifid 0
python3 pfchat/scripts/pfchat_query.py connections --host <host-or-ip> --limit 100This lets you explain not only that a host is noisy, but whether that noise is:
- expected backup/streaming activity
- update traffic
- browsing / SaaS activity
- suspicious egress
- a host worth temporarily constraining
PfChat administrative flows are intentionally staged.
Typical lifecycle:
- create a draft for a block action
- review the generated alias/rule proposal
- apply only with explicit confirmation
- validate impact after apply
- roll back using stored metadata if needed
Example:
python3 pfchat/scripts/pfchat_query.py block-device --target lab-host
python3 pfchat/scripts/pfchat_query.py draft-show --draft-id <id>
python3 pfchat/scripts/pfchat_query.py apply-draft --draft-id <id> --confirm
python3 pfchat/scripts/pfchat_query.py rollback-draft --draft-id <id> --confirmUse the quick egress path when you need immediate, test-oriented containment for a specific host and protocol/port combination.
Example:
python3 pfchat/scripts/pfchat_query.py quick-egress-block --target lab-host --proto tcp --port 443
python3 pfchat/scripts/pfchat_query.py quick-egress-unblock --target lab-host --proto tcp --port 443This path is useful when:
- you want immediate effect during live investigation
- you do not want to redesign long-term LAN policy yet
- you need to validate whether a single outbound dependency is the issue
Use draft/apply/rollback when:
- you want a managed, reviewable firewall change
- you expect to preserve the change longer than a short test
- you want stored metadata for cleanup and rollback
Use quick egress block/unblock when:
- you need temporary containment during investigation
- timing matters more than long-term policy structure
- you want immediate effect plus state cleanup
This section matters because the pfSense API is not native by default. PfChat depends on the upstream pfSense-pkg-RESTAPI package being installed on the firewall.
Canonical upstream project:
Useful upstream docs:
- installation: https://pfrest.org/INSTALL_AND_CONFIG/
- authentication: https://pfrest.org/AUTHENTICATION_AND_AUTHORIZATION/
- Swagger/OpenAPI: https://pfrest.org/SWAGGER_AND_OPENAPI/
Practical walkthrough used during this project:
Typical install command for pfSense CE:
pkg-static add https://github.com/pfrest/pfSense-pkg-RESTAPI/releases/latest/download/pfSense-2.8.1-pkg-RESTAPI.pkgTypical install command for pfSense Plus:
pkg-static -C /dev/null add https://github.com/pfrest/pfSense-pkg-RESTAPI/releases/latest/download/pfSense-25.11-pkg-RESTAPI.pkgImportant notes:
- use the package build that matches your pfSense version
- unofficial packages may disappear after pfSense upgrades, so you may need to reinstall it
- PfChat has been validated against a real pfSense instance exposing
/api/v2/schema/openapi
After installation, verify:
System -> REST APIexists in the webConfigurator- the REST API is enabled/configured correctly
- the authentication method you plan to use is allowed
- the account behind the API key has the permissions you need
PfChat uses API key authentication for pfSense by default via the X-API-Key header.
According to upstream docs, keys are managed from:
System -> REST API -> Keys
Important notes:
- the key inherits the privileges of the user that created it
- treat it as a secret
- if exposed, revoke it and create a new one
Useful checks:
- confirm the API responds at
https://<pfsense>/api/v2/... - confirm your API key works
- confirm the live OpenAPI schema responds at
/api/v2/schema/openapi - confirm the endpoints you care about exist in that schema
If /api/v2/schema/openapi works, PfChat can use schema-aware discovery and adapt to that installation much more reliably.
PfChat expects a reachable ntopng instance that can be queried over HTTP(S). In many environments this is the ntopng deployment integrated with or adjacent to pfSense.
PfChat uses ntopng for:
- active hosts
- top talkers
- host profiles
- host applications/protocols
- alerts
- network-activity summaries
Important notes:
- some ntopng endpoints vary by version, edition, or local install behavior
- some top-talker endpoints may be Pro-only
- PfChat includes fallbacks and normalization so operator output stays stable even when ntopng behavior varies
- if ntopng returns an HTML login page instead of JSON, enable API auth or use an auth token
PfChat looks for configuration in this order:
- inherited environment variables
.envin the current working directory.envnext to the skill/project when present
Create a local .env from the example:
cp .env.example .envExample:
PFSENSE_HOST=192.168.0.254
PFSENSE_API_KEY=replace-me
PFSENSE_VERIFY_SSL=false
NTOPNG_BASE_URL=https://192.168.0.254:3000
NTOPNG_USERNAME=admin
NTOPNG_PASSWORD=replace-me
NTOPNG_AUTH_TOKEN=
NTOPNG_VERIFY_SSL=falsePFSENSE_HOST— host or IP only, withouthttps://or URL pathsPFSENSE_API_KEY— real API key, not the placeholderPFSENSE_VERIFY_SSL— acceptstrue/false,1/0,yes/no,on/off
NTOPNG_BASE_URL— full URL such ashttps://192.168.0.254:3000NTOPNG_USERNAME/NTOPNG_PASSWORD— used for Basic Auth when HTTP API auth is enabledNTOPNG_AUTH_TOKEN— optional alternative that takes precedence over username/password when presentNTOPNG_VERIFY_SSL— accepts the same boolean forms as pfSense SSL verification
PFSENSE_VERIFY_SSL=false and NTOPNG_VERIFY_SSL=false still use HTTPS.
They only disable certificate trust validation, which is common with self-signed certs or internal CAs not installed on the client host.
PfChat now uses the same config-loading model for both surfaces:
- the repo CLI
- the active OpenClaw skill
There is no longer a split where ntopng support exists in one surface but not the other. Keep configuration portable; do not rely on one machine-specific absolute path.
Do not commit real API keys, passwords, or tokens.
python3 pfchat/scripts/pfchat_query.py capabilities
python3 pfchat/scripts/pfchat_query.py devices
python3 pfchat/scripts/pfchat_query.py health
python3 pfchat/scripts/pfchat_query.py snapshot --limit 150
python3 pfchat/scripts/pfchat_query.py ntop-capabilities
python3 pfchat/scripts/pfchat_query.py ntop-hosts --ifid 0 --limit 50
python3 pfchat/scripts/pfchat_query.py ntop-host --host 192.168.0.95 --ifid 0
python3 pfchat/scripts/pfchat_query.py ntop-top-talkers --ifid 0 --direction local
python3 pfchat/scripts/pfchat_query.py ntop-alerts --ifid 0 --hours 24
python3 pfchat/scripts/pfchat_query.py ntop-host-apps --host 192.168.0.95 --ifid 0
python3 pfchat/scripts/pfchat_query.py ntop-network-stats --ifid 0 --hours 24 --limit 10Examples:
check what devices are connected to pfSensesee if there is anything suspicious on my firewallwhat is example-client doing right now?what is my WAN address?show me firewall rules related to OpenVPNshow ntopng active hostswhat does ntopng know about 192.168.0.160?show ntopng top talkersshow ntopng alerts from the last 24 hourswhat applications is 192.168.0.95 using in ntopng?
capabilitiesdevicesconnectionslogsinterfaceshealthrulessnapshot
ntop-capabilitiesntop-hostsntop-hostntop-top-talkersntop-alertsntop-host-appsntop-network-stats
block-ipblock-deviceblock-egress-portblock-egress-protoapply-draftrollback-draftquick-egress-blockquick-egress-unblockunblock-ipunblock-devicepfchat-managed-listpfchat-managed-cleanup
PfChat supports real administrative changes on pfSense, but it is designed around guardrails:
- draft first
- preview before apply
- explicit confirm for live changes
- rollback support where possible
- managed-object cleanup support
- schema-aware checks before write paths
This matters because PfChat is not just for observation. It is also meant to be useful during real firewall operations.
python3 pfchat/scripts/pfchat_query.py connections --host 192.168.0.95 --limit 100
python3 pfchat/scripts/pfchat_query.py logs --host 192.168.0.95 --limit 100
python3 pfchat/scripts/pfchat_query.py ntop-host --host 192.168.0.95 --ifid 0
python3 pfchat/scripts/pfchat_query.py ntop-host-apps --host 192.168.0.95 --ifid 0python3 pfchat/scripts/pfchat_query.py ntop-top-talkers --ifid 0 --direction local
python3 pfchat/scripts/pfchat_query.py ntop-alerts --ifid 0 --hours 24python3 pfchat/scripts/pfchat_query.py block-device --target lab-host
python3 pfchat/scripts/pfchat_query.py apply-draft --draft-id <id>
python3 pfchat/scripts/pfchat_query.py apply-draft --draft-id <id> --confirm
python3 pfchat/scripts/pfchat_query.py rollback-draft --draft-id <id> --confirmpython3 pfchat/scripts/pfchat_query.py quick-egress-block --target lab-host --proto tcp --port 443
python3 pfchat/scripts/pfchat_query.py quick-egress-unblock --target lab-host --proto tcp --port 443pfchat/
├── README.md
├── README.en.md
├── README.es.md
├── CHANGELOG.md
├── CHANGELOG.en.md
├── CHANGELOG.es.md
├── TODO.md
├── TODO.en.md
├── TODO.es.md
├── ROADMAP.md
├── ROADMAP.es.md
├── docs/
│ └── unification-2026-03-19.md
├── .env.example
├── pfchat/
│ ├── SKILL.md
│ ├── scripts/
│ │ ├── pfchat_query.py
│ │ ├── pfsense_client.py
│ │ ├── ntopng_client.py
│ │ ├── ntopng_adapter.py
│ │ └── ntopng_pyapi_backend.py
│ └── references/
│ ├── endpoints.md
│ ├── output-shapes.md
│ ├── upstream-notes.md
│ ├── investigation-patterns.md
│ └── investigation-examples.md
└── tests/
- PfChat prefers the live OpenAPI schema from pfSense when available
- PfChat caches capability/schema data to reduce repeated fetches
- ntopng output is normalized so the operator gets stable JSON even when the underlying install varies
- known local device names can be enriched from local inventory data so output is more readable than raw vendor strings
pfchat/SKILL.mddocs/unification-2026-03-19.mdpfchat/references/endpoints.mdpfchat/references/output-shapes.mdpfchat/references/investigation-patterns.mdpfchat/references/investigation-examples.md