155 lines
3.9 KiB
Markdown
155 lines
3.9 KiB
Markdown
# stunnel.js
|
|
|
|
A client that works in combination with [stunneld.js](https://github.com/Daplie/node-tunnel-server)
|
|
to allow you to serve http and https from any computer, anywhere through a secure tunnel.
|
|
|
|
* CLI
|
|
* Library
|
|
|
|
CLI
|
|
===
|
|
|
|
Installs as `stunnel.js` with the alias `jstunnel`
|
|
(for those that regularly use `stunnel` but still like commandline completion).
|
|
|
|
### Install
|
|
|
|
```bash
|
|
npm install -g stunnel
|
|
```
|
|
|
|
### Advanced Usage
|
|
|
|
How to use `stunnel.js` with your own instance of `stunneld.js`:
|
|
|
|
```bash
|
|
stunnel.js --locals john.example.com --stunneld wss://tunnel.example.com:443 --secret abc123
|
|
```
|
|
|
|
```bash
|
|
stunnel.js \
|
|
--locals http:john.example.com:3000,https:john.example.com \
|
|
--stunneld wss://tunnel.example.com:443 \
|
|
--secret abc123
|
|
```
|
|
|
|
```
|
|
--secret the same secret used by stunneld (used for authentication)
|
|
--locals comma separated list of <proto>:<servername>:<port> to which
|
|
incoming http and https should be forwarded
|
|
--stunneld the domain or ip address at which you are running stunneld.js
|
|
-k, --insecure ignore invalid ssl certificates from stunneld
|
|
```
|
|
|
|
### Usage
|
|
|
|
**NOT YET IMPLEMENTED**
|
|
|
|
Daplie's tunneling service is not yet publicly available.
|
|
|
|
**Terms of Service**: The Software and Services shall be used for Good, not Evil.
|
|
Examples of good: education, business, pleasure. Examples of evil: crime, abuse, extortion.
|
|
|
|
```bash
|
|
stunnel.js --agree-tos --email john@example.com --locals http:john.example.com:4080,https:john.example.com:8443
|
|
```
|
|
|
|
Library
|
|
=======
|
|
|
|
### Example
|
|
|
|
```javascript
|
|
var stunnel = require('stunnel');
|
|
|
|
stunnel.connect({
|
|
stunneld: 'wss://tunnel.example.com'
|
|
, token: '...'
|
|
, locals: [
|
|
// defaults to sending http to local port 80 and https to local port 443
|
|
{ hostname: 'doe.net' }
|
|
|
|
// sends both http and https to local port 3000 (httpolyglot)
|
|
, { protocol: 'https', hostname: 'john.doe.net', port: 3000 }
|
|
|
|
// send http to local port 4080 and https to local port 8443
|
|
, { protocol: 'https', hostname: 'jane.doe.net', port: 4080 }
|
|
, { protocol: 'https', hostname: 'jane.doe.net', port: 8443 }
|
|
]
|
|
|
|
, net: require('net')
|
|
, insecure: false
|
|
});
|
|
```
|
|
|
|
* You can get sneaky with `net` and provide a `createConnection` that returns a `stream.Duplex`.
|
|
|
|
### Token
|
|
|
|
```javascript
|
|
var tokenData = { domains: [ 'doe.net', 'john.doe.net', 'jane.doe.net' ] }
|
|
var secret = 'shhhhh';
|
|
var token = jwt.sign(tokenData, secret);
|
|
```
|
|
|
|
### net
|
|
|
|
Let's say you want to handle http requests in-process
|
|
or decrypt https before passing it to the local http handler.
|
|
|
|
You'll need to create a pair of streams to connect between the
|
|
local handler and the tunnel handler.
|
|
|
|
You could do a little magic like this:
|
|
|
|
```
|
|
var Dup = {
|
|
write: function (chunk, encoding, cb) {
|
|
this.__my_socket.write(chunk, encoding);
|
|
cb();
|
|
}
|
|
, read: function (size) {
|
|
var x = this.__my_socket.read(size);
|
|
if (x) { this.push(x); }
|
|
}
|
|
};
|
|
|
|
stunnel.connect({
|
|
// ...
|
|
, net: {
|
|
createConnection: function (info, cb) {
|
|
// data is the hello packet / first chunk
|
|
// info = { data, servername, port, host, remoteAddress: { family, address, port } }
|
|
|
|
var myDuplex = new (require('stream').Duplex)();
|
|
var myDuplex2 = new (require('stream').Duplex)();
|
|
// duplex = { write, push, end, events: [ 'readable', 'data', 'error', 'end' ] };
|
|
|
|
myDuplex2.__my_socket = myDuplex;
|
|
myDuplex2._write = Dup.write;
|
|
myDuplex2._read = Dup.read;
|
|
|
|
myDuplex.__my_socket = myDuplex2;
|
|
myDuplex._write = Dup.write;
|
|
myDuplex._read = Dup.read;
|
|
|
|
myDuplex.remoteFamily = info.remoteFamily;
|
|
myDuplex.remoteAddress = info.remoteAddress;
|
|
myDuplex.remotePort = info.remotePort;
|
|
|
|
// socket.local{Family,Address,Port}
|
|
myDuplex.localFamily = 'IPv4';
|
|
myDuplex.localAddress = '127.0.01';
|
|
myDuplex.localPort = info.port;
|
|
|
|
httpsServer.emit('connection', myDuplex);
|
|
|
|
if (cb) {
|
|
process.nextTick(cb);
|
|
}
|
|
|
|
return myDuplex2;
|
|
}
|
|
});
|
|
```
|