Created
April 19, 2021 01:12
-
-
Save christroutner/99c3749006259cb3b18541427b21f673 to your computer and use it in GitHub Desktop.
Scanning the IPFS DHT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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