Skip to content

Instantly share code, notes, and snippets.

@liamgriffiths
Last active May 10, 2024 07:40
Show Gist options
  • Save liamgriffiths/9064335 to your computer and use it in GitHub Desktop.
Save liamgriffiths/9064335 to your computer and use it in GitHub Desktop.
traceroute clone in javascript
// sloppy traceroute clone
// inpired by https://blogs.oracle.com/ksplice/entry/learning_by_doing_writing_your
// and made possible by https://www.npmjs.org/package/raw-socket
var raw = require('raw-socket');
var dns = require('dns');
var target = process.argv[2] || '173.230.146.29';
var MAX_HOPS = 64;
var TIME_LIMIT = 5000;
function resolveFirst(dest, cb) {
dns.resolve(dest, function (err, addresses) {
if (err) throw err;
dns.reverse(addresses[0], function(err, domains) {
if (err) {
cb(addresses[0], '');
} else {
cb(addresses[0], domains);
}
});
});
}
function ping(dest, ttl, cb) {
var sentTime;
var buffer = new Buffer ([
0x08, 0x00, 0x43, 0x52, 0x00, 0x01, 0x0a, 0x09,
0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x61,
0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69]);
var socketLevel = raw.SocketLevel.IPPROTO_IP
var socketOption = raw.SocketOption.IP_TTL;
var socket = raw.createSocket();
socket.setOption(socketLevel, socketOption, ttl);
socket.send(buffer, 0, buffer.length, dest, function(err, bytes) {
if (err) throw err;
sentTime = new Date().getTime();
});
var timeout = true;
socket.on("message", function (buffer, source) {
socket.close();
timeout = false;
cb(buffer, source, (new Date().getTime() - sentTime));
});
setTimeout(function() {
if (timeout) cb(null, '???', TIME_LIMIT);
}, TIME_LIMIT);
}
function trace(dest, ttl) {
ping(dest, ttl, function(buffer, source, time) {
if (time <= TIME_LIMIT && source) {
resolveFirst(source, function(address, domains) {
console.log(ttl + '\t' + address + '\t' + domains + '\t' + time + 'ms');
if (source == dest || ttl == MAX_HOPS) process.exit(0);
trace(dest, ttl + 1);
});
} else {
console.log(ttl + '\t' + source);
if (source == dest || ttl == MAX_HOPS) process.exit(0);
trace(dest, ttl + 1);
}
});
}
resolveFirst(target, function(address, domains) {
console.log('Traceroute to', address, domains);
trace(address, 1);
});
@jacobSingh
Copy link

I'm getting this:
Error: Operation not permitted
at new Socket (/private/tmp/node_modules/raw-socket/index.js:47:14)
at Object.exports.createSocket (/private/tmp/node_modules/raw-socket/index.js:202:9)
at ping (/private/tmp/goo.js:38:20)
at trace (/private/tmp/goo.js:59:3)
at /private/tmp/goo.js:76:3
at /private/tmp/goo.js:19:9
at asyncCallback (dns.js:68:16)
at Object.onanswer as oncomplete

Any ideas?

@waldin
Copy link

waldin commented Jan 14, 2015

Did you have any luck with this??

@MikeJansen
Copy link

Looks like this code requires Node.js, not just plain old javascript.

@leovolpatto
Copy link

Yes, that's a snippet of NodeJS code.

@rot26
Copy link

rot26 commented Nov 2, 2015

Required:
node js + npm

Install packages:

$ npm install raw-socket
$ npm install dns

Run:

node traceroute.js

If you get Error: Operation not permitted either fix the permissions with chmod or chown, or run with sudo:

sudo node traceroute.js

@kfcviptel
Copy link

Interesting code, but how to run it?
In a browser, a browser extention or ex. Apache Cordova on a mobile?
Command line does not makes much sence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment