Zum Inhalt

dns-server: Lua DNS-Server-Treiber für nginx-module-lua

Installation

Wenn Sie noch kein RPM-Repository-Abonnement eingerichtet haben, melden Sie sich an. Dann können Sie mit den folgenden Schritten fortfahren.

CentOS/RHEL 7 oder Amazon Linux 2

yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-dns-server

CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023

dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-dns-server

Um diese Lua-Bibliothek mit NGINX zu verwenden, stellen Sie sicher, dass nginx-module-lua installiert ist.

Dieses Dokument beschreibt lua-resty-dns-server v0.2, veröffentlicht am 23. Juli 2019.


Diese Lua-Bibliothek bietet einen DNS-Server-Treiber für das ngx_lua NGINX-Modul:

https://github.com/openresty/stream-lua-nginx-module/#readme

Synopsis

stream {
    server {
        listen 53 udp;
        content_by_lua_block {
            local server = require 'resty.dns.server'
            local sock, err = ngx.req.socket()
            if not sock then
                ngx.log(ngx.ERR, "Fehler beim Abrufen des Anfrage-Sockets: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local req, err = sock:receive()
            if not req then
                ngx.log(ngx.ERR, "Fehler beim Empfangen: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local dns = server:new()
            local request, err = dns:decode_request(req)
            if not request then
                ngx.log(ngx.ERR, "Fehler beim Dekodieren der Anfrage: ", err)

                local resp = dns:encode_response()
                local ok, err = sock:send(resp)
                if not ok then
                    ngx.log(ngx.ERR, "Fehler beim Senden: ", err)
                    ngx.exit(ngx.ERROR)
                end

                return
            end

            local query = request.questions[1]
            ngx.log(ngx.DEBUG, "qname: ", query.qname, " qtype: ", query.qtype)

            local subnet = request.subnet[1]
            if subnet then
                ngx.log(ngx.DEBUG, "Subnetzadresse: ",  subnet.address, " Maske: ", subnet.mask, " Familie: ", subnet.family)
            end

            local cname = "sinacloud.com"

            if query.qtype == server.TYPE_CNAME or
                query.qtype == server.TYPE_AAAA or query.qtype == server.TYPE_A then

                local err = dns:create_cname_answer(query.qname, 600, cname)
                if err then
                    ngx.log(ngx.ERR, "Fehler beim Erstellen der CNAME-Antwort: ", err)
                    return
                end
            else
                dns:create_soa_answer("test.com", 600, "a.root-test.com", "vislee.test.com", 1515161223, 1800, 900, 604800, 86400)
            end

            local resp = dns:encode_response()
            local ok, err = sock:send(resp)
            if not ok then
                ngx.log(ngx.ERR, "Fehler beim Senden: ", err)
                return
            end
        }
    }

    server {
        listen 53;
        content_by_lua_block {
            local bit    = require 'bit'
            local lshift = bit.lshift
            local rshift = bit.rshift
            local band   = bit.band
            local byte   = string.byte
            local char   = string.char
            local server = require 'resty.dns.server'

            local sock, err = ngx.req.socket()
            if not sock then
                ngx.log(ngx.ERR, "Fehler beim Abrufen des Anfrage-Sockets: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local buf, err = sock:receive(2)
            if not buf then
                ngx.log(ngx.ERR, "Fehler beim Empfangen: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local len_hi = byte(buf, 1)
            local len_lo = byte(buf, 2)
            local len = lshift(len_hi, 8) + len_lo
            local data, err = sock:receive(len)
            if not data then
                ngx.log(ngx.ERR, "Fehler beim Empfangen: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local dns = server:new()
            local request, err = dns:decode_request(data)
            if not request then
                ngx.log(ngx.ERR, "Fehler beim Dekodieren der DNS-Anfrage: ", err)
                return
            end

            local query = request.questions[1]
            ngx.log(ngx.DEBUG, "qname: ", query.qname, " qtype: ", query.qtype)

            local subnet = request.subnet[1]
            if subnet then
                ngx.log(ngx.DEBUG, "Subnetzadresse: ",  subnet.address, " Maske: ", subnet.mask, " Familie: ", subnet.family)
            end

            if query.qtype == server.TYPE_CNAME or query.qtype == server.TYPE_A then
                dns:create_cname_answer(query.qname, 600, "sinacloud.com")
            elseif query.qtype == server.TYPE_AAAA then
                local resp_header, err = dns:create_response_header(server.RCODE_NOT_IMPLEMENTED)
                resp_header.ra = 0
            else
                dns:create_soa_answer("test.com", 600, "a.root-test.com", "vislee.test.com", 1515161223, 1800, 900, 604800, 86400)
            end

            local resp = dns:encode_response()
            local len = #resp
            local len_hi = char(rshift(len, 8))
            local len_lo = char(band(len, 0xff))

            local ok, err = sock:send({len_hi, len_lo, resp})
            if not ok then
                ngx.log(ngx.ERR, "Fehler beim Senden: ", err)
                return
            end
            return
        }
    }
}

Methoden

new

syntax: s, err = class:new()

Erstellt ein dns.server-Objekt. Gibt nil und eine Fehlermeldung im Fehlerfall zurück.

decode_request

syntax: request, err = s:decode_request(buf)

Analysiert die DNS-Anfrage.

Die zurückgegebene Anfrage ist eine Lua-Tabelle, die einige der folgenden Felder enthält:

  • header: Der header ist ebenfalls eine Lua-Tabelle, die normalerweise einige der folgenden Felder enthält:

    • id : Die Kennung, die vom Programm zugewiesen wird, das eine Art von Anfrage generiert.
    • qr : Das Feld gibt an, ob diese Nachricht eine Anfrage (0) oder eine Antwort (1) ist.
    • opcode : Das Feld gibt die Art der Anfrage in dieser Nachricht an.
    • tc : Das Feld gibt an, dass diese Nachricht aufgrund einer Länge, die die auf dem Übertragungskanal zulässige Länge überschreitet, gekürzt wurde.
    • rd : Rekursion gewünscht. Wenn RD gesetzt ist, weist es den Nameserver an, die Anfrage rekursiv zu verfolgen.
    • rcode : Antwortcode.
    • qdcount : Das Feld, das die Anzahl der Einträge im Fragenabschnitt angibt.
  • questions : Jeder Eintrag in den questions ist ebenfalls eine Lua-Tabelle, die einige der folgenden Felder enthält:

    • qname : Ein Domainname der Anfrage.
    • qtype : Gibt den Typ der Anfrage an.
    • qclass : Gibt die Klasse der Anfrage an. Normalerweise ist das Feld IN für das Internet.

create_a_answer

syntax: err = s:create_a_answer(name, ttl, ipv4)

Erstellt die A-Records. Gibt nil oder eine Fehlermeldung im Fehlerfall zurück. Die normalerweise einige der folgenden Felder enthält:

  • name

    Der Name des Ressourcensatzes. * ttl

    Der Time-to-Live (TTL)-Wert in Sekunden für den aktuellen Ressourcensatz. * ipv4

    Die IPv4-Adresse.

create_aaaa_answer

syntax: err = s:create_aaaa_answer(name, ttl, ipv6)

Erstellt die AAAA-Records. Gibt nil oder eine Fehlermeldung im Fehlerfall zurück. Die normalerweise einige der folgenden Felder enthält:

  • name

    Der Name des Ressourcensatzes. * ttl

    Der Time-to-Live (TTL)-Wert in Sekunden für den aktuellen Ressourcensatz. * ipv6

    Die IPv6-Adresse.

create_cname_answer

syntax: err = s:create_cname_answer(name, ttl, cname)

Erstellt die CNAME-Records. Gibt nil oder eine Fehlermeldung im Fehlerfall zurück. Die normalerweise einige der folgenden Felder enthält:

  • name

    Der Name des Ressourcensatzes. * ttl

    Der Time-to-Live (TTL)-Wert in Sekunden für den aktuellen Ressourcensatz. * cname

    Der Name für ein Alias.

create_txt_answer

syntax: err = s:create_txt_answer(name, ttl, txt)

Erstellt die TXT-Records. Gibt nil oder eine Fehlermeldung im Fehlerfall zurück. Die normalerweise einige der folgenden Felder enthält:

  • name

    Der Name des Ressourcensatzes. * ttl

    Der Time-to-Live (TTL)-Wert in Sekunden für den aktuellen Ressourcensatz. * txt

    Die Textzeichenfolgen.

create_ns_answer

syntax: err = s:create_ns_answer(name, ttl, nsdname)

Erstellt die NS-Records. Gibt nil oder eine Fehlermeldung im Fehlerfall zurück. Die normalerweise einige der folgenden Felder enthält:

  • name

    Der Name des Ressourcensatzes. * ttl

    Der Time-to-Live (TTL)-Wert in Sekunden für den aktuellen Ressourcensatz. * nsdname

    Gibt einen Host an, der für die angegebene Klasse und Domain autoritativ sein sollte.

create_soa_answer

syntax: err = s:create_soa_answer(name, ttl, mname, rname, serial, refresh, retry, expire, minimum)

Erstellt die SOA-Records. Gibt nil oder eine Fehlermeldung im Fehlerfall zurück. Die normalerweise einige der folgenden Felder enthält:

  • name

    Der Name des Ressourcensatzes. * ttl

    Der Time-to-Live (TTL)-Wert in Sekunden für den aktuellen Ressourcensatz. * mname

    Der Nameserver, der die ursprüngliche oder primäre Datenquelle für diese Zone war. * rname

    Die Mailbox der Person, die für diese Zone verantwortlich ist. * serial

    Die unsigned 32-Bit Versionsnummer der ursprünglichen Kopie der Zone. * refresh

    Ein 32-Bit Zeitintervall, bevor die Zone aktualisiert werden sollte. * retry

    Ein 32-Bit Zeitintervall, das vergehen sollte, bevor ein fehlgeschlagenes Update erneut versucht werden sollte. * expire

    Ein 32-Bit Zeitwert, der das obere Limit für das Zeitintervall angibt, das vergehen kann, bevor die Zone nicht mehr autoritativ ist. * minimum

    Das unsigned 32-Bit Minimum TTL-Feld, das mit jedem RR aus dieser Zone exportiert werden sollte.

create_mx_answer

syntax: err = s:create_mx_answer(name, ttl, preference, exchange)

Erstellt die MX-Records. Gibt nil oder eine Fehlermeldung im Fehlerfall zurück. Die normalerweise einige der folgenden Felder enthält:

  • name

    Der Name des Ressourcensatzes. * ttl

    Der Time-to-Live (TTL)-Wert in Sekunden für den aktuellen Ressourcensatz. * preference

    Die Präferenz dieses Mail-Exchange. * exchange

    Der Mail-Exchange.

create_srv_answer

syntax: err = s:create_srv_answer(name, ttl, priority, weight, port, target)

Erstellt die SRV-Records. Gibt nil oder eine Fehlermeldung im Fehlerfall zurück. Die normalerweise einige der folgenden Felder enthält:

  • name

    Der Name des Ressourcensatzes. * ttl

    Der Time-to-Live (TTL)-Wert in Sekunden für den aktuellen Ressourcensatz. * priority

    Die Priorität dieses Zielhosts. * weight

    Das Gewichtsfeld gibt ein relatives Gewicht für Einträge mit derselben Priorität an. * port

    Der Port auf diesem Zielhost für diesen Dienst. * target

    Der Domainname des Zielhosts.

create_response_header

syntax: resp_header, err = s:create_response_header(rcode)

encode_response

syntax: resp = s:encode_response()

Kodiert die DNS-Antworten. Gibt eine Fehlermeldung bei der Antwort oder nil zurück.

Konstanten

TYPE_A

Der A Ressourcensatztyp, gleich der Dezimalzahl 1.

TYPE_NS

Der NS Ressourcensatztyp, gleich der Dezimalzahl 2.

TYPE_CNAME

Der CNAME Ressourcensatztyp, gleich der Dezimalzahl 5.

TYPE_SOA

Der SOA Ressourcensatztyp, gleich der Dezimalzahl 6.

TYPE_MX

Der MX Ressourcensatztyp, gleich der Dezimalzahl 15.

TYPE_TXT

Der TXT Ressourcensatztyp, gleich der Dezimalzahl 16.

TYPE_AAAA

syntax: typ = s.TYPE_AAAA

Der AAAA Ressourcensatztyp, gleich der Dezimalzahl 28.

TYPE_SRV

syntax: typ = s.TYPE_SRV

Der SRV Ressourcensatztyp, gleich der Dezimalzahl 33.

Siehe RFC 2782 für Details.

TYPE_ANY

syntax: typ = s.TYPE_ANY

Der Typ aller Ressourcensätze, gleich der Dezimalzahl 255.

RCODE_FORMAT_ERROR

RCODE_NOT_IMPLEMENTED

Siehe auch

GitHub

Sie finden zusätzliche Konfigurationstipps und Dokumentationen für dieses Modul im GitHub-Repository für nginx-module-dns-server.