Tutorial Strictly for Academic DNS-over-TLS

  • ATTENTION! As of November 1, 2020, you are not able to reply to threads 6 months after the thread is opened if there are more than 500 posts in the thread.
    Threads will not be locked, so posts may still be edited by their authors.
    Just start a new thread on the topic to post if you get an error message when trying to reply to a thread.

SomeWhereOverTheRainBow

Very Senior Member
Strictly for Academic purpose For those wanting to create their own personal DoT server. It is easy with Asuswrt-Merlin and Entware.
First step: setup a DDNS service. (side note: if you plan on using ipv6 you need a ddns service that supports it such as dynv6)
If you decide to setup with dynv6, here is an adaptation of their IP update script for use on Merlin
/jffs/scripts/dynv6.sh
Code:
#!/bin/sh -e
hostname=$1
device=$2
file=$HOME/.dynv6.addr6
[ -e $file ] && old=`cat $file`

if [ -z "$hostname" -o -z "$token" ]; then
  echo "Usage: token=<your-authentication-token> [netmask=64] $0 your-name.dynv6.net [device]"
  exit 1
fi

if [ -z "$netmask" ]; then
  netmask=128
fi

if [ -n "$device" ]; then
  device="dev $device"
fi
address=$(ip -6 addr list scope global $device | grep -v " fd" | sed -n 's/.*inet6 \([0-9a-f:]\+\).*/\1/p' | head -n 1)

if [ -e /usr/sbin/curl ]; then
  bin="curl -fsS"
elif [ -e /usr/sbin/wget ]; then
  bin="wget -O-"
else
  echo "neither curl nor wget found"
  exit 1
fi

if [ -z "$address" ]; then
  echo "no IPv6 address found"
  exit 1
fi

# address with netmask
current=$address/$netmask

if [ "$old" = "$current" ]; then
  echo "IPv6 address unchanged"
  exit
fi

# send addresses to dynv6
$bin "http://dynv6.com/api/update?hostname=$hostname&ipv6=$current&token=$token"
$bin "http://ipv4.dynv6.com/api/update?hostname=$hostname&ipv4=auto&token=$token"

# save current address
echo $current > $file
chmod 755 /jffs/scripts/dynv6.sh
You can pass it off in cru
the argument must look like

