Skip to content

Instantly share code, notes, and snippets.

@christroutner
Created April 19, 2021 01:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save christroutner/99c3749006259cb3b18541427b21f673 to your computer and use it in GitHub Desktop.
Save christroutner/99c3749006259cb3b18541427b21f673 to your computer and use it in GitHub Desktop.
Scanning the IPFS DHT
/*
Scan the DHT for peers with `/wss` in their multiaddr.
The purpose of this program is to catalog the secure websockets (wss) peers
on the network that are also configured as circuit relays, so that they can
be used to strengthen network connections between web browsers.
This is a prototype program. A proof of concept. It demonstrates the approach
taken to scan the DHT.
Workflow:
- 1) Connect to 5 bootstrap peers.
- 2) use ipfs.dht.query() to get the peers 'near' those 5 boostrap peers
- 3) use ipfs.dht.findPeer() to get the multiaddrs of the candidate peers.
- 4) filter results into known valid an invalid wss peers.
- 5) Loop from step 2.
*/
const IPFS = require("ipfs");
// Local library for reading and writing to JSON files.
const JsonFiles = require('./json-files')
const jsonFiles = new JsonFiles()
// Used to bootstrap IPFS connections
const bootstrapMultiaddrs = [
"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
"/dns4/node0.preload.ipfs.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic",
"/dns4/node1.preload.ipfs.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6",
"/dns4/ipfs-service-provider.fullstackcash.nl/tcp/443/wss/ipfs/QmbyYXKbnAmMbMGo8LRBZ58jYs58anqUzY1m4jxDmhDsjd",
"/dns4/go-ipfs-wss.fullstackcash.nl/tcp/443/wss/ipfs/QmTtXA18C6sg3ji9zem4wpNyoz9m4UZT85mA2D2jx2gzEk",
];
const knownValidAddrs = [];
const knownInvalidAddrs = [];
async function startScan() {
try {
// Use DHT routing and ipfs.io delegates.
const ipfsOptions = {
config: {
Routing: {
Type: "dhtclient",
},
},
libp2p: {
config: {
dht: {
enabled: true,
clientMode: true,
},
},
},
};
const ipfs = await IPFS.create(ipfsOptions);
// Display config settings
// const config = await ipfs.config.getAll();
// console.log("config: ", config);
console.log(" ");
// Loop through list of bootstrap peers and connect to them.
for (let i = 0; i < bootstrapMultiaddrs.length; i++) {
const thisPeer = bootstrapMultiaddrs[i];
try {
await ipfs.swarm.connect(thisPeer);
console.log(`Connected to ${thisPeer}`);
} catch (err) {
console.log(`Could not connect to ${thisPeer}`);
}
}
for (let i = 0; i < 2; i++) {
console.log(`\nIteration ${i}`);
const now = new Date();
console.log(`Timestamp: ${now.toLocaleString()}`);
const peers = await ipfs.swarm.peers();
console.log(`Connected to ${peers.length} peers.\n`);
// console.log(`peers: ${JSON.stringify(peers, null, 2)}`);
const connectedPeers = peers.map((elem) => elem.peer);
// console.log('connectedPeers: ', connectedPeers)
// Loop through a max of 25 peers. Missed peers will naturally get
// interrogated in later iterations of the loop.
let loopLimit = connectedPeers.length
if(loopLimit > 25) loopLimit = 25
const candidatePeers = [];
// Loop through the known addresses
for (let j = 0; j < loopLimit; j++) {
// for (let j = 0; j < 2; j++) {
const thisAddr = connectedPeers[j];
const nearbyPeers = [];
// Find the nearby peers for current address.
try {
for await (const info of ipfs.dht.query(thisAddr)) {
// console.log(info);
nearbyPeers.push(info.id);
}
} catch (err) {
/* exit quietly */
}
// console.log(
// `Peers near ${thisAddr}: ${JSON.stringify(nearbyPeers, null, 2)}`
// )
// Loop through each nearby peer for the current address.
for (let k = 0; k < nearbyPeers.length; k++) {
const thisPeer = nearbyPeers[k];
const notInCandidateList = !candidatePeers.includes(thisPeer);
const notInKnownValid = !knownValidAddrs.includes(thisPeer);
const notInKnownInvalid = !knownInvalidAddrs.includes(thisPeer);
// Add the peer to the candidate list if it doesn't already exist in
// one of the other lists.
if (notInCandidateList && notInKnownValid && notInKnownInvalid) {
candidatePeers.push(thisPeer);
}
}
const now = new Date()
console.log(`DHT queried for ${thisAddr} at ${now.toLocaleString()}`)
}
// console.log(`Candidate Peers: ${JSON.stringify(candidatePeers, null, 2)}`)
console.log(`Scanning ${candidatePeers.length} candidates.`);
// Loop through each candidate address.
for (let j = 0; j < candidatePeers.length; j++) {
// for (let j = 0; j < 3; j++) {
const thisCandidate = candidatePeers[j];
// console.log('thisCandidate: ', thisCandidate)
const info = await ipfs.dht.findPeer(thisCandidate);
// console.log('info: ', info)
const addrs = [];
info.addrs.forEach((addr) => addrs.push(addr.toString()));
// console.log('addrs: ', addrs)
let wssFound = false;
// Loop through each multiaddr string.
for (let k = 0; k < addrs.length; k++) {
const thisAddr = addrs[k];
if (thisAddr.indexOf("wss") > -1) {
knownValidAddrs.push(thisCandidate);
wssFound = true;
console.log(`WSS peer found: ${thisCandidate}`);
break;
}
}
// Add the candidate to the known-invalid array.
if (!wssFound) {
knownInvalidAddrs.push(thisCandidate);
// console.log(`Added ${thisCandidate} to knownInvalidAddrs list`);
}
}
console.log(`Known invalid addresses: ${knownInvalidAddrs.length}`);
console.log(`Known valid addresses: ${knownValidAddrs.length}`);
await sleep(10000);
}
// Write results to the screen.
console.log(
`knownInvalidAddrs: ${JSON.stringify(knownInvalidAddrs, null, 2)}`
);
console.log(`knownValidAddrs: ${JSON.stringify(knownValidAddrs, null, 2)}`);
// Write results to the JSON files.
await jsonFiles.writeJSON(knownInvalidAddrs, 'known-invalid-addrs.json')
await jsonFiles.writeJSON(knownValidAddrs, 'known-valid-addrs.json')
} catch (err) {
console.error(err);
}
}
startScan();
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment