CZ-NIC / knot-resolver

Knot Resolver - resolve DNS names like it's 2024
https://www.knot-resolver.cz/
Other
362 stars 59 forks source link

dnstap freezes service startup #111

Closed agfp closed 3 months ago

agfp commented 3 months ago

When dnstap is enabled, knot-resolver freezes on start until systemd kills it with a timeout.

Package version: 5.7.4 System: Debian GNU/Linux 12 (bookworm) Log:

Aug 01 12:26:00 homeserver.localdomain systemd[1]: Starting kresd@1.service - Knot Resolver daemon...
░░ Subject: A start job for unit kresd@1.service has begun execution
░░ Defined-By: systemd
░░ Support: https://www.debian.org/support
░░ 
░░ A start job for unit kresd@1.service has begun execution.
░░ 
░░ The job identifier is 5266.
Aug 01 12:26:00 homeserver.localdomain kresd[9641]: [dnstap] fstrm iothread destroyed
Aug 01 12:26:00 homeserver.localdomain kresd[9641]: [dnstap] opening sock file /tmp/dnstap.sock
Aug 01 12:27:30 homeserver.localdomain systemd[1]: kresd@1.service: State 'stop-sigterm' timed out. Killing.
Aug 01 12:27:30 homeserver.localdomain systemd[1]: kresd@1.service: Killing process 9641 (kresd) with signal SIGKILL.
Aug 01 12:27:30 homeserver.localdomain systemd[1]: kresd@1.service: Main process exited, code=killed, status=9/KILL

Socket reader:

admin@homeserver ~> python3 tap.py
Listening on /tmp/dnstap.sock
Connection accepted
"protobuf:dnstap.Dnstap

tap.py:

import socket
import os
import stat

# Define the path to the Dnstap socket
SOCKET_PATH = "/tmp/dnstap.sock"

def read_dnstap_socket():
    # Ensure the socket file doesn't exist before binding
    if os.path.exists(SOCKET_PATH):
        os.remove(SOCKET_PATH)

    with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
        sock.bind(SOCKET_PATH)
        sock.listen(1)

        # Set permissions to a+rw
        os.chmod(SOCKET_PATH, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH)

        print(f"Listening on {SOCKET_PATH}")

        while True:
            conn, _ = sock.accept()
            with conn:
                print("Connection accepted")
                while True:
                    data = conn.recv(4096)
                    if not data:
                        break
                    print(data.decode('utf-8', errors='ignore'))

if __name__ == "__main__":
    read_dnstap_socket()

kresd.conf:

log_level('debug')

modules = {
    dnstap = {
        socket_path = "/tmp/dnstap.sock",
        identity = "",
        version = package_version(),
        client = {
            log_queries = true,
            log_responses = true,
        },
    }
}

-- Include the blocklist configuration
policy.add(
    policy.rpz(policy.DENY_MSG('Domain blocked'),
               '/etc/knot-resolver/blocklist.rpz',
               true))

-- Forward all other queries to OpenDNS FamilyShield servers
policy.add(policy.all(
    policy.FORWARD({ '208.67.222.123', '208.67.220.123' })))

-- Listen on specific addresses/ports
net.listen({'0.0.0.0', '::'}, 53)
net.listen({'0.0.0.0', '::'}, 853, { kind = 'tls' })
net.listen({'0.0.0.0', '::'}, 443, { kind = 'doh2' })

-- TLS configuration
net.tls('REDACTED', 'REDACTED')
agfp commented 3 months ago

It works with dnstap utility