update to working
This commit is contained in:
parent
f47c46c88e
commit
9d93a11327
180
p2ns.js
180
p2ns.js
@ -1,4 +1,3 @@
|
|||||||
require('dotenv').config(); // Load environment variables
|
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const dgram = require('dgram');
|
const dgram = require('dgram');
|
||||||
const dnsPacket = require('dns-packet');
|
const dnsPacket = require('dns-packet');
|
||||||
@ -9,16 +8,11 @@ const http = require('http');
|
|||||||
const b4a = require('b4a');
|
const b4a = require('b4a');
|
||||||
const { createHash } = require('crypto');
|
const { createHash } = require('crypto');
|
||||||
const net = require('net');
|
const net = require('net');
|
||||||
|
const os = require('os');
|
||||||
|
|
||||||
// Corestore and Hyperswarm setup for P2P sync
|
// Corestore and Hyperswarm setup for P2P sync
|
||||||
const store = new Corestore('./my-storage');
|
const store = new Corestore('./my-storage');
|
||||||
const swarm = new Hyperswarm();
|
const swarm = new Hyperswarm();
|
||||||
|
|
||||||
// Option for setting a customizable masterNetwork_discoveryKey for TLD syncing
|
|
||||||
const masterNetworkDiscoveryKey = process.env.masterNetworkDiscoveryKey
|
|
||||||
? Buffer.from(process.env.masterNetworkDiscoveryKey, 'hex')
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const dnsCore = store.get({ name: 'dns-core' });
|
const dnsCore = store.get({ name: 'dns-core' });
|
||||||
|
|
||||||
let holesailClient = null;
|
let holesailClient = null;
|
||||||
@ -26,8 +20,6 @@ const dnsServer = dgram.createSocket('udp4');
|
|||||||
const domainToIPMap = {};
|
const domainToIPMap = {};
|
||||||
let currentIP = 2; // Start assigning IP addresses from 192.168.100.2
|
let currentIP = 2; // Start assigning IP addresses from 192.168.100.2
|
||||||
|
|
||||||
console.log(`Loaded masterNetworkDiscoveryKey: ${masterNetworkDiscoveryKey ? masterNetworkDiscoveryKey.toString('hex') : 'None'}`);
|
|
||||||
|
|
||||||
// Helper function to remove existing virtual interface if it already exists (for macOS)
|
// Helper function to remove existing virtual interface if it already exists (for macOS)
|
||||||
function removeExistingInterface(subnetName) {
|
function removeExistingInterface(subnetName) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@ -110,7 +102,7 @@ function checkPublicDNS(domain) {
|
|||||||
questions: [{ type: 'A', name: domain }]
|
questions: [{ type: 'A', name: domain }]
|
||||||
});
|
});
|
||||||
|
|
||||||
resolver.send(query, 53, '1.1.1.1', (err) => {
|
resolver.send(query, 53, '192.168.0.16', (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logDebug(`Error forwarding DNS query to 1.1.1.1: ${err}`);
|
logDebug(`Error forwarding DNS query to 1.1.1.1: ${err}`);
|
||||||
return resolve(null);
|
return resolve(null);
|
||||||
@ -130,45 +122,44 @@ function checkPublicDNS(domain) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeConnections = {}; // Store active connections by domain
|
|
||||||
|
|
||||||
// Function to start Holesail client for tunneling and use port 80 with SO_REUSEADDR
|
// Function to start Holesail client for tunneling and use port 80 with SO_REUSEADDR
|
||||||
function startHolesailClient(domain, hash, ip, port) {
|
function startHolesailClient(domain, hash, ip, port) {
|
||||||
logDebug(`Attempting to start/reuse Holesail client for domain: ${domain}`);
|
logDebug(`Starting Holesail client for domain: ${domain}, hash: ${hash}, IP: ${ip}, Port: ${port}`);
|
||||||
|
|
||||||
if (activeConnections[domain]) {
|
|
||||||
logDebug(`Reusing existing Holesail client for domain: ${domain} on ${ip}:${port}`);
|
|
||||||
return activeConnections[domain]; // Reuse the existing connection
|
|
||||||
}
|
|
||||||
|
|
||||||
logDebug(`Starting new Holesail client for domain: ${domain}, hash: ${hash}, IP: ${ip}, Port: ${port}`);
|
|
||||||
|
|
||||||
const connector = setupConnector(hash);
|
const connector = setupConnector(hash);
|
||||||
const holesailClient = new HolesailClient(connector);
|
holesailClient = new HolesailClient(connector);
|
||||||
|
|
||||||
holesailClient.connect({ port: port, address: ip, reuseAddr: true }, () => {
|
holesailClient.connect({ port: port, address: ip, reuseAddr: true }, () => {
|
||||||
logDebug(`Holesail client for ${domain} connected on ${ip}:${port}`);
|
logDebug(`Holesail client for ${domain} connected on ${ip}:${port}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Store the client in activeConnections
|
|
||||||
activeConnections[domain] = holesailClient;
|
|
||||||
|
|
||||||
// Set a timeout to destroy and remove from activeConnections after 5 minutes (300,000 ms)
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
logDebug(`Destroying Holesail client for domain ${domain}`);
|
logDebug(`Destroying Holesail client for ${domain}`);
|
||||||
holesailClient.destroy();
|
holesailClient.destroy();
|
||||||
delete activeConnections[domain]; // Remove the client from activeConnections
|
|
||||||
}, 300000);
|
}, 300000);
|
||||||
|
}
|
||||||
|
|
||||||
return holesailClient;
|
// Function to restart Holesail client if the port is unresponsive
|
||||||
|
async function restartHolesailClient(domain, hash, ip, port) {
|
||||||
|
const isResponsive = await checkPortResponsive(ip, port);
|
||||||
|
|
||||||
|
if (!isResponsive) {
|
||||||
|
logDebug(`Port ${port} on ${ip} is unresponsive, destroying and recreating the Holesail client`);
|
||||||
|
if (holesailClient) {
|
||||||
|
holesailClient.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
await createInterfaceForDomain(domain);
|
||||||
|
startHolesailClient(domain, hash, ip, port);
|
||||||
|
} else {
|
||||||
|
logDebug(`Port ${port} on ${ip} is responsive, using the existing connection.`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the DNS Core is ready before joining the swarm
|
// Ensure the DNS Core is ready before joining the swarm
|
||||||
(async () => {
|
(async () => {
|
||||||
await dnsCore.ready();
|
await dnsCore.ready();
|
||||||
|
const topic = dnsCore.discoveryKey;
|
||||||
// Use masterNetworkDiscoveryKey if provided; otherwise, use dnsCore.discoveryKey
|
|
||||||
const topic = masterNetworkDiscoveryKey || dnsCore.discoveryKey;
|
|
||||||
|
|
||||||
logDebug(`DNS Core ready, joining Hyperswarm with topic: ${topic.toString('hex')}`);
|
logDebug(`DNS Core ready, joining Hyperswarm with topic: ${topic.toString('hex')}`);
|
||||||
|
|
||||||
@ -190,5 +181,130 @@ async function addDomain(domain, hash) {
|
|||||||
logDebug(`Domain ${domain} added to DNS core`);
|
logDebug(`Domain ${domain} added to DNS core`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to handle long connectors (128-byte) or standard connectors (64-byte)
|
||||||
|
function setupConnector(keyInput) {
|
||||||
|
if (keyInput.length === 64) {
|
||||||
|
logDebug(`Using 64-byte connector: ${keyInput}`);
|
||||||
|
return keyInput;
|
||||||
|
} else {
|
||||||
|
logDebug(`Hashing 128-byte connector: ${keyInput}`);
|
||||||
|
const connector = createHash('sha256').update(keyInput.toString()).digest('hex');
|
||||||
|
const seed = Buffer.from(connector, 'hex');
|
||||||
|
return b4a.toString(seed, 'hex');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DNS Server Setup for listening on port 53
|
||||||
|
dnsServer.on('message', async (msg, rinfo) => {
|
||||||
|
const query = dnsPacket.decode(msg);
|
||||||
|
const domain = query.questions[0].name;
|
||||||
|
const type = query.questions[0].type;
|
||||||
|
|
||||||
|
logDebug(`DNS query received: Domain = ${domain}, Type = ${type}`);
|
||||||
|
|
||||||
|
await dnsCore.ready();
|
||||||
|
let p2pRecord = null;
|
||||||
|
|
||||||
|
for await (const data of dnsCore.createReadStream()) {
|
||||||
|
const record = JSON.parse(data.toString());
|
||||||
|
if (record.domain === domain) {
|
||||||
|
p2pRecord = record;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const publicDNSRecords = await checkPublicDNS(domain);
|
||||||
|
|
||||||
|
if (p2pRecord) {
|
||||||
|
const localIP = domainToIPMap[domain] || await createInterfaceForDomain(domain);
|
||||||
|
startHolesailClient(domain, p2pRecord.hash, localIP, 80);
|
||||||
|
|
||||||
|
const response = dnsPacket.encode({
|
||||||
|
type: 'response',
|
||||||
|
id: query.id,
|
||||||
|
questions: query.questions,
|
||||||
|
answers: [{
|
||||||
|
type: 'A',
|
||||||
|
name: domain,
|
||||||
|
ttl: 300,
|
||||||
|
data: localIP
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
dnsServer.send(response, rinfo.port, rinfo.address);
|
||||||
|
} else if (publicDNSRecords) {
|
||||||
|
const response = dnsPacket.encode({
|
||||||
|
type: 'response',
|
||||||
|
id: query.id,
|
||||||
|
questions: query.questions,
|
||||||
|
answers: publicDNSRecords
|
||||||
|
});
|
||||||
|
dnsServer.send(response, rinfo.port, rinfo.address);
|
||||||
|
} else {
|
||||||
|
logDebug(`No P2P or public DNS records found for ${domain}`);
|
||||||
|
const response = dnsPacket.encode({
|
||||||
|
type: 'response',
|
||||||
|
id: query.id,
|
||||||
|
questions: query.questions,
|
||||||
|
answers: []
|
||||||
|
});
|
||||||
|
dnsServer.send(response, rinfo.port, rinfo.address);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ensure DNS server binds to port 53 with elevated permissions (may require sudo)
|
||||||
|
dnsServer.bind(53, '0.0.0.0', (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`Failed to bind DNS server to port 53: ${err.message}`);
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
logDebug('DNS Server running on port 53, bound to 0.0.0.0');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// HTTP Server with DNS query before proxying
|
||||||
|
http.createServer(async (req, res) => {
|
||||||
|
const domain = req.url.replace("/", "");
|
||||||
|
logDebug(`HTTP request for domain: ${domain}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const localIP = domainToIPMap[domain] || await createInterfaceForDomain(domain);
|
||||||
|
|
||||||
|
if (!localIP) {
|
||||||
|
logDebug(`No DNS records for ${domain}`);
|
||||||
|
res.writeHead(404);
|
||||||
|
return res.end('Domain not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await restartHolesailClient(domain, '78b94094b5ee1e352fec1f37e9cf3780561bcaa6ef9e0678100c9283888f', localIP, 80);
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
hostname: localIP,
|
||||||
|
port: 80,
|
||||||
|
path: req.url,
|
||||||
|
method: req.method,
|
||||||
|
headers: req.headers,
|
||||||
|
};
|
||||||
|
|
||||||
|
const proxyRequest = http.request(options, (proxyRes) => {
|
||||||
|
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
||||||
|
proxyRes.pipe(res, { end: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
proxyRequest.on('error', (err) => {
|
||||||
|
logDebug(`Error proxying request for ${domain}: ${err.message}`);
|
||||||
|
res.writeHead(500);
|
||||||
|
res.end('Internal Server Error');
|
||||||
|
});
|
||||||
|
|
||||||
|
req.pipe(proxyRequest, { end: true });
|
||||||
|
} catch (err) {
|
||||||
|
logDebug(`Failed to handle request for ${domain}: ${err.message}`);
|
||||||
|
res.writeHead(500);
|
||||||
|
res.end('Internal Server Error');
|
||||||
|
}
|
||||||
|
}).listen(80, '127.0.0.1', () => {
|
||||||
|
logDebug('HTTP server running on port 80');
|
||||||
|
});
|
||||||
|
|
||||||
// Example: Add a domain to the P2P DNS system
|
// Example: Add a domain to the P2P DNS system
|
||||||
addDomain('hello.geek', '07b8b52fbbad7a89ce26ad2d8375e6a82b2e3c02f18596bddff18e9c31164b04');
|
addDomain('hello.geek', '78b94094b5ee1e352fec1f37e9cf3780561bcaa6ef9e0678100c9283888f');
|
||||||
|
Loading…
Reference in New Issue
Block a user