add skynet-sponsor-key dnslink functionality

This commit is contained in:
Karol Wypchlo 2022-04-08 13:56:20 +02:00
parent 51952c88ed
commit cfe4ca0d87
No known key found for this signature in database
GPG Key ID: B515DE9EEBE241E1
2 changed files with 38 additions and 8 deletions

View File

@ -5,6 +5,7 @@ location / {
set $path $uri;
rewrite_by_lua_block {
local cjson = require("cjson")
local cache = ngx.shared.dnslink
local cache_value = cache:get(ngx.var.host)
@ -28,13 +29,23 @@ location / {
ngx.exit(ngx.status)
end
else
ngx.var.skylink = res.body
local resolved = cjson.decode(res.body)
ngx.var.skylink = resolved.skylink
if resolved.sponsor then
ngx.req.set_header("Skynet-Api-Key", resolved.sponsor)
end
local cache_ttl = 300 -- 5 minutes cache expire time
cache:set(ngx.var.host, ngx.var.skylink, cache_ttl)
cache:set(ngx.var.host, res.body, cache_ttl)
end
else
ngx.var.skylink = cache_value
local resolved = cjson.decode(cache_value)
ngx.var.skylink = resolved.skylink
if resolved.sponsor then
ngx.req.set_header("Skynet-Api-Key", resolved.sponsor)
end
end
ngx.var.skylink = require("skynet.skylink").parse(ngx.var.skylink)

View File

@ -8,12 +8,14 @@ const port = Number(process.env.DNSLINK_API_PORT) || 3100;
const server = express();
const dnslinkNamespace = "skynet-ns";
const sponsorNamespace = "skynet-sponsor-key";
const dnslinkRegExp = new RegExp(`^dnslink=/${dnslinkNamespace}/.+$`);
const sponsorRegExp = new RegExp(`^${sponsorNamespace}=[a-zA-Z0-9]+$`);
const dnslinkSkylinkRegExp = new RegExp(`^dnslink=/${dnslinkNamespace}/([a-zA-Z0-9_-]{46}|[a-z0-9]{55})`);
const hint = `valid example: dnslink=/${dnslinkNamespace}/3ACpC9Umme41zlWUgMQh1fw0sNwgWwyfDDhRQ9Sppz9hjQ`;
server.get("/dnslink/:name", async (req, res) => {
const success = (skylink) => res.send(skylink);
const success = (response) => res.json(response);
const failure = (message) => res.status(400).send(message);
if (!isValidDomain(req.params.name)) {
@ -22,7 +24,7 @@ server.get("/dnslink/:name", async (req, res) => {
const lookup = `_dnslink.${req.params.name}`;
dns.resolveTxt(lookup, (error, records) => {
dns.resolveTxt(lookup, (error, addresses) => {
if (error) {
if (error.code === "ENOTFOUND") {
return failure(`ENOTFOUND: ${lookup} TXT record doesn't exist`);
@ -35,11 +37,12 @@ server.get("/dnslink/:name", async (req, res) => {
return failure(`Failed to fetch ${lookup} TXT record: ${error.message}`);
}
if (records.length === 0) {
if (addresses.length === 0) {
return failure(`No TXT record found for ${lookup}`);
}
const dnslinks = records.flat().filter((record) => dnslinkRegExp.test(record));
const records = addresses.flat();
const dnslinks = records.filter((record) => dnslinkRegExp.test(record));
if (dnslinks.length === 0) {
return failure(`TXT records for ${lookup} found but none of them contained valid skynet dnslink - ${hint}`);
@ -58,9 +61,25 @@ server.get("/dnslink/:name", async (req, res) => {
const skylink = matchSkylink[1];
// check if _dnslink records contain skynet-sponsor-key entries
const sponsors = records.filter((record) => sponsorRegExp.test(record));
if (sponsors.length > 1) {
return failure(`Multiple TXT records with valid sponsor key found for ${lookup}, only one allowed`);
}
if (sponsors.length === 1) {
// extract just the key part from the record
const sponsor = sponsors[0].substring(sponsors[0].indexOf("=") + 1);
console.log(`${req.params.name} => ${skylink} | sponsor: ${sponsor}`);
return success({ skylink, sponsor });
}
console.log(`${req.params.name} => ${skylink}`);
return success(skylink);
return success({ skylink });
});
});