PF pf - redirect all outbound NTP traffic to local NTP server

I thought my NTP redirection was working, but upon further inspection, I see it is not. It appears to only work for clients that explicitly use the NTP server's IP address.

This is my relevant pf conf:

rdr pass on wired proto udp from any to any port ntp -> $LOCAL_NTP_SERVER port ntp
pass in quick on wired proto udp to (wired) port ntp
pass out quick on wired proto udp from port ntp

On the client, I am running:
sntpc -n 54.197.201.246

I ran a tcpdump on the NTP box and I see the traffic going to the NTP server and it responding, but the client doesn't process the response. I see the same traffic on the client itself, so it seems like the redirect works, but I don't get any indication of the NTP offset or delay.

Whereas, if I run
sntpc -n $LOCAL_NTP_SERVER

I get the offset or delay.

sntpc -n 54.197.201.246 returns exit status of 255. The tcpdump capture shows a disconnected stream - the response to the query is not part of the request when selecting follow UDP stream. The IP portion of the packet in the response is set to the local IP address of the NTP server. The problem is that it is not rewriting the address in the response.

The examples I see are for redirecting external ingress traffic to some locally running server. I have internal egress traffic that I want to keep entirely local.
 
What is wired? It that working?
But it look good. (not the pass rules)

I have rdr rules for any outgoing external address to my NTP, DNS and other rdr ports, protocols to my internal servers. My rdr-rule look like this (for NTP):
Code:
rdr    on $40g_if inet proto udp       from <rfc1918>          to any port 123         -> $NTP_Int            port 123

$40g_if is 40g_if = "lagg0" two QSFP laggports for internal network with a lot of VLANs. I get all of them in this rule.
$NTP_Int is NTP_Int = "{ 10.45.45.20, 10.45.45.21 }"

On all the VLAN network (this for vlan-id 77):
Code:
pass   in      quick on $vlan75 proto udp      from $75net             to $NTP_Int             port $NTP_ports         $UdpState

and the VLAN that have the NTP servers:
Code:
pass   out     quick on $vlan45 proto udp      from <rfc1918>          to $NTP_Int             port $NTP_ports         $UdpState
pass   in      quick on $vlan45 proto udp      from $NTP_Int           to <NTP_IP>             port $NTP_ports         $UdpState

Pass in rule with the <NTP_IP> is list on NTP-servers on the internet that I trust. And I have rules on my ext_if to allow this rule to get out on the internet to the <NTP_IP> servers.
A server can go “out” on any IPv4-address witch rdr to my internal servers 10.45.45.20 and .21. The rule converts the “outgoing IP-address” to the internal server address within my <rfc1918> table. I don’t need to set any NTP-servers on the servers (even if I do). UdpState ="keep state".

Edit: I don't use sntpc, I use ntpd.
 
Hmm, so, I think you answered what I was getting at then.

wired is my LAN interface
wan is my WAN interface

For the redirect to successfully rewrite packets, I need to perform this redirect operation on my egress interface.
As I understand it, a rdr pass means that I don't need subsequent pass statements. But that is an aside really because the traffic is flowing properly. It just is not rewritten and thus my IoT devices (AND sntpc) don't consume the response as a result.

So, then, in theory, this should work:

rdr pass on wan proto udp to any port ntp -> $LOCAL_NTP_SERVER port ntp

Then, in my ntpd.conf, I need to restrict to just my internal traffic only. I don't like this approach even if it works because it would be opening a hole in my firewall.
 
Ok.. I may by a little lost here.

Q: Is the client inside you network to local NTP-server OR on the internet that should connect to your NTP-server inside your network?

If inside - my rules will work.
If it’s connections from the internet, your new rule ( rdr pass on wan proto udp to any port ntp -> $LOCAL_NTP_SERVER port ntp ) should work. But, I would not open that port to the internet! That’s a security risk.


If inside traffic - you will never specify any external interface (just outgoing from you NTP-servers), only local / inside interfaces. My $40g_if is my inside interface for my local networks (many vlans). My $ext_if is my external interface. I never open any NTP-traffic from any server inside my networks to the internet. Every NTP-connection, regardless IP-addresses is rdr to my local NTP-server.

You can use rdr pass, and yes you are correct about subsequent pass statements. I don’t like that way as I want to control every segment rule by rule. But both rules is correct and will work.

If inside – you don’t need to cofigure ntpd.com on the server if you don’t want to (I do). Every NTP-connection, regardless if it direct to you NTP-server och outgoing to some random NTP-server on internet, every connection will rdr to your NTP-server.
 
