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 dgram = require('dgram');
|
||||
const dnsPacket = require('dns-packet');
|
||||
@ -9,16 +8,11 @@ const http = require('http');
|
||||
const b4a = require('b4a');
|
||||
const { createHash } = require('crypto');
|
||||
const net = require('net');
|
||||
const os = require('os');
|
||||
|
||||
// Corestore and Hyperswarm setup for P2P sync
|
||||
const store = new Corestore('./my-storage');
|
||||
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' });
|
||||
|
||||
let holesailClient = null;
|
||||
@ -26,8 +20,6 @@ const dnsServer = dgram.createSocket('udp4');
|
||||
const domainToIPMap = {};
|
||||
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)
|
||||
function removeExistingInterface(subnetName) {
|
||||
return new Promise((resolve) => {
|
||||
@ -110,7 +102,7 @@ function checkPublicDNS(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) {
|
||||
logDebug(`Error forwarding DNS query to 1.1.1.1: ${err}`);
|
||||
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 startHolesailClient(domain, hash, ip, port) {
|
||||
logDebug(`Attempting to start/reuse Holesail client for domain: ${domain}`);
|
||||
|
||||
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}`);
|
||||
logDebug(`Starting Holesail client for domain: ${domain}, hash: ${hash}, IP: ${ip}, Port: ${port}`);
|
||||
|
||||
const connector = setupConnector(hash);
|
||||
const holesailClient = new HolesailClient(connector);
|
||||
holesailClient = new HolesailClient(connector);
|
||||
|
||||
holesailClient.connect({ port: port, address: ip, reuseAddr: true }, () => {
|
||||
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(() => {
|
||||
logDebug(`Destroying Holesail client for domain ${domain}`);
|
||||
logDebug(`Destroying Holesail client for ${domain}`);
|
||||
holesailClient.destroy();
|
||||
delete activeConnections[domain]; // Remove the client from activeConnections
|
||||
}, 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
|
||||
(async () => {
|
||||
await dnsCore.ready();
|
||||
|
||||
// Use masterNetworkDiscoveryKey if provided; otherwise, use dnsCore.discoveryKey
|
||||
const topic = masterNetworkDiscoveryKey || dnsCore.discoveryKey;
|
||||
const topic = dnsCore.discoveryKey;
|
||||
|
||||
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`);
|
||||
}
|
||||
|
||||
// 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
|
||||
addDomain('hello.geek', '07b8b52fbbad7a89ce26ad2d8375e6a82b2e3c02f18596bddff18e9c31164b04');
|
||||
addDomain('hello.geek', '78b94094b5ee1e352fec1f37e9cf3780561bcaa6ef9e0678100c9283888f');
|
||||
|
Loading…
Reference in New Issue
Block a user