mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-04 00:20:45 +00:00
dev: add TXT record verification for domain names
This commit is contained in:
@@ -42,6 +42,7 @@ const { KVStoreModule } = require("./src/modules/kvstore/KVStoreModule.js");
|
||||
const { ExternalExtrasModule } = require("./src/modules/external-extras/ExternalExtrasModule.js");
|
||||
const { FirebaseModule } = require("./src/modules/firebase/FirebaseModule.js");
|
||||
const { DomainModule } = require("./src/modules/domain/DomainModule.js");
|
||||
const { DNSModule } = require("./src/modules/dns/DNSModule.js");
|
||||
|
||||
module.exports = {
|
||||
helloworld: () => {
|
||||
@@ -82,6 +83,8 @@ module.exports = {
|
||||
InternetModule,
|
||||
CaptchaModule,
|
||||
KVStoreModule,
|
||||
FirebaseModule,
|
||||
DNSModule,
|
||||
|
||||
// Development modules
|
||||
PerfMonModule,
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"convertapi": "^1.15.0",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"dedent": "^1.5.3",
|
||||
"dns2": "^2.1.0",
|
||||
"express": "^4.18.2",
|
||||
"file-type": "^18.5.0",
|
||||
"firebase-admin": "^13.3.0",
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
const { AdvancedBase } = require("@heyputer/putility");
|
||||
|
||||
class DNSModule extends AdvancedBase {
|
||||
async install (context) {
|
||||
const services = context.get('services');
|
||||
|
||||
const { DNSService } = require('./DNSService');
|
||||
services.registerService('dns', DNSService);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
DNSModule,
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
const BaseService = require("../../services/BaseService");
|
||||
const { sleep } = require("../../util/asyncutil");
|
||||
|
||||
class DNSService extends BaseService {
|
||||
async _init () {
|
||||
const dns2 = require('dns2');
|
||||
// this.dns = new dns2(this.config.client);
|
||||
this.dns = new dns2({
|
||||
nameServers: ['127.0.0.1'],
|
||||
port: 5300,
|
||||
});
|
||||
|
||||
if ( this.config.test_server ) {
|
||||
this.test_server_();
|
||||
}
|
||||
}
|
||||
|
||||
get_client () {
|
||||
return this.dns;
|
||||
}
|
||||
|
||||
test_server_ () {
|
||||
const dns2 = require('dns2');
|
||||
const { Packet } = dns2
|
||||
|
||||
const server = dns2.createServer({
|
||||
udp: true,
|
||||
handle: (request, send, rinfo) => {
|
||||
const { questions } = request;
|
||||
const response = Packet.createResponseFromRequest(request);
|
||||
for (const question of questions) {
|
||||
if (question.type === Packet.TYPE.A || question.type === Packet.TYPE.ANY) {
|
||||
response.answers.push({
|
||||
name: question.name,
|
||||
type: Packet.TYPE.A,
|
||||
class: Packet.CLASS.IN,
|
||||
ttl: 300,
|
||||
address: '127.0.0.11',
|
||||
});
|
||||
}
|
||||
|
||||
if (question.type === Packet.TYPE.TXT || question.type === Packet.TYPE.ANY) {
|
||||
response.answers.push({
|
||||
name: question.name,
|
||||
type: Packet.TYPE.TXT,
|
||||
class: Packet.CLASS.IN,
|
||||
ttl: 300,
|
||||
data: [
|
||||
JSON.stringify({ username: 'ed3' })
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
send(response);
|
||||
}
|
||||
});
|
||||
|
||||
server.on('listening', () => {
|
||||
this.log.info('Fake DNS server listening', server.addresses());
|
||||
|
||||
if ( this.config.test_server_selftest ) (async () => {
|
||||
await sleep(5000);
|
||||
{
|
||||
console.log('Trying first test')
|
||||
const result = await this.dns.resolveA('test.local');
|
||||
console.log('Test 1', result);
|
||||
}
|
||||
{
|
||||
console.log('Trying second test')
|
||||
const result = await this.dns.resolve(`_puter-verify.test.local`, 'TXT');
|
||||
console.log('Test 2', result);
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
server.on('close', () => {
|
||||
console.log('Fake DNS server closed');
|
||||
this.log.noticeme('Fake DNS server closed');
|
||||
})
|
||||
|
||||
server.on('request', (request, response, rinfo) => {
|
||||
console.log(request.header.id, request.questions[0]);
|
||||
});
|
||||
|
||||
server.on('requestError', (error) => {
|
||||
console.log('Client sent an invalid request', error);
|
||||
});
|
||||
|
||||
|
||||
server.listen({
|
||||
udp: {
|
||||
port: 5300,
|
||||
address: "127.0.0.1",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { DNSService };
|
||||
@@ -2,6 +2,9 @@ const { get_user } = require("../../helpers");
|
||||
const BaseService = require("../../services/BaseService");
|
||||
|
||||
class DomainVerificationService extends BaseService {
|
||||
_init () {
|
||||
this._register_commands();
|
||||
}
|
||||
async get_controlling_user ({ domain }) {
|
||||
const svc_event = this.services.get('event');
|
||||
|
||||
@@ -19,6 +22,20 @@ class DomainVerificationService extends BaseService {
|
||||
// controlling user.
|
||||
return await get_user({ username: 'admin' });
|
||||
}
|
||||
|
||||
_register_commands (commands) {
|
||||
const svc_commands = this.services.get('commands');
|
||||
svc_commands.registerCommands('domain', [
|
||||
{
|
||||
id: 'user',
|
||||
description: '',
|
||||
handler: async (args, log) => {
|
||||
const res = await this.get_controlling_user({ domain: args[0] });
|
||||
log.log(res);
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
const { get_user } = require("../../helpers");
|
||||
const BaseService = require("../../services/BaseService");
|
||||
const { atimeout } = require("../../util/asyncutil");
|
||||
|
||||
class TXTVerifyService extends BaseService {
|
||||
async _init () {
|
||||
const require = this.require;
|
||||
const dns = require('dns').promises;
|
||||
['__on_boot.consolidation'] () {
|
||||
const svc_dns = this.services.get('dns');
|
||||
const dns = svc_dns.get_client();
|
||||
|
||||
const svc_event = this.services.get('event');
|
||||
svc_event.on('domain.get-controlling-user', async (_, event) => {
|
||||
let records = await dns.resolveTxt(`_puter-verify.${event.domain}`);
|
||||
records = records.flat();
|
||||
|
||||
console.log('got records :: ', records);
|
||||
const record_name = `_puter-verify.${event.domain}`;
|
||||
try {
|
||||
const result = await atimeout(
|
||||
5000,
|
||||
dns.resolve(record_name, 'TXT'),
|
||||
);
|
||||
|
||||
const answer = result.answers.filter(
|
||||
a => a.name === record_name &&
|
||||
a.type === 16
|
||||
)[0];
|
||||
|
||||
const data_raw = answer.data;
|
||||
const data = JSON.parse(data_raw);
|
||||
event.user = await get_user({ username: data.username });
|
||||
} catch (e) {
|
||||
console.error('ERROR', e);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
const sleep = async ms => {
|
||||
await new Promise(rslv => setTimeout(rslv, ms));
|
||||
}
|
||||
|
||||
const atimeout = async (ms, p) => {
|
||||
return await Promise.race([
|
||||
p,
|
||||
new Promise(async (rslv, rjct) => {
|
||||
await sleep(ms);
|
||||
rjct("timeout");
|
||||
}),
|
||||
])
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
sleep,
|
||||
atimeout,
|
||||
};
|
||||
Reference in New Issue
Block a user