(token=##some key they give you) /jffs/scripts/dynv6.sh (DDNS address)
1606407189875.png

nano /jffs/scripts/ddns-start

Code:
#!/bin/sh
inadyn --once -f "/jffs/inadyn.conf" -e "/sbin/ddns_custom_updated 1" --continue-on-error "/sbin/ddns_custom_updated 1"
chmod 755 /jffs/scripts/ddns-start
nano /jffs/inadyn.conf

Code:
iterations = 1
provider dynv6.com {
    username = YourTokenKey
    password = n/a
    hostname = { YourHostName.dynv6.net }
}
secure-ssl = false
chmod 755 /jffs/inadyn.conf
This guide can be followed for setting up the basic nginx proxy:
Simply install nginx using opkg install nginx-extras
Instead of the nginx package specified inside the tutorial link (side note: you may have to choose the latest supported PHP package since the one in the guide is a bit dated.)
use the rest of the guide to setup your basic nginx.conf

after that is configured to your liking, simply add this script to the bottom of your nginx.conf:

Code:
load_module "/opt/lib/nginx/ngx_stream_module.so";
stream {
        server {
                listen                  *:853 ssl;
                proxy_pass              127.0.0.1:53;  #you can change this to match your router IP such as 192.168.1.1:53;
                proxy_connect_timeout   1s;
                preread_timeout         2s;
        }
#uncomment for ipv6 segment
#        server {
#                listen                  [::]:853 ssl;
#                proxy_pass              [::1]:53; #you can change this to match your LAN ipv6 address such as [IPV6address::1]:53;
#                proxy_connect_timeout   1s;
#                preread_timeout         2s;
#        }

        ssl_certificate /jffs/.le/(YOUR-DDNS-ADDRESS)/fullchain.pem;
        ssl_certificate_key /jffs/.le/(YOUR-DDNS-ADDRESS)/(YOU-DDNS-ADDRESS).key;

        ssl_session_timeout             1d;
        ssl_session_tickets             off;

        ssl_protocols                   TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers       on;

        # If you're new enough to support DoT you're new enough not to support old broken ciphers
        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;

        ssl_session_cache               shared:DoT:10m;

        log_format dot '$remote_addr\t-\t-\t[$time_local]\t$ssl_protocol\t'
            '$ssl_session_reused\t$ssl_cipher\t$ssl_server_name\t$status\t'
            '$bytes_sent\t$bytes_received';

        access_log /opt/var/log/nginx/dot.log dot;
}
You need to add a few lines to the bottom your /jffs/scripts/firewall-start

Code:
iptables -I INPUT -p tcp --dport 853 -j ACCEPT
ip6tables -I INPUT -p tcp --dport 853 -j ACCEPT #use only if you setup IPV6 with your DDNS service.
After all this is done- you can take your own DoT server for a spin simply by adding your DDNS address to your Smartphone DNS-Privacy option. Give it a test.
(#Let it be noted this is strictly for Academic)
 
Last edited:

SomeWhereOverTheRainBow

Very Senior Member
Here is an example of connection logs from connecting using smartphone
Code:
DeviceIP    -    -    [26/Nov/2020:09:16:43 -0500]    TLSv1.2    .    ECDHE-RSA-AES256-GCM-SHA384    redact.ddns.net    200    272    520
DeviceIP    -    -    [26/Nov/2020:09:18:26 -0500]    TLSv1.2    r    ECDHE-RSA-AES256-GCM-SHA384    redact.ddns.net    200    1619    1560
DeviceIP    -    -    [26/Nov/2020:09:18:52 -0500]    TLSv1.2    .    ECDHE-RSA-AES256-GCM-SHA384    redact.ddns.net    200    2408    2860
DeviceIP    -    -    [26/Nov/2020:09:28:17 -0500]    TLSv1.2    r    ECDHE-RSA-AES256-GCM-SHA384    redact.ddns.net    200    2878    3640
DeviceIP    -    -    [26/Nov/2020:09:29:04 -0500]    TLSv1.2    .    ECDHE-RSA-AES256-GCM-SHA384    redact.ddns.net    200    2472    1300
DeviceIP    -    -    [26/Nov/2020:09:37:00 -0500]    TLSv1.2    r    ECDHE-RSA-AES256-GCM-SHA384    redact.ddns.net    200    1835    1300
DeviceIP    -    -    [26/Nov/2020:09:46:09 -0500]    TLSv1.2    .    ECDHE-RSA-AES256-GCM-SHA384    redact.ddns.net    200    186    260
DeviceIP    -    -    [26/Nov/2020:09:52:37 -0500]    TLSv1.2    r    ECDHE-RSA-AES256-GCM-SHA384    redact.ddns.net    200    3025    1300
DeviceIP    -    -    [26/Nov/2020:10:11:12 -0500]    TLSv1.2    .    ECDHE-RSA-AES256-GCM-SHA384    redact.ddns.net    200    5497    3250
 

SomeWhereOverTheRainBow

Very Senior Member
For those who want Load balancing of MultipleServers and UDP fall backs. (note it can be a combination of any upstream dns servers.)

Code:
load_module "/opt/lib/nginx/ngx_stream_module.so";

#this can be used with multiple servers for load balancing. (example is with piholes...)
stream {

        upstream ipv4_servers {

                least_conn;

                server PI1ADDRESS:53;

                server PI2ADDRESS:53;

                server PI3ADDRESS:53;

                server PI4ADDRESS:53;

        }

        upstream ipv6_servers {

                least_conn;

                server [PI1IPV6]:53;

                server [PI2IPV6]:53;

                server [PI3IPV6]:53;

                server [PI4IPV6]:53;

        }

        server {

                listen                  *:853 ssl;

                proxy_pass              ipv4_servers;

                proxy_timeout           3s;

                proxy_connect_timeout   1s;

                preread_timeout         2s;

        }

        server {

                listen                  [::]:853 ssl;

                proxy_pass              ipv6_servers;

                proxy_timeout           3s;

                proxy_connect_timeout   1s;

                preread_timeout         2s;

        }

        server {

                listen                  *:53 udp;

                proxy_pass              ipv4_servers;

        }

        server {

                listen                  [::]:53 udp;

                proxy_pass              ipv6_servers;

        }

       ssl_certificate /jffs/.le/(YOUR-DDNS-ADDRESS)/fullchain.pem;

        ssl_certificate_key /jffs/.le/(YOUR-DDNS-ADDRESS)/(YOU-DDNS-ADDRESS).key;


        ssl_session_timeout             1d;

        ssl_session_tickets             off;


        ssl_protocols                   TLSv1.2 TLSv1.3;

        ssl_prefer_server_ciphers       on;


        # If you're new enough to support DoT you're new enough not to support old broken ciphers

        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;


        ssl_session_cache               shared:DoT:10m;


        log_format dot '$remote_addr\t-\t-\t[$time_local]\t$ssl_protocol\t'

            '$ssl_session_reused\t$ssl_cipher\t$ssl_server_name\t$status\t'

            '$bytes_sent\t$bytes_received';


        access_log /opt/var/log/nginx/dot.log dot;

}
 

Similar threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top