Compare commits
21 Commits
d700b51494
...
bb018c538d
Author | SHA1 | Date |
---|---|---|
AJ ONeal | bb018c538d | |
AJ ONeal | 06cc7bbaeb | |
AJ ONeal | 82aeffd67c | |
AJ ONeal | 1873cdea50 | |
AJ ONeal | af63322aca | |
AJ ONeal | 8be76e1eb2 | |
AJ ONeal | cb8261fd31 | |
AJ ONeal | 92f37a515a | |
AJ ONeal | e619018276 | |
AJ ONeal | c8c06d1b99 | |
AJ ONeal | 13a9e77998 | |
AJ ONeal | f94e01917e | |
AJ ONeal | 33c3bc9876 | |
AJ ONeal | f2cd8158f7 | |
AJ ONeal | 02c3836883 | |
AJ ONeal | 6cfad96323 | |
AJ ONeal | 24b42e1ed9 | |
AJ ONeal | 39b01fca47 | |
AJ ONeal | 4a3a395c14 | |
AJ ONeal | 7e83b0c3c2 | |
AJ ONeal | c8d974884b |
|
@ -1,4 +1,10 @@
|
||||||
node_modules.*
|
node_modules.*
|
||||||
|
include
|
||||||
|
bin/node
|
||||||
|
bin/npm
|
||||||
|
bin/npx
|
||||||
|
share
|
||||||
|
etc
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
|
|
35
README.md
35
README.md
|
@ -63,6 +63,41 @@ Windows & Node.js
|
||||||
|
|
||||||
There is [a bug](https://github.com/nodejs/node/issues/20241) in node v9.x that causes telebit-relay to crash.
|
There is [a bug](https://github.com/nodejs/node/issues/20241) in node v9.x that causes telebit-relay to crash.
|
||||||
|
|
||||||
|
Manually Install
|
||||||
|
-----------
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.coolaj86.com/coolaj86/telebit-relay.js.git telebit-relay
|
||||||
|
|
||||||
|
# we're very picky to due to bugs in various versions of v8, v9, and v10
|
||||||
|
export NODEJS_VER="v10.2.1"
|
||||||
|
|
||||||
|
# We can keep everything self-contained
|
||||||
|
export NPM_CONFIG_PREFIX=/opt/telebit-relay
|
||||||
|
export NODE_PATH=/opt/telebit-relay/lib/node_modules
|
||||||
|
|
||||||
|
curl -fsSL https://bit.ly/node-installer | bash -s -- --no-dev-deps
|
||||||
|
|
||||||
|
pushd /opt/telebit-relay
|
||||||
|
bin/node bin/npm install
|
||||||
|
rsync -a examples/telebit-relay.yml etc/telebit-relay.yml
|
||||||
|
rsync -a dist/etc/systemd/system/telebit-relay.service /etc/systemd/system/telebit-relay.service
|
||||||
|
popd
|
||||||
|
|
||||||
|
# IMPORTANT: Season the config file to taste
|
||||||
|
# IMPORTANT: change your email address and domain
|
||||||
|
edit /opt/telebit-relay/etc/telebit-relay.yml
|
||||||
|
|
||||||
|
adduser --home /opt/telebit-relay --gecos '' --disabled-password telebit >/dev/null 2>&1
|
||||||
|
sudo chown -R telebit:telebit /opt/telebit-relay/
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl restart telebit-relay
|
||||||
|
|
||||||
|
systemctl status telebit-relay
|
||||||
|
journalctl -xefu telebit-relay
|
||||||
|
```
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
====
|
====
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{ "terms_of_service": ":hostname/tos/"
|
||||||
|
, "api_host": ":hostname"
|
||||||
|
, "tunnel": {
|
||||||
|
"method": "wss"
|
||||||
|
, "pathname": ""
|
||||||
|
}
|
||||||
|
}
|
|
@ -134,7 +134,7 @@ function applyConfig(config) {
|
||||||
// TODO specify extensions in config file
|
// TODO specify extensions in config file
|
||||||
state.extensions = require('../lib/extensions');
|
state.extensions = require('../lib/extensions');
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (state.debug) { console.log('[DEBUG] no extensions loaded', e); }
|
if ('ENOENT' !== e.code || state.debug) { console.log('[DEBUG] no extensions loaded', e); }
|
||||||
state.extensions = {};
|
state.extensions = {};
|
||||||
}
|
}
|
||||||
require('../lib/handlers').create(state); // adds directly to config for now...
|
require('../lib/handlers').create(state); // adds directly to config for now...
|
||||||
|
|
|
@ -2,6 +2,8 @@ email: 'jon@example.com' # must be valid (for certificate recovery and sec
|
||||||
agree_tos: true # agree to the Telebit, Greenlock, and Let's Encrypt TOSes
|
agree_tos: true # agree to the Telebit, Greenlock, and Let's Encrypt TOSes
|
||||||
community_member: true # receive infrequent relevant updates
|
community_member: true # receive infrequent relevant updates
|
||||||
telemetry: true # contribute to project telemetric data
|
telemetry: true # contribute to project telemetric data
|
||||||
|
webmin_domain: example.com
|
||||||
|
shared_domain: xm.pl
|
||||||
servernames: # hostnames that direct to the Telebit Relay admin console
|
servernames: # hostnames that direct to the Telebit Relay admin console
|
||||||
- telebit.example.com
|
- telebit.example.com
|
||||||
- telebit.example.net
|
- telebit.example.net
|
|
@ -68,6 +68,7 @@ my_app="telebit-relay"
|
||||||
my_bin="telebit-relay.js"
|
my_bin="telebit-relay.js"
|
||||||
my_name="Telebit Relay"
|
my_name="Telebit Relay"
|
||||||
my_repo="telebit-relay.js"
|
my_repo="telebit-relay.js"
|
||||||
|
exec 3<>/dev/tty
|
||||||
|
|
||||||
if [ -z "${my_email}" ]; then
|
if [ -z "${my_email}" ]; then
|
||||||
echo ""
|
echo ""
|
||||||
|
@ -77,7 +78,7 @@ if [ -z "${my_email}" ]; then
|
||||||
echo "To accept the Terms of Service for Telebit, Greenlock and Let's Encrypt,"
|
echo "To accept the Terms of Service for Telebit, Greenlock and Let's Encrypt,"
|
||||||
echo "please enter your email."
|
echo "please enter your email."
|
||||||
echo ""
|
echo ""
|
||||||
read -p "email: " my_email
|
read -u 3 -p "email: " my_email
|
||||||
echo ""
|
echo ""
|
||||||
# UX - just want a smooth transition
|
# UX - just want a smooth transition
|
||||||
sleep 0.5
|
sleep 0.5
|
||||||
|
@ -86,7 +87,7 @@ fi
|
||||||
if [ -z "${my_servername}" ]; then
|
if [ -z "${my_servername}" ]; then
|
||||||
echo "What is the domain of this server (for admin interface)?"
|
echo "What is the domain of this server (for admin interface)?"
|
||||||
echo ""
|
echo ""
|
||||||
read -p "domain (ex: telebit-relay.example.com): " my_servername
|
read -u 3 -p "domain (ex: telebit-relay.example.com): " my_servername
|
||||||
echo ""
|
echo ""
|
||||||
# UX - just want a smooth transition
|
# UX - just want a smooth transition
|
||||||
sleep 0.5
|
sleep 0.5
|
||||||
|
@ -120,8 +121,8 @@ mkdir -p $my_tmp
|
||||||
|
|
||||||
echo "sudo mkdir -p '$TELEBIT_RELAY_PATH'"
|
echo "sudo mkdir -p '$TELEBIT_RELAY_PATH'"
|
||||||
sudo mkdir -p "$TELEBIT_RELAY_PATH"
|
sudo mkdir -p "$TELEBIT_RELAY_PATH"
|
||||||
echo "sudo mkdir -p '/opt/$my_app/etc'"
|
echo "sudo mkdir -p '$TELEBIT_RELAY_PATH/etc'"
|
||||||
sudo mkdir -p "/opt/$my_app/etc/"
|
sudo mkdir -p "$TELEBIT_RELAY_PATH/etc/"
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
#https://git.coolaj86.com/coolaj86/telebit-relay.js.git
|
#https://git.coolaj86.com/coolaj86/telebit-relay.js.git
|
||||||
|
@ -172,17 +173,17 @@ if [ -z "$(cat /etc/passwd | grep $my_user)" ]; then
|
||||||
sudo adduser --home $TELEBIT_RELAY_PATH --gecos '' --disabled-password $my_user >/dev/null 2>&1
|
sudo adduser --home $TELEBIT_RELAY_PATH --gecos '' --disabled-password $my_user >/dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "/opt/$my_app/etc/$my_app.yml" ]; then
|
if [ ! -f "$TELEBIT_RELAY_PATH/etc/$my_app.yml" ]; then
|
||||||
echo "### Creating config file from template. sudo may be required"
|
echo "### Creating config file from template. sudo may be required"
|
||||||
#echo "sudo rsync -a examples/$my_app.yml /opt/$my_app/etc/$my_app.yml"
|
#echo "sudo rsync -a examples/$my_app.yml $TELEBIT_RELAY_PATH/etc/$my_app.yml"
|
||||||
sudo bash -c "echo 'email: $my_email' >> /opt/$my_app/etc/$my_app.yml"
|
sudo bash -c "echo 'email: $my_email' >> $TELEBIT_RELAY_PATH/etc/$my_app.yml"
|
||||||
sudo bash -c "echo 'secret: $my_secret' >> /opt/$my_app/etc/$my_app.yml"
|
sudo bash -c "echo 'secret: $my_secret' >> $TELEBIT_RELAY_PATH/etc/$my_app.yml"
|
||||||
sudo bash -c "echo 'servernames: [ $my_servername ]' >> /opt/$my_app/etc/$my_app.yml"
|
sudo bash -c "echo 'servernames: [ $my_servername ]' >> $TELEBIT_RELAY_PATH/etc/$my_app.yml"
|
||||||
sudo bash -c "cat examples/$my_app.yml.tpl >> /opt/$my_app/etc/$my_app.yml"
|
sudo bash -c "cat $TELEBIT_RELAY_PATH/examples/$my_app.yml.tpl >> $TELEBIT_RELAY_PATH/etc/$my_app.yml"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "sudo chown -R $my_user '$TELEBIT_RELAY_PATH' '/opt/$my_app/etc'"
|
echo "sudo chown -R $my_user '$TELEBIT_RELAY_PATH'"
|
||||||
sudo chown -R $my_user "$TELEBIT_RELAY_PATH" "/opt/$my_app/etc"
|
sudo chown -R $my_user "$TELEBIT_RELAY_PATH"
|
||||||
|
|
||||||
echo "### Adding $my_app is a system service"
|
echo "### Adding $my_app is a system service"
|
||||||
echo "sudo rsync -a $TELEBIT_RELAY_PATH/dist/etc/systemd/system/$my_app.service /etc/systemd/system/$my_app.service"
|
echo "sudo rsync -a $TELEBIT_RELAY_PATH/dist/etc/systemd/system/$my_app.service /etc/systemd/system/$my_app.service"
|
||||||
|
@ -201,7 +202,7 @@ echo "=============================================="
|
||||||
echo " Privacy Settings in Config"
|
echo " Privacy Settings in Config"
|
||||||
echo "=============================================="
|
echo "=============================================="
|
||||||
echo ""
|
echo ""
|
||||||
echo "The example config file /opt/$my_app/etc/$my_app.yml opts-in to"
|
echo "The example config file $TELEBIT_RELAY_PATH/etc/$my_app.yml opts-in to"
|
||||||
echo "contributing telemetrics and receiving infrequent relevant updates"
|
echo "contributing telemetrics and receiving infrequent relevant updates"
|
||||||
echo "(probably once per quarter or less) such as important notes on"
|
echo "(probably once per quarter or less) such as important notes on"
|
||||||
echo "a new release, an important API change, etc. No spam."
|
echo "a new release, an important API change, etc. No spam."
|
||||||
|
@ -218,13 +219,13 @@ echo "=============================================="
|
||||||
echo ""
|
echo ""
|
||||||
echo "Edit the config and restart, if desired:"
|
echo "Edit the config and restart, if desired:"
|
||||||
echo ""
|
echo ""
|
||||||
echo " sudo vim /opt/$my_app/etc/$my_app.yml"
|
echo " sudo vim $TELEBIT_RELAY_PATH/etc/$my_app.yml"
|
||||||
echo " sudo systemctl restart $my_app"
|
echo " sudo systemctl restart $my_app"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Or disabled the service and start manually:"
|
echo "Or disabled the service and start manually:"
|
||||||
echo ""
|
echo ""
|
||||||
echo " sudo systemctl stop $my_app"
|
echo " sudo systemctl stop $my_app"
|
||||||
echo " sudo systemctl disable $my_app"
|
echo " sudo systemctl disable $my_app"
|
||||||
echo " $my_app --config /opt/$my_app/etc/$my_app.yml"
|
echo " $my_app --config $TELEBIT_RELAY_PATH/etc/$my_app.yml"
|
||||||
echo ""
|
echo ""
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
|
@ -52,7 +52,7 @@ module.exports.create = function (state) {
|
||||||
|| redirectHttpsAndClose
|
|| redirectHttpsAndClose
|
||||||
);
|
);
|
||||||
state.handleInsecureHttp = function (servername, socket) {
|
state.handleInsecureHttp = function (servername, socket) {
|
||||||
console.log("handleInsecureHttp('" + servername + "', socket)");
|
console.log("[handlers] insecure http for '" + servername + "'");
|
||||||
socket.__my_servername = servername;
|
socket.__my_servername = servername;
|
||||||
state.httpInsecureServer.emit('connection', socket);
|
state.httpInsecureServer.emit('connection', socket);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,42 +2,55 @@
|
||||||
|
|
||||||
var Packer = require('proxy-packer');
|
var Packer = require('proxy-packer');
|
||||||
|
|
||||||
module.exports = function pipeWs(servername, service, conn, remote, serviceport) {
|
module.exports = function pipeWs(servername, service, srv, conn, serviceport) {
|
||||||
var browserAddr = Packer.socketToAddr(conn);
|
var browserAddr = Packer.socketToAddr(conn);
|
||||||
var cid = Packer.addrToId(browserAddr);
|
var cid = Packer.addrToId(browserAddr);
|
||||||
browserAddr.service = service;
|
browserAddr.service = service;
|
||||||
browserAddr.serviceport = serviceport;
|
browserAddr.serviceport = serviceport;
|
||||||
browserAddr.name = servername;
|
browserAddr.name = servername;
|
||||||
conn.tunnelCid = cid;
|
conn.tunnelCid = cid;
|
||||||
var rid = Packer.socketToId(remote.upgradeReq.socket);
|
var rid = Packer.socketToId(srv.upgradeReq.socket);
|
||||||
|
|
||||||
//if (state.debug) { console.log('[pipeWs] client', cid, '=> remote', rid, 'for', servername, 'via', service); }
|
//if (state.debug) { console.log('[pipeWs] client', cid, '=> remote', rid, 'for', servername, 'via', service); }
|
||||||
|
|
||||||
function sendWs(data, serviceOverride) {
|
function sendWs(data, serviceOverride) {
|
||||||
if (remote.ws && (!conn.tunnelClosing || serviceOverride)) {
|
if (srv.ws && (!conn.tunnelClosing || serviceOverride)) {
|
||||||
try {
|
try {
|
||||||
remote.ws.send(Packer.pack(browserAddr, data, serviceOverride), { binary: true });
|
if (data && !Buffer.isBuffer(data)) {
|
||||||
|
data = Buffer.from(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
srv.ws.send(Packer.packHeader(browserAddr, data, serviceOverride), { binary: true });
|
||||||
|
if (data) {
|
||||||
|
srv.ws.send(data, { binary: true });
|
||||||
|
}
|
||||||
// If we can't send data over the websocket as fast as this connection can send it to us
|
// If we can't send data over the websocket as fast as this connection can send it to us
|
||||||
// (or there are a lot of connections trying to send over the same websocket) then we
|
// (or there are a lot of connections trying to send over the same websocket) then we
|
||||||
// need to pause the connection for a little. We pause all connections if any are paused
|
// need to pause the connection for a little. We pause all connections if any are paused
|
||||||
// to make things more fair so a connection doesn't get stuck waiting for everyone else
|
// to make things more fair so a connection doesn't get stuck waiting for everyone else
|
||||||
// to finish because it got caught on the boundary. Also if serviceOverride is set it
|
// to finish because it got caught on the boundary. Also if serviceOverride is set it
|
||||||
// means the connection is over, so no need to pause it.
|
// means the connection is over, so no need to pause it.
|
||||||
if (!serviceOverride && (remote.pausedConns.length || remote.ws.bufferedAmount > 1024*1024)) {
|
if (!serviceOverride && (srv.pausedConns.length || srv.ws.bufferedAmount > 1024*1024)) {
|
||||||
// console.log('pausing', cid, 'to allow web socket to catch up');
|
// console.log('pausing', cid, 'to allow web socket to catch up');
|
||||||
conn.pause();
|
conn.pause();
|
||||||
remote.pausedConns.push(conn);
|
srv.pausedConns.push(conn);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('[pipeWs] remote', rid, ' => client', cid, 'error sending websocket message', err);
|
console.warn('[pipeWs] srv', rid, ' => client', cid, 'error sending websocket message', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remote.clients[cid] = conn;
|
srv.clients[cid] = conn;
|
||||||
|
conn.servername = servername;
|
||||||
|
conn.serviceport = serviceport;
|
||||||
|
conn.service = service;
|
||||||
|
|
||||||
|
// send peek at data too?
|
||||||
|
srv.ws.send(Packer.packHeader(browserAddr, null, 'connection'), { binary: true });
|
||||||
|
|
||||||
|
// TODO convert to read stream?
|
||||||
conn.on('data', function (chunk) {
|
conn.on('data', function (chunk) {
|
||||||
//if (state.debug) { console.log('[pipeWs] client', cid, ' => remote', rid, chunk.byteLength, 'bytes'); }
|
//if (state.debug) { console.log('[pipeWs] client', cid, ' => srv', rid, chunk.byteLength, 'bytes'); }
|
||||||
sendWs(chunk);
|
sendWs(chunk);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -48,7 +61,7 @@ module.exports = function pipeWs(servername, service, conn, remote, serviceport)
|
||||||
conn.on('close', function (hadErr) {
|
conn.on('close', function (hadErr) {
|
||||||
//if (state.debug) { console.log('[pipeWs] client', cid, 'closing'); }
|
//if (state.debug) { console.log('[pipeWs] client', cid, 'closing'); }
|
||||||
sendWs(null, hadErr ? 'error': 'end');
|
sendWs(null, hadErr ? 'error': 'end');
|
||||||
delete remote.clients[cid];
|
delete srv.clients[cid];
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
949
lib/relay.js
949
lib/relay.js
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,11 @@ module.exports.createTcpConnectionHandler = function (state) {
|
||||||
|
|
||||||
//return;
|
//return;
|
||||||
conn.once('data', function (firstChunk) {
|
conn.once('data', function (firstChunk) {
|
||||||
|
var service = 'tcp';
|
||||||
|
var servername;
|
||||||
|
var str;
|
||||||
|
var m;
|
||||||
|
|
||||||
conn.pause();
|
conn.pause();
|
||||||
conn.unshift(firstChunk);
|
conn.unshift(firstChunk);
|
||||||
|
|
||||||
|
@ -31,18 +36,13 @@ module.exports.createTcpConnectionHandler = function (state) {
|
||||||
// defer after return (instead of being in many places)
|
// defer after return (instead of being in many places)
|
||||||
function deferData(fn) {
|
function deferData(fn) {
|
||||||
if (fn) {
|
if (fn) {
|
||||||
state[fn](servername, conn)
|
state[fn](servername, conn);
|
||||||
}
|
}
|
||||||
process.nextTick(function () {
|
process.nextTick(function () {
|
||||||
conn.resume();
|
conn.resume();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var service = 'tcp';
|
|
||||||
var servername;
|
|
||||||
var str;
|
|
||||||
var m;
|
|
||||||
|
|
||||||
function tryTls() {
|
function tryTls() {
|
||||||
var vhost;
|
var vhost;
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ module.exports.createTcpConnectionHandler = function (state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.debug) { console.log("pipeWs(servername, service, socket, deviceLists['" + servername + "'])"); }
|
if (state.debug) { console.log("pipeWs(servername, service, deviceLists['" + servername + "'], socket)"); }
|
||||||
deferData();
|
deferData();
|
||||||
pipeWs(servername, service, conn, nextDevice, serviceport);
|
pipeWs(servername, service, nextDevice, conn, serviceport);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO don't run an fs check if we already know this is working elsewhere
|
// TODO don't run an fs check if we already know this is working elsewhere
|
||||||
|
@ -90,7 +90,7 @@ module.exports.createTcpConnectionHandler = function (state) {
|
||||||
//return;
|
//return;
|
||||||
require('fs').readdir(vhost, function (err, nodes) {
|
require('fs').readdir(vhost, function (err, nodes) {
|
||||||
if (state.debug && err) { console.log("VHOST error", err); }
|
if (state.debug && err) { console.log("VHOST error", err); }
|
||||||
if (err) { run(); return; }
|
if (err || !nodes) { run(); return; }
|
||||||
//if (nodes) { deferData('httpsVhost'); return; }
|
//if (nodes) { deferData('httpsVhost'); return; }
|
||||||
deferData('httpsVhost');
|
deferData('httpsVhost');
|
||||||
});
|
});
|
||||||
|
@ -131,7 +131,7 @@ module.exports.createTcpConnectionHandler = function (state) {
|
||||||
// HTTP
|
// HTTP
|
||||||
if (Devices.exist(state.deviceLists, servername)) {
|
if (Devices.exist(state.deviceLists, servername)) {
|
||||||
deferData();
|
deferData();
|
||||||
pipeWs(servername, service, conn, Devices.next(state.deviceLists, servername), serviceport);
|
pipeWs(servername, service, Devices.next(state.deviceLists, servername), conn, serviceport);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deferData('handleHttp');
|
deferData('handleHttp');
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "telebit-relay",
|
"name": "telebit-relay",
|
||||||
"version": "0.12.1",
|
"version": "0.20.0",
|
||||||
"description": "Friends don't let friends localhost. Expose your bits with a secure connection even from behind NAT, Firewalls, in a box, with a fox, on a train or in a plane... or a Raspberry Pi in your closet. An attempt to create a better localtunnel.me server, a more open ngrok. Uses Automated HTTPS (Free SSL) via ServerName Indication (SNI). Can also tunnel tls and plain tcp.",
|
"description": "Friends don't let friends localhost. Expose your bits with a secure connection even from behind NAT, Firewalls, in a box, with a fox, on a train or in a plane... or a Raspberry Pi in your closet. An attempt to create a better localtunnel.me server, a more open ngrok. Uses Automated HTTPS (Free SSL) via ServerName Indication (SNI). Can also tunnel tls and plain tcp.",
|
||||||
"main": "lib/relay.js",
|
"main": "lib/relay.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -43,15 +43,15 @@
|
||||||
"greenlock": "^2.2.4",
|
"greenlock": "^2.2.4",
|
||||||
"human-readable-ids": "^1.0.4",
|
"human-readable-ids": "^1.0.4",
|
||||||
"js-yaml": "^3.11.0",
|
"js-yaml": "^3.11.0",
|
||||||
"jsonwebtoken": "^8.2.1",
|
"jsonwebtoken": "^8.3.0",
|
||||||
"proxy-packer": "^1.4.3",
|
"proxy-packer": "^2.0.0",
|
||||||
"recase": "^1.0.4",
|
"recase": "^1.0.4",
|
||||||
"redirect-https": "^1.1.5",
|
"redirect-https": "^1.1.5",
|
||||||
"serve-static": "^1.13.2",
|
"serve-static": "^1.13.2",
|
||||||
"sni": "^1.0.0",
|
"sni": "^1.0.0",
|
||||||
"ws": "^5.1.1"
|
"ws": "^5.1.1"
|
||||||
},
|
},
|
||||||
"engineStrict" : true,
|
"engineStrict": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "10.2.1"
|
"node": "10.2.1"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue