shadowsocks-single
Version:
Yet another shadowsocks implementation for nodejs to help you bypass firewalls.
178 lines (144 loc) • 4.78 kB
JavaScript
;
const shttp = require('socks5-http-client');
const shttps = require('socks5-https-client');
const http = require('http');
const assert = require('assert');
const ip = require('ip');
const testServer = require('./testServer');
const ssLocal = require('../lib/ssLocal');
const ssServer = require('../lib/ssServer');
const utils = require('../lib/utils');
const _config = require('../lib/defaultConfig.js').default;
const config = Object.assign({}, _config, {
'level': 'error',
});
const strictEqual = assert.strictEqual;
const getDstInfo = utils.getDstInfo;
const DST_RES_TEXT = testServer.DST_RES_TEXT;
const DST_ADDR = testServer.DST_ADDR;
const DST_PORT = testServer.DST_PORT;
const createHTTPServer = testServer.createHTTPServer;
const TIMEOUT = 5000;
describe('getDstInfo', () => {
it('should return `null` when the `atyp` type is not supported ', () => {
const buffer = new Buffer(10);
buffer.write('050100027f000001a496', 'hex');
const dstInfo = getDstInfo(buffer);
strictEqual(dstInfo, null);
});
it('should return correct DST info when parsing ipv4', () => {
const buffer = new Buffer(10);
buffer.write('050100017f000001a496', 'hex');
const dstInfo = getDstInfo(buffer);
strictEqual(dstInfo.atyp, 0x01);
strictEqual(dstInfo.dstAddrLength, 4);
strictEqual(ip.toString(dstInfo.dstAddr), '127.0.0.1');
strictEqual(dstInfo.dstPort.readUInt16BE(), 42134);
});
it('should return correct DST info when parsing domain', () => {
const buffer = new Buffer(18);
buffer.write('050100030b', 0, 'hex');
buffer.write('example.com', 5, 'ascii');
buffer.writeUInt16BE(80, 16);
const dstInfo = getDstInfo(buffer);
strictEqual(dstInfo.atyp, 0x03);
strictEqual(dstInfo.dstAddrLength, 11);
strictEqual(dstInfo.dstAddr.toString('ascii'), 'example.com');
strictEqual(dstInfo.dstPort.readUInt16BE(), 80);
});
it('should return correct DST info when parsing ipv6', () => {
const buffer = new Buffer(22);
buffer.write('0501000400000000000000000000000000000001a496', 'hex');
const dstInfo = getDstInfo(buffer);
strictEqual(dstInfo.atyp, 0x04);
strictEqual(dstInfo.dstAddrLength, 16);
strictEqual(ip.toString(dstInfo.dstAddr), '::1');
strictEqual(dstInfo.dstPort.readUInt16BE(), 42134);
});
// TODO: ipv6
});
describe('http proxy', () => {
let dstServer;
let ssLocalServer;
let ssServerServer;
before(function(cb) {
this.timeout(5000);
ssLocalServer = ssLocal.startServer(config);
ssServerServer = ssServer.startServer(config);
dstServer = createHTTPServer(cb);
});
describe('ipv4', () => {
it('should get correct response through ipv4', function(cb) {
this.timeout(TIMEOUT);
const options = {
port: DST_PORT,
host: DST_ADDR,
socksHost: config.localHost,
socksPort: config.localPort,
};
shttp.get(options, res => {
res.on('readable', () => {
strictEqual(res.read().toString('utf8'), DST_RES_TEXT,
'Responsed text is not same');
cb();
});
});
});
it('should get correct response when the `atyp` is `domain`', function(cb) {
this.timeout(TIMEOUT);
let success = false;
shttp.get('http://example.com', res => {
res.on('readable', () => {
let text = res.read();
if (text) {
text = text.toString('utf8');
if (~text.indexOf('Example Domain')) {
success = true;
cb();
}
}
});
res.on('close', () => {
if (!success) {
cb(new Error('failed'));
}
});
});
});
// TODO: this test seems to be invalid
it('should get correct response when the requesting by ssl', function(cb) {
this.timeout(TIMEOUT);
shttps.get('https://example.com', res => {
res.on('readable', () => {
let text = res.read().toString('utf8');
assert(!!~text.indexOf('Example Domain'));
cb();
});
});
});
});
describe('ipv6', () => {
it('should get correct response through ipv6', function(cb) {
this.timeout(TIMEOUT);
const options = {
port: DST_PORT,
host: '::1',
socksHost: config.localHost,
socksPort: config.localPort,
};
shttp.get(options, res => {
res.on('readable', () => {
strictEqual(res.read().toString('utf8'), DST_RES_TEXT,
'Responsed text is not same');
cb()
});
});
});
});
after(() => {
dstServer.close();
ssLocalServer.closeAll();
ssServerServer.server.close();
ssServerServer.udpRelay.close();
});
});