What's new

Script to query for DNSCrypt resolvers

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

Denna

Senior Member
I'm trying to create a script that:

a) Extracts DNSCrypt resolver names from all filenames beginning with "S09dnscrypt-proxy" in the /mnt/sda1/entware-ng.arm/etc/init.d directory.

b) Performs a lookup for the resolver names' ip address

c) Adds the resolver names' ip addresses to an ipset set called dnscrypt_ips

Currently, there are two S09dnscrypt-proxy files. In the future, there could be more by appending the next number to the end of the base filename "S09dnscrypt-proxy".

S09dnscrypt-proxy

S09dnscrypt-proxy1​

Step 1 - Extract the resolver name in the file "S09dnscrypt-proxy".

Each of the S09dnscrypt-proxy* files contain the following line where the resolver name to be extracted is after the "-R ".

ARGS="--local-address=127.0.0.1:40 --daemonize -R dnscrypt.eu-dk"

In this example, the resolver name is "dnscrypt.eu-dk".​

Step 2 - Lookup the resolver name and get its ip address.

Resolver names are stored in /opt/share/dnscrypt-proxy/dnscrypt-resolvers.csv. There are dozens of lines in this file, each starting with a different resolver name. Below is an example file.

https://github.com/jedisct1/dnscrypt-proxy/blob/master/dnscrypt-resolvers.csv

The column headers in this file are as follows:

Name,"Full name","Description","Location","Coordinates",URL,Version,DNSSEC validation,No logs,Namecoin,Resolver address,Provider name,Provider public key,Provider public key TXT record

In this file, the dnscrypt.eu-dk line is as follows:

The ip address to be extracted is "77.66.84.233".​

Step 3 - Add this ip address to the dnscrypt_ips ipset set.
Code:
ipset create DNSCRYPT_IPS hash:ip
ipset add dnscrypt_ips 77.66.84.233

Step 4 - Iterate for additional S09dnscrypt-proxy* files, if any.

I came up with the following partial solution.

1) Create a script with the following commands.
Code:
#!/bin/sh
#DNSCRYPT_RES1 variable = Search for the line that begins with "ARGS=" (without quotes) and print the 4th column.
export DNSCRYPT_RES1=$(awk ' /^ARGS=/ {print $4}' /mnt/sda1/entware-ng.arm/etc/init.d/S09dnscrypt-proxy | sed 's/"/,/')

... which returns

dnscrypt.eu-dk,

NOTE: This only works if the syntax of the "ARGS=" line doesn't change. I'd prefer to determine the position of the character after the string "-R " (note the space character) and extract the following consecutive characters up to the next quote OR space character.
Lookup the resolver's name in the .CSV file and extract the characters between the 10th and 11th commas.

Iterate for additional files.​
 
Last edited:
Grab the IP
Code:
/bin/grep -F "ns0.dnscrypt.is" /opt/share/dnscrypt-proxy/dnscrypt-resolvers.csv | /bin/sed "s/\([^\"]*\"\)[^\"]*\(\"[^\"]*\)/\1(he cut me)\2/g" | /usr/bin/cut -d, -f11

Now the IP will always be in the 11th column because the sed command will remove everything between the quotes. This fixes the issue with embedded commas. Not perfect, but it works.
 
Last edited:
@Fitz Mutch,

o_O

I'm reading up on the sed command and regexp.

The s command is for substituting. What does the rest do ?
Code:
sed "s/\([^\"]*\"\)[^\"]*\(\"[^\"]*\)/\1(he cut me)\2/g"
 
Last edited:
The s command is for substituting. What does the rest do ?

sed -r 's/pattern/replacement/g'

The pattern string says:
  • match a string of characters ending with a double-quote
  • then match all characters between the double-quotes and discard them
  • then match a second string of characters beginning with a double-quote until the next double-quote or end of line
The replacement string says:
  • print the first string of matched characters
  • then print an informative message to show where the discarded characters once lived
  • then print the second string of matched characters
The "g" means to replace all occurrences.

Sample output from sed command
Code:
ns0.dnscrypt.is,"he cut","he cut","he cut",,https://dnscrypt.is,1,yes,yes,no,93.95.228.87,2.dnscrypt-cert.ns0.dnscrypt.is,EE41:6A83:451C:218F:37B2:B736:78C4:999F:7DE6:89D1:31D2:7866:7C8E:A8BB:1C95:B402,pubkey.ns0.dnscrypt.is

Here's a more readable version of the command
Code:
/bin/grep -F "ns0.dnscrypt.is" /opt/share/dnscrypt-proxy/dnscrypt-resolvers.csv | /bin/sed -r 's/([^"]*")[^"]*("[^"]*)/\1he cut\2/g' | /usr/bin/cut -d, -f11
 
