Dynamic download a list of upstream servers

knot

#1

Hi!

I would like to setup kresd to resolve certain TLD with OpenNIC while loading the list of DNS servers dynamically.
Currently I use the following bash script:

COMMAND=$(
echo -n "policy.add(policy.suffix(policy.STUB({'"
{
        curl -s "https://api.opennicproject.org/geoip/?res=2&ipv=4"
        curl -s "https://api.opennicproject.org/geoip/?res=2&ipv=6"
} | sed -e 's/^\([^ ]*\).*$/\1/' | sed -e :a -e N -e "s/\n/', '/" -e ta |tr -d '\n'
echo "'}), {todname('opennic.glue'), todname('bbs'), todname('chan'), todname('dyn'), todname('free'), todname('geek'), todname('gopher'),         todname('indy'), todname('ing'), todname('micro'), todname('neo'), todname('null'), todname('o'), todname('oss'), todname('oz'),                   todname('parody'), todname('pirate'), todname('stl'), todname('ko'), todname('ku'), todname('te'), todname('ti'), todname('uu'), todname('fur'),   todname('bit'), todname('coin'), todname('emc'), todname('lib'), todname('bazar')}))"
)
echo "$COMMAND" | socat - UNIX-CONNECT:$(ls -1 /tmp/kresd/tty/*) > /dev/null

But since kresd supports lua, I would like to do everything in its configuration.

My first approach was the following:

local https = require("ssl.https")

local OpenNIC = {}

for ip in string.gmatch(https.request("https://api.opennicproject.org/geoip/?res=2&ipv=4"), "([^ ]+)[^\n]+\n") do table.insert(OpenNIC, ip) end
for ip in string.gmatch(https.request("https://api.opennicproject.org/geoip/?res=2&ipv=6"), "([^ ]+)[^\n]+\n") do table.insert(OpenNIC, ip) end

policy.add(policy.suffix(policy.STUB(OpenNIC), {todname('opennic.glue'), todname('bbs'), todname('chan'), todname('dyn'), todname('free'), todname('geek'), todname('gopher'), todname('indy'), todname('ing'), todname('micro'), todname('neo'), todname('null'), todname('o'), todname('oss'), todname('oz'), todname('parody'), todname('pirate'), todname('stl'), todname('ko'), todname('ku'), todname('te'), todname('ti'), todname('uu'), todname('fur'), todname('bit'), todname('coin'), todname('emc'), todname('lib'), todname('bazar')}))

However, I found out that https.request fails with “temporary failure in name resolution”. It looks like kresd is doing the configuration and serve DNS requests in one thread which is blocked during lua execution. So I tried this:

worker.coroutine(function ()

local https = require("ssl.https")

local OpenNIC = {}

for ip in string.gmatch(https.request("https://api.opennicproject.org/geoip/?res=2&ipv=4"), "([^ ]+)[^\n]+\n") do table.insert(OpenNIC, ip) end
for ip in string.gmatch(https.request("https://api.opennicproject.org/geoip/?res=2&ipv=6"), "([^ ]+)[^\n]+\n") do table.insert(OpenNIC, ip) end

policy.add(policy.suffix(policy.STUB(OpenNIC), {todname('opennic.glue'), todname('bbs'), todname('chan'), todname('dyn'), todname('free'), todname('geek'), todname('gopher'), todname('indy'), todname('ing'), todname('micro'), todname('neo'), todname('null'), todname('o'), todname('oss'), todname('oz'), todname('parody'), todname('pirate'), todname('stl'), todname('ko'), todname('ku'), todname('te'), todname('ti'), todname('uu'), todname('fur'), todname('bit'), todname('coin'), todname('emc'), todname('lib'), todname('bazar')}))

end)

However this way it doesn’t seem to apply the policy for the main thread.

What would be the suggested approach?

Best regards,
Denis Shulyaka


#2

Well, yes, if you block in your configuration or module code, kresd will get blocked, as it’s single-threaded and utilizing asynchronicity heavily. It’s basically the same situation as when bootstrapping root TA; pointers to suggested solution in there, i.e. use the resolve() function to get the IP, then in its callback do the download via IP+SNI.

EDIT: but I think your “external” shell solution is simpler, really. (you can cron it)