Zum Inhalt

dns: DNS-Resolver für nginx-module-lua

Installation

Wenn Sie das RPM-Repository-Abonnement noch nicht 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

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

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

Dieses Dokument beschreibt lua-resty-dns v0.23, veröffentlicht am 06. August 2023.


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

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

Diese Lua-Bibliothek nutzt die cosocket-API von ngx_lua, die ein 100% nicht blockierendes Verhalten gewährleistet.

Beachten Sie, dass mindestens ngx_lua 0.5.12 oder OpenResty 1.2.1.11 erforderlich ist.

Außerdem wird die bit-Bibliothek benötigt. Wenn Sie LuaJIT 2.0 mit ngx_lua verwenden, ist die bit-Bibliothek standardmäßig bereits verfügbar.

Beachten Sie, dass diese Bibliothek im OpenResty-Bundle gebündelt und standardmäßig aktiviert ist.

WICHTIG: Um eindeutige IDs generieren zu können, muss der Zufallszahlengenerator vor der Verwendung dieses Moduls ordnungsgemäß mit math.randomseed initialisiert werden.

Synopsis

server {
    location = /dns {
        content_by_lua_block {
            local resolver = require "resty.dns.resolver"
            local r, err = resolver:new{
                nameservers = {"8.8.8.8", {"8.8.4.4", 53} },
                retrans = 5,  -- 5 Retransmissionen bei Empfangszeitüberschreitung
                timeout = 2000,  -- 2 Sek
                no_random = true, -- immer mit dem ersten Nameserver beginnen
            }

            if not r then
                ngx.say("Fehler beim Instanziieren des Resolvers: ", err)
                return
            end

            local answers, err, tries = r:query("www.google.com", nil, {})
            if not answers then
                ngx.say("Fehler beim Abfragen des DNS-Servers: ", err)
                ngx.say("Wiederholungsprotokoll:\n  ", table.concat(tries, "\n  "))
                return
            end

            if answers.errcode then
                ngx.say("Server hat Fehlercode zurückgegeben: ", answers.errcode,
                        ": ", answers.errstr)
            end

            for i, ans in ipairs(answers) do
                ngx.say(ans.name, " ", ans.address or ans.cname,
                        " Typ:", ans.type, " Klasse:", ans.class,
                        " TTL:", ans.ttl)
            end
        }
    }
}

Methoden

new

syntax: r, err = class:new(opts)

Erstellt ein dns.resolver-Objekt. Gibt nil und eine Fehlermeldung zurück, wenn ein Fehler auftritt.

Es akzeptiert ein opts-Tabellenargument. Die folgenden Optionen werden unterstützt:

  • nameservers

    Eine Liste von Nameservern, die verwendet werden sollen. Jeder Nameserver-Eintrag kann entweder eine einzelne Hostnamen-Zeichenfolge oder eine Tabelle sein, die sowohl die Hostnamen-Zeichenfolge als auch die Portnummer enthält. Der Nameserver wird für jeden Aufruf der query-Methode durch einen einfachen Round-Robin-Algorithmus ausgewählt. Diese Option ist erforderlich. * retrans

    Die Gesamtanzahl der Übertragungen der DNS-Anfrage, wenn der Empfang einer DNS-Antwort zeitüberschreitet, gemäß der timeout-Einstellung. Standardmäßig 5 Mal. Bei dem Versuch, die Anfrage erneut zu übertragen, wird der nächste Nameserver gemäß dem Round-Robin-Algorithmus ausgewählt. * timeout

    Die Zeit in Millisekunden, die auf die Antwort für einen einzelnen Übertragungsversuch gewartet wird. Beachten Sie, dass dies ''nicht'' die maximale Gesamtwartezeit ist, bevor aufgegeben wird; die maximale Gesamtwartezeit kann durch den Ausdruck timeout x retrans berechnet werden. Die timeout-Einstellung kann auch durch Aufrufen der Methode set_timeout geändert werden. Die Standard-timeout-Einstellung beträgt 2000 Millisekunden oder 2 Sekunden. * no_recurse

    Ein boolescher Flag, das steuert, ob das "Recursion Desired" (RD)-Flag in der UDP-Anfrage deaktiviert werden soll. Standardmäßig false. * no_random

    Ein boolescher Flag, das steuert, ob der Nameserver zufällig ausgewählt werden soll, um zuerst abgefragt zu werden. Wenn true, wird immer mit dem ersten aufgeführten Nameserver begonnen. Standardmäßig false.

destroy

syntax: r:destroy()

Zerstört das dns.resolver-Objekt, indem alle intern belegten Ressourcen freigegeben werden.

query

syntax: answers, err, tries? = r:query(name, options?, tries?)

Führt eine standardmäßige DNS-Abfrage an die durch die new-Methode angegebenen Nameserver durch und gibt alle Antwortdatensätze in einer array-ähnlichen Lua-Tabelle zurück. Im Fehlerfall gibt es nil und eine Zeichenfolge zurück, die den Fehler beschreibt.

Wenn der Server einen Fehlercode ungleich Null zurückgibt, werden die Felder errcode und errstr entsprechend in der zurückgegebenen Lua-Tabelle gesetzt.

