TuxInvader / nginx-dns

Sample Configuration for DNS over HTTPS (DoH/DoT gateway) and GSLB with NGINX
BSD 2-Clause "Simplified" License
194 stars 47 forks source link

Example nginx-dns-routing.conf not working after njs deprecation #15

Closed cookiemonsteruk closed 2 years ago

cookiemonsteruk commented 2 years ago

Hi. Using master, downloaded today 04/01/2022 13:34 I'm trying to setup one of the examples before making my configuration changes, but I'm struggling with the changes to njs deprecating js_include for js_import. Vanilla install of nginx-full on Ubuntu 20.04. Nginx installed from nginx repo, not Ubuntu's. I also installed from nginx: http://nginx.org/packages/mainline/ubuntu focal/nginx amd64 nginx-module-njs amd64 1.21.5+0.7.1-1~focal. Also from this repo I dowloaded the master as zip, unzipped on the server and as per instructions, copied the njs.d directory to /etc/nginx. That's the setup. Then to start from a working baseline I backed up /etc/nginx/nginx.conf and used the example /nginx-dns-master/examples/nginx-dns-routing.conf However:

root@webserv2:/etc/nginx# service nginx configtest nginx: [emerg] invalid number of arguments in "js_import" directive in /etc/nginx/nginx.conf:26 nginx: configuration file /etc/nginx/nginx.conf test failed

From the conversation here #14 I've ended up with this nginx.conf

user  nginx;
worker_processes  auto;

load_module modules/ngx_stream_js_module.so;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

stream {

  # logging
  log_format  dns   '$remote_addr [$time_local] $protocol "$dns_qname" "$upstream_pool"';
  access_log /var/log/nginx/dns-access.log dns;

  # import NJS module
  #js_import /etc/nginx/njs.d/nginx_stream.js;
  js_import /etc/nginx/njs.d/dns/dns.js

  # NJS function to get the dns_qname, requires a js_preread in the server to populate the variable from the DNS packet
 # js_set $dns_qname dns_get_qname;
  js_set $dns.qname dns.get_qname;

  # This maps the qname domain to the DNS server for routing
  map $dns_qname $upstream_pool {
    hostnames;
    *.nginx dnsmasq;
    *.k8s dnsmasq;
    default google;
  }

  # Google upstream
  upstream google {
    zone dns 64k;
    server 8.8.8.8:53;
  }

  # dnsmasq local upstream
  upstream dnsmasq {
    zone dns 64k;
    server 192.168.5.1:53;
  }

  # DNS(TCP) Serverr
  server {
    listen 53;
    js_preread dns_preread_dns_request;
    proxy_pass $upstream_pool;
  }

  # DNS(UDP) Server
  server {
    listen 53 udp;
    js_preread dns_preread_dns_request;
    proxy_responses 1;
    proxy_pass $upstream_pool;
  }

}

What other changes I need to make to get this example working again please?

cookiemonsteruk commented 2 years ago

@TuxInvader for when you can spare a moment please.

cookiemonsteruk commented 2 years ago

Spotted the errors I made. I missed a semicolon at the end of line 25 and made a typo missing a letter. With those I got the error after adding the semicolon nginx: [emerg] unknown "dns_qname" variable With the line now reading: js_set $dns.qname dns.get_qname; Now the config test if happy. Now I can start testing.

cookiemonsteruk commented 2 years ago

I was too early to close. First I had to change from worker_process auto; to 2 . I was getting failed to spawn messages. Then I got 2022/01/04 21:03:23 [error] 91486#91486: *1 js function "dns_preread_dns_request" not found while prereading client data, udp client: 192.168.5.183, server: 0.0.0.0:53 when sending a dns dig request to nginx. Call is dig www.example.com @192.168.5.56

So I thought I needed to look at what changes might be needed in that function and made some (see below) but I end up with gobs of errors 2022/01/04 21:09:06 [alert] 91486#91486: recvmsg() truncated data I am most confused how we're to use the example configs now. To reiterate I'm just using nginx-dns-routing.conf example file. I've tried both ways, putting at the top

#load_module modules/ngx_stream_js_module.so;
load_module njs.d/dns/dns.js;

and

load_module modules/ngx_stream_js_module.so;
#load_module njs.d/dns/dns.js;

and changing in the DNS TCP and UDP server blocks js_preread dns.dns_preread_dns_request;

In all cases I get those truncated data errors, both with dns. in front of dns_preread_dns_request and without. Also both cases of loading modules at the top. Clearly I'm misunderstanding the instruction, could you please point out my error?

TuxInvader commented 2 years ago

I think you want

user  nginx;
worker_processes  auto;

load_module modules/ngx_stream_js_module.so;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

stream {

  # logging
  log_format  dns   '$remote_addr [$time_local] $protocol "$dns_qname" "$upstream_pool"';
  access_log /var/log/nginx/dns-access.log dns;

  # import NJS module
  js_import /etc/nginx/njs.d/dns/dns.js

  # NJS function to get the dns_qname, requires a js_preread in the server to populate the variable from the DNS packet
  js_set $dns_qname dns.get_qname;

  # This maps the qname domain to the DNS server for routing
  map $dns_qname $upstream_pool {
    hostnames;
    *.nginx dnsmasq;
    *.k8s dnsmasq;
    default google;
  }

  # Google upstream
  upstream google {
    zone dns 64k;
    server 8.8.8.8:53;
  }

  # dnsmasq local upstream
  upstream dnsmasq {
    zone dns 64k;
    server 192.168.5.1:53;
  }

  # DNS(TCP) Serverr
  server {
    listen 53;
    js_preread dns.preread_dns_request;
    proxy_pass $upstream_pool;
  }

  # DNS(UDP) Server
  server {
    listen 53 udp;
    js_preread dns.preread_dns_request;
    proxy_responses 1;
    proxy_pass $upstream_pool;
  }

}
cookiemonsteruk commented 2 years ago

Thank you for taking the time to put it together. I'll be tryng this setup asap.

Dual-0 commented 2 years ago

Thanks @TuxInvader for your help. My setup is working again.

stream section:

stream {
    # DNS logging

    # Disable DNS logging
    access_log off;

    log_format  dns   '$remote_addr [$time_local] $protocol "$dns_qname"';
    access_log /var/log/nginx/dns-access.log dns;

    # import NJS module
    js_import /etc/nginx/njs.d/dns/dns.js;

    # NJS function to get the dns_qname, requires a js_preread in the server to populate the variable from the DNS packet
    js_set $dns_qname dns.get_qname;

    # DNS upstream pool.
    upstream dns {
        zone dns 64k;
        server 127.0.0.1:53;
    }

    # DNS(TCP) and DNS over TLS (DoT) Server
    # Terminate DoT and DNS TCP, and proxy onto standard DNS
    server {
        listen 853 ssl;
        listen [::]:853 ssl;
        include global/dot-ssl.conf;
        include global/cert.conf;
        js_preread dns.preread_dns_request;
        proxy_pass dns;
    }

    # DNS over HTTPS (gateway) Service
    # Upstream can be either DNS(TCP) or DoT. If upstream is DNS, proxy_ssl should be off.
    server {
        listen 127.0.0.1:8853;
        js_filter dns.filter_doh_request;
        proxy_pass dns;
    }
}
cookiemonsteruk commented 2 years ago

Yes @TuxInvader the config you provided has made the testconfig pass now. Much obliged.