I found another sed command.

HOWTO: remove commas enclosed in double-quotes using the sed command
Code:
cat /opt/share/dnscrypt-proxy/dnscrypt-resolvers.csv | sed -r ':a;s/^(([^"]*,?|"[^",]*",?)*"[^",]*),/\1/;ta'

Once you get to this level of complicated sed programming, I imagine most people would have move on and program it using perl instead. However, perl is not included with the Asuswrt firmware.

Trying to understand that nested group pattern, used in the above sed command, it just makes my head explode like a watermelon.

SOURCE: https://unix.stackexchange.com/ques...een-the-quotes-only-in-a-comma-delimited-file
 
Last edited:
@Fitz Mutch,

Thanks for the detailed help !​

The resolver name "dnscrypt.eu-dk," is output to the DNSCRYPT_RES1 variable with the code below:​
Code:
#!/bin/sh
#DNSCRYPT_RES1 variable = Search for the line that begins with "ARGS=" (without quotes) and print the 4th column.
export DNSCRYPT_RES1=$(awk ' /^ARGS=/ {print $4}' /mnt/sda1/entware-ng.arm/etc/init.d/S09dnscrypt-proxy | sed 's/"/,/')

The resolver name's IP address is output with the code below:
Code:
#Search for the line that begins with "dnscrypt.eu-dk,", filters out quoted commas and prints the 11th column.
grep -F "dnscrypt.eu-dk," /opt/share/dnscrypt-proxy/dnscrypt-resolvers.csv | sed -r ':r; s/("[^",]+),([^",]*)/\1 \2/g; tr; s/"//g' | cut -f 11 -d ','

How do you use the DNSCRYPT_RES1 variable in place of the "dnscrypt.eu-dk," string with grep ?
 
Last edited:
Maybe something like this?
Code:
#!/bin/sh
INIT_SCRIPTS="/opt/etc/init.d/S09dnscrypt-proxy*"
RESOLVERS_CSV="/opt/share/dnscrypt-proxy/dnscrypt-resolvers.csv"

for script in $INIT_SCRIPTS; do
  RESOLVER=$(sed -n "s/\"$//;/^ARGS/s/^.*-R //p" $script) # pick next word after "-R"
  RESOLVER_IP=$(sed -n "/^$RESOLVER,/p" $RESOLVERS_CSV | sed -r ':r; s/("[^",]+),([^",]*)/\1 \2/g; tr; s/"//g' | cut -d, -f11)
  echo "Resolver=$RESOLVER IP=${RESOLVER_IP%:*}"
done

That should get you further along your quest. Note ipv6 resolvers would have the ipv6 address in third brackets
 
Last edited:
@redhat27,

Thanks for the detailed help. Your input is appreciated.

I'm deciphering how this syntax works.​
 
RESOLVER=$(sed -n "s/\"$//;/^ARGS/s/^.*-R //p" $script) # pick next word after "-R"
the s/\"$// removes trailing double quote, the /^ARGS/s/^.*-R //p will remove anything upto -R and the space following it on the line starting with ARGS. sed -n would only print what is remaining, which is the resolver name
RESOLVER_IP=$(sed -n "/^$RESOLVER,/p" $RESOLVERS_CSV | sed -r ':r; s/("[^",]+),([^",]*)/\1 \2/g; tr; s/"//g' | cut -d, -f11)
the first sed -n behaves like grep (could have used grep -E as well) it will print only the line on the csv that starts with the resolver name and a comma
the second part (sed -r and cut) is what you've already used before (so no explanation necessary)
echo "Resolver=$RESOLVER IP=${RESOLVER_IP%:*}"
The ${RESOLVER_IP%:*} bit is to show the ip only (some IPs have a port mentioned along with it after a colon, so dropping that in the display)
 
@redhat27,

It's taking a while to integrate this into the firewall script, but I did want to say thank you for the detailed help and explanations.

I'll post the firewall script when it's done so you'll be able to see your handiwork in action !​
 
The scripting above provides the method to extract the IP address for the S09dnscrypt-proxy file.

How would you iterate through other "S09dnscrypt-proxy" files with a number appended to the end of the filename ?

For example, S09dnscrypt-proxy1 ?
 
@redhat27,

To get the IP address added to the IP set, would the echo line be replaced with ... ?
Code:
ipset add DNSCRYPT_IPS ${RESOLVER_IP%:*}
 

Similar threads

Latest threads

Sign Up For SNBForums Daily Digest

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