Expose your local endpoints to the Internet
inlets combines a reverse proxy and websocket tunnels to expose your internal and development endpoints to the public Internet via an exit-node. An exit-node may be a 5-10 USD VPS or any other computer with an IPv4 IP address.
Why do we need this project? Similar tools such as ngrok or Argo Tunnel from Cloudflare are closed-source, have limits built-in, can work out expensive and have limited support for arm/arm64. Ngrok is also often banned by corporate firewall policies meaning it can be unusable. Other open-source tunnel tools are designed to only set up a static tunnel. inlets aims to dynamically bind and discover your local services to DNS entries with automated TLS certificates to a public IP address over its websocket tunnel.
When combined with SSL - inlets can be used with any corporate HTTP proxy which supports
- automatically create endpoints on exit-node based upon client definitions
- multiplex sites on same port through use of DNS / host entries
- link encryption using SSL over websockets (
- automatic reconnect
- authentication using service account or basic auth
- automatic TLS provisioning for endpoints using cert-magic
- configure staging or production LetsEncrypt issuer using HTTP01 challenge
- discover and configure endpoints for Ingress definitions from Kubernetes
- configuration to run "exit-node" as serverless container with Azure ACI / AWS Fargate
- automatic configuration of DNS / A records
- configure staging or production LetsEncrypt issuer using DNS01 challenge
- tunnelling plain (non-HTTP) traffic over TCP
Unlike HTTP 1.1 which follows a synchronous request/response model websockets use an asynchronous pub/sub model for sending and receiving messages. This presents a challenge for tunneling a synchronous protocol over an asynchronous bus. This is a working prototype that can be used for testing, development and to generate discussion, but is not production-ready.
There is currently no authentication on the server componentThe tunnel link is secured via
-tokenflag and a shared secret
- The default configuration uses websockets without SSL
ws://, but to enable encryption you could enable SSL
There is no timeout for when the tunnel is disconnectedtimeout can be configured via args on the server The upstream URL has to be configured on both server and client until a discovery or service advertisement mechanism is addedadvertise on the client
Binaries for Linux, Darwin (MacOS) and armhf are made available via the releases page
Test it out
You can get a binary release from the releases pages and skip the installation of Go.
- On the server or exit-node
Start the tunnel server on a machine with a publicly-accessible IPv4 IP address such as a VPS.
./inlets -server=true -port=80
Note: You can pass the
-tokenargument followed by a token value to both the server and client to prevent unauthorized connections to the tunnel.
Example with token:
token=$(head -c 16 /dev/urandom | shasum | cut -d" " -f1); ./inlets -server=true -port=8090 -token="$token"
Note down your public IPv4 IP address i.e. 192.168.0.101
- On your machine behind the firewall start an example service that you want to expose to the Internet
You can use my hash-browns service for instance which generates hashes.
Install hash-browns or run your own HTTP server
go get -u github.com/alexellis/hash-browns cd $GOPATH/src/github.com/alexellis/hash-browns port=3000 go run server.go
- On your machine behind the firewall
Start the tunnel client
./inlets -server=false \ -remote=192.168.0.101:80 \ -upstream=http://127.0.0.1:3000
-remote with the address where your other machine is listening.
We now have an example service running (hash-browns), a tunnel server and a tunnel client.
So send a request to the public IP address or hostname:
./inlets -server=false -remote=192.168.0.101:80 -upstream "gateway.mydomain.tk=http://127.0.0.1:3000"
curl -d "hash this" http://192.168.0.101/hash -H "Host: gateway.mydomain.tk" # or curl -d "hash this" http://192.168.0.101/hash # or curl -d "hash this" http://gateway.mydomain.tk/hash
You will see the traffic pass between the exit node / server and your development machine. You'll see the hash message appear in the logs as below:
~/go/src/github.com/alexellis/hash-browns$ port=3000 go run server.go 2018/12/23 20:15:00 Listening on port: 3000 "hash this"
Now check the metrics endpoint which is built-into the hash-browns example service:
curl http://192.168.0.101/metrics | grep hash
For development you will need Golang 1.10 or 1.11 on both the exit-node or server and the client.
You can get the code like this:
go get -u github.com/alexellis/inlets cd $GOPATH/src/github.com/alexellis/inlets
Contributions are welcome. All commits must be signed-off with
git commit -s to accept the Developer Certificate of Origin.
Take things further
You can expose an OpenFaaS or OpenFaaS Cloud deployment with
inlets - just change
-upstream=http://127.0.0.1:31112. You can even point at an IP address inside or outside your network for instance:
You can build a basic supervisor script for
inlets in case of a crash, it will re-connect within 5 seconds:
In this example the Host/Client is acting as a relay for OpenFaaS running on port 8080 on the IP 192.168.0.28 within the internal network.
while [ true ] ; do sleep 5 && ./inlets -server=false -upstream=http://192.168.0.28:8080 -remote=exit.my.club ; done
while [ true ] ; do sleep 5 && ./inlets -server=true -upstream=http://192.168.0.28:8080 ; done
Run as a deployment on Kubernetes
You can even run
inlets within your Kubernetes in Docker (kind) cluster to get ingress (incoming network) for your services such as the OpenFaaS gateway:
apiVersion: apps/v1beta1 # for versions before 1.6.0 use extensions/v1beta1 kind: Deployment metadata: name: inlets spec: replicas: 1 template: metadata: labels: app: inlets spec: containers: - name: inlets image: alexellis2/inlets-runtime:0.4.0 imagePullPolicy: Always command: ["./inlets"] args: - "-server=false" - "-upstream=http://gateway.openfaas:8080" - "-remote=your-public-ip"
Replace the line:
- "-remote=your-public-ip" with the public IP belonging to your VPS.
Run on a VPS
Provisioning on a VPS will see inlets running as a systemd service. All the usual
service commands should be used with
inlets as the service name.
Inlets uses a token to prevent unauthorized access to the server component. A known token can be configured by amending userdata.sh prior to provisioning
# Enables randomly generated authentication token by default. # Change the value here if you desire a specific token value. export INLETSTOKEN=$(head -c 16 /dev/urandom | shasum | cut -d" " -f1)
If the token value is randomly generated then you will need to access the VPS in order to obtain the token value.
Scaleway offer probably the cheapest option at 1.99 EUR / month using the "1-XS" from the "Start" tier.
If you have the Scaleway CLI installed you can provision a host with ./hack/provision-scaleway.sh.
- Digital Ocean
If you are a Digital Ocean user and use
doctl then you can provision a host with ./hack/provision-digitalocean.sh. Please ensure you have configured
droplet.create.ssh-keys within your
Where can I get a cheap / free domain-name?
You can get a free domain-name with a .tk / .ml or .ga TLD from https://www.freenom.com - make sure the domain has at least 4 letters to get it for free. You can also get various other domains starting as cheap as 1-2USD from https://www.namecheap.com
Namecheap provides wildcard TLS out of the box, but freenom only provides root/naked domain and a list of sub-domains. Domains from both providers can be moved to alternative nameservers for use with AWS Route 53 or Google Cloud DNS - this then enables wildcard DNS and the ability to get a wildcard TLS certificate from LetsEncrypt.