mirror of
https://github.com/bitinflow/server.git
synced 2026-04-28 10:06:21 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f6640a9d6 | ||
|
|
386910032e | ||
|
|
cfdb42ee9c | ||
|
|
8af4fe19b8 | ||
|
|
8d91892ace | ||
|
|
4b485fecda | ||
|
|
fa4802d488 | ||
|
|
5046c360ba | ||
|
|
57ebcc90e1 | ||
|
|
dd7d8d6aa6 |
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require('stackup');
|
||||
var log = require('bookrc');
|
||||
var dotenv = require('dotenv').load();
|
||||
var localenv = require('localenv');
|
||||
var optimist = require('optimist');
|
||||
var debug = require('debug')('localtunnel');
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/// bookrc logging setup
|
||||
var log = require('book').default();
|
||||
require('stackup');
|
||||
|
||||
log.use(require('book-git')(__dirname));
|
||||
log.use(require('book-raven')(process.env.SENTRY_DSN));
|
||||
|
||||
33
devops/nginx/nginx.conf
Normal file
33
devops/nginx/nginx.conf
Normal file
@@ -0,0 +1,33 @@
|
||||
user nginx;
|
||||
worker_processes 1;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 10240;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log off;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
gzip on;
|
||||
gzip_min_length 1000;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
include /etc/nginx/sites/*;
|
||||
}
|
||||
65
devops/nginx/sites/localtunnel
Normal file
65
devops/nginx/sites/localtunnel
Normal file
@@ -0,0 +1,65 @@
|
||||
proxy_http_version 1.1;
|
||||
|
||||
# http://nginx.org/en/docs/http/websocket.html
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
upstream lt-server {
|
||||
server 127.0.0.1:2000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server ipv6only=on;
|
||||
|
||||
server_name .localtunnel.me;
|
||||
|
||||
location / {
|
||||
proxy_pass http://lt-server/;
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-Proto http;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
proxy_redirect off;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 default_server ssl spdy;
|
||||
listen [::]:443 default_server ipv6only=on;
|
||||
|
||||
server_name .localtuunel.me;
|
||||
|
||||
ssl on;
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/STAR.localtunnel.me.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/STAR.localtunnel.me.key;
|
||||
|
||||
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://lt-server/;
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
proxy_redirect off;
|
||||
}
|
||||
}
|
||||
5
devops/run.sh
Normal file
5
devops/run.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker run --restart always --name localtunnel -d --net host defunctzombie/localtunnel-server:0.0.5 bin/server --secure --port 2000 --max-sockets 5
|
||||
|
||||
docker run --restart always --name nginx -d --net host -v /home/core/nginx/nginx.conf:/etc/nginx/nginx.conf -v /home/core/nginx/sites:/etc/nginx/sites -v /home/core/nginx/ssl:/etc/nginx/ssl nginx:1.7.8
|
||||
65
nginx.conf
65
nginx.conf
@@ -1,65 +0,0 @@
|
||||
proxy_http_version 1.1;
|
||||
|
||||
# http://nginx.org/en/docs/http/websocket.html
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
upstream lt-server {
|
||||
server 127.0.0.1:8000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server ipv6only=on;
|
||||
|
||||
server_name .localtunnel.me;
|
||||
|
||||
location / {
|
||||
proxy_pass http://lt-server/;
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-Proto http;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
proxy_redirect off;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 default_server ssl spdy;
|
||||
listen [::]:443 default_server ipv6only=on;
|
||||
|
||||
server_name .localtuunel.me;
|
||||
|
||||
ssl on;
|
||||
|
||||
ssl_certificate ...;
|
||||
ssl_certificate_key ...;
|
||||
|
||||
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://lt-server/;
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
proxy_redirect off;
|
||||
}
|
||||
}
|
||||
29
package.json
29
package.json
@@ -2,32 +2,33 @@
|
||||
"author": "Roman Shtylman <shtylman@gmail.com>",
|
||||
"name": "localtunnel-server",
|
||||
"description": "expose localhost to the world",
|
||||
"version": "0.0.5",
|
||||
"version": "0.0.6",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/shtylman/localtunnel-server.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"book": "1.3.1",
|
||||
"optimist": "0.6.1",
|
||||
"debug": "2.1.0",
|
||||
"bookrc": "0.0.1",
|
||||
"book-git": "0.0.2",
|
||||
"book-raven": "1.0.1",
|
||||
"browserkthx": "0.0.2",
|
||||
"hbs": "2.7.0",
|
||||
"taters": "1.0.0",
|
||||
"express": "4.10.5",
|
||||
"makeup": "0.0.1",
|
||||
"enchilada": "0.11.0",
|
||||
"bookrc": "0.0.1",
|
||||
"bouncy": "3.2.2",
|
||||
"browserkthx": "0.0.2",
|
||||
"debug": "2.1.0",
|
||||
"enchilada": "0.11.0",
|
||||
"express": "4.10.5",
|
||||
"hbs": "2.7.0",
|
||||
"localenv": "0.2.2",
|
||||
"makeover": "0.0.1",
|
||||
"makeup": "0.0.1",
|
||||
"on-finished": "2.2.0",
|
||||
"optimist": "0.6.1",
|
||||
"serve-favicon": "2.1.7",
|
||||
"stackup": "0.0.5",
|
||||
"stylish": "0.5.0",
|
||||
"makeover": "0.0.1",
|
||||
"taters": "1.0.0",
|
||||
"tldjs": "1.5.1",
|
||||
"on-finished": "2.1.1",
|
||||
"localenv": "0.2.2",
|
||||
"serve-favicon": "2.1.7"
|
||||
"ws": "0.6.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "2.0.1",
|
||||
|
||||
28
proxy.js
28
proxy.js
@@ -21,16 +21,13 @@ var Proxy = function(opt, cb) {
|
||||
|
||||
// new tcp server to service requests for this client
|
||||
var client_server = net.createServer();
|
||||
client_server.listen(function() {
|
||||
var port = client_server.address().port;
|
||||
debug('tcp server listening on port: %d', port);
|
||||
|
||||
cb(null, {
|
||||
// port for lt client tcp connections
|
||||
port: port,
|
||||
// maximum number of tcp connections allowed by lt client
|
||||
max_conn_count: max_tcp_sockets
|
||||
});
|
||||
client_server.on('error', function(err) {
|
||||
if (err.code == 'ECONNRESET' || err.code == 'ETIMEDOUT') {
|
||||
return;
|
||||
}
|
||||
|
||||
log.error(err);
|
||||
});
|
||||
|
||||
// track initial user connection setup
|
||||
@@ -71,7 +68,6 @@ var Proxy = function(opt, cb) {
|
||||
|
||||
// new tcp connection from lt client
|
||||
client_server.on('connection', function(socket) {
|
||||
|
||||
// no more socket connections allowed
|
||||
if (self.sockets.length >= max_tcp_sockets) {
|
||||
return socket.end();
|
||||
@@ -119,8 +115,16 @@ var Proxy = function(opt, cb) {
|
||||
}
|
||||
});
|
||||
|
||||
client_server.on('error', function(err) {
|
||||
log.error(err);
|
||||
client_server.listen(function() {
|
||||
var port = client_server.address().port;
|
||||
debug('tcp server listening on port: %d', port);
|
||||
|
||||
cb(null, {
|
||||
// port for lt client tcp connections
|
||||
port: port,
|
||||
// maximum number of tcp connections allowed by lt client
|
||||
max_conn_count: max_tcp_sockets
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -53,6 +53,10 @@ function maybe_bounce(req, res, bounce) {
|
||||
// we can't respond to these requests
|
||||
var finished = false;
|
||||
on_finished(res, function(err) {
|
||||
if (req.headers['upgrade'] == 'websocket') {
|
||||
return;
|
||||
}
|
||||
|
||||
finished = true;
|
||||
req.connection.destroy();
|
||||
});
|
||||
@@ -197,8 +201,8 @@ module.exports = function(opt) {
|
||||
var req_id = req.param('req_id');
|
||||
|
||||
// limit requested hostnames to 20 characters
|
||||
if (! /^[A-Za-z0-9]{4,20}$/.test(req_id)) {
|
||||
var err = new Error('Invalid subdomain. Subdomains must be between 4 and 20 alphanumeric characters.');
|
||||
if (! /^[a-z0-9]{4,20}$/.test(req_id)) {
|
||||
var err = new Error('Invalid subdomain. Subdomains must be lowercase and between 4 and 20 alphanumeric characters.');
|
||||
err.statusCode = 403;
|
||||
return next(err);
|
||||
}
|
||||
|
||||
@@ -126,7 +126,20 @@ test('request domain that is too long', function(done) {
|
||||
|
||||
localtunnel(test._fake_port, opt, function(err, tunnel) {
|
||||
assert(err);
|
||||
assert.equal(err.message, 'Invalid subdomain. Subdomains must be between 4 and 20 alphanumeric characters.');
|
||||
assert.equal(err.message, 'Invalid subdomain. Subdomains must be lowercase and between 4 and 20 alphanumeric characters.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('request uppercase domain', function(done) {
|
||||
var opt = {
|
||||
host: 'http://localhost:' + lt_server_port,
|
||||
subdomain: 'ABCD'
|
||||
};
|
||||
|
||||
localtunnel(test._fake_port, opt, function(err, tunnel) {
|
||||
assert(err);
|
||||
assert.equal(err.message, 'Invalid subdomain. Subdomains must be lowercase and between 4 and 20 alphanumeric characters.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
63
test/websocket.js
Normal file
63
test/websocket.js
Normal file
@@ -0,0 +1,63 @@
|
||||
var http = require('http');
|
||||
var url = require('url');
|
||||
var assert = require('assert');
|
||||
var localtunnel = require('localtunnel');
|
||||
var WebSocket = require('ws');
|
||||
var WebSocketServer = require('ws').Server;
|
||||
|
||||
var localtunnel_server = require('../server')();
|
||||
|
||||
var lt_server_port
|
||||
|
||||
test('setup localtunnel server', function(done) {
|
||||
var server = localtunnel_server.listen(function() {
|
||||
lt_server_port = server.address().port;
|
||||
console.log('lt server on:', lt_server_port);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('setup local websocket server', function(done) {
|
||||
|
||||
var wss = new WebSocketServer({ port: 0 }, function() {
|
||||
test._fake_port = wss._server.address().port;
|
||||
done();
|
||||
});
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.on('message', function incoming(message) {
|
||||
ws.send(message);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('setup localtunnel client', function(done) {
|
||||
var opt = {
|
||||
host: 'http://localhost:' + lt_server_port,
|
||||
};
|
||||
|
||||
localtunnel(test._fake_port, opt, function(err, tunnel) {
|
||||
assert.ifError(err);
|
||||
var url = tunnel.url;
|
||||
assert.ok(new RegExp('^http:\/\/.*localhost:' + lt_server_port + '$').test(url));
|
||||
test._fake_url = url;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('test websocket server request', function(done) {
|
||||
var hostname = url.parse(test._fake_url).hostname;
|
||||
var ws = new WebSocket('http://localhost:' + lt_server_port, {
|
||||
headers: {
|
||||
host: hostname + '.tld'
|
||||
}
|
||||
});
|
||||
ws.on('message', function(msg) {
|
||||
assert.equal(msg, 'something');
|
||||
done();
|
||||
});
|
||||
|
||||
ws.on('open', function open() {
|
||||
ws.send('something');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user