Help me understand these PF rules and troubleshoot the problem

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:

Code:
    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

Code:
;; 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:
  1. send request by Requester
  2. intercept traffic and route to the Forwarder
  3. request DNS resolution from the remote server
  4. receive response by the Forwarder
  5. 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?
 
Code:
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.

Code:
     If the pass modifier is given, packets matching the translation rule are
     passed without inspecting the filter rules:
pf.conf(5)
 
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:

Code:
 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?
 
Back
Top