Ok.. I may by a little lost here.

Q: Is the client inside you network to local NTP-server OR on the internet that should connect to your NTP-server inside your network?

If inside - my rules will work.
If it’s connections from the internet, your new rule ( rdr pass on wan proto udp to any port ntp -> $LOCAL_NTP_SERVER port ntp ) should work. But, I would not open that port to the internet! That’s a security risk.


If inside traffic - you will never specify any external interface (just outgoing from you NTP-servers), only local / inside interfaces. My $40g_if is my inside interface for my local networks (many vlans). My $ext_if is my external interface. I never open any NTP-traffic from any server inside my networks to the internet. Every NTP-connection, regardless IP-addresses is rdr to my local NTP-server.

You can use rdr pass, and yes you are correct about subsequent pass statements. I don’t like that way as I want to control every segment rule by rule. But both rules is correct and will work.

If inside – you don’t need to cofigure ntpd.com on the server if you don’t want to (I do). Every NTP-connection, regardless if it direct to you NTP-server och outgoing to some random NTP-server on internet, every connection will rdr to your NTP-server.
This is for a home network. I want to redirect all of the clients (on the inside of my network) to my NTP and DNS servers.

Again, the redirect works, but the problem is that the response coming back is from the internal server:

request: NTP (8.8.8.8 - this is not the IP address the client is using, but for demonstrative purposes)

response: NTP (192.168.0.1 - time / offset / NTP stuff)

The problem is that some clients don't consume the response because the IP address does not match the request. The clients are expecting it to be 8.8.8.8 in this example, but it is 192.168.0.1.
 
Ok! Starting to understand. My head is soon in sleep mode. Long workday, and what are you doing when you are home.. computer.. something is wrong here..

But. Are you sure that is the rdr rule? I can’t remember if ‘rdr pass’ change something.
If you run tcpdump on the server, NTP-server and firewall, where in the chain is it changing?

In my setup (above rules) it’s like in the picture.
1. Client to local NTP-server address. (Normal rules)
----gren line ----
2. Client to some random NTP-server on internet. (RDR rules)

Is this what you want? Sorry--- sleep-mode. ;)

ntp_conn.jpg
 
Hi - thanks for the detailed response and nice graphics.

Let me try to articulate it again:

client: 10.10.10.11
local NTP server: 10.10.10.10
firewall / router: 10.10.10.1

The firewall / router serves DNS (I would also like to redirect any outbound DNS queries from the local network to the DNS server). Since the firewall / router runs in a jail, it does not run a time server, I could run another time server I think, but I decided before to just run the time server on the host itself so that it could set the clock and serve time.

What I want is that any client, in this case, 10.10.10.11, to automatically have its NTP queries redirected to the local NTP server, 10.10.10.10, and the response to be rewritten such that it appears to have come from the original target. With the rule I have above, that traffic is redirected, BUT it is not rewritten. So, when the local NTP server responds back, the response contains the local NTP server's IP instead of the original destination address and thus the client is ignoring it.

I think explaining to you is making me realize that the rewrite part of it is tightly coupled with NAT. The NAT functionality is happening on the WAN interface, right?
 
OK! NOW I am with you. :)
I my thoughts, your rules is working correct. But that’s not want you want.

So, how do you do that? I don’t know.. can you do that with a rdr rule? hmm...
 
What I want is that any client, in this case, 10.10.10.11, to automatically have its NTP queries redirected to the local NTP server, 10.10.10.10, and the response to be rewritten such that it appears to have come from the original target.
You cannot "bounce" packets out the same interface they came in on.

Code:
     Redirections cannot reflect packets back through the interface they
     arrive on, they can only be redirected to hosts connected to different
     interfaces or to the firewall itself.
pf.conf(5)
 
Hmm, I think the rdr rule above is working, but the part that isn't is the translation because the translation happens on the outbound interface.

I think an alternative might be to modify my DNS server to merely handle those lookups for the time server by answering with my local NTP server's IP address. Then, I don't need to worry about redirect rules.

Since I'm using dnsmasq, I think I could do just add those entries in /etc/hosts.

I will report back once I've tried this.
 
The above works, but it is a bit hackish.

Is there anyway to redirect outbound traffic to a local DNS or NTP server without opening up my router to external traffic? If I just do rdr without the pass, would that work?

Once outbound traffic is on the wan interface, I lose where it originated from, so I won't be able to say from <source_client> any longer. Then, the problem may become, how do I allow the internal NTP traffic out without redirecting it back onto itself?
 
Back
Top