Jeder Eintrag in der zurückgegebenen answers-Tabelle ist ebenfalls eine hash-ähnliche Lua-Tabelle, die normalerweise einige der folgenden Felder enthält:

  • name

    Der Name des Ressourcendatensatzes. * type

    Der aktuelle Typ des Ressourcendatensatzes, mögliche Werte sind 1 (TYPE_A), 5 (TYPE_CNAME), 28 (TYPE_AAAA) und andere durch RFC 1035 erlaubte Werte. * address

    Die IPv4- oder IPv6-Adresse in ihrer textuellen Darstellung, wenn der Ressourcendatensatztyp entweder 1 (TYPE_A) oder 28 (TYPE_AAAA) ist. Erfolgreiche 16-Bit-Nullgruppen in IPv6-Adressen werden standardmäßig nicht komprimiert; wenn Sie dies möchten, müssen Sie stattdessen die statische Methode compress_ipv6_addr aufrufen. * section

    Die Kennung des Abschnitts, zu dem der aktuelle Antwortdatensatz gehört. Mögliche Werte sind 1 (SECTION_AN), 2 (SECTION_NS) und 3 (SECTION_AR). * cname

    Der (dekodierte) Datensatzwert für CNAME-Ressourcendatensätze. Nur vorhanden für CNAME-Datensätze. * ttl

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

    Die aktuelle Klasse des Ressourcendatensatzes, mögliche Werte sind 1 (CLASS_IN) oder andere durch RFC 1035 erlaubte Werte. * preference

    Die Präferenz ganzzahlig für MX-Ressourcendatensätze. Nur vorhanden für MX-Typ-Datensätze. * exchange

    Der Austausch-Domainname für MX-Ressourcendatensätze. Nur vorhanden für MX-Typ-Datensätze. * nsdname

    Ein Domainname, der einen Host angibt, der für die angegebene Klasse und Domain autoritativ sein sollte. Üblicherweise vorhanden für NS-Typ-Datensätze. * rdata

    Die Rohressourcendaten (RDATA) für Ressourcendatensätze, die nicht erkannt werden. * txt

    Der Datensatzwert für TXT-Datensätze. Wenn es nur eine Zeichenfolge in diesem Datensatz gibt, dann nimmt dieses Feld eine einzelne Lua-Zeichenfolge an. Andernfalls nimmt dieses Feld eine Lua-Tabelle an, die alle Zeichenfolgen enthält. * ptrdname

    Der Datensatzwert für PTR-Datensätze.

Diese Methode akzeptiert auch ein optionales options-Argument, das die folgenden Felder enthält:

  • qtype

    Der Typ der Frage. Mögliche Werte sind 1 (TYPE_A), 5 (TYPE_CNAME), 28 (TYPE_AAAA) oder andere QTYPE-Werte, die durch RFC 1035 und RFC 3596 angegeben sind. Standardmäßig 1 (TYPE_A). * authority_section

    Wenn auf einen wahren Wert gesetzt, enthält der Rückgabewert answers den Abschnitt Authority der DNS-Antwort. Standardmäßig false. * additional_section

    Wenn auf einen wahren Wert gesetzt, enthält der Rückgabewert answers den Abschnitt Additional der DNS-Antwort. Standardmäßig false.

Der optionale Parameter tries kann als leere Tabelle bereitgestellt werden und wird als drittes Ergebnis zurückgegeben. Die Tabelle wird ein Array mit der Fehlermeldung für jeden (falls vorhanden) fehlgeschlagenen Versuch sein.

Wenn es zu Datenabschneidungen kommt, wird der Resolver automatisch erneut versuchen, den aktuellen Nameserver im TCP-Transportmodus abzufragen. Alle TCP-Verbindungen sind kurzlebig.

tcp_query

syntax: answers, err = r:tcp_query(name, options?)

Genau wie die query-Methode, aber erzwingt den TCP-Transportmodus anstelle von UDP.

Alle TCP-Verbindungen sind kurzlebig.

Hier ist ein Beispiel:

    local resolver = require "resty.dns.resolver"

    local r, err = resolver:new{
        nameservers = { "8.8.8.8" }
    }
    if not r then
        ngx.say("Fehler beim Instanziieren des Resolvers: ", err)
        return
    end

    local ans, err = r:tcp_query("www.google.com", { qtype = r.TYPE_A })
    if not ans then
        ngx.say("Fehler bei der Abfrage: ", err)
        return
    end

    local cjson = require "cjson"
    ngx.say("Datensätze: ", cjson.encode(ans))

set_timeout

syntax: r:set_timeout(time)

Überschreibt die aktuelle timeout-Einstellung durch das time-Argument in Millisekunden für alle Nameserver-Peers.

compress_ipv6_addr

syntax: compressed = resty.dns.resolver.compress_ipv6_addr(address)

Komprimiert die aufeinanderfolgenden 16-Bit-Nullgruppen in der textuellen Darstellung der IPv6-Adresse.

Zum Beispiel,

    local resolver = require "resty.dns.resolver"
    local compress = resolver.compress_ipv6_addr
    local new_addr = compress("FF01:0:0:0:0:0:0:101")

