An API Gateway based on websockets to expose HTTP(S) endpoints not reachable from the Internet - implemented in node.js. The gateway allows you to reach endpoints not reachable due to NAT, ISP restrictions, or any other reasons.
In the preceding scenario Client
can not directly connect to Server
as no connection to Router 2
can be established from the Internet
.
When using the socket-gateway the inner layer (a component that is able to establish a connection to Server
) creates a persistent websocket connection (Inner layer -> Router 2 -> Internet -> Router 3 -> Outer layer
) to the outer layer (a compoent that can be connected to from the Internet
).
The outer layer uses that connection to forward requests to the target network (if allowed).
Client
can connect to Server
using the socket-gateway via Client -> Router 1 -> Internet -> Router 3 -> Outer layer -> Router 3 -> Internet -> Router 2 -> Inner layer -> Router 2 -> Server
.
# https://hub.docker.com/r/markushinz/socket-gateway/tags
docker pull markushinz/socket-gateway:latest
⚠️ This is a very simple setup. Check out the help section for all configuration options and this example for a secure production setup.
# npm https://github.com/markushinz/socket-gateway/releases
npm install -g https://github.com/markushinz/socket-gateway/releases/latest/download/socket-gateway.tgz
socket-gateway certificates # generate certificate (innerLayer.crt and innerLayer.key)
echo '{"targets":{"localhost":{"hostname":"jsonplaceholder.typicode.com"}}}' > targets.yaml
socket-gateway outer-layer \
--inner-layer-certificate innerLayer.crt \
--targets targets.yaml \
--app-port 3000 \
--socket-port 3001 # keep running
socket-gateway inner-layer \
--inner-layer-private-key innerLayer.key \
--outer-layer ws://localhost:3001 # keep running
curl http://localhost:3000 # just like curl https://jsonplaceholder.typicode.com
- Outer Layer: A machine/server that is reachable from the Internet (usually cloud hosted).
- Inner Layer(s): A machine/server that is able to reach the desired endpoint(s) (usually a machine/server located in the same LAN) that is able to reach the Internet. The other way round is not required! If you deploy multiple inner layers, the requests will be forwarded to the different inner layers using a custom scheduling technique.
Define host mappings between DNS names of the gateway (outer layer) and request targets. Keep in mind that multiple A or CNAME DNS records can point to the same outer layer 🥳! Check the following example:
targets:
"socket.gateway": # DNS name of the outer layer
protocol: "https" # optional, target protocol, defaults to "https"
hostname: "my.private.api" # required, target hostname
port: 443 # optional, target port, defaults to 443
policy: # optional, defaults to *
# /helloworld gets compiled to ^/helloworld$
# specify paths with a leading ^ if you want to use more advanced regexes
"/helloworld": # allowed path(s), may be *
- "GET"
- "POST" # allowed method(s), may be or include *
identifier: "inner-layer" # optional, identifier or list of identifiers to route to. If not specified, requests will get routed to any connected inner layer
Now, all requests that are allowed py the specified policy that have the request header "host" set to "socket.gateway" get proxied to "my.private.api".
Optional: Provide an environment variable NODE_EXTRA_CA_CERTS
to extend the well known "root" CAs for your private APIs.
$ socket-gateway certificates --help
Generate certificates
Options:
--help Show help [boolean]
--version Show version number [boolean]
--private-key The private key file to write
[default: "innerLayer.key"]
--certificate, --public-key The public key file to write
[default: "innerLayer.crt"]
--common-name The common name of the certificate
[default: "inner-layer"]
--validity The certificate validity in years [default: 100]
$ socket-gateway outer-layer
Start the outer-layer --help
Options:
--help Show help [boolean]
--version Show version number [boolean]
--admin-password The admin password [string]
--trust-proxy [default: "loopback, linklocal, uniquelocal"]
--timeout [default: 180000]
--validity [default: 1000]
--remove-csps Removes content-security-policy response headers
[boolean] [default: false]
--app-port The port the gateway consumers connect to [default: 3000]
--socket-port The port the inner layer(s) connect to [default: 3001]
--public-key The corresponsing public key or certificate file of the
inner layer(s) [required]
--targets The targets file
$ socket-gateway inner-layer --help
Start the inner-layer
Options:
--help Show help [boolean]
--version Show version number [boolean]
--inner-layer-identifier, --identifier The identifier to distinguish
multiple inner layers
[default: "<hostname>"]
--outer-layer-ca The outer layer cert or CA file to
check against. If not provided all
well known CAs are accepted.[string]
--inner-layer-private-key, --private-key The private key file used to
authenticate against the outer
layer. The private key is used
during a challenge-response
authentication mechanism. [required]
--inner-layer-certificate The certificate file signed by the
private key to use when establishing
the TLS connection to the outer
layer. Provide the certificate if
you want to use client certificate
authenticaion on top of the
challenge-response authentication
mechanism. [string]
--outer-layer The outer layer URI to connect to
[required]
--insecure Allow connections to the outer layer
via http/ws
[boolean] [default: false]