Pular para conteúdo

dns-server: Driver de servidor DNS Lua para nginx-module-lua

Instalação

Se você ainda não configurou a assinatura do repositório RPM, inscreva-se. Em seguida, você pode prosseguir com os seguintes passos.

CentOS/RHEL 7 ou 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

Para usar esta biblioteca Lua com NGINX, certifique-se de que o nginx-module-lua esteja instalado.

Este documento descreve o lua-resty-dns-server v0.2 lançado em 23 de julho de 2019.


Esta biblioteca Lua fornece um driver de servidor DNS para o módulo ngx_lua do NGINX:

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

Sinopse

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, "falha ao obter o socket da requisição: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local req, err = sock:receive()
            if not req then
                ngx.log(ngx.ERR, "falha ao receber: ", 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, "falha ao decodificar a requisição: ", err)

                local resp = dns:encode_response()
                local ok, err = sock:send(resp)
                if not ok then
                    ngx.log(ngx.ERR, "falha ao enviar: ", 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, "endereço da subnet: ",  subnet.address, " máscara: ", subnet.mask, " família: ", 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, "falha ao criar resposta cname: ", 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, "falha ao enviar: ", 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, "falha ao obter o socket da requisição: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local buf, err = sock:receive(2)
            if not buf then
                ngx.log(ngx.ERR, "falha ao receber: ", 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, "falha ao receber: ", 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, "falha ao decodificar a requisição dns: ", 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, "endereço da subnet: ",  subnet.address, " máscara: ", subnet.mask, " família: ", 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, "falha ao enviar: ", err)
                return
            end
            return
        }
    }
}

Métodos

new

syntax: s, err = class:new()

Cria um objeto dns.server. Retorna nil e uma string de mensagem em caso de erro.

decode_request

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

Analisa a requisição DNS.

A requisição retornada é uma tabela lua que contém alguns dos seguintes campos:

  • header: O header também é uma tabela lua que geralmente contém alguns dos seguintes campos:

    • id : O identificador atribuído pelo programa que gera qualquer tipo de consulta.
    • qr : O campo especifica se esta mensagem é uma consulta (0), ou uma resposta (1).
    • opcode : O campo especifica o tipo de consulta nesta mensagem.
    • tc : O campo especifica que esta mensagem foi truncada devido a um comprimento maior do que o permitido no canal de transmissão.
    • rd : Recursão desejada. Se RD estiver definido, ele direciona o servidor de nomes a seguir a consulta recursivamente.
    • rcode : código de resposta.
    • qdcount : O campo que especifica o número de entradas na seção de perguntas.
  • questions : Cada entrada em questions também é uma tabela lua que contém alguns dos seguintes campos:

    • qname : Um nome de domínio da consulta.
    • qtype : Especifica o tipo da consulta.
    • qclass : Especifica a classe da consulta. Geralmente o campo é IN para a Internet.

create_a_answer

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

Cria os registros A. Retorna nil ou uma string de mensagem em caso de erro. que geralmente contém alguns dos seguintes campos:

  • name

    O nome do registro de recurso. * ttl

    O valor de tempo de vida (TTL) em segundos para o registro de recurso atual. * ipv4

    O endereço IPv4.

create_aaaa_answer

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

Cria os registros AAAA. Retorna nil ou uma string de mensagem em caso de erro. que geralmente contém alguns dos seguintes campos:

  • name

    O nome do registro de recurso. * ttl

    O valor de tempo de vida (TTL) em segundos para o registro de recurso atual. * ipv6

    O endereço IPv6.

create_cname_answer

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

Cria os registros CNAME. Retorna nil ou uma string de mensagem em caso de erro. que geralmente contém alguns dos seguintes campos:

  • name

    O nome do registro de recurso. * ttl

    O valor de tempo de vida (TTL) em segundos para o registro de recurso atual. * cname

    O nome para um alias.

create_txt_answer

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

