Page Menu
Home
VyOS Platform
Search
Configure Global Search
Log In
Files
F117520436
dns_forwarding.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
dns_forwarding.py
View Options
#!/usr/bin/env python3
#
# Copyright (C) 2018-2020 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import
os
from
sys
import
exit
from
copy
import
deepcopy
from
vyos.config
import
Config
from
vyos.hostsd_client
import
Client
as
hostsd_client
from
vyos
import
ConfigError
from
vyos.util
import
call
from
vyos.template
import
render
from
vyos
import
airbag
airbag
.
enable
()
pdns_rec_run_dir
=
'/run/powerdns'
pdns_rec_lua_conf_file
=
f
'{pdns_rec_run_dir}/recursor.conf.lua'
pdns_rec_hostsd_lua_conf_file
=
f
'{pdns_rec_run_dir}/recursor.vyos-hostsd.conf.lua'
pdns_rec_hostsd_zones_file
=
f
'{pdns_rec_run_dir}/recursor.forward-zones.conf'
pdns_rec_config_file
=
f
'{pdns_rec_run_dir}/recursor.conf'
default_config_data
=
{
'allow_from'
:
[],
'cache_size'
:
10000
,
'export_hosts_file'
:
'yes'
,
'listen_address'
:
[],
'name_servers'
:
[],
'negative_ttl'
:
3600
,
'system'
:
False
,
'domains'
:
{},
'dnssec'
:
'process-no-validate'
,
'dhcp_interfaces'
:
[]
}
def
get_config
(
conf
):
dns
=
deepcopy
(
default_config_data
)
base
=
[
'service'
,
'dns'
,
'forwarding'
]
if
not
conf
.
exists
(
base
):
return
None
conf
.
set_level
(
base
)
if
conf
.
exists
([
'allow-from'
]):
dns
[
'allow_from'
]
=
conf
.
return_values
([
'allow-from'
])
if
conf
.
exists
([
'cache-size'
]):
cache_size
=
conf
.
return_value
([
'cache-size'
])
dns
[
'cache_size'
]
=
cache_size
if
conf
.
exists
(
'negative-ttl'
):
negative_ttl
=
conf
.
return_value
([
'negative-ttl'
])
dns
[
'negative_ttl'
]
=
negative_ttl
if
conf
.
exists
([
'domain'
]):
for
domain
in
conf
.
list_nodes
([
'domain'
]):
conf
.
set_level
(
base
+
[
'domain'
,
domain
])
entry
=
{
'nslist'
:
bracketize_ipv6_addrs
(
conf
.
return_values
([
'server'
])),
'addNTA'
:
conf
.
exists
([
'addnta'
]),
'recursion-desired'
:
conf
.
exists
([
'recursion-desired'
])
}
dns
[
'domains'
][
domain
]
=
entry
conf
.
set_level
(
base
)
if
conf
.
exists
([
'ignore-hosts-file'
]):
dns
[
'export_hosts_file'
]
=
"no"
if
conf
.
exists
([
'name-server'
]):
dns
[
'name_servers'
]
=
bracketize_ipv6_addrs
(
conf
.
return_values
([
'name-server'
]))
if
conf
.
exists
([
'system'
]):
dns
[
'system'
]
=
True
if
conf
.
exists
([
'listen-address'
]):
dns
[
'listen_address'
]
=
conf
.
return_values
([
'listen-address'
])
if
conf
.
exists
([
'dnssec'
]):
dns
[
'dnssec'
]
=
conf
.
return_value
([
'dnssec'
])
if
conf
.
exists
([
'dhcp'
]):
dns
[
'dhcp_interfaces'
]
=
conf
.
return_values
([
'dhcp'
])
return
dns
def
bracketize_ipv6_addrs
(
addrs
):
"""Wraps each IPv6 addr in addrs in [], leaving IPv4 addrs untouched."""
return
[
'[{0}]'
.
format
(
a
)
if
a
.
count
(
':'
)
>
1
else
a
for
a
in
addrs
]
def
verify
(
conf
,
dns
):
# bail out early - looks like removal from running config
if
dns
is
None
:
return
None
if
not
dns
[
'listen_address'
]:
raise
ConfigError
(
"Error: DNS forwarding requires a listen-address"
)
if
not
dns
[
'allow_from'
]:
raise
ConfigError
(
"Error: DNS forwarding requires an allow-from network"
)
if
dns
[
'domains'
]:
for
domain
in
dns
[
'domains'
]:
if
not
dns
[
'domains'
][
domain
][
'nslist'
]:
raise
ConfigError
((
f
'Error: No server configured for domain {domain}'
))
no_system_nameservers
=
False
if
dns
[
'system'
]
and
not
(
conf
.
exists
([
'system'
,
'name-server'
])
or
conf
.
exists
([
'system'
,
'name-servers-dhcp'
])
):
no_system_nameservers
=
True
print
((
"DNS forwarding warning: No 'system name-server' or "
"'system name-servers-dhcp' set
\n
"
))
if
(
no_system_nameservers
or
not
dns
[
'system'
])
and
not
(
dns
[
'name_servers'
]
or
dns
[
'dhcp_interfaces'
]):
print
((
"DNS forwarding warning: No 'dhcp', 'name-server' or 'system' "
"nameservers set. Forwarding will operate as a recursor.
\n
"
))
return
None
def
generate
(
dns
):
# bail out early - looks like removal from running config
if
dns
is
None
:
return
None
render
(
config_file
,
'dns-forwarding/recursor.conf.tmpl'
,
dns
,
trim_blocks
=
True
,
user
=
'pdns'
,
group
=
'pdns'
)
return
None
def
apply
(
dns
):
if
dns
is
None
:
# DNS forwarding is removed in the commit
call
(
"systemctl stop pdns-recursor.service"
)
if
os
.
path
.
isfile
(
pdns_rec_config_file
):
os
.
unlink
(
pdns_rec_config_file
)
else
:
call
(
"systemctl restart pdns-recursor.service"
)
if
__name__
==
'__main__'
:
try
:
conf
=
Config
()
c
=
get_config
(
conf
)
verify
(
conf
,
c
)
generate
(
c
)
apply
(
c
)
except
ConfigError
as
e
:
print
(
e
)
exit
(
1
)
File Metadata
Details
Attached
Mime Type
text/x-script.python
Expires
Sat, Sep 26, 10:16 AM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4284922
Default Alt Text
dns_forwarding.py (5 KB)
Attached To
Mode
rVYOSONEX vyos-1x
Attached
Detach File
Event Timeline
Log In to Comment