Skip to content
Browse files

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

  • Loading branch information...
1 parent 1c4a6ce commit 05eaba0c4a22c195585dfa3e62018d53b196dc37 @igrigorik committed Jun 21, 2012
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);

0 comments on commit 05eaba0

Please sign in to comment.
Something went wrong with that request. Please try again.