firewall: always allow outgoing DNS traffic to root servers

Message ID a7933368-6423-d028-baeb-d34c53119d5d@ipfire.org
State Dropped
Headers
Series firewall: always allow outgoing DNS traffic to root servers |

Commit Message

Peter Müller Sept. 25, 2019, 7:45 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.

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           | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)
  

Comments

Michael Tremer Sept. 26, 2019, 3:25 p.m. UTC | #1
Hi,

> On 25 Sep 2019, at 20:45, 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.

I think we need to document this on the wiki before we merge this patch.

> 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           | 16 ++++++++++++++--
> 2 files changed, 15 insertions(+), 2 deletions(-)
> 
> 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..ff63a2ede 100644
> --- a/src/initscripts/system/firewall
> +++ b/src/initscripts/system/firewall
> @@ -6,10 +6,11 @@
> 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)
> -IFACE=`/bin/cat /var/ipfire/red/iface 2> /dev/null | /usr/bin/tr -d '\012'`
> +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
> -	DEVICE=`/bin/cat /var/ipfire/red/device 2> /dev/null | /usr/bin/tr -d '\012'`
> +	DEVICE=$( /bin/cat /var/ipfire/red/device 2> /dev/null | /usr/bin/tr -d '\012' )
> fi

Why the added whitespace? Should have been an extra patch.

> 
> function iptables() {
> @@ -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
> +	ROOTSERVERIPS="$( awk '/\s+A\s+/ { print $4 }' ${ROOTHINTS} | xargs )"
> +	ipset -N root-servers iphash

ROOTSERVERIPS could have been an array and could have been local.

You do not need to call xargs. It is a rather expensive way to remove line breaks.

> +
> +	for ip in ${ROOTSERVERIPS}; do
> +		ipset add root-servers $ip
> +	done

It is also interesting that ipset does not allow to add more IP addresses in one go. This looks like a very expensive loop for a lot of IP addresses. I think this is fine here for about a dozen addresses, but importing a blacklist of thousands or tens of thousands of IP addresses will take a long time.

> +
> +	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

-Michael
  
ummeegge Sept. 26, 2019, 7:17 p.m. UTC | #2
Hi all,


On Do, 2019-09-26 at 16:25 +0100, Michael Tremer wrote:
> Hi,
> 
> > On 25 Sep 2019, at 20:45, 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.
> 
> I think we need to document this on the wiki before we merge this
> patch.
> 
> > 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           | 16 ++++++++++++++--
> > 2 files changed, 15 insertions(+), 2 deletions(-)
> > 
> > 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..ff63a2ede 100644
> > --- a/src/initscripts/system/firewall
> > +++ b/src/initscripts/system/firewall
> > @@ -6,10 +6,11 @@
> > 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)
> > -IFACE=`/bin/cat /var/ipfire/red/iface 2> /dev/null | /usr/bin/tr
> > -d '\012'`
> > +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
> > -	DEVICE=`/bin/cat /var/ipfire/red/device 2> /dev/null |
> > /usr/bin/tr -d '\012'`
> > +	DEVICE=$( /bin/cat /var/ipfire/red/device 2> /dev/null |
> > /usr/bin/tr -d '\012' )
> > fi
> 
> Why the added whitespace? Should have been an extra patch.
> 
> > 
> > function iptables() {
> > @@ -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
> > +	ROOTSERVERIPS="$( awk '/\s+A\s+/ { print $4 }' ${ROOTHINTS} |
> > xargs )"
> > +	ipset -N root-servers iphash
> 
> ROOTSERVERIPS could have been an array and could have been local.
> 
> You do not need to call xargs. It is a rather expensive way to remove
> line breaks.
> 
> > +
> > +	for ip in ${ROOTSERVERIPS}; do
> > +		ipset add root-servers $ip
> > +	done
> 
> It is also interesting that ipset does not allow to add more IP
> addresses in one go. This looks like a very expensive loop for a lot
> of IP addresses. I think this is fine here for about a dozen
> addresses, but importing a blacklist of thousands or tens of
> thousands of IP addresses will take a long time.
there is the possiblity to speed this process significantly up via
'ipset restore' whereby the format from 'ipset save' can be used which
looks like this (if no counters has been set) -->

