Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'Force Clients To Use Router DNS Servers' breaks when using a local DNS server #794

Open
dquam opened this issue Feb 28, 2019 · 16 comments
Open

Comments

@dquam
Copy link

dquam commented Feb 28, 2019

When using Force Clients To Use Router DNS Servers configured with a local DNS server, DNS requests get trapped in a loop per these firewall rules. Is there any appetite to change these rules to something more akin to:

iptables -t nat -I zone_lan_prerouting !-s [DNS_SERVER1] -p tcp --dport 53 -j DNAT --to [DNS_SERVER1]
iptables -t nat -I zone_lan_prerouting !-s [DNS_SERVER1] -p udp --dport 53 -j DNAT --to [DNS_SERVER1]
//repeat for all DNS servers entered

Or would adding logic to the shell script to only apply the above rules for local DNS servers and use the REDIRECT rules by default be more appropriate?

@lantis1008
Copy link
Contributor

Just for my understanding, you’re saying that in the case where a local DNS server is used (not on the router, and not somewhere on the WAN side):

  • the client sends request to router
  • router redirects to local DNS
  • local DNS sends request to remote DNS
  • router redirects to local DNS

Is that the gist?

@dquam
Copy link
Author

dquam commented Feb 28, 2019

Exactly.

@lantis1008
Copy link
Contributor

Should the rule still be REDIRECT? The router should still be the end point.
The DNAT rule would only apply under Option 6 right?

This would make the rule much simpler.

@dquam
Copy link
Author

dquam commented Feb 28, 2019

Yes, well spotted.

@dquam
Copy link
Author

dquam commented Feb 28, 2019

To be clear, you mean the rules should read:

iptables -t nat -I zone_lan_prerouting !-s [DNS_SERVER1] -p tcp --dport 53 -j REDIRECT
//etc

@lantis1008
Copy link
Contributor

Yes, however in the case of multiple servers, we can comma separate them under the source field. If we don’t do this, we need to do packet marking.

I think this rule can be applied at all times, as the source should never be outside the LAN subnet in that table/chain. So this probably simplifies the shell logic also.

If you’re in a position to test this, that would be good.

@dquam
Copy link
Author

dquam commented Feb 28, 2019

I’m running the REDIRECT version with just my lone internal DNS right now and it’s working. I’ll test adding external DNS servers with an internal DNS server and just external DNS servers tonight. Thanks for the help.

@lantis1008
Copy link
Contributor

Thanks, please let me know outcomes of additional tests.

@dquam
Copy link
Author

dquam commented Mar 1, 2019

So I ran into a problem in my other tests:

iptables v1.4.21: ! not allowed with multiple source or destination IP addresses
Try `iptables -h' or 'iptables --help' for more information.

I tried adding a new chain just to test:

force_router_dns()
{
        force_router_dns=$(uci get firewall.@defaults[0].force_router_dns 2> /dev/null)
        if [ "$force_router_dns" = "1" ] ; then
                iptables -t nat -N dns_list
                dnslist=$(uci get network.lan.dns 2> /dev/null)
                for dns in $dnslist ; do
                        iptables -t nat -I zone_lan_prerouting ! -s "$dns" -p tcp --dport 53 -j dns_list
                        iptables -t nat -I zone_lan_prerouting ! -s "$dns" -p udp --dport 53 -j dns_list
                done
                iptables -t nat -A dns_list -j REDIRECT
        fi
}

This worked in all configurations, but I haven't tested extensively. Is this reasonable?

@lantis1008
Copy link
Contributor

No, not quite.
Packers from the second dns server will fail the first set of rules.

@dquam
Copy link
Author

dquam commented Mar 1, 2019 via email

@dquam
Copy link
Author

dquam commented Mar 1, 2019

I need to ACCEPT all my port 53 traffic from my dns servers. And then add a rule to REDIRECT the rest of port 53 traffic. How’s that?

@dquam
Copy link
Author

dquam commented Mar 1, 2019

force_router_dns()
{
        force_router_dns=$(uci get firewall.@defaults[0].force_router_dns 2> /dev/null)
        if [ "$force_router_dns" = "1" ] ; then
                dnslist=$(uci get network.lan.dns 2> /dev/null)
                for dns in $dnslist ; do
                        iptables -t nat -I zone_lan_prerouting -s "$dns" -p tcp --dport 53 -j ACCEPT
                        iptables -t nat -I zone_lan_prerouting -s "$dns" -p udp --dport 53 -j ACCEPT
                done
                iptables -t nat -I zone_lan_prerouting -p udp --dport 53 -j REDIRECT
                iptables -t nat -I zone_lan_prerouting -p tcp --dport 53 -j REDIRECT
        fi
}

I probably need to flip that order or change to append but that’s the gist.

@lantis1008
Copy link
Contributor

Potentially bad, as this causes the packets to finish the chain early.
I’m not sure if there are other things in that chain that come afterwards that would be needed?
I think the correct method is to mark the packets based on source, check the mark and redirect if necessary, then clear the mark

@dquam
Copy link
Author

dquam commented Mar 1, 2019

Ok, I’ll look at that tomorrow. Thanks for the continued feedback.

@lantis1008
Copy link
Contributor

IPSets are a potential solution to this problem, however the ipset kmod is not currently required on all targets (it is a dependency of Tor, which is not installed by default on all targets).
However, i am working on another change which would make ipset kmod mandatory for all targets, which might then make this ok.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants