Skip to content

Commit

Permalink
Merge pull request #21 from NethServer/feat-7210
Browse files Browse the repository at this point in the history
Inhibit DNS service if Samba is installed

Refs NethServer/dev#7210
  • Loading branch information
DavidePrincipi authored Dec 12, 2024
2 parents b2a8304 + 843d8a3 commit 5947555
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 48 deletions.
2 changes: 1 addition & 1 deletion container/dnsmasq.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# container related configuration
keep-in-foreground
log-facility=/dev/stdout
log-facility=-
cache-size=4000

# DNS
Expand Down
2 changes: 1 addition & 1 deletion imageroot/actions/configure-module/10validate
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ if request["dhcp-server"]["enabled"]:
sys.exit(2)

if request["dns-server"]["enabled"]:
is_dns_bound = network.are_ports_53_bound()
is_dns_bound = network.are_ports_53_bound() or bool(network.get_local_samba_dcs())
# read config.json and determine if dns is used for this instance
config = json.load(open("config.json"))
is_dns_enabled = config["dns-server"]["enabled"]
Expand Down
22 changes: 2 additions & 20 deletions imageroot/actions/configure-module/20configure
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,11 @@

import json
import sys
import agent

request = json.load(sys.stdin)

# write dnsmasq configuration to easy json file, will be used by UI
open("config.json", "w").write(json.dumps(request))

# convert json to configuration file
with open("dnsmasq.d/00config.conf", "w") as file:
file.write("# This file is automatically generated by NethServer, manual changes will be lost.\n")
# write interface only if dhcp-server or dns-server are enabled
if request["dhcp-server"]["enabled"] or request["dns-server"]["enabled"]:
file.write("interface=" + request["interface"] + "\n")

# write dhcp-server configuration
if request["dhcp-server"]["enabled"]:
file.write("dhcp-range=set:default," + request["dhcp-server"]["start"] + "," + request["dhcp-server"]["end"] + "," + str(request["dhcp-server"]["lease"]) + "h\n")

# write dns-server configuration
if request["dns-server"]["enabled"]:
file.write("server=" + request["dns-server"]["primary-server"] + "\n")
if request["dns-server"]["secondary-server"] != "":
file.write("server=" + request["dns-server"]["secondary-server"] + "\n")

else:
# shut down dns server if not enabled
file.write("port=0\n")
agent.run_helper('expand-config').check_returncode()
19 changes: 3 additions & 16 deletions imageroot/actions/create-module/20default_config
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,9 @@
#

import json
import agent

config = {
"interface": "",
"dhcp-server": {
"enabled": False,
"start": "",
"end": "",
"lease": 12
},
"dns-server": {
"enabled": False,
"primary-server": "",
"secondary-server": ""
},
}

open("config.json", "w").write(json.dumps(config))
# Force the initialization of config.json for get-configuration:
agent.run_helper('expand-config').check_returncode()

open("dns-records.json", "w").write(json.dumps({"records": []}))
18 changes: 12 additions & 6 deletions imageroot/actions/get-configuration/10get
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import json
import sys

import agent
import network

config = json.load(open("config.json"))
Expand All @@ -18,10 +18,16 @@ if config["interface"] != "" and config["dhcp-server"]["start"] == "" and config
config["dhcp-server"]["start"] = str(interface["start"])
config["dhcp-server"]["end"] = str(interface["end"])

# we test if tcp/53 or udp/53 is bound to the interface
config["is_dns_bound"] = network.are_ports_53_bound()
# check if dnsmasq is enabled in the configuration, needed to determine in the UI if the DNS server was enabled and used by dnsmasq.
# the dnsmasq service is always running, we cannot state if it is enabled/active or not.
config['is_dns_enabled'] = config["dns-server"]["enabled"]
# we test if tcp/53 or udp/53 is bound to the interface, or local Samba DCs are present
local_samba_dcs = network.get_local_samba_dcs()
if len(local_samba_dcs) > 0:
config["is_dns_bound"] = True
config["is_dns_enabled"] = False
config["dns-server"]["enabled"] = False
else:
config["is_dns_bound"] = network.are_ports_53_bound()
# check if dnsmasq is enabled in the configuration, needed to determine in the UI if the DNS server was enabled and used by dnsmasq.
# the dnsmasq service is always running, we cannot state if it is enabled/active or not.
config['is_dns_enabled'] = config["dns-server"]["enabled"]

json.dump(config, sys.stdout)
59 changes: 59 additions & 0 deletions imageroot/bin/expand-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3

#
# Copyright (C) 2024 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-3.0-or-later
#

import json
import sys
import agent
import network

