refactor cmds for goreleaser
This commit is contained in:
parent
750f339f58
commit
ade7f0ba80
|
@ -0,0 +1,48 @@
|
||||||
|
# This is an example goreleaser.yaml file with some sane defaults.
|
||||||
|
# Make sure to check the documentation at http://goreleaser.com
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
# You may remove this if you don't use go modules.
|
||||||
|
- go mod download
|
||||||
|
# you may remove this if you don't need go generate
|
||||||
|
- go generate ./...
|
||||||
|
builds:
|
||||||
|
- id: telebit-client
|
||||||
|
main: ./cmd/telebit/telebit.go
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
- darwin
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
- arm
|
||||||
|
- id: telebit-mgmt
|
||||||
|
main: ./cmd/mgmt/mgmt.go
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
- darwin
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
- arm
|
||||||
|
archives:
|
||||||
|
- replacements:
|
||||||
|
386: i386
|
||||||
|
amd64: x86_64
|
||||||
|
arm64: aarch64
|
||||||
|
checksum:
|
||||||
|
name_template: 'checksums.txt'
|
||||||
|
snapshot:
|
||||||
|
name_template: "{{ .Tag }}-next"
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- '^docs:'
|
||||||
|
- '^test:'
|
352
README.md
352
README.md
|
@ -1,9 +1,45 @@
|
||||||
# Telebit
|
# Telebit
|
||||||
|
|
||||||
|
| **Telebit Client** | [Telebit Relay](/tree/master/cmd/telebit) | [Telebit Mgmt](/tree/master/cmd/mgmt) |
|
||||||
|
|
||||||
A secure, end-to-end Encrypted tunnel.
|
A secure, end-to-end Encrypted tunnel.
|
||||||
|
|
||||||
Because friends don't let friends localhost.
|
Because friends don't let friends localhost.
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
telebit --env ./.env --verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
Command-line flags or `.env` may be used.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# --acme-agree
|
||||||
|
export ACME_AGREE=true
|
||||||
|
# --acme-email
|
||||||
|
export ACME_EMAIL=johndoe@example.com
|
||||||
|
# --vendor-id
|
||||||
|
export VENDOR_ID=example.com
|
||||||
|
# --secret
|
||||||
|
export SECRET=QQgPyfzVdxJTcUc1ceot3pgJFKtWSHMQ
|
||||||
|
# --tunnel-relay
|
||||||
|
export TUNNEL_RELAY_URL=https://tunnel.example.com/
|
||||||
|
# --tls-locals
|
||||||
|
export TLS_LOCALS=https:*:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
See `./telebit --help` for all options. \
|
||||||
|
See [`examples/client.env`][client-env] for detail explanations.
|
||||||
|
|
||||||
|
[client-env]: /tree/master/examples/client.env
|
||||||
|
|
||||||
|
# Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
goreleaser --rm-dist --skip-publish
|
||||||
|
```
|
||||||
|
|
||||||
## Install Go
|
## Install Go
|
||||||
|
|
||||||
Installs Go to `~/.local/opt/go` for MacOS and Linux:
|
Installs Go to `~/.local/opt/go` for MacOS and Linux:
|
||||||
|
@ -37,239 +73,6 @@ The binary can be built with `VENDOR_ID` and `CLIENT_SECRET` built into the bina
|
||||||
You can also change the `serviceName` and `serviceDescription` at build time.
|
You can also change the `serviceName` and `serviceDescription` at build time.
|
||||||
See `examples/run-as-client.sh`.
|
See `examples/run-as-client.sh`.
|
||||||
|
|
||||||
### Configure
|
|
||||||
|
|
||||||
Command-line flags or `.env` may be used.
|
|
||||||
|
|
||||||
See `./telebit --help` for all options, and `examples/relay.env` for their corresponding ENVs.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
Copy `examples/relay.env` as `.env` in the working directory.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# For Tunnel Relay Server
|
|
||||||
API_HOSTNAME=devices.example.com
|
|
||||||
LISTEN=:443
|
|
||||||
LOCALS=https:mgmt.devices.example.com:3010
|
|
||||||
VERBOSE=false
|
|
||||||
|
|
||||||
# For Device Management & Authentication
|
|
||||||
AUTH_URL=http://localhost:3010/api
|
|
||||||
|
|
||||||
# For Let's Encrypt / ACME registration
|
|
||||||
ACME_AGREE=true
|
|
||||||
ACME_EMAIL=letsencrypt@example.com
|
|
||||||
|
|
||||||
# For Let's Encrypt / ACME challenges
|
|
||||||
ACME_HTTP_01_RELAY_URL=http://localhost:3010/api/http
|
|
||||||
ACME_RELAY_URL=http://localhost:3010/api/dns
|
|
||||||
SECRET=xxxxxxxxxxxxxxxx
|
|
||||||
GODADDY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
GODADDY_API_SECRET=xxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: It is not necessary to specify the `--flags` when using the ENVs.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./telebit \
|
|
||||||
--api-hostname $API_HOSTNAME \
|
|
||||||
--auth-url "$AUTH_URL" \
|
|
||||||
--acme-agree "$ACME_AGREE" \
|
|
||||||
--acme-email "$ACME_EMAIL" \
|
|
||||||
--secret "$SECRET" \
|
|
||||||
--listen "$LISTEN"
|
|
||||||
```
|
|
||||||
|
|
||||||
### API
|
|
||||||
|
|
||||||
List all connected devices
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bash examples/admin-list-devices.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -L https://devices.example.com/api/subscribers -H "Authorization: Bearer ${TOKEN}"
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"subscribers": [{ "since": "2020-07-22T08:20:40Z", "sub": "ruby", "sockets": ["73.228.72.97:50737"], "clients": 0 }]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Show connectivity, of a single device, if any
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -L https://devices.example.com/api/subscribers -H "Authorization: Bearer ${TOKEN}"
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"subscribers": [{ "since": "2020-07-22T08:20:40Z", "sub": "ruby", "sockets": ["73.228.72.97:50737"], "clients": 0 }]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Force a device to disconnect:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bash examples/admin-disconnect-device.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
my_subdomain="ruby"
|
|
||||||
curl -X DELETE http://mgmt.example.com:3010/api/subscribers/ruby" -H "Authorization: Bearer ${TOKEN}"
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "success": true }
|
|
||||||
```
|
|
||||||
|
|
||||||
## Management Server
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go generate ./...
|
|
||||||
|
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod vendor -o mgmt-server-linux ./cmd/mgmt/*.go
|
|
||||||
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -mod vendor -o mgmt-server-macos ./cmd/mgmt/*.go
|
|
||||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -o mgmt-server-windows-debug.exe ./cmd/mgmt/*.go
|
|
||||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -ldflags "-H windowsgui" -o mgmt-server-windows.exe ./cmd/mgmt/*.go
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./telebit-mgmt --domain devices.example.com --port 3010
|
|
||||||
```
|
|
||||||
|
|
||||||
Copy `examples/mgmt.env` as `.env` in the working directory.
|
|
||||||
|
|
||||||
### Device Management API
|
|
||||||
|
|
||||||
Create a token with the same `SECRET` used with the `mgmt` server,
|
|
||||||
and add a device by its `subdomain`.
|
|
||||||
|
|
||||||
To build `signjwt`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -mod=vendor -ldflags "-s -w" -o signjwt cmd/signjwt/*.go
|
|
||||||
```
|
|
||||||
|
|
||||||
To generate an `admin` token:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
VENDOR_ID="test-id"
|
|
||||||
SECRET="xxxxxxxxxxx"
|
|
||||||
TOKEN=$(./signjwt \
|
|
||||||
--expires-in 15m \
|
|
||||||
--vendor-id $VENDOR_ID \
|
|
||||||
--secret $SECRET \
|
|
||||||
--machine-ppid $SECRET
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
Authorize a device:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
my_subdomain="xxxx"
|
|
||||||
my_mgmt_host=http://mgmt.example.com:3010
|
|
||||||
curl -X POST $my_mgmt_host/api/devices \
|
|
||||||
-H "Authorization: Bearer ${TOKEN}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{ "slug": "'$my_subdomain'" }'
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "shared_key": "ZZZZZZZZ" }
|
|
||||||
```
|
|
||||||
|
|
||||||
Show data of a single device
|
|
||||||
|
|
||||||
```bash
|
|
||||||
my_subdomain="xxxx"
|
|
||||||
curl -L http://mgmt.example.com:3010/api/devices/${my_subdomain} -H "Authorization: Bearer ${TOKEN}"
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "subdomain": "sub1", "updated_at": "2020-05-20T12:00:01Z" }
|
|
||||||
```
|
|
||||||
|
|
||||||
Get a list of connected devices:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -L http://mgmt.example.com:3010/api/devices -H "Authorization: Bearer ${TOKEN}"
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
[{ "subdomain": "sub1", "updated_at": "2020-05-20T12:00:01Z" }]
|
|
||||||
```
|
|
||||||
|
|
||||||
Get a list of disconnected devices:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -L http://mgmt.example.com:3010/api/devices?inactive=true -H "Authorization: Bearer ${TOKEN}"
|
|
||||||
```
|
|
||||||
|
|
||||||
Deauthorize a device:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
my_subdomain="xxxx"
|
|
||||||
curl -L -X DELETE http://mgmt.example.com:3010/api/devices/${my_subdomain} -H "Authorization: Bearer ${TOKEN}"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tunnel Client
|
|
||||||
|
|
||||||
The tunnel relay binary is also the client binary.
|
|
||||||
|
|
||||||
You do not need to build a separate client binary.
|
|
||||||
|
|
||||||
### Configure
|
|
||||||
|
|
||||||
Command-line flags or `.env` may be used.
|
|
||||||
|
|
||||||
See `./telebit --help` for all options, and `examples/client.env` for their corresponding ENVs.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
Copy `examples/client.env` as `.env` in the working directory.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# For Client
|
|
||||||
VENDOR_ID=test-id
|
|
||||||
CLIENT_SUBJECT=newieb
|
|
||||||
CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
AUTH_URL="https://mgmt.devices.example.com/api"
|
|
||||||
TUNNEL_RELAY_URL=https://devices.example.com/
|
|
||||||
LOCALS=https:newbie.devices.example.com:3000,http:newbie.devices.example.com:3000
|
|
||||||
#PORT_FORWARDS=3443:3001,8443:3002
|
|
||||||
|
|
||||||
# For Debugging
|
|
||||||
VERBOSE=true
|
|
||||||
#VERBOSE_BYTES=true
|
|
||||||
#VERBOSE_RAW=true
|
|
||||||
|
|
||||||
# For Let's Encrypt / ACME registration
|
|
||||||
ACME_AGREE=true
|
|
||||||
ACME_EMAIL=letsencrypt@example.com
|
|
||||||
|
|
||||||
# For Let's Encrypt / ACME challenges
|
|
||||||
ACME_RELAY_URL="https://mgmt.devices.example.com/api/dns"
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./telebit \
|
|
||||||
--vendor-id "$VENDOR_ID" \
|
|
||||||
--secret "$CLIENT_SECRET" \
|
|
||||||
--tunnel-relay-url $TUNNEL_RELAY_URL \
|
|
||||||
--locals "$LOCALS" \
|
|
||||||
--acme-agree="$ACME_AGREE" \
|
|
||||||
--acme-email "$ACME_EMAIL" \
|
|
||||||
--verbose=$VERBOSE
|
|
||||||
```
|
|
||||||
|
|
||||||
## Local Web Application
|
## Local Web Application
|
||||||
|
|
||||||
Currently only raw TCP is tunneled.
|
Currently only raw TCP is tunneled.
|
||||||
|
@ -288,20 +91,75 @@ EOF
|
||||||
python3 -m http.server 3000
|
python3 -m http.server 3000
|
||||||
```
|
```
|
||||||
|
|
||||||
## Glossary
|
## Help
|
||||||
|
|
||||||
```
|
```
|
||||||
--vendor-id $VENDOR_ID an arbitrary id used as part of authentication
|
Usage of telebit:
|
||||||
--secret $SECRET the secret for creating JWTs
|
ACME_AGREE
|
||||||
--tunnel-relay-url $TUNNEL_RELAY_URL the url of the tunnel server
|
--acme-agree
|
||||||
--auth-url $AUTH_URL use to override the server-provided auth url
|
agree to the terms of the ACME service provider (required)
|
||||||
--acme-relay-url $ACME_RELAY_URL use to override the server-provided acme dns 01 proxy
|
--acme-directory string
|
||||||
--locals $LOCALS a list of `scheme:domainname:port`
|
ACME Directory URL
|
||||||
for forwarding incoming `domainname` to local `port`
|
ACME_EMAIL
|
||||||
--port-forwards $PORT_FORWARDS a list of `remote:local` tcp port-forwarding
|
--acme-email string
|
||||||
--verbose $VERBOSE logs everything, including abbreviated data (as hex)
|
email to use for Let's Encrypt / ACME registration
|
||||||
$VERBOSE_BYTES logs full data (as hex)
|
--acme-http-01
|
||||||
$VERBOSE_RAW logs full data (as string)
|
enable HTTP-01 ACME challenges
|
||||||
--acme-agree $ACME_AGREE agree to the ACME service agreement
|
ACME_HTTP_01_RELAY_URL
|
||||||
--acme-email $ACME_EMAIL the webmaster email for ACME notices
|
--acme-http-01-relay-url string
|
||||||
|
the base url of the ACME HTTP-01 relay, if not the same as the DNS-01 relay
|
||||||
|
--acme-relay-url string
|
||||||
|
the base url of the ACME DNS-01 relay, if not the same as the tunnel relay
|
||||||
|
--acme-staging
|
||||||
|
get fake certificates for testing
|
||||||
|
--acme-storage string
|
||||||
|
path to ACME storage directory (default "./acme.d/")
|
||||||
|
--acme-tls-alpn-01
|
||||||
|
enable TLS-ALPN-01 ACME challenges
|
||||||
|
API_HOSTNAME
|
||||||
|
--api-hostname string
|
||||||
|
the hostname used to manage clients
|
||||||
|
--auth-url string
|
||||||
|
the base url for authentication, if not the same as the tunnel relay
|
||||||
|
DEBUG
|
||||||
|
--debug
|
||||||
|
show debug output (default true)
|
||||||
|
--dns-01-delay duration
|
||||||
|
add an extra delay after dns self-check to allow DNS-01 challenges to propagate
|
||||||
|
--dns-resolvers string
|
||||||
|
a list of resolvers in the format 8.8.8.8:53,8.8.4.4:53
|
||||||
|
--env string
|
||||||
|
path to .env file
|
||||||
|
--leeway duration
|
||||||
|
allow for time drift / skew (hard-coded to 15 minutes) (default 15m0s)
|
||||||
|
LISTEN
|
||||||
|
--listen string
|
||||||
|
list of bind addresses on which to listen, such as localhost:80, or :443
|
||||||
|
LOCALS
|
||||||
|
--locals string
|
||||||
|
a list of <from-domain>:<to-port>
|
||||||
|
PORT_FORWARD
|
||||||
|
--port-forward string
|
||||||
|
a list of <from-port>:<to-port> for raw port-forwarding
|
||||||
|
SECRET
|
||||||
|
--secret string
|
||||||
|
the same secret used by telebit-relay (used for JWT authentication)
|
||||||
|
--spf-domain string
|
||||||
|
domain with SPF-like list of IP addresses which are allowed to connect to clients
|
||||||
|
TLS_LOCALS
|
||||||
|
--tls-locals string
|
||||||
|
like --locals, but TLS will be used to connect to the local port
|
||||||
|
--token string
|
||||||
|
an auth token for the server (instead of generating --secret); use --token=false to ignore any $TOKEN in env
|
||||||
|
TUNNEL_RELAY_URL
|
||||||
|
--tunnel-relay-url string
|
||||||
|
the websocket url at which to connect to the tunnel relay
|
||||||
|
VENDOR_ID
|
||||||
|
--vendor-id string
|
||||||
|
a unique identifier for a deploy target environment
|
||||||
|
VERBOSE
|
||||||
|
VERBOSE_BYTES
|
||||||
|
VERBOSE_RAW
|
||||||
|
--verbose
|
||||||
|
log excessively
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# MGMT Server
|
# Telebit Mgmt
|
||||||
|
|
||||||
# Config
|
# Config
|
||||||
|
|
||||||
|
@ -18,6 +18,17 @@ NAMECOM_USERNAME=johndoe
|
||||||
NAMECOM_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
NAMECOM_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```bash
|
||||||
|
my_subdomain="ruby"
|
||||||
|
curl -X DELETE http://mgmt.example.com:3010/api/subscribers/ruby" -H "Authorization: Bearer ${TOKEN}"
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "success": true }
|
||||||
|
```
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -27,3 +38,95 @@ pushd cmd/mgmt
|
||||||
go build -mod vendor -o telebit-mgmt
|
go build -mod vendor -o telebit-mgmt
|
||||||
popd
|
popd
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Management Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go generate ./...
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod vendor -o mgmt-server-linux ./cmd/mgmt/*.go
|
||||||
|
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -mod vendor -o mgmt-server-macos ./cmd/mgmt/*.go
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -o mgmt-server-windows-debug.exe ./cmd/mgmt/*.go
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -ldflags "-H windowsgui" -o mgmt-server-windows.exe ./cmd/mgmt/*.go
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./telebit-mgmt --domain devices.example.com --port 3010
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy `examples/mgmt.env` as `.env` in the working directory.
|
||||||
|
|
||||||
|
### Device Management API
|
||||||
|
|
||||||
|
Create a token with the same `SECRET` used with the `mgmt` server,
|
||||||
|
and add a device by its `subdomain`.
|
||||||
|
|
||||||
|
To build `signjwt`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go build -mod=vendor -ldflags "-s -w" -o signjwt cmd/signjwt/*.go
|
||||||
|
```
|
||||||
|
|
||||||
|
To generate an `admin` token:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
VENDOR_ID="test-id"
|
||||||
|
SECRET="xxxxxxxxxxx"
|
||||||
|
TOKEN=$(./signjwt \
|
||||||
|
--expires-in 15m \
|
||||||
|
--vendor-id $VENDOR_ID \
|
||||||
|
--secret $SECRET \
|
||||||
|
--machine-ppid $SECRET
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Authorize a device:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
my_subdomain="xxxx"
|
||||||
|
my_mgmt_host=http://mgmt.example.com:3010
|
||||||
|
curl -X POST $my_mgmt_host/api/devices \
|
||||||
|
-H "Authorization: Bearer ${TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{ "slug": "'$my_subdomain'" }'
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "shared_key": "ZZZZZZZZ" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Show data of a single device
|
||||||
|
|
||||||
|
```bash
|
||||||
|
my_subdomain="xxxx"
|
||||||
|
curl -L http://mgmt.example.com:3010/api/devices/${my_subdomain} -H "Authorization: Bearer ${TOKEN}"
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "subdomain": "sub1", "updated_at": "2020-05-20T12:00:01Z" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Get a list of connected devices:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -L http://mgmt.example.com:3010/api/devices -H "Authorization: Bearer ${TOKEN}"
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
[{ "subdomain": "sub1", "updated_at": "2020-05-20T12:00:01Z" }]
|
||||||
|
```
|
||||||
|
|
||||||
|
Get a list of disconnected devices:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -L http://mgmt.example.com:3010/api/devices?inactive=true -H "Authorization: Bearer ${TOKEN}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Deauthorize a device:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
my_subdomain="xxxx"
|
||||||
|
curl -L -X DELETE http://mgmt.example.com:3010/api/devices/${my_subdomain} -H "Authorization: Bearer ${TOKEN}"
|
||||||
|
```
|
||||||
|
|
|
@ -10,12 +10,14 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.rootprojects.org/root/telebit/mgmt/authstore"
|
"git.rootprojects.org/root/telebit/internal/mgmt"
|
||||||
|
"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
|
||||||
|
|
||||||
"github.com/go-acme/lego/v3/challenge"
|
"github.com/go-acme/lego/v3/challenge"
|
||||||
"github.com/go-acme/lego/v3/providers/dns/duckdns"
|
"github.com/go-acme/lego/v3/providers/dns/duckdns"
|
||||||
"github.com/go-acme/lego/v3/providers/dns/godaddy"
|
"github.com/go-acme/lego/v3/providers/dns/godaddy"
|
||||||
"github.com/go-acme/lego/v3/providers/dns/namedotcom"
|
"github.com/go-acme/lego/v3/providers/dns/namedotcom"
|
||||||
|
|
||||||
_ "github.com/joho/godotenv/autoload"
|
_ "github.com/joho/godotenv/autoload"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,14 +30,8 @@ var (
|
||||||
GitTimestamp = "0000-00-00T00:00:00+0000"
|
GitTimestamp = "0000-00-00T00:00:00+0000"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MWKey is a type guard
|
|
||||||
type MWKey string
|
|
||||||
|
|
||||||
var store authstore.Store
|
var store authstore.Store
|
||||||
var provider challenge.Provider = nil // TODO is this concurrency-safe?
|
|
||||||
var secret string
|
var secret string
|
||||||
var primaryDomain string
|
|
||||||
var relayDomain string
|
|
||||||
|
|
||||||
func help() {
|
func help() {
|
||||||
fmt.Fprintf(os.Stderr, "Usage: mgmt --domain <devices.example.com> --secret <128-bit secret>\n")
|
fmt.Fprintf(os.Stderr, "Usage: mgmt --domain <devices.example.com> --secret <128-bit secret>\n")
|
||||||
|
@ -59,22 +55,22 @@ func main() {
|
||||||
"database (postgres) connection url")
|
"database (postgres) connection url")
|
||||||
flag.StringVar(&secret, "secret", "",
|
flag.StringVar(&secret, "secret", "",
|
||||||
"a >= 16-character random string for JWT key signing")
|
"a >= 16-character random string for JWT key signing")
|
||||||
flag.StringVar(&primaryDomain, "domain", "",
|
flag.StringVar(&mgmt.DeviceDomain, "domain", "",
|
||||||
"the base domain to use for all clients")
|
"the base domain to use for all clients")
|
||||||
flag.StringVar(&relayDomain, "tunnel-domain", "",
|
flag.StringVar(&mgmt.RelayDomain, "tunnel-domain", "",
|
||||||
"the domain name of the tunnel relay service, if different from base domain")
|
"the domain name of the tunnel relay service, if different from base domain")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if 0 == len(primaryDomain) {
|
if 0 == len(mgmt.DeviceDomain) {
|
||||||
primaryDomain = os.Getenv("DOMAIN")
|
mgmt.DeviceDomain = os.Getenv("DOMAIN")
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 == len(relayDomain) {
|
if 0 == len(mgmt.RelayDomain) {
|
||||||
relayDomain = os.Getenv("TUNNEL_DOMAIN")
|
mgmt.RelayDomain = os.Getenv("TUNNEL_DOMAIN")
|
||||||
}
|
}
|
||||||
if 0 == len(relayDomain) {
|
if 0 == len(mgmt.RelayDomain) {
|
||||||
relayDomain = primaryDomain
|
mgmt.RelayDomain = mgmt.DeviceDomain
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 == len(dbURL) {
|
if 0 == len(dbURL) {
|
||||||
|
@ -99,6 +95,8 @@ func main() {
|
||||||
lnAddr = "localhost:" + port
|
lnAddr = "localhost:" + port
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO are these concurrency-safe?
|
||||||
|
var provider challenge.Provider = nil
|
||||||
if len(os.Getenv("GODADDY_API_KEY")) > 0 {
|
if len(os.Getenv("GODADDY_API_KEY")) > 0 {
|
||||||
id := os.Getenv("GODADDY_API_KEY")
|
id := os.Getenv("GODADDY_API_KEY")
|
||||||
apiSecret := os.Getenv("GODADDY_API_SECRET")
|
apiSecret := os.Getenv("GODADDY_API_SECRET")
|
||||||
|
@ -120,7 +118,7 @@ func main() {
|
||||||
fmt.Println("DNS-01 relay disabled")
|
fmt.Println("DNS-01 relay disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 == len(primaryDomain) || 0 == len(secret) || 0 == len(dbURL) {
|
if 0 == len(mgmt.DeviceDomain) || 0 == len(secret) || 0 == len(dbURL) {
|
||||||
help()
|
help()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return
|
return
|
||||||
|
@ -134,7 +132,7 @@ func main() {
|
||||||
connStr += "?sslmode=required"
|
connStr += "?sslmode=required"
|
||||||
}
|
}
|
||||||
|
|
||||||
store, err = authstore.NewStore(connStr, initSQL)
|
store, err = authstore.NewStore(connStr, mgmt.InitSQL)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
log.Fatal("connection error", err)
|
log.Fatal("connection error", err)
|
||||||
return
|
return
|
||||||
|
@ -142,16 +140,18 @@ func main() {
|
||||||
_ = store.SetMaster(secret)
|
_ = store.SetMaster(secret)
|
||||||
defer store.Close()
|
defer store.Close()
|
||||||
|
|
||||||
|
mgmt.Init(store, provider)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
fmt.Println("Listening for ACME challenges on :" + challengesPort)
|
fmt.Println("Listening for ACME challenges on :" + challengesPort)
|
||||||
if err := http.ListenAndServe(":"+challengesPort, routeStatic()); nil != err {
|
if err := http.ListenAndServe(":"+challengesPort, mgmt.RouteStatic()); nil != err {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
fmt.Println("Listening on", lnAddr)
|
fmt.Println("Listening on", lnAddr)
|
||||||
fmt.Fprintf(os.Stderr, "failed: %s", http.ListenAndServe(lnAddr, routeAll()))
|
fmt.Fprintf(os.Stderr, "failed: %s", http.ListenAndServe(lnAddr, mgmt.RouteAll()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// newNameDotComDNSProvider is for the sake of demoing the tunnel
|
// newNameDotComDNSProvider is for the sake of demoing the tunnel
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
var initSQL = "./postgres.init.sql"
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
# Telebit Relay
|
||||||
|
|
||||||
|
| [Telebit Client](../../) | **Telebit Relay** | [Telebit Mgmt](../mgmt) |
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
Copy `examples/relay.env` as `.env` in the working directory.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For Tunnel Relay Server
|
||||||
|
API_HOSTNAME=devices.example.com
|
||||||
|
LISTEN=:443
|
||||||
|
LOCALS=https:mgmt.devices.example.com:3010
|
||||||
|
VERBOSE=false
|
||||||
|
|
||||||
|
# For Device Management & Authentication
|
||||||
|
AUTH_URL=http://localhost:3010/api
|
||||||
|
|
||||||
|
# For Let's Encrypt / ACME registration
|
||||||
|
ACME_AGREE=true
|
||||||
|
ACME_EMAIL=letsencrypt@example.com
|
||||||
|
|
||||||
|
# For Let's Encrypt / ACME challenges
|
||||||
|
ACME_HTTP_01_RELAY_URL=http://localhost:3010/api/http
|
||||||
|
ACME_RELAY_URL=http://localhost:3010/api/dns
|
||||||
|
SECRET=xxxxxxxxxxxxxxxx
|
||||||
|
GODADDY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
GODADDY_API_SECRET=xxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: It is not necessary to specify the `--flags` when using the ENVs.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./telebit \
|
||||||
|
--api-hostname $API_HOSTNAME \
|
||||||
|
--auth-url "$AUTH_URL" \
|
||||||
|
--acme-agree "$ACME_AGREE" \
|
||||||
|
--acme-email "$ACME_EMAIL" \
|
||||||
|
--secret "$SECRET" \
|
||||||
|
--listen "$LISTEN"
|
||||||
|
```
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
List all connected devices
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash examples/admin-list-devices.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -L https://devices.example.com/api/subscribers -H "Authorization: Bearer ${TOKEN}"
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"subscribers": [{ "since": "2020-07-22T08:20:40Z", "sub": "ruby", "sockets": ["73.228.72.97:50737"], "clients": 0 }]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Show connectivity, of a single device, if any
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -L https://devices.example.com/api/subscribers -H "Authorization: Bearer ${TOKEN}"
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"subscribers": [{ "since": "2020-07-22T08:20:40Z", "sub": "ruby", "sockets": ["73.228.72.97:50737"], "clients": 0 }]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Force a device to disconnect:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash examples/admin-disconnect-device.sh
|
||||||
|
```
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -22,21 +23,23 @@ import (
|
||||||
"git.rootprojects.org/root/telebit/dbg"
|
"git.rootprojects.org/root/telebit/dbg"
|
||||||
"git.rootprojects.org/root/telebit/internal/dns01"
|
"git.rootprojects.org/root/telebit/internal/dns01"
|
||||||
"git.rootprojects.org/root/telebit/internal/http01"
|
"git.rootprojects.org/root/telebit/internal/http01"
|
||||||
|
"git.rootprojects.org/root/telebit/internal/mgmt"
|
||||||
|
"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
|
||||||
"git.rootprojects.org/root/telebit/internal/service"
|
"git.rootprojects.org/root/telebit/internal/service"
|
||||||
|
telebitX "git.rootprojects.org/root/telebit/internal/telebit"
|
||||||
"git.rootprojects.org/root/telebit/iplist"
|
"git.rootprojects.org/root/telebit/iplist"
|
||||||
"git.rootprojects.org/root/telebit/mgmt"
|
|
||||||
"git.rootprojects.org/root/telebit/mgmt/authstore"
|
|
||||||
"git.rootprojects.org/root/telebit/table"
|
"git.rootprojects.org/root/telebit/table"
|
||||||
"git.rootprojects.org/root/telebit/tunnel"
|
"git.rootprojects.org/root/telebit/tunnel"
|
||||||
legoDNS01 "github.com/go-acme/lego/v3/challenge/dns01"
|
|
||||||
|
|
||||||
"github.com/coolaj86/certmagic"
|
"github.com/coolaj86/certmagic"
|
||||||
"github.com/denisbrodbeck/machineid"
|
"github.com/denisbrodbeck/machineid"
|
||||||
jwt "github.com/dgrijalva/jwt-go"
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
"github.com/go-acme/lego/v3/challenge"
|
"github.com/go-acme/lego/v3/challenge"
|
||||||
|
legoDNS01 "github.com/go-acme/lego/v3/challenge/dns01"
|
||||||
"github.com/go-acme/lego/v3/providers/dns/duckdns"
|
"github.com/go-acme/lego/v3/providers/dns/duckdns"
|
||||||
"github.com/go-acme/lego/v3/providers/dns/godaddy"
|
"github.com/go-acme/lego/v3/providers/dns/godaddy"
|
||||||
"github.com/go-acme/lego/v3/providers/dns/namedotcom"
|
"github.com/go-acme/lego/v3/providers/dns/namedotcom"
|
||||||
|
"github.com/go-chi/chi"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
_ "github.com/joho/godotenv/autoload"
|
_ "github.com/joho/godotenv/autoload"
|
||||||
)
|
)
|
||||||
|
@ -80,8 +83,6 @@ type Forward struct {
|
||||||
localTLS bool
|
localTLS bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var authorizer telebit.Authorizer
|
|
||||||
|
|
||||||
var isHostname = regexp.MustCompile(`^[A-Za-z0-9_\.\-]+$`).MatchString
|
var isHostname = regexp.MustCompile(`^[A-Za-z0-9_\.\-]+$`).MatchString
|
||||||
|
|
||||||
// VendorID may be baked in, or supplied via ENVs or --args
|
// VendorID may be baked in, or supplied via ENVs or --args
|
||||||
|
@ -383,7 +384,6 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("Auth URL", *authURL)
|
fmt.Println("Auth URL", *authURL)
|
||||||
authorizer = NewAuthorizer(*authURL)
|
|
||||||
|
|
||||||
dns01Base := directory.DNS01Proxy.URL
|
dns01Base := directory.DNS01Proxy.URL
|
||||||
if 0 == len(*acmeRelay) {
|
if 0 == len(*acmeRelay) {
|
||||||
|
@ -428,7 +428,6 @@ func main() {
|
||||||
fmt.Printf("[Grants]\n\t%#v\n", grants)
|
fmt.Printf("[Grants]\n\t%#v\n", grants)
|
||||||
*relay = grants.Audience
|
*relay = grants.Audience
|
||||||
}
|
}
|
||||||
authorizer = NewAuthorizer(*authURL)
|
|
||||||
|
|
||||||
fmt.Printf("Email: %q\n", *email)
|
fmt.Printf("Email: %q\n", *email)
|
||||||
|
|
||||||
|
@ -590,9 +589,11 @@ func muxAll(
|
||||||
}
|
}
|
||||||
if "" != *apiHostname {
|
if "" != *apiHostname {
|
||||||
// this is a generic net listener
|
// this is a generic net listener
|
||||||
InitAdmin(*authURL)
|
r := chi.NewRouter()
|
||||||
|
telebitX.RouteAdmin(*authURL, r)
|
||||||
apiListener := tunnel.NewListener()
|
apiListener := tunnel.NewListener()
|
||||||
go func() {
|
go func() {
|
||||||
|
httpsrv := &http.Server{Handler: r}
|
||||||
httpsrv.Serve(apiListener)
|
httpsrv.Serve(apiListener)
|
||||||
}()
|
}()
|
||||||
fmt.Printf("Will respond to Websocket and API requests to %q\n", *apiHostname)
|
fmt.Printf("Will respond to Websocket and API requests to %q\n", *apiHostname)
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
# VERBOSE
|
||||||
|
# Show more output in the logs
|
||||||
|
#VERBOSE=true
|
||||||
|
|
||||||
|
# DEBUG
|
||||||
|
# Show binary output in the longs too
|
||||||
|
#DEBUG=true
|
||||||
|
|
||||||
|
# Used for Let's Encrypt registration
|
||||||
|
# ACME_AGREE
|
||||||
|
ACME_AGREE=true
|
||||||
|
# ACME_EMAIL
|
||||||
|
ACME_EMAIL=johndoe@example.com
|
||||||
|
|
||||||
# TUNNEL_RELAY_URL
|
# TUNNEL_RELAY_URL
|
||||||
# The URL of the Telebit Relay, of course.
|
# The URL of the Telebit Relay, of course.
|
||||||
# Note that many client configuration details can be preassigned at
|
# Note that many client configuration details can be preassigned at
|
||||||
|
@ -9,23 +23,53 @@ TUNNEL_RELAY_URL=https://devices.example.com/
|
||||||
# It's just as well to generate a random ID for your organization.
|
# It's just as well to generate a random ID for your organization.
|
||||||
VENDOR_ID=
|
VENDOR_ID=
|
||||||
|
|
||||||
# Used for Let's Encrypt registration
|
# SECRET
|
||||||
# ACME_AGREE
|
# This is the shared secret between the client device
|
||||||
ACME_AGREE=true
|
# and the device management server.
|
||||||
# ACME_EMAIL
|
SECRET=shared-secret
|
||||||
ACME_EMAIL=johndoe@example.com
|
|
||||||
|
|
||||||
# CLIENT_SUBJECT (optional)
|
# CLIENT_SUBJECT (optional)
|
||||||
# NOT used by Telebit.
|
# NOT used by Telebit.
|
||||||
# This is for the Device Management & Authentication server.
|
# This is for the example scripts
|
||||||
|
# (for the Device Management & Authentication server)
|
||||||
CLIENT_SUBJECT=newbie
|
CLIENT_SUBJECT=newbie
|
||||||
CLIENT_SECRET=xxxxxxxxxxxxxxxx
|
CLIENT_SECRET=xxxxxxxxxxxxxxxx
|
||||||
LOCALS=https:$CLIENT_SUBJECT.devices.example.com:3000,https:*.$CLIENT_SUBJECT.devices.example.com:3000
|
|
||||||
#ACME_HTTP_01_RELAY_URL=http://localhost:4200/api/http
|
# TLS_LOCALS
|
||||||
#PORT_FORWARDS=3443:3001,8443:3002
|
# ReverseProxy any matching requests to the given local port.
|
||||||
#DUCKDNS_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
# This DOES NOT terminate TLS
|
||||||
|
TLS_LOCALS=https:*:3000
|
||||||
|
|
||||||
|
# LOCALS
|
||||||
|
# ReverseProxy any matching requests to the given local port.
|
||||||
|
# This terminates TLS
|
||||||
|
# Ex: LOCALS=https:$CLIENT_SUBJECT.devices.example.com:3000,https:*.$CLIENT_SUBJECT.devices.example.com:3000
|
||||||
|
LOCALS=https:*:3000
|
||||||
|
|
||||||
|
# PORT_FORWARDS
|
||||||
|
# ReverseProxy any matching TCP streams from the given remote incoming port,
|
||||||
|
# directly to the given destination port.
|
||||||
|
PORT_FORWARDS=3443:3001,8443:3002
|
||||||
|
|
||||||
# AUTH_URL
|
# AUTH_URL
|
||||||
# The client may receive this as `.authn.url`
|
# The client may receive this as `.authn.url`
|
||||||
# through `https://$API_DOMAIN/.well-known/telebit.app/index.json`
|
# through `https://$API_DOMAIN/.well-known/telebit.app/index.json`
|
||||||
# Setting the ENV AUTH_URL or the flag --auth-url overrides the discovery endpoint
|
# Setting the ENV AUTH_URL or the flag --auth-url overrides the discovery endpoint
|
||||||
|
|
||||||
|
# ACME_HTTP_01_RELAY_URL
|
||||||
|
# Overrides `.acme_http_01_relay.url`
|
||||||
|
# from `https://$API_DOMAIN/.well-known/telebit.app/index.json`
|
||||||
|
ACME_HTTP_01_RELAY_URL=https://tunnel.example.com/api/acme-relay
|
||||||
|
|
||||||
|
# ACME_RELAY_URL (deprecated)
|
||||||
|
# Overrides `.acme_dns_01_relay.url`
|
||||||
|
# from `https://$API_DOMAIN/.well-known/telebit.app/index.json`
|
||||||
|
#ACME_RELAY_URL=https://tunnel.example.com/api/acme-relay
|
||||||
|
|
||||||
|
# ACME DNS-01 Challenge Strategies
|
||||||
|
# Rather than use the http-01 or dns-01 relay you can set one of these
|
||||||
|
#DUCKDNS_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
|
#NAMECOM_USERNAME=
|
||||||
|
#NAMECOM_API_TOKEN=
|
||||||
|
#GODADDY_API_KEY=
|
||||||
|
#GODADDY_API_SECRET=
|
|
@ -11,8 +11,9 @@ CLIENT_SECRET="${CLIENT_SECRET:-}"
|
||||||
#go build -mod=vendor -o ./telebit \
|
#go build -mod=vendor -o ./telebit \
|
||||||
# -ldflags="-X 'main.VendorID=$VENDOR_ID' -X 'main.ClientSecret=$CLIENT_SECRET' -X 'main.serviceName=telebit' -X 'main.serviceDesc=securely tunnel through telebit.io'" \
|
# -ldflags="-X 'main.VendorID=$VENDOR_ID' -X 'main.ClientSecret=$CLIENT_SECRET' -X 'main.serviceName=telebit' -X 'main.serviceDesc=securely tunnel through telebit.io'" \
|
||||||
# cmd/telebit/*.go
|
# cmd/telebit/*.go
|
||||||
go build -mod=vendor -o telebit \
|
pushd cmd/telebit
|
||||||
cmd/telebit/*.go
|
go build -mod=vendor -o telebit .
|
||||||
|
popd
|
||||||
|
|
||||||
# For Device Authorization across services
|
# For Device Authorization across services
|
||||||
#AUTH_URL=${AUTH_URL:-"https://devices.examples.com/api"}
|
#AUTH_URL=${AUTH_URL:-"https://devices.examples.com/api"}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package mgmt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
telebit "git.rootprojects.org/root/telebit"
|
telebit "git.rootprojects.org/root/telebit"
|
||||||
"git.rootprojects.org/root/telebit/dbg"
|
"git.rootprojects.org/root/telebit/dbg"
|
||||||
"git.rootprojects.org/root/telebit/mgmt/authstore"
|
"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SuccessResponse struct {
|
type SuccessResponse struct {
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package mgmt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
@ -10,7 +10,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rootprojects.org/root/telebit/mgmt/authstore"
|
"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
|
||||||
|
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package mgmt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
|
||||||
|
|
||||||
|
"github.com/go-acme/lego/v3/challenge"
|
||||||
|
)
|
||||||
|
|
||||||
|
var store authstore.Store
|
||||||
|
|
||||||
|
var provider challenge.Provider = nil
|
||||||
|
|
||||||
|
// DeviceDomain is the base hostname used for devices, such as devices.example.com
|
||||||
|
// which has devices as foo.devices.example.com
|
||||||
|
var DeviceDomain string
|
||||||
|
|
||||||
|
// RelayDomain is the API hostname used for the tunnel
|
||||||
|
// ( currently NOT used, but will be used for wss://RELAY_DOMAIN/ )
|
||||||
|
var RelayDomain string
|
||||||
|
|
||||||
|
// MWKey is a type guard
|
||||||
|
type MWKey string
|
||||||
|
|
||||||
|
// Init initializes some package variables
|
||||||
|
func Init(s authstore.Store, p challenge.Provider) {
|
||||||
|
store = s
|
||||||
|
provider = p
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package mgmt
|
||||||
|
|
||||||
|
// InitSQL is the filepath to the SQL file used to initialize the database on each start
|
||||||
|
var InitSQL = "./postgres.init.sql"
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package mgmt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -12,7 +12,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rootprojects.org/root/telebit/dbg"
|
"git.rootprojects.org/root/telebit/dbg"
|
||||||
"git.rootprojects.org/root/telebit/mgmt/authstore"
|
"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
|
||||||
|
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
"github.com/go-chi/chi/middleware"
|
"github.com/go-chi/chi/middleware"
|
||||||
|
@ -27,7 +28,7 @@ type MgmtClaims struct {
|
||||||
var presenters = make(chan *Challenge)
|
var presenters = make(chan *Challenge)
|
||||||
var cleanups = make(chan *Challenge)
|
var cleanups = make(chan *Challenge)
|
||||||
|
|
||||||
func routeStatic() chi.Router {
|
func RouteStatic() chi.Router {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
|
|
||||||
r.Use(middleware.Logger)
|
r.Use(middleware.Logger)
|
||||||
|
@ -49,7 +50,7 @@ func routeStatic() chi.Router {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func routeAll() chi.Router {
|
func RouteAll() chi.Router {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
|
@ -125,8 +126,8 @@ func routeAll() chi.Router {
|
||||||
return nil, fmt.Errorf("invalid jwt payload 'sub' (mismatch)")
|
return nil, fmt.Errorf("invalid jwt payload 'sub' (mismatch)")
|
||||||
}
|
}
|
||||||
claims.Subject = claims.Slug
|
claims.Subject = claims.Slug
|
||||||
claims.Issuer = primaryDomain
|
claims.Issuer = DeviceDomain
|
||||||
claims.Audience = fmt.Sprintf("wss://%s/ws", relayDomain)
|
claims.Audience = fmt.Sprintf("wss://%s/ws", RelayDomain)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// a little misdirection there
|
// a little misdirection there
|
||||||
|
@ -181,7 +182,7 @@ func routeAll() chi.Router {
|
||||||
claims.Subject,
|
claims.Subject,
|
||||||
claims.Audience,
|
claims.Audience,
|
||||||
claims.Slug,
|
claims.Slug,
|
||||||
primaryDomain,
|
DeviceDomain,
|
||||||
)))
|
)))
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package telebit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -13,7 +13,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
telebit "git.rootprojects.org/root/telebit"
|
"git.rootprojects.org/root/telebit"
|
||||||
"git.rootprojects.org/root/telebit/admin"
|
"git.rootprojects.org/root/telebit/admin"
|
||||||
"git.rootprojects.org/root/telebit/dbg"
|
"git.rootprojects.org/root/telebit/dbg"
|
||||||
"git.rootprojects.org/root/telebit/table"
|
"git.rootprojects.org/root/telebit/table"
|
||||||
|
@ -23,10 +23,11 @@ import (
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
var httpsrv *http.Server
|
var authorizer telebit.Authorizer
|
||||||
|
|
||||||
func InitAdmin(authURL string) {
|
// RouteAdmin sets up the API, including the Mgmt proxy and ACME relay
|
||||||
r := chi.NewRouter()
|
func RouteAdmin(authURL string, r chi.Router) {
|
||||||
|
authorizer = NewAuthorizer(authURL)
|
||||||
|
|
||||||
r.Use(middleware.Logger)
|
r.Use(middleware.Logger)
|
||||||
//r.Use(middleware.Timeout(120 * time.Second))
|
//r.Use(middleware.Timeout(120 * time.Second))
|
||||||
|
@ -113,10 +114,6 @@ func InitAdmin(authURL string) {
|
||||||
fmt.Println("Request Path:", r.URL.Path)
|
fmt.Println("Request Path:", r.URL.Path)
|
||||||
adminUI.ServeHTTP(w, r)
|
adminUI.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
|
|
||||||
httpsrv = &http.Server{
|
|
||||||
Handler: r,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiPingContent = []byte("{ \"success\": true, \"error\": \"\" }\n")
|
var apiPingContent = []byte("{ \"success\": true, \"error\": \"\" }\n")
|
|
@ -1,11 +1,11 @@
|
||||||
package main
|
package telebit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
telebit "git.rootprojects.org/root/telebit"
|
"git.rootprojects.org/root/telebit"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewAuthorizer(authURL string) telebit.Authorizer {
|
func NewAuthorizer(authURL string) telebit.Authorizer {
|
Loading…
Reference in New Issue