...
add ipset_setname 11.22.33.44 -exist
add ipset_setname 22.33.44.55 -exist
...

so if there is a vast list you can convert it e.g. via perl and pipe it
to 'ipset restore'.

Example:
IP list called 'vast_list' is formatted one per line

...
11.22.33.44
22.33.44.55
...

can be formatted and restored with a

perl -pe 'chomp; $_ = "add ipset_setname $_ -exist\n"' vast_list | ipset restore

Just as a little gimmick :-).


> 
> > +
> > +	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
> 
> -Michael
> 

Best,

Erik
  
Michael Tremer Sept. 30, 2019, 9:05 a.m. UTC | #3
Hi,

> On 26 Sep 2019, at 20:17, ummeegge <ummeegge@ipfire.org> wrote:
> 
> Hi all,
> 
> 
> On Do, 2019-09-26 at 16:25 +0100, Michael Tremer wrote:
>> Hi,
>> 
>>> On 25 Sep 2019, at 20:45, 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.
>> 
>> I think we need to document this on the wiki before we merge this
>> patch.
>> 
>>> 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           | 16 ++++++++++++++--
>>> 2 files changed, 15 insertions(+), 2 deletions(-)
>>> 
>>> 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..ff63a2ede 100644
>>> --- a/src/initscripts/system/firewall
>>> +++ b/src/initscripts/system/firewall
>>> @@ -6,10 +6,11 @@
>>> 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)
>>> -IFACE=`/bin/cat /var/ipfire/red/iface 2> /dev/null | /usr/bin/tr
>>> -d '\012'`
>>> +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
>>> -	DEVICE=`/bin/cat /var/ipfire/red/device 2> /dev/null |
>>> /usr/bin/tr -d '\012'`
>>> +	DEVICE=$( /bin/cat /var/ipfire/red/device 2> /dev/null |
>>> /usr/bin/tr -d '\012' )
>>> fi
>> 
>> Why the added whitespace? Should have been an extra patch.
>> 
>>> 
>>> function iptables() {
>>> @@ -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
>>> +	ROOTSERVERIPS="$( awk '/\s+A\s+/ { print $4 }' ${ROOTHINTS} |
>>> xargs )"
>>> +	ipset -N root-servers iphash
>> 
>> ROOTSERVERIPS could have been an array and could have been local.
>> 
>> You do not need to call xargs. It is a rather expensive way to remove
>> line breaks.
>> 
>>> +
>>> +	for ip in ${ROOTSERVERIPS}; do
>>> +		ipset add root-servers $ip
>>> +	done
>> 
>> It is also interesting that ipset does not allow to add more IP
>> addresses in one go. This looks like a very expensive loop for a lot
>> of IP addresses. I think this is fine here for about a dozen
>> addresses, but importing a blacklist of thousands or tens of
>> thousands of IP addresses will take a long time.
> there is the possiblity to speed this process significantly up via
> 'ipset restore' whereby the format from 'ipset save' can be used which
> looks like this (if no counters has been set) -->
> 
> ...
> add ipset_setname 11.22.33.44 -exist
> add ipset_setname 22.33.44.55 -exist
> ...
> 
> so if there is a vast list you can convert it e.g. via perl and pipe it
> to 'ipset restore’.

Ah, that is what I was looking for.

> Example:
> IP list called 'vast_list' is formatted one per line
> 
> ...
> 11.22.33.44
> 22.33.44.55
> ...
> 
> can be formatted and restored with a
> 
> perl -pe 'chomp; $_ = "add ipset_setname $_ -exist\n"' vast_list | ipset restore
> 
> Just as a little gimmick :-).

You can also do this without perl:

xargs printf — “add ipset_setname %s -exist\n” | ipset restore

It is quite expensive to launch the perl interpreter and this solution should be a little bit more lightweight. It has become a little bit of a sport now to have minimal bash snippets :)