# Read configuration from a JSON file or initialize it.
try:
config = json.load(open("config.json"))
except FileNotFoundError:
print(agent.SD_NOTICE, "Generating a new config.json file...", file=sys.stderr)
config = {
"interface": "",
"dhcp-server": {
"enabled": False,
"start": "",
"end": "",
"lease": 12
},
"dns-server": {
"enabled": False,
"primary-server": "",
"secondary-server": ""
},
}
json.dump(config, fp=open("config.json", "w"))


# Lookup local Samba DCs. They want to bind DNS port 53 like us.
local_samba_dcs = network.get_local_samba_dcs()

# convert json to configuration file
with open("dnsmasq.d/00config.conf", "w") as file:
file.write("# This file is automatically generated by NethServer, manual changes will be lost.\n")
# write interface only if dhcp-server or dns-server are enabled
if config["dhcp-server"]["enabled"] or config["dns-server"]["enabled"]:
file.write("interface=" + config["interface"] + "\n")

# write dhcp-server configuration
if config["dhcp-server"]["enabled"]:
file.write("dhcp-range=set:default," + config["dhcp-server"]["start"] + "," + config["dhcp-server"]["end"] + "," + str(config["dhcp-server"]["lease"]) + "h\n")

# write dns-server configuration, if no local Samba DC is present
if len(local_samba_dcs) > 0:
print("Local Active Directory DC found, DNS feature is blocked.", local_samba_dcs, file=sys.stderr)
file.write("port=0\n")
elif config["dns-server"]["enabled"]:
file.write("server=" + config["dns-server"]["primary-server"] + "\n")
if config["dns-server"]["secondary-server"] != "":
file.write("server=" + config["dns-server"]["secondary-server"] + "\n")
else:
# shut down dns server if not enabled
file.write("port=0\n")
8 changes: 4 additions & 4 deletions imageroot/dnsmasq.service
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ RequiresMountsFor=%t/containers
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
EnvironmentFile=/var/lib/nethserver/%N/state/environment
Restart=on-failure
Restart=always
TimeoutStopSec=70
ExecStartPre=/bin/rm \
-f %t/%n.ctr-id
ExecStartPre=runagent -m %N reload_hosts
ExecStartPre=runagent -m %N expand-config
ExecStart=/usr/bin/podman run \
--cidfile=%t/%n.ctr-id \
--cgroups=no-conmon \
--rm \
--sdnotify=conmon \
-d \
--replace \
--name=dnsmasq \
--detach \
--replace --name=%N \
--network=host \
--cap-add=NET_ADMIN,NET_RAW \
--volume=/var/lib/nethserver/%N/state/dnsmasq.d:/etc/dnsmasq.d:Z \
Expand Down
19 changes: 19 additions & 0 deletions imageroot/events/module-added/10restart_dnsmasq
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3

#
# Copyright (C) 2024 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-3.0-or-later
#

import json
import os
import sys
import agent

data = json.load(sys.stdin)

# skip if the event comes from another node
if os.environ['NODE_ID'] != str(data['node']):
sys.exit(0)

agent.run_helper('systemctl', 'try-restart', os.getenv('MODULE_ID'))
19 changes: 19 additions & 0 deletions imageroot/events/module-removed/10restart_dnsmasq
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3

#
# Copyright (C) 2024 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-3.0-or-later
#

import json
import os
import sys
import agent

data = json.load(sys.stdin)

# skip if the event comes from another node
if os.environ['NODE_ID'] != str(data['node']):
sys.exit(0)

agent.run_helper('systemctl', 'try-restart', os.getenv('MODULE_ID'))
18 changes: 18 additions & 0 deletions imageroot/pypkg/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#

import sys
import os
import agent
import ipaddress
import json
import subprocess
Expand Down Expand Up @@ -78,3 +81,18 @@ def are_ports_53_bound(ip='127.0.0.1'):
Check if both TCP and UDP ports 53 are bound on a specific IP address.
"""
return __is_port_bound(53, 'tcp', ip) or __is_port_bound(53, 'udp', ip)

def get_local_samba_dcs():
"""
Lookup Samba modules installed on the local node. Returns an array of
Samba module IDs that were installed on the local node. Typically the
array has 1 element at most.
"""
rdb = agent.redis_connect(use_replica=True)
local_samba_dcs = []
for module_id, node_id in rdb.hgetall("cluster/module_node").items():
if node_id != os.environ["NODE_ID"]:
continue
if module_id.startswith('samba'):
local_samba_dcs.append(module_id)
return local_samba_dcs

0 comments on commit 5947555

Please sign in to comment.