goldilocks.js/README.md

484 lines
12 KiB
Markdown
Raw Normal View History

2017-01-27 06:07:51 +00:00
Goldilocks
==========
2017-07-26 00:37:29 +00:00
The node.js netserver that's just right.
* **HTTPS Web Server** with Automatic TLS (SSL) via ACME ([Let's Encrypt](https://letsencrypt.org))
* Static Web Server
* URL Redirects
* SSL on localhost (with bundled localhost.daplie.me certificates)
2017-07-28 19:03:06 +00:00
* Uses node cluster to take advantage of multiple CPUs (in progress)
2017-07-26 00:37:29 +00:00
* **TLS** name-based (SNI) proxy
* **TCP** port-based proxy
* WS **Tunnel Server** (i.e. run on Digital Ocean and expose a home-firewalled Raspberry Pi to the Internet)
* WS **Tunnel Client** (i.e. run on a Raspberry Pi and connect to a Daplie Tunnel)
2017-07-28 19:03:29 +00:00
* UPnP / NAT-PMP forwarding and loopback testing (in progress)
2017-07-26 00:37:29 +00:00
* Configurable via API
* mDNS Discoverable (configure in home or office with mobile and desktop apps)
* OAuth3 Authentication
Install Standalone
2015-06-24 21:44:42 +00:00
-------
```bash
2017-07-26 00:37:29 +00:00
# v1 in npm
2017-02-22 22:00:14 +00:00
npm install -g goldilocks
2017-01-08 00:21:12 +00:00
# v1 in git (via ssh)
2017-05-05 07:33:36 +00:00
npm install -g git+ssh://git@git.daplie.com:Daplie/goldilocks.js#v1
2017-01-08 00:21:12 +00:00
# v1 in git (unauthenticated)
2017-05-05 07:33:36 +00:00
npm install -g git+https://git@git.daplie.com:Daplie/goldilocks.js#v1
2015-06-24 21:44:42 +00:00
```
2017-01-07 23:43:45 +00:00
```bash
2017-02-22 22:00:14 +00:00
goldilocks
2015-06-24 21:44:42 +00:00
```
2017-01-07 23:43:45 +00:00
```bash
Serving /Users/foo/ at https://localhost.daplie.me:8443
2015-06-24 21:44:42 +00:00
```
2017-07-26 00:37:29 +00:00
Install as a System Service (daemon-mode)
We have service support for
2017-05-05 07:33:36 +00:00
2017-07-26 00:37:29 +00:00
* systemd (Linux, Ubuntu)
* launchd (macOS)
2017-05-05 07:33:36 +00:00
```bash
curl https://git.daplie.com/Daplie/goldilocks.js/raw/master/install.sh | bash
```
2017-07-26 00:37:29 +00:00
Modules & Configuration
2015-06-24 21:44:42 +00:00
-----
Goldilocks has several core systems, which all have their own configuration and
some of which have modules:
* [http](#http)
- [proxy (reverse proxy)](#httpproxy-how-to-reverse-proxy-ruby-python-etc)
- [static](#httpstatic-how-to-serve-a-web-page)
- [redirect](#httpredirect-how-to-redirect-urls)
* [tls](#tls)
- [proxy (reverse proxy)](#tlsproxy)
- [acme](#tlsacme)
* [tcp](#tcp)
- [forward](#tcpforward)
* [udp](#udp)
- [forward](#udpforward)
* [domains](#domains)
* [tunnel_server](#tunnel_server)
* [tunnel_client](#tunnel)
* [mdns](#mdns)
2017-10-13 18:39:31 +00:00
* [socks5](#socks5)
2017-07-26 00:37:29 +00:00
* api
All modules require a `type` and an `id`, and any modules not defined inside the
`domains` system also require a `domains` field (with the exception of the `forward`
modules that require the `ports` field).
2017-07-26 00:37:29 +00:00
### http
The HTTP system handles plain http (TLS / SSL is handled by the tls system)
Example config:
```yml
2017-07-26 00:37:29 +00:00
http:
trust_proxy: true # allow localhost, 192.x, 10.x, 172.x, etc to set headers
allow_insecure: false # allow non-https even without proxy https headers
primary_domain: example.com # attempts to access via IP address will redirect here
# An array of modules that define how to handle incoming HTTP requests
2017-07-26 00:37:29 +00:00
modules:
- type: static
2017-07-26 00:37:29 +00:00
domains:
- example.com
root: /srv/www/:hostname
```
### http.proxy - how to reverse proxy (ruby, python, etc)
2017-07-26 00:37:29 +00:00
The proxy module is for reverse proxying, typically to an application on the same machine.
(Though it can also reverse proxy to other devices on the local network.)
2017-07-26 00:37:29 +00:00
It has the following options:
2017-07-26 00:37:29 +00:00
```
address The DNS-resolvable hostname (or IP address) and port connected by `:` to proxy the request to.
Takes priority over host and port if they are also specified.
ex: locahost:3000
ex: 192.168.1.100:80
host The DNS-resolvable hostname (or IP address) of the system to which the request will be proxied.
Defaults to localhost if only the port is specified.
ex: localhost
ex: 192.168.1.100
port The port on said system to which the request will be proxied
ex: 3000
ex: 80
2017-07-26 00:37:29 +00:00
```
Example config:
```yml
2017-07-26 00:37:29 +00:00
http:
modules:
- type: proxy
2017-07-26 00:37:29 +00:00
domains:
- api.example.com
host: 192.168.1.100
port: 80
- type: proxy
domains:
- www.example.com
address: 192.168.1.16:80
- type: proxy
domains:
- '*'
port: 3000
2017-07-26 00:37:29 +00:00
```
### http.static - how to serve a web page
2017-07-26 00:37:29 +00:00
The static module is for serving static web pages and assets and has the following options:
2017-01-20 20:13:41 +00:00
2016-10-17 23:50:17 +00:00
```
root The path to serve as a string.
The template variable `:hostname` represents the HTTP Host header without port information
ex: `root: /srv/www/example.com` would load the example.com folder for any domain listed
ex: `root: /srv/www/:hostname` would load `/srv/www/example.com` if so indicated by the Host header
2017-07-26 00:37:29 +00:00
```
2016-10-17 23:52:32 +00:00
2017-07-26 00:37:29 +00:00
Example config:
```yml
2017-07-26 00:37:29 +00:00
http:
modules:
- type: static
2017-07-26 00:37:29 +00:00
domains:
- example.com
root: /srv/www/:hostname
2017-07-26 00:37:29 +00:00
```
2016-10-17 23:46:11 +00:00
2017-07-26 00:37:29 +00:00
### http.redirect - how to redirect URLs
2017-07-26 00:37:29 +00:00
The redirect module is for, you guessed it, redirecting URLs.
2017-07-26 00:37:29 +00:00
It has the following options:
2015-07-08 07:46:01 +00:00
```
2017-07-26 00:37:29 +00:00
status The HTTP status code to issue (301 is usual permanent redirect, 302 is temporary)
ex: 301
from The URL path that was used in the request.
The `*` wildcard character can be used for matching a full segment of the path
ex: /photos/
ex: /photos/*/*/
to The new URL path which should be used.
If wildcards matches were used they will be available as `:1`, `:2`, etc.
ex: /pics/
ex: /pics/:1/:2/
2015-07-08 07:46:01 +00:00
```
2017-07-26 00:37:29 +00:00
Example config:
```yml
2017-07-26 00:37:29 +00:00
http:
modules:
- type: proxy
2017-07-26 00:37:29 +00:00
domains:
- example.com
status: 301
from: /archives/*/*/*/
to: https://example.net/year/:1/month/:2/day/:3/
```
2015-07-08 07:46:01 +00:00
2017-07-26 00:37:29 +00:00
### tls
2015-06-30 23:11:01 +00:00
2017-07-26 00:37:29 +00:00
The tls system handles encrypted connections, including fetching certificates,
and uses ServerName Indication (SNI) to determine if the connection should be
handled by the http system, a tls system module, or rejected.
2017-07-26 00:37:29 +00:00
Example config:
```yml
tls:
modules:
- type: proxy
2017-07-26 00:37:29 +00:00
domains:
- example.com
- example.net
address: '127.0.0.1:6443'
```
2017-07-26 00:37:29 +00:00
Certificates are saved to `~/acme`, which may be `/var/www/acme` if Goldilocks is run as the www-data user.
### tls.proxy
The proxy module routes the traffic based on the ServerName Indication (SNI) **without decrypting** it.
It has the same options as the [HTTP proxy module](#httpproxy-how-to-reverse-proxy-ruby-python-etc).
2015-07-08 06:51:38 +00:00
Example config:
2017-07-26 00:37:29 +00:00
```yml
tls:
modules:
- type: proxy
2017-07-26 00:37:29 +00:00
domains:
- example.com
address: '127.0.0.1:5443'
```
### tls.acme
2017-07-26 00:37:29 +00:00
The acme module defines the setting used when getting new certificates.
2017-07-26 00:37:29 +00:00
It has the following options:
```
email The email address for ACME certificate issuance
ex: john.doe@example.com
server The ACME server to use
ex: https://acme-v01.api.letsencrypt.org/directory
ex: https://acme-staging.api.letsencrypt.org/directory
challenge_type The ACME challenge to request
ex: http-01, dns-01, tls-01
```
2017-07-26 00:37:29 +00:00
Example config:
```yml
tls:
modules:
- type: acme
2017-07-26 00:37:29 +00:00
domains:
- example.com
- example.net
email: 'joe.shmoe@example.com'
server: 'https://acme-staging.api.letsencrypt.org/directory'
challenge_type: 'http-01'
2017-07-26 00:37:29 +00:00
```
### tcp
The tcp system handles all tcp network traffic **before decryption** and may use port numbers
or traffic sniffing to determine how the connection should be handled.
It has the following options:
```
2017-07-26 00:37:29 +00:00
bind An array of numeric ports on which to bind
ex: 80
```
Example Config:
```yml
2017-07-26 00:37:29 +00:00
tcp:
bind:
- 22
- 80
- 443
modules:
- type: forward
2017-07-26 00:37:29 +00:00
ports:
- 22
address: '127.0.0.1:2222'
```
### tcp.forward
The forward module routes traffic based on port number **without decrypting** it.
In addition to the same options as the [HTTP proxy module](#httpproxy-how-to-reverse-proxy-ruby-python-etc),
the TCP forward modules also has the following options:
2017-07-26 00:37:29 +00:00
```
ports A numeric array of source ports
ex: 22
```
Example Config:
```yml
2017-07-26 00:37:29 +00:00
tcp:
bind:
- 22
- 80
- 443
modules:
- type: forward
2017-07-26 00:37:29 +00:00
ports:
- 22
port: 2222
```
### udp
The udp system handles all udp network traffic. It currently only supports
forwarding the messages without any examination.
It has the following options:
```
bind An array of numeric ports on which to bind
ex: 53
```
Example Config:
```yml
udp:
bind:
- 53
modules:
- type: forward
ports:
- 53
address: '127.0.0.1:8053'
```
### udp.forward
The forward module routes traffic based on port number **without decrypting** it.
It has the same options as the [TCP forward module](#tcpforward).
Example Config:
```yml
udp:
bind:
- 53
modules:
- type: forward
ports:
- 53
address: '127.0.0.1:8053'
```
### domains
To reduce repetition defining multiple modules that operate on the same domain
name the `domains` field can define multiple modules of multiple types for a
single list of names. The modules defined this way do not need to have their
own `domains` field.
Example Config
```yml
domains:
names:
- example.com
- www.example.com
- api.example.com
modules:
tls:
- type: acme
email: joe.schmoe@example.com
challenge_type: 'http-01'
http:
- type: redirect
from: /deprecated/path
to: /new/path
- type: proxy
port: 3000
2017-07-26 00:37:29 +00:00
```
### tunnel\_server
The tunnel server system is meant to be run on a publicly accessible IP address to server tunnel clients
which are behind firewalls, carrier-grade NAT, or otherwise Internet-connect but inaccessible devices.
It has the following options:
```
secret A 128-bit or greater string to use for signing tokens (HMAC JWT)
ex: abc123
servernames An array of string servernames that should be captured as the
tunnel server, ignoring the TLS forward module
2017-07-26 00:37:29 +00:00
ex: api.tunnel.example.com
```
Example config:
```yml
2017-07-26 00:37:29 +00:00
tunnel_server:
secret: abc123def456ghi789
servernames:
- 'api.tunnel.example.com'
```
2017-07-26 17:44:08 +00:00
### tunnel
2017-07-26 00:37:29 +00:00
2017-07-26 17:44:08 +00:00
The tunnel client is meant to be run from behind a firewalls, carrier-grade NAT,
or otherwise inaccessible devices to allow them to be accessed publicly on the
internet.
It has no options per se, but is rather a list of tokens that can be used to
connect to tunnel servers. If the token does not have an `aud` field it must be
provided in an object with the token provided in the `jwt` field and the tunnel
server url provided in the `tunnelUrl` field.
Example config:
```yml
tunnel:
- 'some.jwt_encoded.token'
- jwt: 'other.jwt_encoded.token'
tunnelUrl: 'wss://api.tunnel.example.com/'
```
2017-07-26 00:37:29 +00:00
### ddns
TODO
### mdns
enabled by default
Although it does not announce itself, Goldilocks is discoverable via mDNS with the special query `_cloud._tcp.local`.
This is so that it can be easily configured via Desktop and Mobile apps when run on devices such as a Raspberry Pi or
SOHO servers.
```yaml
2017-07-26 00:37:29 +00:00
mdns:
disabled: false
port: 5353
broadcast: '224.0.0.251'
ttl: 300
```
You can discover goldilocks with `mdig`.
```
npm install -g git+https://git.daplie.com/Daplie/mdig.git
mdig _cloud._tcp.local
```
2017-08-04 21:23:15 +00:00
### socks5
Run a Socks5 proxy server.
```yaml
socks5:
enable: true
port: 1080
```
2017-07-26 00:37:29 +00:00
### api
See [API.md](/API.md)
2017-07-26 00:37:29 +00:00
@tigerbot: How are the APIs used (in terms of URL, Method, Headers, etc)?
TODO
----
* [ ] http - nowww module
* [ ] http - Allow match styles of `www.*`, `*`, and `*.example.com` equally
* [ ] http - redirect based on domain name (not just path)
* [ ] tcp - bind should be able to specify localhost, uniquelocal, private, or ip
* [ ] tcp - if destination host is omitted default to localhost, if dst port is missing, default to src
* [ ] sys - `curl https://daplie.me/goldilocks | bash -s example.com`
* [ ] oauth3 - `example.com/.well-known/domains@oauth3.org/directives.json`
* [ ] oauth3 - commandline questionnaire
* [x] modules - use consistent conventions (i.e. address vs host + port)
* [x] tls - tls.acme vs tls.modules.acme
* [ ] tls - forward should be able to match on source port to reach different destination ports