Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 240 lines (219 sloc) 8.72 KB
<html>
<head>
<title>Local IPs</title>
<style>
body {
font-family: 'Open Sans', Helvetica, Arial, FreeSans;
font-size: 12pt;
color: #666;
margin-top: 40px;
text-align: center;
}
#container {
width: 60%;
display: inline-block;
max-width: 700px;
margin: 0 auto;
text-align: left;
padding: 0px;
}
pre {
width: 96%;
overflow-x: scroll;
background-color: #eee;
border-radius: 4px;
padding: 10px;
}
hr {
width: 98%;
}
#right-footer {
float: right;
}
#left-footer {
float: left;
}
a {
text-decoration: none;
color: #ccc;
}
a:hover {
color: #333;
}
</style>
<script>
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, function(ip, success) {
if (success) onHostFound(ip);
cb();
});
}).bind(this, i));
}
}
function enumLocalIPs(cb) {
var RTCPeerConnection = window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
if (!RTCPeerConnection) return false;
var addrs = Object.create(null);
addrs['0.0.0.0'] = false;
function addAddress(newAddr) {
if (newAddr in addrs) return;
addrs[newAddr] = true;
cb(newAddr);
}
function grepSDP(sdp) {
var hosts = [];
sdp.split('\r\n').forEach(function(line) {
if (~line.indexOf('a=candidate')) {
var parts = line.split(' '),
addr = parts[4],
type = parts[7];
if (type === 'host') addAddress(addr);
} else if (~line.indexOf('c=')) {
var parts = line.split(' '),
addr = parts[2];
addAddress(addr);
}
});
}
var rtc = new RTCPeerConnection({
iceServers: []
});
rtc.createDataChannel('', {
reliable: false
});
rtc.onicecandidate = function(evt) {
if (evt.candidate) grepSDP('a=' + evt.candidate.candidate);
};
setTimeout(function() {
rtc.createOffer(function(offerDesc) {
grepSDP(offerDesc.sdp);
rtc.setLocalDescription(offerDesc);
}, function(e) {});
}, 500);
return true;
}
function getLocalNetworkInfo() {
var q = new TaskController(1);
enumLocalIPs(function(localIp) {
document.getElementById('localips').innerHTML += localIp + '<br>';
q.queue(function(cb) {
probeNet(localIp,
function(ip) {
document.getElementById('results').innerHTML += ip + '<br>';
},
cb);
});
}) || (document.getElementById('localips').innerHTML = 'WebRTC seems not to be supported');
}
function getUserAgent() {
document.getElementById('user-agent').innerHTML = navigator.userAgent;
}
function getPublicNetworkInfo() {
fetch('https://freegeoip.net/json/').then(function (response) {
return response.json();
}).then(function (body) {
document.getElementById('public-ip').innerHTML = body.ip;
document.getElementById('location').innerHTML = body.city + ', ' + body.region_name + ', ' + body.country_name;
});
}
function go() {
getUserAgent();
getPublicNetworkInfo();
getLocalNetworkInfo();
}
</script>
</head>
<body onload="go()">
<div id="container">
<p>Your User Agent:</p>
<pre id="user-agent">Javascript must be enabled.</pre>
<p>Your Location:</p>
<pre id="location">Loading...</pre>
<p>Your Public IP:</p>
<pre id="public-ip">Loading...</pre>
<p>Your local IPs:</p>
<pre id="localips"></pre>
<p>Other devices on your LAN:</p>
<pre id="results"></pre>
<hr/>
<span id="left-footer">
<a href="https://hacking.ventures/local-ip-discovery-with-html5-webrtc-security-and-privacy-risk/">How is this done?</a> &mdash;
<a href="https://github.com/pirate/nicksweeting.com/blob/master/scan.html">View on github</a>
</span>
<span id="right-footer">
<a href="https://nicksweeting.com">sweeting.me</a>
</span>
</div>
<link rel="stylesheet" href="https://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">
</body>
</html>
You can’t perform that action at this time.