Ok updating now the solutions I have which might help others also.
Solution 1:
My first post was about to do by port-forwarding without any reject.
Idea is to redirect external queries to the local dns, so I got it working by small addition.
When setting from Luci looks like below:
This example is for the lan subnet, redirecting to the that subnet’s dns, so the lan is 192.168.1.0/24 then redirecting to the 192.168.1.1:53 where dns listens.
For other subnets eg. iot (192.168.10.0/24) will be from iot to iot and to dns eg.192.168.10.1:53.
Additionally can be done manually by editing /etc/config/firewall:
config redirect 'dns_int_lan'
option name 'Intercept-DNS_lan'
option src 'lan'
option src_dport '53'
option proto 'tcp udp'
option target 'DNAT'
option family 'any'
option dest_ip '192.168.1.1'
option dest 'lan'
option dest_port '53'
Solution 2:
Reject external queries, this may broke some functionality if the device insists on using external dns rather than the router’s one.
I realized that it should be forwarding rule but not output rule(my previous post).
Solution with logging(I want to believe if really rejected):
Adding custom rule to the /etc/firewall.user file or can be added in Luci Firewall Custom Rules tab.
if ! iptables -S|grep -q "\-N\ forward_log_and_reject"; then
iptables -N forward_log_and_reject
iptables -A forward_log_and_reject -m limit --limit 10/sec -m comment --comment "!log" -j LOG --log-prefix "FORWARD WAN REJECT: "
iptables -A forward_log_and_reject -m comment --comment "!fw3" -j reject
fi
iptables -A forwarding_lan_rule -o eth2 -p tcp -m tcp --dport 53 -m comment --comment "!fw3: Block external DNS lan" -j forward_log_and_reject
iptables -A forwarding_lan_rule -o eth2 -p tcp -m tcp --dport 853 -m comment --comment "!fw3: Block external DNS lan" -j forward_log_and_reject
iptables -A forwarding_lan_rule -o eth2 -p udp -m udp --dport 53 -m comment --comment "!fw3: Block external DNS lan" -j forward_log_and_reject
iptables -A forwarding_lan_rule -o eth2 -p udp -m udp --dport 853 -m comment --comment "!fw3: Block external DNS lan" -j forward_log_and_reject
First creating new custom chain to log and reject.
Then adding rules to the already existing forwarding_lan_rule chain. Those last 4 lines can be repeated for each subnet, eg. forwarding_iot_rule, where iot is the subnet.
This will flood your logs so I split into separate log file by setting in /etc/syslog-ng.conf.
Surprised to see that the devices in your network don’t use router’s dns at all:
root@turris:~# cat /etc/syslog-ng.conf
#############################################################################
# OpenWrt syslog-ng.conf specific file
# which collects all local logs into a single file called /var/log/messages.
# More details about these settings can be found here:
# https://www.syslog-ng.com/technical-documents/list/syslog-ng-open-source-edition
@version: 3.35
@include "scl.conf"
options {
chain_hostnames(no); # Enable or disable the chained hostname format.
create_dirs(yes);
keep_hostname(yes); # Enable or disable hostname rewriting.
log_fifo_size(256); # The number of messages that the output queue can store.
log_msg_size(1024); # Maximum length of a message in bytes.
stats_freq(0); # The period between two STATS messages (sent by syslog-ng, containing statistics about dropped logs) in seconds.
flush_lines(0); # How many lines are flushed to a destination at a time.
use_fqdn(no); # Add Fully Qualified Domain Name instead of short hostname.
};
# syslog-ng gets messages from syslog-ng (internal) and from /dev/log
source src {
internal();
unix-dgram("/dev/log");
};
source net {
network_localhost();
};
source s_network {
default-network-drivers(
# NOTE: TLS support
#
# the default-network-drivers() source driver opens the TLS
# enabled ports as well, however without an actual key/cert
# pair they will not operate and syslog-ng would display a
# warning at startup.
#
#tls(key-file("/path/to/ssl-private-key") cert-file("/path/to/ssl-cert"))
);
};
source kernel {
file("/proc/kmsg" program_override("kernel"));
};
filter f_iptables_forward_wan_reject_not_match {
not match(".*FORWARD WAN REJECT: .*" value(MESSAGE));
};
filter f_iptables_forward_wan_reject_match {
match(".*FORWARD WAN REJECT: .*" value(MESSAGE));
};
filter f_not_cron {
not program(".*cron.*");
};
filter f_cron {
program(".*cron.*");
};
destination messages {
file("/var/log/messages");
};
destination cron {
file("/var/log/cron" suppress(5) template("${ISODATE} ${PRIORITY} ${PROGRAM}[${PID}]: ${MSGONLY}\n") log_fifo_size(256));
};
destination iptables_forward_wan_reject {
file("/var/log/forwardwanreject" suppress(5) template("${ISODATE} ${PROGRAM}: ${MSGONLY}\n") log_fifo_size(256));
};
log {
source(src);
source(net);
source(kernel);
filter(f_iptables_forward_wan_reject_not_match);
filter(f_not_cron);
destination(messages);
# uncomment this line to open port 514 to receive messages
#source(s_network);
};
log {
source(src);
source(kernel);
filter(f_cron);
destination(cron);
};
log {
source(src);
source(kernel);
filter(f_iptables_forward_wan_reject_match);
destination(iptables_forward_wan_reject);
};
#
# Finally, include any user settings last so that s/he can override or
# supplement all "canned" settings inherited from the distribution.
#
@include "/etc/syslog-ng.d/" # Put any customization files in this directory
Solution without logging:
You can do it simply from Luci Firewall Traffic-Rules:
Or by editing /etc/config/firewall
config rule
option dest_port '53 853'
option target 'REJECT'
option dest 'wan'
option src 'lan'
list proto 'tcp'
list proto 'udp'
option name 'Block external DNS lan'
This example is for lan subnet, can be repeated for other subnets.