From 4d6497c196845d89c57e0fe83f9bdf473714f4b5 Mon Sep 17 00:00:00 2001 From: Nicolas Dextraze Date: Sun, 28 Sep 2025 10:56:25 -0400 Subject: [PATCH] add get-exit-nodes script --- src/get-exit-nodes.js | 65 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/get-exit-nodes.js diff --git a/src/get-exit-nodes.js b/src/get-exit-nodes.js new file mode 100644 index 0000000..8278caa --- /dev/null +++ b/src/get-exit-nodes.js @@ -0,0 +1,65 @@ +const fs = require('fs'); +const path = require('path'); +const util = require('util'); +const Consensus = require('./tor/Consensus'); +const OR = require('./tor/OnionRouter'); + +const LogLevels = { + off: 0, + error: 1, + warn: 2, + info: 3, + debug: 4 +} +let logLevel = LogLevels.error; +function timestamp() { + const d = new Date().toISOString(); + return [d.slice(5, 5), d.slice(11, 8)].join(' ') +} +class Logger { + debug(...args) { + if (LogLevels.debug > logLevel) return; + const [format, ...rest] = args; + console.error(timestamp(), "D", util.format(format, ...rest)); + } + info(...args) { + if (LogLevels.info > logLevel) return; + const [format, ...rest] = args; + console.error(timestamp(), "I", util.format(format, ...rest)); + } + warn(...args) { + if (LogLevels.warn > logLevel) return; + const [format, ...rest] = args; + console.error(timestamp(), "W", util.format(format, ...rest)); + } + error(...args) { + if (LogLevels.error > logLevel) return; + const [format, ...rest] = args; + console.error(timestamp(), "E", util.format(format, ...rest)); + } +} + +(async function main(args) { + try { + const ip_only = args[0] === '--ip-only'; + const logger = new Logger(); + const home = process.env.HOME || process.env.USERPROFILE; + const app_cache_path = path.join(home, '.cache', 'mini-tor-js'); + const cached_consensus_path = path.join(app_cache_path, 'cached-consensus') + fs.mkdirSync(app_cache_path, {recursive: true}); + // Load consensus + const consensus = new Consensus(logger); + await consensus.fetch(cached_consensus_path); + consensus.set_allowed_dir_ports(80, 443); + + const routers = consensus.get_onion_routers_by_criteria({ + flags: OR.valid | OR.exit + }); + for (const router of routers) { + if (ip_only) console.log(router.ip); + else console.log(router.name, router.ip, router.dir_port, router.or_port); + } + } catch (error) { + console.error(error); + } +})(process.argv.slice(2))