If you had only a single local interface (even if it’s a bridged one - just… have it be one), you could’ve most easily just have the following two rules
The key is the dst-port. It’s what the “input” chain matches, while in “output”, it would’ve been the “src-port”, but THAT rule would be pointless… But in more detail:
Let’s say we have two devices - “A” and “B”.
When “A” connect to “B” via TCP or UDP, it needs to connect to a particular port on “B”. In order for “B” to respond back to “A”, “A” (kind of) creates a temporary server on itself, at a random port, where it waits for response from “B”, until the connection is over for one reason or another. “A” sends that temporary port to the port on “B” from which it wants answers, and similarly, when “B” answers, it puts the original port to identify itself.
So what’s happening is that the in-interface receives the following message
“I’m looking for , and I’m . I’d like to ask to answer me on . Can you do that please?”
and if the server decides to respond, that same interface would send back a packet that would mean
“I’m looking for , and I’m . I want to tell that I can indeed answer its requests to .”
And here’s the tricky part… when a router (“B”) sees the first message (AND is its IP address on in-interface), it assigns it on the “input” firewall chain, where the “src-address” is the address of the device that looked for it (“A”), the “src-port” is the source where the device wants answers, and “in-interface” is the interface where the packet came from. The router’s IP that the client wants is the “dst-address”, and the port that it wants answers from is the “dst-port”.
If the packet is accepted, the router proceeds to answering, at which point, the “output” firewall chain is triggered, where the src-* and dst-* stuff are reversed, and the “in-interface” is now actually the “out-interface”.
As for the connection state… It doesn’t really make a difference here, but in theory, you could for example allow an initial exchange like above, but then forbid the actual data from being given. If you omit the connection state, the router will not bother answering on any event. With connection-state=new, if the client claims to have already been connected previously, the router will check whether that’s true, and answer if so. Since new connections are forbidden, it will fail to see that’s true, and thus not answer. So… yeah… it won’t answer in any event either way.
If “my way” are used, specifyng “NEW”, not legit DNS reply request FROM INTERNET is blocked.
Usually one DNS query are (from RB input/output point of view):
1.2.3.4:34473 UDP device request → 5.6.7.8:53 UDP RouterOS receive
5.6.7.8:34526 UDP RouterOS Request new packet → 8.8.8.8:53 UDP Receive
8.8.8.8:53 UDP Reply (new packet RELATED on one ESTABILISHED virtual connection-> 5.6.7.8:34526 UDP Receive
5.6.7.8:53 UDP reply to device → 1.2.3.4:34473 UDP device receive
source port can vary, the fixed port is the destination port
for example source port vary if a device are natted and the request go directly to 8.8.8.8 (on forward point of view):
Try it my way, and clear your DNS cache, to see your clients successfully filling it back up. I tried it with my router just now (just in case you had a point…), and as expected, it still works flawlessly.
I assume that by “to”, you mean as in “Device sends a DNS query to ROS, ROS sends a query to another DNS server, the other DNS server answers to ROS, ROS answers device”?
When ROS does that, it will use a different UDP/TCP port as the source port of its DNS query, and will use 53 as the destination port of the remote device. Therefore, the legitimate DNS reply will never be matching rules with dst-port=53, but will instead use as dst-port whatever ROS gave as its src-port upon making the DNS query. Why will ROS do that? Because it can’t receive replies on the same port is expects requests from. In other words, the DNS client and DNS server are two different services.
source port can vary, the fixed port is the destination port
Right. When RouterOS sends a DNS query, the dst-port (in the “output” chain) is fixed to 53 (because that’s where RouterOS sends DNS queries to), but the src-port varies. When you get a reply to a DNS query that you’ve sent, you receive it on the “input” chain with src-port=53 (because that’s the port you’re receiving a reply from), and the dst-port varies depending on what RouterOS chose when sending the DNS query.
So… if you ONLY have rules matching the dst-port on the “input” chain, you’ll still be able to accept replies from DNS queries that RouterOS sent, because the dst-port of DNS replies that come in can be anything OTHER than 53, since 53 is where DNS requests would come in.
=>
The above rules are sufficient even without connection-state=new, and don’t prevent DNS replies from coming in. They only prevent DNS requests from coming in. If one wants to prevent DNS replies from coming to the router, they’d need to check the “input” chain for src-port=53.