Skip to content

Instantly share code, notes, and snippets.

@zachary822
Created December 2, 2015 04:34
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save zachary822/937ac765cc7d6ffbde06 to your computer and use it in GitHub Desktop.
Save zachary822/937ac765cc7d6ffbde06 to your computer and use it in GitHub Desktop.
Send TCP SYN with node.js and raw-socket package
/**
* Sending a TCP SYN packet properly using the raw-socket package.
*/
var raw = require('raw-socket');
var crypto = require('crypto');
// create a raw socket using TCP
var s = raw.createSocket({
protocol: raw.Protocol.TCP
});
/**
* generate pseudo-header. Used to calculate package checksum.
* @param {number} srcIp - source ip as an integer
* @param {number} dstIp - destination ip as an integer
* @param {number} tcpPacketLength - tcp packet length
* @return {Buffer} the pseudo-header, used later
*/
var genPseudoHeader = function (srcIp, dstIp, tcpPacketLength) {
// new buffer of length 12. The pseudo-header length
var pseudoHeader = new Buffer(12);
// Important to fill with zeroes. Node.js does not zero the memory before creating the buffer.
pseudoHeader.fill(0);
pseudoHeader.writeUInt32BE(srcIp, 0); // write source ip, a 32 bit integer!
pseudoHeader.writeUInt32BE(dstIp, 4); // write destination ip, a 32 bit integer!
pseudoHeader.writeUInt8(6, 9); // specifies protocol. Here we write 6 for TCP. Other protocols have other numbers.
// Write the TCP packet length of which we are generating a pseudo-header for.
// Does not include the length of the psuedo-header.
pseudoHeader.writeUInt16BE(tcpPacketLength, 10);
return pseudoHeader;
};
/**
* generate SYN packet
* @param {number} srcIp - source ip as an integer
* @param {number} dstIp - destination ip as an integer
* @param {number} srcPort - source port
* @param {number} dstPort - destination port
* @return {Buffer} the TCP SYN packet
*/
var genSynPacket = function (srcIp, dstIp, srcPort, dstPort) {
// A scaffolding TCP syn packet. Notice all zeroes except a few options.
// The "few options" include setting the SYN flags.
// Don't change it if you don't know what you're doing.
var p = new Buffer('0000000000000000000000005002200000000000', 'hex');
// Need 4 random bytes as sequence. Needs to be random to avoid collision.
// You can choose your own random source. I chose the crypto module.
crypto.randomBytes(4).copy(p, 4);
p.writeUInt16BE(srcPort, 0); // Write source port
p.writeUInt16BE(dstPort, 2); // Write destination port
// generate checksum with utility function
// using a pseudo header and the tcp packet scaffold
var sum = raw.createChecksum(genPseudoHeader(srcIp, dstIp, p.length), p);
// writing the checksum back to the packet. Packet complete!
p.writeUInt16BE(sum, 16);
return p;
};
// generate the packet.
var p = genSynPacket(srcIp, dstIp, srcPort, dstPort)
// send packet with offset 0, length = packet.length, to the dstIP
// The port data is in the packet already, so we don't worry about that during sending.
// Open tcpdump or wireshark and watch the not quite three way handshake. Useful to test for open ports.
s.send(p, 0, p.length, dstIp, function () {
console.log("sent TCP SYN");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment