[v2] firewall: always allow outgoing DNS traffic to root servers

Message ID 6972e22e-fb8f-772d-42f0-a7fb0e5cbe3f@ipfire.org
State Dropped
Headers
Series [v2] firewall: always allow outgoing DNS traffic to root servers |

Commit Message

Peter Müller Oct. 1, 2019, 3:22 p.m. UTC
  Allowing outgoing DNS traffic (destination port 53, both TCP
and UDP) to the root servers is BCP for some reasons. First,
RFC 5011 assumes resolvers are able to fetch new trust ancors
from the root servers for a certain time period in order to
do key rollovers.

Second, Unbound shows some side effects if it cannot do trust
anchor signaling (see RFC 8145) or fetch the current trust anchor,
resulting in SERVFAILs for arbitrary requests a few minutes.

There is little security implication of allowing DNS traffic
to the root servers: An attacker might abuse this for exfiltrating
data via DNS queries, but is unable to infiltrate data unless
he gains control over at least one root server instance. If
there is no firewall ruleset in place which prohibits any other
DNS traffic than to chosen DNS servers, this patch will not
have security implications at all.

The second version of this patch does not use unnecessary xargs-
call nor changes anything else not related to this issue.

Fixes #12183

Cc: Michael Tremer <michael.tremer@ipfire.org>
Suggested-by: Horace Michael <horace.michael@gmx.com>
Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
---
 config/rootfiles/core/137/filelists/files |  1 +
 src/initscripts/system/firewall           | 12 ++++++++++++
 2 files changed, 13 insertions(+)
  

Comments

Michael Tremer Oct. 1, 2019, 5:24 p.m. UTC | #1
Acked-by: Michael Tremer <michael.tremer@ipfire.org>

> On 1 Oct 2019, at 16:22, peter.mueller@ipfire.org wrote:
> 
> Allowing outgoing DNS traffic (destination port 53, both TCP
> and UDP) to the root servers is BCP for some reasons. First,
> RFC 5011 assumes resolvers are able to fetch new trust ancors
> from the root servers for a certain time period in order to
> do key rollovers.
> 
> Second, Unbound shows some side effects if it cannot do trust
> anchor signaling (see RFC 8145) or fetch the current trust anchor,
> resulting in SERVFAILs for arbitrary requests a few minutes.
> 
> There is little security implication of allowing DNS traffic
> to the root servers: An attacker might abuse this for exfiltrating
> data via DNS queries, but is unable to infiltrate data unless
> he gains control over at least one root server instance. If
> there is no firewall ruleset in place which prohibits any other
> DNS traffic than to chosen DNS servers, this patch will not
> have security implications at all.
> 
> The second version of this patch does not use unnecessary xargs-
> call nor changes anything else not related to this issue.
> 
> Fixes #12183
> 
> Cc: Michael Tremer <michael.tremer@ipfire.org>
> Suggested-by: Horace Michael <horace.michael@gmx.com>
> Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
> ---
> config/rootfiles/core/137/filelists/files |  1 +
> src/initscripts/system/firewall           | 12 ++++++++++++
> 2 files changed, 13 insertions(+)
> 
> diff --git a/config/rootfiles/core/137/filelists/files b/config/rootfiles/core/137/filelists/files
> index ce4e51768..a02840d12 100644
> --- a/config/rootfiles/core/137/filelists/files
> +++ b/config/rootfiles/core/137/filelists/files
> @@ -1,4 +1,5 @@
> etc/system-release
> etc/issue
> +etc/rc.d/init.d/firewall
> srv/web/ipfire/cgi-bin/credits.cgi
> var/ipfire/langs
> diff --git a/src/initscripts/system/firewall b/src/initscripts/system/firewall
> index ec396c708..602bd6c5b 100644
> --- a/src/initscripts/system/firewall
> +++ b/src/initscripts/system/firewall
> @@ -6,6 +6,7 @@
> eval $(/usr/local/bin/readhash /var/ipfire/ppp/settings)
> eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
> eval $(/usr/local/bin/readhash /var/ipfire/optionsfw/settings)
> +ROOTHINTS="/etc/unbound/root.hints"
> IFACE=`/bin/cat /var/ipfire/red/iface 2> /dev/null | /usr/bin/tr -d '\012'`
> 
> if [ -f /var/ipfire/red/device ]; then
> @@ -307,6 +308,17 @@ iptables_init() {
> 	iptables -A INPUT -j TOR_INPUT
> 	iptables -N TOR_OUTPUT
> 	iptables -A OUTPUT -j TOR_OUTPUT
> +
> +	# Allow outgoing DNS traffic (TCP and UDP) to DNS root servers
> +	local rootserverips="$( awk '/\s+A\s+/ { print $4 }' ${ROOTHINTS} )"
> +	ipset -N root-servers iphash
> +
> +	for ip in "${rootserverips[@]}"; do
> +		ipset add root-servers $ip
> +	done
> +
> +	iptables -A OUTPUT -m set --match-set root-servers dst -p tcp --dport 53 -j ACCEPT
> +	iptables -A OUTPUT -m set --match-set root-servers dst -p udp --dport 53 -j ACCEPT
> 	
> 	# Jump into the actual firewall ruleset.
> 	iptables -N INPUTFW
> -- 
> 2.16.4
  
Arne Fitzenreiter Oct. 18, 2019, 7:08 a.m. UTC | #2
this Code will not work:
> +	for ip in "${rootserverips[@]}"; do
> +		ipset add root-servers $ip
> +	done

it call
ipset add ip1 ip2 ip3 ...
because the doublequotes.

And if i fix this
/etc/init.d/firewall restart
complains because the ipset was not cleaned up before!

Arne



Am 2019-10-01 17:22, schrieb peter.mueller@ipfire.org:
> Allowing outgoing DNS traffic (destination port 53, both TCP
> and UDP) to the root servers is BCP for some reasons. First,
> RFC 5011 assumes resolvers are able to fetch new trust ancors
> from the root servers for a certain time period in order to
> do key rollovers.
> 
> Second, Unbound shows some side effects if it cannot do trust
> anchor signaling (see RFC 8145) or fetch the current trust anchor,
> resulting in SERVFAILs for arbitrary requests a few minutes.
> 
> There is little security implication of allowing DNS traffic
> to the root servers: An attacker might abuse this for exfiltrating
> data via DNS queries, but is unable to infiltrate data unless
> he gains control over at least one root server instance. If
> there is no firewall ruleset in place which prohibits any other
> DNS traffic than to chosen DNS servers, this patch will not
> have security implications at all.
> 
> The second version of this patch does not use unnecessary xargs-
> call nor changes anything else not related to this issue.
> 
> Fixes #12183
> 
> Cc: Michael Tremer <michael.tremer@ipfire.org>
> Suggested-by: Horace Michael <horace.michael@gmx.com>
> Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
> ---
>  config/rootfiles/core/137/filelists/files |  1 +
>  src/initscripts/system/firewall           | 12 ++++++++++++
>  2 files changed, 13 insertions(+)
> 
> diff --git a/config/rootfiles/core/137/filelists/files
> b/config/rootfiles/core/137/filelists/files
> index ce4e51768..a02840d12 100644
> --- a/config/rootfiles/core/137/filelists/files
> +++ b/config/rootfiles/core/137/filelists/files
> @@ -1,4 +1,5 @@
>  etc/system-release
>  etc/issue
> +etc/rc.d/init.d/firewall
>  srv/web/ipfire/cgi-bin/credits.cgi
>  var/ipfire/langs
> diff --git a/src/initscripts/system/firewall 
> b/src/initscripts/system/firewall
> index ec396c708..602bd6c5b 100644
> --- a/src/initscripts/system/firewall
> +++ b/src/initscripts/system/firewall
> @@ -6,6 +6,7 @@
>  eval $(/usr/local/bin/readhash /var/ipfire/ppp/settings)
>  eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
>  eval $(/usr/local/bin/readhash /var/ipfire/optionsfw/settings)
> +ROOTHINTS="/etc/unbound/root.hints"
>  IFACE=`/bin/cat /var/ipfire/red/iface 2> /dev/null | /usr/bin/tr -d 
> '\012'`
> 
>  if [ -f /var/ipfire/red/device ]; then
> @@ -307,6 +308,17 @@ iptables_init() {
>  	iptables -A INPUT -j TOR_INPUT
>  	iptables -N TOR_OUTPUT
>  	iptables -A OUTPUT -j TOR_OUTPUT
> +
> +	# Allow outgoing DNS traffic (TCP and UDP) to DNS root servers
> +	local rootserverips="$( awk '/\s+A\s+/ { print $4 }' ${ROOTHINTS} )"
> +	ipset -N root-servers iphash
> +
> +	for ip in "${rootserverips[@]}"; do
> +		ipset add root-servers $ip
> +	done
> +
> +	iptables -A OUTPUT -m set --match-set root-servers dst -p tcp
> --dport 53 -j ACCEPT
> +	iptables -A OUTPUT -m set --match-set root-servers dst -p udp
> --dport 53 -j ACCEPT
> 
>  	# Jump into the actual firewall ruleset.
>  	iptables -N INPUTFW
  
Arne Fitzenreiter Oct. 18, 2019, 11:47 a.m. UTC | #3
I have also found another problem.
This patch is useless because you need the rootserver only in recursor 
mode but
in recursor mode you need access to all dns servers of the domain 
ownwers.

So allowing only the rootservers is useless because you still cannot 
resolve domains.

Arne



Am 2019-10-18 09:08, schrieb Arne Fitzenreiter:
> this Code will not work:
>> +	for ip in "${rootserverips[@]}"; do
>> +		ipset add root-servers $ip
>> +	done
> 
> it call
> ipset add ip1 ip2 ip3 ...
> because the doublequotes.
> 
> And if i fix this
> /etc/init.d/firewall restart
> complains because the ipset was not cleaned up before!
> 
> Arne
> 
> 
> 
> Am 2019-10-01 17:22, schrieb peter.mueller@ipfire.org:
>> Allowing outgoing DNS traffic (destination port 53, both TCP
>> and UDP) to the root servers is BCP for some reasons. First,
>> RFC 5011 assumes resolvers are able to fetch new trust ancors
>> from the root servers for a certain time period in order to
>> do key rollovers.
>> 
>> Second, Unbound shows some side effects if it cannot do trust
>> anchor signaling (see RFC 8145) or fetch the current trust anchor,
>> resulting in SERVFAILs for arbitrary requests a few minutes.
>> 
>> There is little security implication of allowing DNS traffic
>> to the root servers: An attacker might abuse this for exfiltrating
>> data via DNS queries, but is unable to infiltrate data unless
>> he gains control over at least one root server instance. If
>> there is no firewall ruleset in place which prohibits any other
>> DNS traffic than to chosen DNS servers, this patch will not
>> have security implications at all.
>> 
>> The second version of this patch does not use unnecessary xargs-
>> call nor changes anything else not related to this issue.
>> 
>> Fixes #12183
>> 
>> Cc: Michael Tremer <michael.tremer@ipfire.org>
>> Suggested-by: Horace Michael <horace.michael@gmx.com>
>> Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
>> ---
>>  config/rootfiles/core/137/filelists/files |  1 +
>>  src/initscripts/system/firewall           | 12 ++++++++++++
>>  2 files changed, 13 insertions(+)
>> 
>> diff --git a/config/rootfiles/core/137/filelists/files
>> b/config/rootfiles/core/137/filelists/files
>> index ce4e51768..a02840d12 100644
>> --- a/config/rootfiles/core/137/filelists/files
>> +++ b/config/rootfiles/core/137/filelists/files
>> @@ -1,4 +1,5 @@
>>  etc/system-release
>>  etc/issue
>> +etc/rc.d/init.d/firewall
>>  srv/web/ipfire/cgi-bin/credits.cgi
>>  var/ipfire/langs
>> diff --git a/src/initscripts/system/firewall 
>> b/src/initscripts/system/firewall
>> index ec396c708..602bd6c5b 100644
>> --- a/src/initscripts/system/firewall
>> +++ b/src/initscripts/system/firewall
>> @@ -6,6 +6,7 @@
>>  eval $(/usr/local/bin/readhash /var/ipfire/ppp/settings)
>>  eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
>>  eval $(/usr/local/bin/readhash /var/ipfire/optionsfw/settings)
>> +ROOTHINTS="/etc/unbound/root.hints"
>>  IFACE=`/bin/cat /var/ipfire/red/iface 2> /dev/null | /usr/bin/tr -d 
>> '\012'`
>> 
>>  if [ -f /var/ipfire/red/device ]; then
>> @@ -307,6 +308,17 @@ iptables_init() {
>>  	iptables -A INPUT -j TOR_INPUT
>>  	iptables -N TOR_OUTPUT
>>  	iptables -A OUTPUT -j TOR_OUTPUT
>> +
>> +	# Allow outgoing DNS traffic (TCP and UDP) to DNS root servers
>> +	local rootserverips="$( awk '/\s+A\s+/ { print $4 }' ${ROOTHINTS} )"
>> +	ipset -N root-servers iphash
>> +
>> +	for ip in "${rootserverips[@]}"; do
>> +		ipset add root-servers $ip
>> +	done
>> +
>> +	iptables -A OUTPUT -m set --match-set root-servers dst -p tcp
>> --dport 53 -j ACCEPT
>> +	iptables -A OUTPUT -m set --match-set root-servers dst -p udp
>> --dport 53 -j ACCEPT
>> 
>>  	# Jump into the actual firewall ruleset.
>>  	iptables -N INPUTFW
  

Patch

diff --git a/config/rootfiles/core/137/filelists/files b/config/rootfiles/core/137/filelists/files
index ce4e51768..a02840d12 100644
--- a/config/rootfiles/core/137/filelists/files
+++ b/config/rootfiles/core/137/filelists/files
@@ -1,4 +1,5 @@ 
 etc/system-release
 etc/issue
+etc/rc.d/init.d/firewall
 srv/web/ipfire/cgi-bin/credits.cgi
 var/ipfire/langs
diff --git a/src/initscripts/system/firewall b/src/initscripts/system/firewall
index ec396c708..602bd6c5b 100644
--- a/src/initscripts/system/firewall
+++ b/src/initscripts/system/firewall
@@ -6,6 +6,7 @@ 
 eval $(/usr/local/bin/readhash /var/ipfire/ppp/settings)
 eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
 eval $(/usr/local/bin/readhash /var/ipfire/optionsfw/settings)
+ROOTHINTS="/etc/unbound/root.hints"
 IFACE=`/bin/cat /var/ipfire/red/iface 2> /dev/null | /usr/bin/tr -d '\012'`
 
 if [ -f /var/ipfire/red/device ]; then
@@ -307,6 +308,17 @@  iptables_init() {
 	iptables -A INPUT -j TOR_INPUT
 	iptables -N TOR_OUTPUT
 	iptables -A OUTPUT -j TOR_OUTPUT
+
+	# Allow outgoing DNS traffic (TCP and UDP) to DNS root servers
+	local rootserverips="$( awk '/\s+A\s+/ { print $4 }' ${ROOTHINTS} )"
+	ipset -N root-servers iphash
+
+	for ip in "${rootserverips[@]}"; do
+		ipset add root-servers $ip
+	done
+
+	iptables -A OUTPUT -m set --match-set root-servers dst -p tcp --dport 53 -j ACCEPT
+	iptables -A OUTPUT -m set --match-set root-servers dst -p udp --dport 53 -j ACCEPT
 	
 	# Jump into the actual firewall ruleset.
 	iptables -N INPUTFW