Cria os registros txt. Retorna nil ou uma string de mensagem em caso de erro. que geralmente contém alguns dos seguintes campos:

  • name

    O nome do registro de recurso. * ttl

    O valor de tempo de vida (TTL) em segundos para o registro de recurso atual. * txt

    As strings de texto.

create_ns_answer

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

Cria os registros NS. Retorna nil ou uma string de mensagem em caso de erro. que geralmente contém alguns dos seguintes campos:

  • name

    O nome do registro de recurso. * ttl

    O valor de tempo de vida (TTL) em segundos para o registro de recurso atual. * nsdname

    Especifica um host que deve ser autoritativo para a classe e domínio especificados.

create_soa_answer

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

Cria os registros SOA. Retorna nil ou uma string de mensagem em caso de erro. que geralmente contém alguns dos seguintes campos:

  • name

    O nome do registro de recurso. * ttl

    O valor de tempo de vida (TTL) em segundos para o registro de recurso atual. * mname

    O servidor de nomes que foi a fonte original ou primária de dados para esta zona. * rname

    A caixa de correio da pessoa responsável por esta zona. * serial

    O número da versão não assinado de 32 bits da cópia original da zona. * refresh

    Um intervalo de tempo de 32 bits antes que a zona deva ser atualizada. * retry

    Um intervalo de tempo de 32 bits que deve passar antes que uma atualização falhada deva ser tentada novamente. * expire

    Um valor de tempo de 32 bits que especifica o limite superior do intervalo de tempo que pode passar antes que a zona não seja mais autoritativa. * minimum

    O campo mínimo TTL não assinado de 32 bits que deve ser exportado com qualquer RR desta zona.

create_mx_answer

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

Cria os registros MX. Retorna nil ou uma string de mensagem em caso de erro. que geralmente contém alguns dos seguintes campos:

  • name

    O nome do registro de recurso. * ttl

    O valor de tempo de vida (TTL) em segundos para o registro de recurso atual. * preference

    A preferência deste intercâmbio de correio. * exchange

    O intercâmbio de correio.

create_srv_answer

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

Cria os registros SRV. Retorna nil ou uma string de mensagem em caso de erro. que geralmente contém alguns dos seguintes campos:

  • name

    O nome do registro de recurso. * ttl

    O valor de tempo de vida (TTL) em segundos para o registro de recurso atual. * priority

    A prioridade deste host alvo. * weight

    O campo de peso especifica um peso relativo para entradas com a mesma prioridade. * port

    A porta deste host alvo deste serviço. * target

    O nome de domínio do host alvo.

create_response_header

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

encode_response

syntax: resp = s:encode_response()

Codifica as respostas DNS. Retorna uma string de mensagem na resposta ou nil.

Constantes

TYPE_A

O tipo de registro de recurso A, igual ao número decimal 1.

TYPE_NS

O tipo de registro de recurso NS, igual ao número decimal 2.

TYPE_CNAME

O tipo de registro de recurso CNAME, igual ao número decimal 5.

TYPE_SOA

O tipo de registro de recurso SOA, igual ao número decimal 6.

TYPE_MX

O tipo de registro de recurso MX, igual ao número decimal 15.

TYPE_TXT

O tipo de registro de recurso TXT, igual ao número decimal 16.

TYPE_AAAA

syntax: typ = s.TYPE_AAAA

O tipo de registro de recurso AAAA, igual ao número decimal 28.

TYPE_SRV

syntax: typ = s.TYPE_SRV

O tipo de registro de recurso SRV, igual ao número decimal 33.

Veja a RFC 2782 para detalhes.

TYPE_ANY

syntax: typ = s.TYPE_ANY

O tipo de registro de recurso todos, igual ao número decimal 255.

RCODE_FORMAT_ERROR

RCODE_NOT_IMPLEMENTED

Veja Também

GitHub

Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório do GitHub para nginx-module-dns-server.