# store pf state table in a file



## lenshunnel (Jul 8, 2021)

Hello Guys,

Is there a way/solution to store pf state table ( filtered by IP would be great) in pf ? 

On pfctl manual page on OpenBSD there is an option "-S statefile: Store the _pf state_ table in the _file". _

Thanks


----------



## ralphbsz (Jul 8, 2021)

Depends on what you want to do with the file. If you want to read it yourself (human inspection), you can use "pfctl -s states > file" to show the states. What OpenBSD's version of pfctl can do (for which I don't see any support in FreeBSD) is to save the states in a file with the -S you described, and then later load them back. Is that what you want to do?


----------



## Kristof Provost (Jul 9, 2021)

ralphbsz said:


> Depends on what you want to do with the file. If you want to read it yourself (human inspection), you can use "pfctl -s states > file" to show the states. What OpenBSD's version of pfctl can do (for which I don't see any support in FreeBSD) is to save the states in a file with the -S you described, and then later load them back. Is that what you want to do?


Do you happen to know what the point of that feature is? It doesn't strike me as very hard to do, in that pfsync already does 95% of what's needed for that, but I struggle to think of any reason why you'd want to persistently store inherently transient information.


----------



## ralphbsz (Jul 9, 2021)

I don't know. Most of IP networking is built so that the network can go down and back up, causing only a performance hit. So you can theoretically throw the state table away (for example in a NAT setting), all existing connections will break, but they will regrow quickly.

Perhaps the idea is to avoid that performance hit? For example: Save the state table, shut down PF, do some operation like an upgrade or a reconfiguration that can only be done with PF down, then bring it back up, and do it so quickly that the consumers of the state table (the ongoing connection) don't even notice? I guess it could be done.

Perhaps for stateful transfers between hosts, as part of an active-passive failover strategy? But it doesn't cover the case of the active host dying without writing the state table first.

Or perhaps it's a debugging tool, built by developers and for developers. I could see this as useful in testing: Carefully construct a set of states, set them once. Then start pf, load these specific states, and run with them for tests.


----------



## lenshunnel (Jul 11, 2021)

Thanks for your reply. There is another use case with Nat. We're using Nat to have some users access internet. We want to log only new states for outgoing connections and we could track which users were behind the Nat address at a specific time. We did not find any way to to that with Freebsd.


----------



## Kristof Provost (Jul 11, 2021)

I know someone did that by parsing pfsync updates. That'd work.
Or you could look at adding static Dtrace probes at appropriate locations.

Persisting the state table is entirely the wrong solution for that use case.


----------



## lenshunnel (Jul 13, 2021)

Kristof Provost said:


> I know someone did that by parsing pfsync updates. That'd work.
> Or you could look at adding static Dtrace probes at appropriate locations.
> 
> Persisting the state table is entirely the wrong solution for that use case.


Hello, Do you know which tool he used? Programming language ? Thanks


----------



## Kristof Provost (Jul 13, 2021)

lenshunnel said:


> Hello, Do you know which tool he used? Programming language ? Thanks


I do not know, no. I don't think it's an open source tool.

If you're only interested in state creations you're only going to have to look for a single message in the pfsync packet stream. I'd expect a you'd be able to get a prototype implementation running in a day or so quite easily.


----------



## lenshunnel (Jul 13, 2021)

I'm not really sure about how pfsync works. I don't know if there is a way to filter the pfsync packet stream to get only the insert state. Also what do you mean by pfsync packet stream ? the data in  interface used to synchronise the state ? 

I was hoping for a more efficient way than parsing the result of  this command : sudo tcpdump -vvv -i em0 proto pfsync. which looks like :

17:27:43.758200 IP (tos 0x10, ttl 255, id 0, offset 0, flags [DF], proto pfsync (240), length 290)
    192.168.2.1 > 192.168.2.2: PFSYNCv5 len 270
    insert count 1\0x0a all proto 17 172.20.8.117.161 <- 172.16.3.205.53114   SINGLE:MULTIPLE
        age 00:00:00, expires in 00:00:30, 1:1 pkts, 80:81 bytes, rule 256
        id: 000000006115413c creatorid: c07b841e
    eof count 1
Thanks for your help


----------



## Kristof Provost (Jul 13, 2021)

pfsync sends out state updates over the network. Look at `man 4 pfsync`. That includes new state creation. You can look at the pfsync code, or at the tcpdump code to work out how the protocol works. Given that you'll just be passively observing you really only need to look for the correct sub-packet type and parse that one and ignore everything else.

In your position I'd look at writing a parser in Python, using scapy (https://scapy.net). There are even examples of doing packet parsing in the pf tests.


----------



## lenshunnel (Jul 16, 2021)

Hello again,

where could I find these examples? 

Thanks


----------



## Kristof Provost (Jul 16, 2021)

/usr/src/tests/sys/netpfil/common/pft_ping.py
/usr/src/tests/sys/netpfil/pf/CVE-2019-5598.py


----------



## lenshunnel (Aug 6, 2021)

Thanks  Kristof Provost   for your help. I did it. By parsing pfsync packet : https://gist.github.com/LensHunnel/3fe393f6f26a09669b20d5bbba334a05


----------