ergibt FF01::101 im Rückgabewert new_addr.

expand_ipv6_addr

syntax: expanded = resty.dns.resolver.expand_ipv6_addr(address)

Erweitert die aufeinanderfolgenden 16-Bit-Nullgruppen in der textuellen Darstellung der IPv6-Adresse.

Zum Beispiel,

    local resolver = require "resty.dns.resolver"
    local expand = resolver.expand_ipv6_addr
    local new_addr = expand("FF01::101")

ergibt FF01:0:0:0:0:0:0:101 im Rückgabewert new_addr.

arpa_str

syntax: arpa_record = resty.dns.resolver.arpa_str(address)

Generiert den umgekehrten Domainnamen für PTR-Abfragen für sowohl IPv4- als auch IPv6-Adressen. Komprimierte IPv6-Adressen werden automatisch erweitert.

Zum Beispiel,

    local resolver = require "resty.dns.resolver"
    local ptr4 = resolver.arpa_str("1.2.3.4")
    local ptr6 = resolver.arpa_str("FF01::101")

ergibt 4.3.2.1.in-addr.arpa für ptr4 und 1.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.F.F.ip6.arpa für ptr6.

reverse_query

syntax: answers, err = r:reverse_query(address)

Führt eine PTR-Abfrage für sowohl IPv4- als auch IPv6-Adressen durch. Diese Funktion ist im Grunde ein Wrapper für den query-Befehl, der den arpa_str-Befehl verwendet, um die IP-Adresse im laufenden Betrieb zu konvertieren.

Konstanten

TYPE_A

Der A-Ressourcendatensatztyp, gleich der Dezimalzahl 1.

TYPE_NS

Der NS-Ressourcendatensatztyp, gleich der Dezimalzahl 2.

TYPE_CNAME

Der CNAME-Ressourcendatensatztyp, gleich der Dezimalzahl 5.

TYPE_SOA

Der SOA-Ressourcendatensatztyp, gleich der Dezimalzahl 6.

TYPE_PTR

Der PTR-Ressourcendatensatztyp, gleich der Dezimalzahl 12.

TYPE_MX

Der MX-Ressourcendatensatztyp, gleich der Dezimalzahl 15.

TYPE_TXT

Der TXT-Ressourcendatensatztyp, gleich der Dezimalzahl 16.

TYPE_AAAA

syntax: typ = r.TYPE_AAAA

Der AAAA-Ressourcendatensatztyp, gleich der Dezimalzahl 28.

TYPE_SRV

syntax: typ = r.TYPE_SRV

Der SRV-Ressourcendatensatztyp, gleich der Dezimalzahl 33.

Siehe RFC 2782 für Details.

TYPE_SPF

syntax: typ = r.TYPE_SPF

Der SPF-Ressourcendatensatztyp, gleich der Dezimalzahl 99.

Siehe RFC 4408 für Details.

CLASS_IN

syntax: class = r.CLASS_IN

Der Internet-Ressourcendatensatztyp, gleich der Dezimalzahl 1.

SECTION_AN

syntax: stype = r.SECTION_AN

Kennung des Answer-Abschnitts in der DNS-Antwort. Gleich der Dezimalzahl 1.

SECTION_NS

syntax: stype = r.SECTION_NS

Kennung des Authority-Abschnitts in der DNS-Antwort. Gleich der Dezimalzahl 2.

SECTION_AR

syntax: stype = r.SECTION_AR

Kennung des Additional-Abschnitts in der DNS-Antwort. Gleich der Dezimalzahl 3.

Automatische Fehlerprotokollierung

Standardmäßig protokolliert das zugrunde liegende ngx_lua-Modul Fehler, wenn Socket-Fehler auftreten. Wenn Sie bereits eine ordnungsgemäße Fehlerbehandlung in Ihrem eigenen Lua-Code durchführen, wird empfohlen, diese automatische Fehlerprotokollierung zu deaktivieren, indem Sie die lua_socket_log_errors-Direktive von ngx_lua deaktivieren, das heißt,

    lua_socket_log_errors off;

Einschränkungen

  • Diese Bibliothek kann nicht in Codekontexten wie set_by_lua*, log_by_lua* und header_filter_by_lua* verwendet werden, in denen die ngx_lua cosocket-API nicht verfügbar ist.
  • Die resty.dns.resolver-Objektinstanz kann nicht auf Modulebene in einer Lua-Variablen gespeichert werden, da sie dann von allen gleichzeitigen Anfragen, die vom selben NGINX-Worker-Prozess verarbeitet werden, geteilt wird (siehe https://github.com/openresty/lua-nginx-module/#data-sharing-within-an-nginx-worker) und zu schlechten Race-Conditions führen kann, wenn gleichzeitige Anfragen versuchen, dieselbe resty.dns.resolver-Instanz zu verwenden. Sie sollten immer resty.dns.resolver-Objekte in lokalen Funktionsvariablen oder in der ngx.ctx-Tabelle initiieren. Diese Orte haben alle ihre eigenen Datenkopien für jede Anfrage.

Siehe auch

GitHub

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