Best,
-Michael

> 
> 
>> 
>>> +
>>> +	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
>> 
>> -Michael
>> 
> 
> Best,
> 
> Erik
  
Peter Müller Sept. 30, 2019, 2:35 p.m. UTC | #4
Hello Michael, hello Erik,

thank you for your replies on this.

>>> I think we need to document this on the wiki before we merge this
>>> patch.
>>>
Certainly, yes. I will do so if a patch covering this is merged.

>>>
>>> Why the added whitespace? Should have been an extra patch.
>>>
All right. shellcheck complained here, and I thought this would be
a low-hanging fruit. Shall I change something like this for multiple
scripts in a patch?

Quality of our scripts in IPFire 2.x is quite poor at some points, and
since we will have do deal with it for some time, I thought improving
might be a good idea...

>>>
>>> ROOTSERVERIPS could have been an array and could have been local.
Okay.
>>>
>>> You do not need to call xargs. It is a rather expensive way to remove
>>> line breaks.
>>>Does this suit you:
> local ROOTSERVERIPS="$( awk '/\s+A\s+/ { print $4 }' ${ROOTHINTS} )"
> [...]
> for ip in "${ROOTSERVERIPS[@]}"; do
> [...]

If yes, I will hand in a second patch. If not, please give me some suggestion. :-)

>>> It is also interesting that ipset does not allow to add more IP
>>> addresses in one go. This looks like a very expensive loop for a lot
>>> of IP addresses. I think this is fine here for about a dozen
>>> addresses, but importing a blacklist of thousands or tens of
>>> thousands of IP addresses will take a long time.
>> there is the possiblity to speed this process significantly up via
>> 'ipset restore' whereby the format from 'ipset save' can be used which
>> looks like this (if no counters has been set) -->
>>
>> ...
>> add ipset_setname 11.22.33.44 -exist
>> add ipset_setname 22.33.44.55 -exist
>> ...
>>
>> so if there is a vast list you can convert it e.g. via perl and pipe it
>> to 'ipset restore’.
> 
> Ah, that is what I was looking for.
> 
>> Example:
>> IP list called 'vast_list' is formatted one per line
>>
>> ...
>> 11.22.33.44
>> 22.33.44.55
>> ...
>>
>> can be formatted and restored with a
>>
>> perl -pe 'chomp; $_ = "add ipset_setname $_ -exist\n"' vast_list | ipset restore
>>
>> Just as a little gimmick :-).
> 
> You can also do this without perl:
> 
> xargs printf — “add ipset_setname %s -exist\n” | ipset restore
> 
> It is quite expensive to launch the perl interpreter and this solution should be a little bit more lightweight. It has become a little bit of a sport now to have minimal bash snippets :)
Well, I consider processing 13 IP addresses not that problematic. How often
does one a reboot, and how much extra time will ipset need here?

This simply is not a problem. Anyway, thank you for the hints - there still
is an issue for processing some blacklists via firewall engine... :-)

Thanks, and best regards,
Peter Müller
  
ummeegge Sept. 30, 2019, 7:19 p.m. UTC | #5
Hi Michael and Peter,
just another beside one sorry for that...

