NATS for firewall admins
You do not need to know NATS to run pfCentral. This page is for the moment you see a word like subject, callout or JetStream in a log and want to know what it means. It assumes you know firewalls and TCP, and nothing about message brokers.
A post office for programs
Section titled “A post office for programs”NATS is a message broker. Think of it as a post office that programs connect to:
- A program publishes a message to an address. NATS calls the address a subject.
- A program subscribes to a subject to receive every message sent to it.
- A message can ask for an answer. That is request and reply: the sender waits a few seconds for one reply.
The sender does not need the receiver’s IP address, port or hostname. It only needs the subject. NATS does the delivery.
In pfCentral the post office runs inside the server. You do not install, patch or configure a separate NATS server unless you choose to bring your own.
Why this removes inbound ports
Section titled “Why this removes inbound ports”A post office only works if everyone visits it. In NATS, every program opens one outbound TCP connection to the broker and keeps it open. Messages flow both ways on that connection.
So the agent on your firewall connects out to the server’s NATS port (24222), exactly as a browser connects out to a website. The server never opens a connection to the firewall. When the server has a job for the firewall, it publishes a message, and NATS sends it down the connection the agent already opened.
- 1. Nothing listens on your firewalls
Your firewalls sit at remote sites, often behind NAT. They accept no incoming management connections, and pfCentral never asks you to open one.
- 2. Each agent dials out
The agent on each firewall opens one outbound connection to the server's NATS port, the same way a browser opens a website. If the firewall can reach the server, it works.
- 3. The connection stays open
Every few seconds the agent sends a heartbeat and live stats (CPU, memory, traffic) up the connection. This is how the UI knows a firewall is online.
- 4. You click Save
The server publishes a request to an address called a subject. Only fw-hq-01 listens on
pfsense.fw-hq-01.…, so only it receives the request. It travels down the connection the agent already opened. - 5. The agent applies it and replies
The agent writes the change to the pfSense configuration, applies it, and sends the result back the same way. The UI shows you the outcome.
- 6. Each firewall only hears its own subjects
When an agent connects, the server gives it a pass that allows
pfsense.<its-id>.>only. One firewall can never read or answer messages for another.
From the firewall’s point of view, this is an outbound session to one host and one port, like any other. It works through NAT, CGNAT, and upstream routers you do not control.
Subjects are addresses with dots
Section titled “Subjects are addresses with dots”A subject is a string made of words separated by dots. pfCentral uses one pattern everywhere:
pfsense.<device-id>.<resource>.<action>Try it. Pick a firewall and an action, and see which agent receives the message:
pfsenseproduct . fw-hq-01which firewall . firewall.ruleswhat . listdo what pfsense.fw-hq-01.> pfsense.fw-syd-02.> pfsense.fw-mel-03.> The device ID in the middle is what keeps firewalls apart. The agent on fw-syd-02 subscribes only to subjects that start with pfsense.fw-syd-02.. A message for fw-hq-01 never reaches it.
In the real system the device ID is the firewall’s SMBIOS UUID, such as 4c4c4544-0042-5a10-8048-b4c04f4d3132, not its name. Names can change; the UUID does not.
Wildcards
Section titled “Wildcards”NATS permissions and subscriptions can use two wildcards:
| Wildcard | Matches | Example |
|---|---|---|
* | exactly one word | pfsense.*.telemetry.metrics matches telemetry from every firewall |
> | one or more words, at the end | pfsense.fw-hq-01.> matches everything for fw-hq-01 |
You will see pfsense.<id>.> in the pfSense package’s Status tab as the agent’s credential scope. It means “this agent may only send and receive messages about itself”.
Who may say what: accounts and passes
Section titled “Who may say what: accounts and passes”Anyone who can reach port 24222 can try to connect, so NATS must check who is connecting and what they may do. pfCentral uses three ideas for this.
Accounts are separate rooms inside one broker. The server’s own connection, the devices, and the login checker live in different accounts. Messages do not cross between accounts unless the server allows it.
The sentinel is a shared login that every agent uses to knock on the door. On its own it has no permissions at all. It only gets the agent into the waiting room.
The authorization callout is how the door is opened. When an agent knocks, NATS asks pfCentral: “this is device X with secret Y, may it in?” pfCentral checks the secret against its database and that the device is enrolled. If yes, it signs a short-lived pass (a JWT) that allows pfsense.<device-id>.> and nothing else. The pass expires after one hour, and the agent gets a new one when it reconnects.
The enrollment page animates this sequence step by step.
Remembering things: JetStream
Section titled “Remembering things: JetStream”Plain NATS is fire and forget: if nobody listens, the message is gone. JetStream is the part of NATS that stores messages. pfCentral uses it for three things:
| Name | Kind | Holds | Kept for |
|---|---|---|---|
TELEMETRY | stream | CPU, memory, interface and gateway samples from every agent | 6 hours |
device-presence | key-value bucket | one entry per online device | 15 seconds after the last heartbeat |
device-state | key-value bucket | recent answers from devices, such as rule lists, so pages load fast | 5 minutes |
The presence bucket is how pfCentral knows a firewall is online. Read Online, offline and telemetry for the full story, with a simulator.
JetStream stores its data in the server’s state directory, under nats/js/. Losing it only loses recent telemetry and caches.
What a request looks like on the wire
Section titled “What a request looks like on the wire”When you open a firewall’s rule list, the server sends a request like this:
subject: pfsense.4c4c4544-0042-5a10-8048-b4c04f4d3132.firewall.rules.listreply-to: _INBOX.Yk3Zr7c… (a one-time return address)payload: {"request_id":"cs1q…","payload":{}}The agent answers on the return address:
{ "request_id": "cs1q…", "device_id": "4c4c4544-…", "data": [ …rules… ] }The server waits up to 5 seconds. If the firewall is offline or busy, you see a timeout error in the UI instead of a hang.
Words you will see in logs
Section titled “Words you will see in logs”| Term | Meaning |
|---|---|
| Broker, server | The NATS process. In pfCentral it runs inside the pfCentral server. |
| Subject | The address of a message, such as pfsense.<id>.firewall.rules.list. |
| Publish, subscribe | Send to a subject; listen on a subject. |
| Request, reply | A message that expects one answer on a temporary _INBOX. subject. |
| Micro service | A NATS convention for request and reply handlers. The agent is one, named pfsense-agent. |
| Account | An isolated space inside one broker. |
| Operator | The top-level key that signs accounts. pfCentral creates it on first boot. |
| JWT, creds | A signed pass that says who you are and what you may do. A .creds file holds one plus its key. |
| Sentinel | The shared, permission-less login agents use to reach the callout. |
| Authorization callout | NATS asking pfCentral whether to admit a connection. |
| JetStream | NATS storage: streams and key-value buckets. |
$SYS | NATS’s own system account. It reports connects and disconnects. |
Learn more
Section titled “Learn more”- The official NATS concepts documentation.
- Enrollment and identity for the full connect sequence.
- Bring your own NATS if your team already runs NATS.
- NATS subjects reference for every subject the agent answers.