diff --git a/dns/bind/src/opnsense/mvc/app/controllers/OPNsense/Bind/forms/general.xml b/dns/bind/src/opnsense/mvc/app/controllers/OPNsense/Bind/forms/general.xml
index 23e9c92026..89e11ab844 100644
--- a/dns/bind/src/opnsense/mvc/app/controllers/OPNsense/Bind/forms/general.xml
+++ b/dns/bind/src/opnsense/mvc/app/controllers/OPNsense/Bind/forms/general.xml
@@ -195,4 +195,26 @@
true
The base64-encoded RNDC key. This requires a restart of the Bind Service.
+
+ header
+
+
+
+ general.dotenable
+
+ checkbox
+ Accept incoming DNS-over-TLS (port 853) connections. Requires BIND 9.18+ and a valid certificate. The same listen addresses used for plain DNS are also used for DoT.
+
+
+ general.dotport
+
+ text
+ Port to listen on for DNS-over-TLS connections. Default is 853.
+
+
+ general.dotcertificate
+
+ dropdown
+ TLS certificate to present to DNS-over-TLS clients. Select a certificate from System > Trust > Certificates.
+
diff --git a/dns/bind/src/opnsense/mvc/app/models/OPNsense/Bind/General.xml b/dns/bind/src/opnsense/mvc/app/models/OPNsense/Bind/General.xml
index 238c9dc248..201ad79d4d 100644
--- a/dns/bind/src/opnsense/mvc/app/models/OPNsense/Bind/General.xml
+++ b/dns/bind/src/opnsense/mvc/app/models/OPNsense/Bind/General.xml
@@ -1,7 +1,7 @@
//OPNsense/bind/general
BIND configuration
- 1.0.12
+ 1.0.13
0
@@ -167,5 +167,17 @@
Y
VxtIzJevSQXqnr7h2qerrcwjnZlMWSGGFBndKeNIDfw=
+
+ 0
+ Y
+
+
+ 853
+ Y
+
+
+ N
+ Please select a valid certificate for DNS over TLS.
+
diff --git a/dns/bind/src/opnsense/scripts/OPNsense/Bind/generate_certs.php b/dns/bind/src/opnsense/scripts/OPNsense/Bind/generate_certs.php
new file mode 100644
index 0000000000..df76502b91
--- /dev/null
+++ b/dns/bind/src/opnsense/scripts/OPNsense/Bind/generate_certs.php
@@ -0,0 +1,69 @@
+#!/usr/local/bin/php
+object();
+$general = $cfg->OPNsense->bind->general ?? new \stdClass();
+
+$dotenable = (string)($general->dotenable ?? '0');
+$certref = (string)($general->dotcertificate ?? '');
+
+if ($dotenable === '1' && $certref !== '') {
+ $cert = Store::getCertificate($certref);
+ if ($cert && isset($cert['prv'])) {
+ File::file_update_contents($certfile, $cert['crt'], 0640);
+ File::file_update_contents($keyfile, $cert['prv'], 0640);
+ chown($certfile, 'bind');
+ chgrp($certfile, 'bind');
+ chown($keyfile, 'bind');
+ chgrp($keyfile, 'bind');
+ exit(0);
+ }
+}
+
+foreach ([$certfile, $keyfile] as $f) {
+ if (file_exists($f)) {
+ unlink($f);
+ }
+}
diff --git a/dns/bind/src/opnsense/service/conf/actions.d/actions_bind.conf b/dns/bind/src/opnsense/service/conf/actions.d/actions_bind.conf
index c3d4a47a5e..ff9f2e7f7f 100644
--- a/dns/bind/src/opnsense/service/conf/actions.d/actions_bind.conf
+++ b/dns/bind/src/opnsense/service/conf/actions.d/actions_bind.conf
@@ -1,5 +1,12 @@
+[certsetup]
+command:/usr/local/bin/php /usr/local/opnsense/scripts/OPNsense/Bind/generate_certs.php
+parameters:
+type:script
+message:setting up BIND TLS certificates
+description: Write BIND DoT certificate files from OPNsense trust store
+
[start]
-command:/usr/local/etc/rc.d/named start
+command:/usr/local/bin/php /usr/local/opnsense/scripts/OPNsense/Bind/generate_certs.php && /usr/local/etc/rc.d/named start
parameters:
type:script
message:starting BIND
@@ -11,7 +18,7 @@ type:script
message:stopping BIND
[restart]
-command:/usr/local/etc/rc.d/named restart
+command:/usr/local/bin/php /usr/local/opnsense/scripts/OPNsense/Bind/generate_certs.php && /usr/local/etc/rc.d/named restart
parameters:
type:script
message:restarting BIND
diff --git a/dns/bind/src/opnsense/service/templates/OPNsense/Bind/named.conf b/dns/bind/src/opnsense/service/templates/OPNsense/Bind/named.conf
index 9196b5de3e..1bcdd01297 100644
--- a/dns/bind/src/opnsense/service/templates/OPNsense/Bind/named.conf
+++ b/dns/bind/src/opnsense/service/templates/OPNsense/Bind/named.conf
@@ -8,6 +8,13 @@ acl "{{ acl_list.name }}" { {{ acl_list.networks.replace(',', '; ') }}; };
{% endfor %}
{% endif %}
+{% if helpers.exists('OPNsense.bind.general.dotenable') and OPNsense.bind.general.dotenable == '1' %}
+tls dot-tls {
+ cert-file "/var/etc/named/dot.crt";
+ key-file "/var/etc/named/dot.key";
+};
+{% endif %}
+
options {
directory "/usr/local/etc/namedb/working";
@@ -21,6 +28,14 @@ options {
{% for listenv6 in OPNsense.bind.general.listenv6.split(',') %}
listen-on-v6 port {{ OPNsense.bind.general.port }} { {% if listenv6 == '::' %}any{% else %}{{ listenv6 }}{% endif %}; };
{% endfor %}
+{% if helpers.exists('OPNsense.bind.general.dotenable') and OPNsense.bind.general.dotenable == '1' %}
+{% for listenv4 in OPNsense.bind.general.listenv4.split(',') %}
+ listen-on port {{ OPNsense.bind.general.dotport }} tls dot-tls { {% if listenv4 == '0.0.0.0' %}any{% else %}{{ listenv4 }}{% endif %}; };
+{% endfor %}
+{% for listenv6 in OPNsense.bind.general.listenv6.split(',') %}
+ listen-on-v6 port {{ OPNsense.bind.general.dotport }} tls dot-tls { {% if listenv6 == '::' %}any{% else %}{{ listenv6 }}{% endif %}; };
+{% endfor %}
+{% endif %}
{% if helpers.exists('OPNsense.bind.general.querysource') and OPNsense.bind.general.querysource != '' %}
query-source {{ OPNsense.bind.general.querysource }};
diff --git a/security/wazuh-agent/src/opnsense/scripts/wazuh/opnsense-fw b/security/wazuh-agent/src/opnsense/scripts/wazuh/opnsense-fw
index 3eefe8154c..aff38306c6 100755
--- a/security/wazuh-agent/src/opnsense/scripts/wazuh/opnsense-fw
+++ b/security/wazuh-agent/src/opnsense/scripts/wazuh/opnsense-fw
@@ -101,7 +101,7 @@ def main(params):
try:
ipaddress.ip_address(srcip)
except ValueError:
- send_log('Unable to process even, invalid srcip (%s)' % srcip)
+ send_log('Unable to process event, invalid srcip (%s)' % srcip)
return -1
if skip_alias != '' and command == 'add':
@@ -113,16 +113,17 @@ def main(params):
if command == 'add':
# return rule id for timeout list
try:
+ unique_key = "%s-%s" % (event['parameters']['alert']['rule']['id'], srcip)
+ send_log('Sending check_keys for: %s' % unique_key)
print(json.dumps({
"version": 1,
"origin": {
"name": sys.argv[0],
- "module":"active-response"
+ "module": "active-response"
},
"command": "check_keys",
- "parameters":{
- unique_key = "%s-%s" % (event['parameters']['alert']['rule']['id'], srcip)
- "keys": [unique_key]
+ "parameters": {
+ "keys": [unique_key]
}
}))
sys.stdout.flush()
@@ -131,6 +132,7 @@ def main(params):
# When attached to stdin we're likely running inside the agent, in which case we will read a second event which
# may abort the first one.
if params.input == '/dev/stdin':
+ send_log('Waiting for manager response...')
timeout_event = None
try:
timeout_event=json.loads(read_data(params.input))
@@ -138,6 +140,7 @@ def main(params):
pass
if timeout_event:
send_log('Received : %s' % json.dumps(timeout_event))
+ send_log('Manager says: %s' % timeout_event.get('command'))
if timeout_event.get('command') == 'abort':
send_log('Aborted')
return 0