goldilocks.js/README.md

468 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
-----
2017-07-26 00:37:29 +00:00
Goldilocks has several core systems, which all have their own configuration and some of which have modules:
```
* http
- static
- redirect
- proxy (reverse proxy)
* tls
- acme
- proxy (reverse proxy)
* tcp
- forward
* tunnel_server
* tunnel_client
* mdns
* api
```
### http
The HTTP system handles plain http (TLS / SSL is handled by the tls system)
```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
# modules can be nested in domains
domains:
- names:
- example.com
modules:
- name: static
root: /srv/www/:hostname
# The configuration above could also be represented as follows:
modules:
- name: static
domains:
- example.com
root: /srv/www/:hostname
```
### http.static - how to serve a web page
The static module is for serving static web pages and assets and has the following options:
```
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
```
Example config:
2016-10-17 23:50:17 +00:00
```yml
2017-07-26 00:37:29 +00:00
http:
modules:
- name: static
domains:
- example.com
root: /srv/www/:hostname
```
### http.proxy - how to reverse proxy (ruby, python, etc)
2017-01-20 20:13:41 +00:00
2017-07-26 00:37:29 +00:00
The proxy module is for reverse proxying, typically to an application on the same machine.
It has the following options:
2017-01-20 20:13:41 +00:00
2016-10-17 23:50:17 +00:00
```
2017-07-26 00:37:29 +00:00
host The DNS-resolvable hostname (or IP address) of the system to which the request will be proxied
ex: localhost
ex: 192.168.1.100
2016-10-17 23:50:17 +00:00
2017-07-26 00:37:29 +00:00
port The port on said system to which the request will be proxied
ex: 3000
ex: 80
```
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:
- name: proxy
domains:
- example.com
host: localhost
port: 3000
```
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:
- name: proxy
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.
2015-06-30 23:11:01 +00:00
2017-07-26 00:37:29 +00:00
It has the following options:
2015-06-30 23:11:01 +00:00
2017-07-26 00:37:29 +00:00
```
acme.email The default email address for ACME certificate issuance
ex: john.doe@example.com
2015-06-30 23:11:01 +00:00
2017-07-26 00:37:29 +00:00
acme.server The default ACME server to use
ex: https://acme-v01.api.letsencrypt.org/directory
ex: https://acme-staging.api.letsencrypt.org/directory
2015-06-30 23:11:01 +00:00
2017-07-26 00:37:29 +00:00
acme.challenge_type The default ACME challenge to request
ex: http-01, dns-01, tls-01
acme.approved_domains The domains for which to request certificates
ex: example.com
2015-06-30 23:11:01 +00:00
```
2017-07-26 00:37:29 +00:00
Example config:
```yml
tls:
acme:
email: 'joe.shmoe@example.com'
# IMPORTANT: Switch to in production 'https://acme-v01.api.letsencrypt.org/directory'
server: 'https://acme-staging.api.letsencrypt.org/directory'
challenge_type: 'http-01'
approved_domains:
- example.com
- example.net
modules:
- name: proxy
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.
2017-07-26 00:37:29 +00:00
### tls.acme
2017-07-26 00:37:29 +00:00
The acme module overrides the acme defaults of the tls system and uses the same options except that `approved_domains`
(in favor of the domains in the scope of the module).
2017-07-26 00:37:29 +00:00
Example config:
2015-07-08 06:51:38 +00:00
2017-07-26 00:37:29 +00:00
```yml
tls:
modules:
- name: acme
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
### tls.proxy
The proxy module routes the traffic based on the ServerName Indication (SNI) **without decrypting** it.
It has the following options:
2017-07-26 00:37:29 +00:00
```
address The hostname (or IP) and port of the system or application that should receive the traffic
```
2017-07-26 00:37:29 +00:00
Example config:
2017-07-26 00:37:29 +00:00
```yml
tls:
modules:
2017-07-26 05:29:38 +00:00
- name: proxy
2017-07-26 00:37:29 +00:00
domains:
- example.com
address: '127.0.0.1:5443'
```
### 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:
- name: forward
ports:
- 22
address: '127.0.0.1:2222'
```
### tcp.forward
The forward module routes traffic based on port number **without decrypting** it.
It has the following options:
```
ports A numeric array of source ports
ex: 22
address The destination hostname and port
ex: 127.0.0.1:2222
```
Example Config
```yml
2017-07-26 00:37:29 +00:00
tcp:
bind:
- 22
- 80
- 443
modules:
- name: forward
ports:
- 22
address: '127.0.0.1:2222'
```
### 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
**NOTE**: The more common way to use the tunnel with goldilocks is to use the
API to have goldilocks get a token from `oauth3.org`. In order to do this you
will need to have initialized goldilocks with a token that has the `dns` and
`domains` scopes. This is probably easiest to do with the `daplie-desktop-app`,
which will also get the first tunnel token for you.
**If you want to add more domains** to handle on your device while using the tunnel
you will need to manually get a new token that will tell the tunnel server to
deliver the requests to the new domain(s) to your device. The first step in this
is to attach the new domains to your device. To get the name of the device you
can use the `config` API, but it's probably easiest to `ssh` onto the device and
get the hostname. You can also use the daplie cli tool to see what device name
your other domains are routed to.
```bash
# for every new domain you want to route attach the domain to your device
daplie devices:attach -n $new_domain -d $device_name
```
After that step you will need to use the API to get goldilocks to get a new token
that includes the new domains you attached. It is also recommended but not
required to remove the older token with the incomplete list of domains. Run the
following commands from the unit.
```bash
# remove the old token
rm /opt/goldilocks/lib/node_modules/goldilocks/var/tokens.json
# set the "refresh_token" to a bash variable `token`
TOKEN=$(python -mjson.tool /opt/goldilocks/lib/node_modules/goldilocks/var/owners.json | sed -n 's|\s*"refresh_token": "\(.*\)",|\1|p')
# tell goldilocks to get a new tunnel token
curl -H "authorization: bearer $TOKEN" -X POST https://localhost.admin.daplie.me/api/goldilocks@daplie.com/tunnel
```
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)
2017-10-24 18:51:21 +00:00
* http.static - indexes: true
2017-07-26 00:37:29 +00:00
* 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 - handle SIGHUP
* sys - `curl https://daplie.me/goldilocks | bash -s example.com`
* oauth3 - `example.com/.well-known/domains@oauth3.org/directives.json`
* oauth3 - commandline questionnaire
* modules - use consistent conventions (i.e. address vs host + port)
* tls - tls.acme vs tls.modules.acme
* tls - forward should be able to match on source port to reach different destination ports