# Help me understand these PF rules and troubleshoot the problem



## rvs (Nov 10, 2022)

Hi,

I have a software that deploys a DNS forwarder and uses PF to redirect local DNS requests to the forwarder. All of sudden this schema stopped working and I am trying to figure out what could be the problem.

I am troubleshooting the issue and trying to verify every piece. My question is focused on PF part of the solution.
The rules the tool creates are following:


```
table <dns_servers> {10.142.0.1}
    rdr pass on lo0 inet proto udp to <dns_servers> port 53 -> 127.0.0.1 port 12299
    pass out route-to lo0 inet proto udp to <dns_servers> port 53 keep state
```

10.142.0.1 is my DNS server, and the local forwarder listens at 12299 local port. As I understand, line #2 redirects traffic coming on the local interface for my DNS server to 127.0.0.1:12299, and line #3 routes it to the local interface. I am not very familiar with PF and asking you to verify if the above rules are enough to serve the purpose. Is the order of rules correct? Unfortunately I do not have logs from the system in working state so I have nothing to compare with.

From the perspective of DNS client, the situation looks like connection being never established. `nslookup` and `dig` fail with


```
;; connection timed out; no servers could be reached
```

*however*, the logs of the forwarder do show that requests are forwarded and meaningful response received. If I logically divide the process into these steps:

send request by Requester
intercept traffic and route to the Forwarder
request DNS resolution from the remote server
receive response by the Forwarder
re-send it to the Requester,
then it fails at step 5. Somehow data does not make its way back to the Requester.

If you look at the above PF rules, would you see any clues? Are those enough to serve the purpose? Any other ideas?


----------



## SirDice (Nov 10, 2022)

rvs said:


> ```
> rdr pass on lo0 inet proto udp to <dns_servers> port 53 -> 127.0.0.1 port 12299
> ```


`rdr pass` ignores all other rules you may have.


```
If the pass modifier is given, packets matching the translation rule are
     passed without inspecting the filter rules:
```
pf.conf(5)


----------



## rvs (Nov 11, 2022)

That is interesting. I added logging to find out what rules work and discovered that both have some output. The problem is that in the log rules are not shown in the log exactly as they are set... Then I added `log (all)` and got this:


```
00:00:00.000000 rule 2.sshuttle-12300.2/0(match): pass out on utun6: 10.142.19.133.51934 > 10.142.0.1.53: 8129+ A? freebsd.org. (29)
 00:00:00.000008 rule 2..2/0(match): pass out on lo0: 10.142.19.133.51934 > 10.142.0.1.53: 8129+ A? freebsd.org. (29)
 00:00:00.000027 rule 1/0(match): rdr in on lo0: 10.142.19.133.51934 > 127.0.0.1.12299: UDP, length 29
 00:00:00.151568 rule 1/0(match): rdr out on lo0: 10.142.0.1.53 > 10.142.19.133.51934: 8129 1/0/0 A 96.47.72.84 (45)
 00:00:00.000038 rule 2..2/0(match): pass in on lo0: 10.142.0.1.53 > 10.142.19.133.51934: 8129 1/0/0 A 96.47.72.84 (45)
```

It seems that the first line is produced by rule #3, and the third line produced by rule #2. What does the rest mean?

Also I don't quite understand this syntax:

`rule 2.sshuttle-12300.2/0(match)`

"sshuttle-12300" is name of the anchor the tool creates, what are the numbers? Why is (match) everywhere?


----------



## VladiBG (Nov 11, 2022)

10.142.19.0/24 is on utun6 interface.


----------

