Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

separate the bin script and proxy logic, add npm package file

  • Loading branch information...
commit 05eaba0c4a22c195585dfa3e62018d53b196dc37 1 parent 1c4a6ce
@igrigorik authored
Showing with 198 additions and 155 deletions.
  1. +55 −0 bin/spdyvpn
  2. +118 −0 lib/server.js
  3. +25 −0 package.json
  4. +0 −155 server.js
View
55 bin/spdyvpn
@@ -0,0 +1,55 @@
+#!/usr/bin/env node
+
+var path = require('path')
+ , pkg = require('../package.json')
+ , version = pkg.version
+ , spdyProxy = require('../lib/server')
+ , fs = require('fs')
+ , opts = require('optimist')
+ .usage('Usage: $0 -x - y')
+ .options({
+ key: {
+ demand: true,
+ alias: 'k',
+ description: 'path to SSL key'
+ },
+ cert: {
+ demand: true,
+ alias: 'c',
+ description: 'path to SSL certificate'
+ },
+ ca: {
+ demand: true,
+ alias: 'a',
+ description: 'path to SSL CA certificate'
+ },
+ port: {
+ demand: false,
+ alias: 'p',
+ description: 'proxy port',
+ default: 44300
+ },
+ user: {
+ demand: false,
+ alias: 'u',
+ description: 'basich auth username'
+ },
+ pass: {
+ demand: false,
+ alias: 'p',
+ description: 'basic auth password'
+ }
+ }).argv;
+
+opts.key = fs.readFileSync(path.resolve(opts.key));
+opts.cert = fs.readFileSync(path.resolve(opts.cert));
+opts.ca = fs.readFileSync(path.resolve(opts.ca));
+
+process.on('uncaughtException', function(e) {
+ console.error('Error: ' + e);
+});
+
+var proxy = new spdyProxy.createServer(opts);
+proxy.listen(opts.port);
+
+console.log("started server");
View
118 lib/server.js
@@ -0,0 +1,118 @@
+var spdy = require('spdy'),
+ http = require('http'),
+ path = require('path'),
+ util = require('util'),
+ url = require('url'),
+ net = require('net'),
+ fs = require('fs');
+
+var SPDYProxy = function(options) {
+ function logRequest(req) {
+ console.log(req.method + ' ' + req.url);
+ for (var i in req.headers)
+ console.log(' * ' + i + ': ' + req.headers[i]);
+ }
+
+ function synReply(socket, code, reason, headers, cb) {
+ socket.lock(function() {
+ var socket = this;
+
+ this.framer.replyFrame(
+ this.id, code, reason, headers,
+ function (err, frame) {
+ socket.connection.write(frame);
+ socket.unlock();
+ cb.call();
+ }
+ );
+ });
+ }
+
+ function handlePlain(req, res) {
+ var requestOptions = {
+ host: req.headers.host,
+ port: req.headers.host.split(':')[1] || 80,
+ path: req.url,
+ method: req.method,
+ headers: req.headers // TODO: remove, host, method, etc?
+ };
+
+ var rreq = http.request(requestOptions, function(rres) {
+ delete rres.headers['transfer-encoding'];
+ rres.headers['x-spdy-proxy'] = 'v1.0.0';
+
+ // write out headers to handle redirects
+ res.writeHead(rres.statusCode, '', rres.headers);
+ rres.pipe(res);
+ });
+
+ rreq.on('error', function(e) {
+ console.log("Client error: " + e.message);
+ res.writeHead(502, 'Proxy fetch failed');
+ res.end();
+ });
+
+ req.pipe(rreq);
+ }
+
+ function handleSecure(req, socket) {
+ var dest = req.headers.host.split(':');
+ var tunnel = net.createConnection(dest[1] || 443, dest[0], function() {
+ synReply(socket, 200, 'Connection established', {'Connection': 'keep-alive'}, function() {
+ tunnel.pipe(socket);
+ socket.pipe(tunnel);
+ });
+ });
+
+ tunnel.setNoDelay(true);
+
+ tunnel.on('error', function(e) {
+ console.log("Tunnel error: " + e);
+ synReply(socket, 502, "Tunnel Error", {}, function() {
+ socket.end();
+ });
+ });
+ }
+
+ function handleRequest(req, res) {
+ logRequest(req);
+
+ // perform basic proxy auth (over SSL tunnel)
+ // - http://www.chromium.org/spdy/spdy-authentication
+ var header = req.headers['proxy-authorization'] || '',
+ token = header.split(/\s+/).pop() || '',
+ auth = new Buffer(token, 'base64').toString(),
+ parts = auth.split(/:/),
+ username = parts[0],
+ password = parts[1];
+
+ // don't pass proxy-auth headers upstream
+ delete req.headers['proxy-authorization'];
+
+ // TODO add config
+ if(username != 'test') {
+ var socket = (req.method == 'CONNECT') ? res : res.socket;
+ synReply(socket, 407, 'Proxy Authentication Required',
+ {'Proxy-Authenticate': 'Basic realm="SPDY Proxy"'},
+ function() { socket.end(); }
+ );
+
+ } else {
+ (req.method == 'CONNECT') ? handleSecure(req, res) : handlePlain(req, res);
+ }
+ }
+
+ spdy.server.Server.call(this, options);
+
+ this.on("connect", handleRequest);
+ this.on("request", handleRequest);
+};
+
+util.inherits(SPDYProxy, spdy.server.Server);
+
+var createServer = function(options) {
+ return new SPDYProxy(options);
+};
+
+exports.SPDYProxy = SPDYProxy;
+exports.createServer = createServer;
View
25 package.json
@@ -0,0 +1,25 @@
+{
+ "name": "spdy-vpn",
+ "description": "SPDY proxy",
+ "version": "0.1.0",
+ "author": "Ilya Grigorik <ilya@igvita.com> (igvita.com)",
+ "keywords": ["spdy", "proxy", "vpn", "chrome"],
+ "repository": "git://github.com/igrigorik/spdy-vpn",
+ "homepage": "https://github.com/igrigorik/spdy-vpn",
+
+ "contributors": [],
+ "devDependencies": {},
+ "scripts": {},
+
+ "dependencies": {
+ "spdy": "1.2.1",
+ "optimist": "*"
+ },
+
+ "main": "./lib/server.js",
+ "bin": { "spdyvpn": "./bin/spdyvpn" },
+
+ "engines": [
+ "node >= 0.7.0"
+ ]
+}
View
155 server.js
@@ -1,155 +0,0 @@
-var spdy = require('spdy'),
- http = require('http'),
- path = require('path'),
- url = require('url'),
- net = require('net'),
- fs = require('fs');
-
-var opts = require('optimist')
- .usage('Usage: $0 -x - y')
- .options({
- key: {
- demand: true,
- alias: 'k',
- description: 'path to SSL key'
- },
- cert: {
- demand: true,
- alias: 'c',
- description: 'path to SSL certificate'
- },
- ca: {
- demand: true,
- alias: 'a',
- description: 'path to SSL CA certificate'
- },
- port: {
- demand: false,
- alias: 'p',
- description: 'proxy port',
- default: 44300
- },
- user: {
- demand: false,
- alias: 'u',
- description: 'basich auth username'
- },
- pass: {
- demand: false,
- alias: 'p',
- description: 'basic auth password'
- }
- })
- .argv;
-
-opts.key = fs.readFileSync(path.resolve(opts.key));
-opts.cert = fs.readFileSync(path.resolve(opts.cert));
-opts.ca = fs.readFileSync(path.resolve(opts.ca));
-
-
-
-process.on('uncaughtException', function(e) {
- console.error('Error: ' + e);
-});
-
-function logRequest(req) {
- console.log(req.method + ' ' + req.url);
- for (var i in req.headers)
- console.log(' * ' + i + ': ' + req.headers[i]);
-}
-
-function synReply(socket, code, reason, headers, cb) {
- socket.lock(function() {
- var socket = this;
-
- this.framer.replyFrame(
- this.id, code, reason, headers,
- function (err, frame) {
- socket.connection.write(frame);
- socket.unlock();
- cb.call();
- }
- );
- });
-}
-
-function handlePlain(req, res) {
- var requestOptions = {
- host: req.headers.host,
- port: req.headers.host.split(':')[1] || 80,
- path: req.url,
- method: req.method,
- headers: req.headers // TODO: remove, host, method, etc?
- };
-
- var rreq = http.request(requestOptions, function(rres) {
- delete rres.headers['transfer-encoding'];
- rres.headers['x-spdy-proxy'] = 'v1.0.0';
-
- // write out headers to handle redirects
- res.writeHead(rres.statusCode, '', rres.headers);
- rres.pipe(res);
- });
-
- rreq.on('error', function(e) {
- console.log("Client error: " + e.message);
- res.writeHead(502, 'Proxy fetch failed');
- res.end();
- });
-
- req.pipe(rreq);
-}
-
-function handleSecure(req, socket) {
- var dest = req.headers.host.split(':');
- var tunnel = net.createConnection(dest[1] || 443, dest[0], function() {
- synReply(socket, 200, 'Connection established', {'Connection': 'keep-alive'}, function() {
- tunnel.pipe(socket);
- socket.pipe(tunnel);
- });
- });
-
- tunnel.setNoDelay(true);
-
- tunnel.on('error', function(e) {
- console.log("Tunnel error: " + e);
- synReply(socket, 502, "Tunnel Error", {}, function() {
- socket.end();
- });
- });
-}
-
-function handleRequest(req, res) {
- logRequest(req);
-
- // perform basic proxy auth (over SSL tunnel)
- // - http://www.chromium.org/spdy/spdy-authentication
- var header = req.headers['proxy-authorization'] || '',
- token = header.split(/\s+/).pop() || '',
- auth = new Buffer(token, 'base64').toString(),
- parts = auth.split(/:/),
- username = parts[0],
- password = parts[1];
-
- // don't pass proxy-auth headers upstream
- delete req.headers['proxy-authorization'];
-
- // TODO add config
- if(username != 'test') {
- var socket = (req.method == 'CONNECT') ? res : res.socket;
- synReply(socket, 407, 'Proxy Authentication Required',
- {'Proxy-Authenticate': 'Basic realm="SPDY Proxy"'},
- function() { socket.end(); }
- );
-
- } else {
- (req.method == 'CONNECT') ? handleSecure(req, res) : handlePlain(req, res);
- }
-}
-
-var server = spdy.createServer(opts);
-
-server.on("request", handleRequest);
-server.on("connect", handleRequest);
-
-server.listen(44300);
Please sign in to comment.
Something went wrong with that request. Please try again.