const { exec } = require('child_process'); const dgram = require('dgram'); const dnsPacket = require('dns-packet'); const HolesailClient = require('holesail-client'); const Corestore = require('corestore'); const Hyperswarm = require('hyperswarm'); 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(); const dnsCore = store.get({ name: 'dns-core' }); let holesailClient = null; const dnsServer = dgram.createSocket('udp4'); const domainToIPMap = {}; let currentIP = 2; // Start assigning IP addresses from 192.168.100.2 // Helper function to remove existing virtual interface if it already exists (for macOS and Linux) function removeExistingInterface(subnetName) { return new Promise((resolve) => { if (os.platform() === 'darwin' || os.platform() === 'linux') { exec(`sudo ifconfig ${subnetName} down`, (err) => { if (err) resolve(); else { console.log(`Removed existing virtual interface: ${subnetName}`); resolve(); } }); } else { resolve(); // No virtual interface removal needed for Windows } }); } // Helper function to create virtual interfaces (for macOS and Linux) async function createVirtualInterface(subnetName, subnetCIDR) { await removeExistingInterface(subnetName); return new Promise((resolve, reject) => { if (os.platform() === 'darwin' || os.platform() === 'linux') { const command = os.platform() === 'darwin' ? `sudo ifconfig ${subnetName} alias ${subnetCIDR}` : `sudo ip addr add ${subnetCIDR} dev ${subnetName}`; exec(command, (err, stdout, stderr) => { if (err) { console.error(`Error creating virtual interface ${subnetName}:`, stderr); reject(`Error creating virtual interface ${subnetName}: ${stderr}`); } else { console.log(`Virtual interface ${subnetName} created with CIDR ${subnetCIDR}.`); resolve(subnetCIDR); } }); } else { console.warn('Virtual interfaces are not supported on Windows. Skipping interface creation.'); resolve(subnetCIDR); // Proceed without creating a virtual interface } }); } // Updated function to create virtual interfaces dynamically, starting from 192.168.100.2 async function createInterfaceForDomain(domain) { const subnetID = currentIP; const subnetName = os.platform() === 'win32' ? '' : `lo0`; // No subnetName for Windows const subnetCIDR = `192.168.100.${subnetID}/24`; try { await createVirtualInterface(subnetName, subnetCIDR); domainToIPMap[domain] = `192.168.100.${subnetID}`; logDebug(`Assigned virtual interface IP: 192.168.100.${subnetID} for domain: ${domain}`); currentIP++; return domainToIPMap[domain]; } catch (error) { console.error(error); return null; } } // Debug log wrapper for standardized output function logDebug(info) { const timestamp = new Date().toISOString(); console.log(`[DEBUG ${timestamp}] ${info}`); } // Function to check if a port is responsive function checkPortResponsive(ip, port) { return new Promise((resolve) => { const client = new net.Socket(); client.setTimeout(2000); client.connect(port, ip, () => { client.destroy(); resolve(true); }); client.on('error', () => resolve(false)); client.on('timeout', () => { client.destroy(); resolve(false); }); }); } // Function to check public DNS using Cloudflare function checkPublicDNS(domain) { return new Promise((resolve) => { const resolver = dgram.createSocket('udp4'); const query = dnsPacket.encode({ type: 'query', id: Math.floor(Math.random() * 65535), questions: [{ type: 'A', name: domain }] }); resolver.send(query, 53, '1.1.1.1', (err) => { if (err) { logDebug(`Error forwarding DNS query to 1.1.1.1: ${err}`); return resolve(null); } }); resolver.on('message', (res) => { const response = dnsPacket.decode(res); if (response.answers.length > 0) { logDebug(`Public DNS returned records for ${domain}`); resolve(response.answers); } else { resolve(null); } resolver.close(); }); }); } // Function to start Holesail client for tunneling and use port 80 with SO_REUSEADDR function startHolesailClient(domain, hash, ip, port) { logDebug(`Starting Holesail client for domain: ${domain}, hash: ${hash}, IP: ${ip}, Port: ${port}`); const connector = setupConnector(hash); holesailClient = new HolesailClient(connector); holesailClient.connect({ port: port, address: ip, reuseAddr: true }, () => { logDebug(`Holesail client for ${domain} connected on ${ip}:${port}`); }); setTimeout(() => { logDebug(`Destroying Holesail client for ${domain}`); holesailClient.destroy(); }, 300000); } // 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(); const topic = dnsCore.discoveryKey; logDebug(`DNS Core ready, joining Hyperswarm with topic: ${topic.toString('hex')}`); swarm.join(topic, { server: true, client: true }); swarm.on('connection', (conn) => { logDebug('Peer connected, starting replication...'); dnsCore.replicate(conn); }); })(); // Function to add a domain and hash to the DNS core (P2P network) async function addDomain(domain, hash) { await dnsCore.ready(); const record = JSON.stringify({ domain, hash }); logDebug(`Adding domain ${domain} with hash ${hash} to DNS core`); await dnsCore.append(Buffer.from(record)); 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', '78b94094b5ee1e352fec1f37e9cf3780561bcaa6ef9e0678100c9283888f');