On Mo, 2019-09-30 at 14:35 +0000, peter.mueller@ipfire.org wrote:
> Hello Michael, hello Erik,
> 
> thank you for your replies on this.
> 
> > > > I think we need to document this on the wiki before we merge
> > > > this
> > > > patch.
> > > > 
> 
> Certainly, yes. I will do so if a patch covering this is merged.
> 
> > > > 
> > > > Why the added whitespace? Should have been an extra patch.
> > > > 
> 
> All right. shellcheck complained here, and I thought this would be
> a low-hanging fruit. Shall I change something like this for multiple
> scripts in a patch?
> 
> Quality of our scripts in IPFire 2.x is quite poor at some points,
> and
> since we will have do deal with it for some time, I thought improving
> might be a good idea...
> 
> > > > 
> > > > ROOTSERVERIPS could have been an array and could have been
> > > > local.
> 
> Okay.
> > > > 
> > > > You do not need to call xargs. It is a rather expensive way to
> > > > remove
> > > > line breaks.
> > > > Does this suit you:
> > 
> > local ROOTSERVERIPS="$( awk '/\s+A\s+/ { print $4 }' ${ROOTHINTS}
> > )"
> > [...]
> > for ip in "${ROOTSERVERIPS[@]}"; do
> > [...]
> 
> If yes, I will hand in a second patch. If not, please give me some
> suggestion. :-)
> 
> > > > It is also interesting that ipset does not allow to add more IP
> > > > addresses in one go. This looks like a very expensive loop for
> > > > a lot
> > > > of IP addresses. I think this is fine here for about a dozen
> > > > addresses, but importing a blacklist of thousands or tens of
> > > > thousands of IP addresses will take a long time.
> > > 
> > > there is the possiblity to speed this process significantly up
> > > via
> > > 'ipset restore' whereby the format from 'ipset save' can be used
> > > which
> > > looks like this (if no counters has been set) -->
> > > 
> > > ...
> > > add ipset_setname 11.22.33.44 -exist
> > > add ipset_setname 22.33.44.55 -exist
> > > ...
> > > 
> > > so if there is a vast list you can convert it e.g. via perl and
> > > pipe it
> > > to 'ipset restore’.
> > 
> > Ah, that is what I was looking for.
> > 
> > > Example:
> > > IP list called 'vast_list' is formatted one per line
> > > 
> > > ...
> > > 11.22.33.44
> > > 22.33.44.55
> > > ...
> > > 
> > > can be formatted and restored with a
> > > 
> > > perl -pe 'chomp; $_ = "add ipset_setname $_ -exist\n"' vast_list
> > > | ipset restore
> > > 
> > > Just as a little gimmick :-).
> > 
> > You can also do this without perl:
> > 
> > xargs printf — “add ipset_setname %s -exist\n” | ipset restore
> > 
> > It is quite expensive to launch the perl interpreter and this
> > solution should be a little bit more lightweight. It has become a
> > little bit of a sport now to have minimal bash snippets :)
Did a fast test with awk, sed and Perl which looks like this:

+ perl -pe 'chomp; $_ = "add ipset_setname $_ -exist\n"' ip

real	0m0.071s
user	0m0.060s
sys	0m0.010s
+ sed -e 's/.*/add ipset_name & -exist/' ip

real	0m0.151s
user	0m0.129s
sys	0m0.012s
+ awk '{ print "add ipset_name "$0" -exist" }' ip

real	0m0.073s
user	0m0.059s
sys	0m0.014s
+ echo

++ wc -l ip
+ echo 'Number of IPs: 18985'
Number of IPs: 18985
+ exit 0

The printf command didn´t work.

> 
> Well, I consider processing 13 IP addresses not that problematic. How
> often
> does one a reboot, and how much extra time will ipset need here?
> 
> This simply is not a problem. Anyway, thank you for the hints - there
> still
> is an issue for processing some blacklists via firewall engine... :-)
Yes true, am handling some bigger lists at this time so it was a
beneath info in general so to say ;-)

> 
> Thanks, and best regards,
> Peter Müller

Best,

Erik
  

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..ff63a2ede 100644
--- a/src/initscripts/system/firewall
+++ b/src/initscripts/system/firewall
@@ -6,10 +6,11 @@ 
 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)
-IFACE=`/bin/cat /var/ipfire/red/iface 2> /dev/null | /usr/bin/tr -d '\012'`
+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
-	DEVICE=`/bin/cat /var/ipfire/red/device 2> /dev/null | /usr/bin/tr -d '\012'`
+	DEVICE=$( /bin/cat /var/ipfire/red/device 2> /dev/null | /usr/bin/tr -d '\012' )
 fi
 
 function iptables() {
@@ -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
+	ROOTSERVERIPS="$( awk '/\s+A\s+/ { print $4 }' ${ROOTHINTS} | xargs )"
+	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