JSFiddle - React, Tailwind, and code Playground
by Jak Wings
HTML
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700&output=1.css">
<body onload="go()">
<div id="container">
<p>The script on this page will attempt to find your local ip addresses, using HTML5 WebRTC, and then use that info to probe for other live hosts on your lan(s).</p>
<p>As provided it should work with Chrome and Firefox on Windows and OS X. Chromium on Linux does not work, Firefox reportedly does.</p>
<p>See this post [<a href="https://2x.io/read/security-by-obscurity">https://2x.io/read/security-by-obscurity</a>] for a discussion on potential security and privacy consequences. Clues: Fingerprinting, Router / Printer exploitation.</p>
<p>Note that reloading the page with F5 or similar tends to cause a lot of false positives. Reset the url instead.</p>
<hr>
<p>Your local ips appear to be:</p>
<div id="localips"></div>
<br/>
<p>Other boxes on your LAN possibly include (this will take some time ..):</p>
<div id="results"></div>
</container>
</body>
CSS
body {
font-family: 'Open Sans', Helvetica, Arial, FreeSans;
font-size: 12pt;
color: #666;
margin-top: 40px;
text-align: center;
}
#container {
width: auto;
display: inline-block;
max-width: 700px;
margin: 0 auto;
text-align: left;
}
JavaScript
function TaskController(numConcurrent, onDone) {
this.numConcurrent = numConcurrent;
this.onDone = onDone || function() {};
this.pending = 0;
this.queued = [];
this.checkTimer = -1;
}
TaskController.prototype.deferCheck = function() {
if (this.checkTimer != -1) return;
this.checkTimer = setTimeout((function() {
this.checkTimer = -1;
this.check();
}).bind(this), 0);
};
TaskController.prototype.check = function() {
if (this.pending < 1 && this.queued.length == 0) return this.onDone();
while (this.pending < this.numConcurrent && this.queued.length > 0) {
try {
this.pending += 1;
setTimeout((function(task) {
task((function() {
this.pending -= 1;
this.deferCheck();
}).bind(this));
}).bind(this, this.queued.shift()), 0);
}
catch (e) {
this.pending -= 1;
this.deferCheck();
}
}
};
TaskController.prototype.queue = function(task) {
this.queued.push(task);
this.deferCheck();
};
function probeIp(ip, timeout, cb) {
var start = Date.now();
var done = false;
var img = document.createElement('img');
var clean = function() {
if (!img) return;
document.body.removeChild(img);
img = null;
};
var onResult = function(success) {
if (done) return;
done = true;
clean();
cb(ip, Date.now() - start < timeout);
};
document.body.appendChild(img);
img.style.display = 'none';
img.onload = function() { onResult(true); };
img.onerror = function() { onResult(false); };
img.src = 'https://' + ip + ':' + ~~(1024+1024*Math.random()) + '/I_DO_NOT_EXIST?' + Math.random();
setTimeout(function() { if (img) img.src = ''; }, timeout + 500);
}
function probeNet(net, onHostFound, onDone) {
net = net.replace(/(\d+\.\d+\.\d+)\.\d+/, '$1.');
var timeout = 5000;
var done = false;
var found = [];
var q = new TaskController(5, onDone);
for (var i = 1; i < 256; ++i) {
q.queue((function(i, cb) {
probeIp(net + i, timeout,...