diff --git a/cmd/dnsclient/dnsclient.go b/cmd/dnsclient/dnsclient.go index bbb9d80..c662fcb 100644 --- a/cmd/dnsclient/dnsclient.go +++ b/cmd/dnsclient/dnsclient.go @@ -32,7 +32,7 @@ func main() { var domains []string // TODO replace the websocket connection with a mock server - acmeRelay := flag.String("acme-relay", "", "the base url of the ACME DNS-01 relay, if not the same as the tunnel relay") + acmeRelay := flag.String("acme-relay-url", "", "the base url of the ACME DNS-01 relay, if not the same as the tunnel relay") secret := flag.String("secret", "", "the same secret used by telebit-relay (used for JWT authentication)") token := flag.String("token", "", "a pre-generated token to give the server (instead of generating one with --secret)") flag.Parse() diff --git a/cmd/telebit-relay/telebit-relay.go b/cmd/telebit-relay/telebit-relay.go index ae67b40..3b4e60e 100644 --- a/cmd/telebit-relay/telebit-relay.go +++ b/cmd/telebit-relay/telebit-relay.go @@ -73,7 +73,7 @@ func init() { flag.BoolVar(&acmeAgree, "acme-agree", false, "agree to the terms of the ACME service provider (required)") flag.BoolVar(&acmeStaging, "staging", false, "get fake certificates for testing") flag.StringVar(&authURL, "auth-url", "http://localhost:3010/api", "the auth server url") - flag.StringVar(&acmeRelay, "acme-relay", "", "the ACME DNS-01 relay, if any") + flag.StringVar(&acmeRelay, "acme-relay-url", "", "the ACME DNS-01 relay, if any") flag.StringVar(&adminHostName, "admin-hostname", "", "the management domain") flag.StringVar(&wssHostName, "wss-hostname", "", "the wss domain for connecting devices, if different from admin") flag.StringVar(&configPath, "config-path", configPath, "Configuration File Path") diff --git a/cmd/telebit/telebit.go b/cmd/telebit/telebit.go index 97e2e65..a5838b8 100644 --- a/cmd/telebit/telebit.go +++ b/cmd/telebit/telebit.go @@ -68,10 +68,10 @@ func main() { acmeDirectory := flag.String("acme-directory", "", "ACME Directory URL") enableHTTP01 := flag.Bool("acme-http-01", false, "enable HTTP-01 ACME challenges") enableTLSALPN01 := flag.Bool("acme-tls-alpn-01", false, "enable TLS-ALPN-01 ACME challenges") - acmeRelay := flag.String("acme-relay", "", "the base url of the ACME DNS-01 relay, if not the same as the tunnel relay") + acmeRelay := flag.String("acme-relay-url", "", "the base url of the ACME DNS-01 relay, if not the same as the tunnel relay") authURL := flag.String("auth-url", "", "the base url for authentication, if not the same as the tunnel relay") relay := flag.String("relay", "", "the domain (or ip address) at which the relay server is running") - apiHostname := flag.String("admin-hostname", "", "the hostname used to manage clients") + apiHostname := flag.String("api-hostname", "", "the hostname used to manage clients") secret := flag.String("secret", "", "the same secret used by telebit-relay (used for JWT authentication)") token := flag.String("token", "", "a pre-generated token to give the server (instead of generating one with --secret)") bindAddrsStr := flag.String("listen", "", "list of bind addresses on which to listen, such as localhost:80, or :443") @@ -140,6 +140,9 @@ func main() { return } + if 0 == len(*bindAddrsStr) { + *bindAddrsStr = os.Getenv("LISTEN") + } bindAddrs, err := parseBindAddrs(*bindAddrsStr) if nil != err { fmt.Fprintf(os.Stderr, "invalid bind address(es) given to --listen\n") @@ -174,7 +177,7 @@ func main() { if len(bindAddrs) > 0 { fmt.Fprintf(os.Stderr, "Acting as Relay\n") } else { - fmt.Fprintf(os.Stderr, "error: must provider or act as Relay\n") + fmt.Fprintf(os.Stderr, "error: must provide Relay, or act as Relay\n") os.Exit(1) return } @@ -189,7 +192,7 @@ func main() { if 0 == len(*authURL) { *authURL = os.Getenv("AUTH_URL") } - if len(*relay) > 0 || len(*acmeRelay) > 0 { + if len(*relay) > 0 /* || len(*acmeRelay) > 0 */ { if "" == *authURL { *authURL = strings.Replace(*relay, "ws", "http", 1) // "https://example.com:443" } @@ -403,7 +406,11 @@ func routeSubscribersAndClients(client net.Conn) error { // tryToServeName picks the server tunnel with the least connections, if any func tryToServeName(servername string, wconn *telebit.ConnWrap) bool { srv, ok := table.GetServer(servername) - if !ok { + if !ok || nil == srv { + if ok { + // TODO BUG: Sometimes srv=nil & ok=true, which should not be possible + fmt.Println("[bug] found 'srv=nil'", servername, srv) + } fmt.Println("[debug] no server to server", servername) return false } @@ -413,8 +420,7 @@ func tryToServeName(servername string, wconn *telebit.ConnWrap) bool { go func() { fmt.Printf("[debug] found server to handle client:\n%#v\n", srv) err := srv.Serve(wconn) - fmt.Printf("a browser client stream is done: %q\n", err) - //srv.clients.Delete(wconn.LocalAddr().String()) + fmt.Printf("[debug] a browser client stream is done: %v\n", err) }() return true @@ -453,7 +459,7 @@ func parseBindAddrs(bindAddrsStr string) ([]string, error) { if len(parts) > 2 { return nil, fmt.Errorf("too many colons (:) in bind address %s", addr) } - if "" == addr || "" == parts[0] { + if "" == addr { continue } @@ -490,7 +496,7 @@ func getACMEProvider(acmeRelay, token *string) (challenge.Provider, error) { } } else { if "" == *acmeRelay { - return nil, fmt.Errorf("No relay for ACME DNS-01 challenges given to --acme-relay") + return nil, fmt.Errorf("No relay for ACME DNS-01 challenges given to --acme-relay-url") } endpoint := *acmeRelay if strings.HasSuffix(endpoint, "/") { diff --git a/cmd/wsserve/wsserve.go b/cmd/wsserve/wsserve.go index 98c7758..e5f2f83 100644 --- a/cmd/wsserve/wsserve.go +++ b/cmd/wsserve/wsserve.go @@ -61,9 +61,8 @@ func main() { acmeDirectory := flag.String("acme-directory", "", "ACME Directory URL") enableHTTP01 := flag.Bool("acme-http-01", false, "enable HTTP-01 ACME challenges") enableTLSALPN01 := flag.Bool("acme-tls-alpn-01", false, "enable TLS-ALPN-01 ACME challenges") - acmeRelay := flag.String("acme-relay", "", "the base url of the ACME DNS-01 relay, if not the same as the tunnel relay") + acmeRelay := flag.String("acme-relay-url", "", "the base url of the ACME DNS-01 relay, if not the same as the tunnel relay") authURL := flag.String("auth-url", "", "the base url for authentication, if not the same as the tunnel relay") - //apiHostname := flag.String("admin-hostname", "", "the hostname used to manage clients") token := flag.String("token", "", "a pre-generated token to give the server (instead of generating one with --secret)") flag.Parse() @@ -73,7 +72,7 @@ func main() { authorizer = NewAuthorizer(*authURL) if 0 == len(*acmeRelay) { - *acmeRelay = os.Getenv("ACME_RELAY_BASEURL") + *acmeRelay = os.Getenv("ACME_RELAY_URL") } provider, err := getACMEProvider(acmeRelay, token) if nil != err { @@ -263,7 +262,7 @@ func getACMEProvider(acmeRelay, token *string) (challenge.Provider, error) { } } else { if "" == *acmeRelay { - return nil, fmt.Errorf("No relay for ACME DNS-01 challenges given to --acme-relay") + return nil, fmt.Errorf("No relay for ACME DNS-01 challenges given to --acme-relay-url") } endpoint := *acmeRelay if strings.HasSuffix(endpoint, "/") { diff --git a/examples/register-new-device.sh b/examples/register-new-device.sh index d9527fc..8e6cc25 100644 --- a/examples/register-new-device.sh +++ b/examples/register-new-device.sh @@ -1,9 +1,9 @@ source .env TOKEN=$(go run -mod=vendor cmd/signjwt/*.go $SECRET) -MGMT_BASEURL=${MGMT_BASEURL:-"http://mgmt.example.com:3010"} +AUTH_URL=${AUTH_URL:-"http://mgmt.example.com:3010"} CLIENT_SUBJECT=${CLIENT_SUBJECT:-"newbie"} -curl -X POST $MGMT_BASEURL/api/devices \ +curl -X POST $AUTH_URL/api/devices \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "slug": "'$CLIENT_SUBJECT'" }' diff --git a/examples/relay.env b/examples/relay.env index 9e4a79e..2b0e323 100644 --- a/examples/relay.env +++ b/examples/relay.env @@ -1,8 +1,16 @@ -MGMT_BASEURL=http://devices.example.com:3010 -SECRET=xxxxxxxxxxxxxxxx -ADMIN_HOSTNAME=devices.example.com -WSS_HOSTNAME= -PORT=443 -DUCKDNS_TOKEN=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX -GODADDY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -GODADDY_API_SECRET=XXXXXXXXXXXXXXXXXXXXXX +# For Tunnel Relay Service +API_HOSTNAME=devices.example.com +LISTEN=":80 :443" + +# For Device Management & Authorization Server +AUTH_URL=http://localhost:4200/api + +# For Let's Encrypt ACME registration +ACME_AGREE=true +ACME_EMAIL=jon.doe@example.com + +# For Let's Encrypt ACME Challenges (pick one) +ACME_RELAY_URL=http://localhost:4200 +#DUCKDNS_TOKEN=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +#GODADDY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +#GODADDY_API_SECRET=XXXXXXXXXXXXXXXXXXXXXX diff --git a/examples/run-as-client.sh b/examples/run-as-client.sh index c39afe5..348bdec 100644 --- a/examples/run-as-client.sh +++ b/examples/run-as-client.sh @@ -8,11 +8,11 @@ go build -mod=vendor -o telebit cmd/telebit/*.go source .env -ACME_RELAY_BASEURL=${ACME_RELAY_BASEURL:-"https://devices.examples.com"} -AUTH_BASEURL=${AUTH_BASEURL:-"https://devices.examples.com"} +ACME_RELAY_URL=${ACME_RELAY_URL:-"https://devices.examples.com"} +AUTH_URL=${AUTH_URL:-"https://devices.examples.com"} CLIENT_SECRET=${CLIENT_SECRET:-"yyyyyyyyyyyyyyyy"} ./telebit --acme-agree=true \ - --acme-relay $ACME_RELAY_BASEURL/api \ - --auth-url $AUTH_BASEURL/api \ + --acme-relay-url $ACME_RELAY_URL/api \ + --auth-url $AUTH_URL/api \ --app-id test-id --secret "$CLIENT_SECRET" diff --git a/examples/run-as-relay.sh b/examples/run-as-relay.sh index 8f00ba6..74a6916 100644 --- a/examples/run-as-relay.sh +++ b/examples/run-as-relay.sh @@ -3,20 +3,34 @@ set -e set -u -#go generate -mod=vendor ./... -go build -mod=vendor -o telebit cmd/telebit/*.go +go mod tidy +go mod vendor +go generate -mod=vendor ./... +go build -mod=vendor -o ./telebit ./cmd/telebit/*.go +if [ -n "$(command -v setcap)" ]; then + sudo setcap 'cap_net_bind_service=+ep' ./telebit +fi source .env -ADMIN_HOSTNAME=${ADMIN_HOSTNAME:-"devices.example.com"} -AUTH_BASEURL=${AUTH_BASEURL:-"https://devices.example.com"} -AUTH_URL=${AUTH_URL:-"$AUTH_BASEURL/api"} -SECRET=${SECRET:-"xxxxxxxxxxxxxxxx"} +# For Tunnel Relay Server +API_HOSTNAME=${API_HOSTNAME:-"devices.example.com"} +LISTEN="${LISTEN:-":80 :443"}" + +# For Device Management & Authentication +AUTH_URL=${AUTH_URL:-"https://devices.example.com/api"} + +# For Let's Encrypt / ACME challenges +ACME_RELAY_URL=${ACME_RELAY_URL:-"http://localhost:4200"} + +# For Let's Encrypt / ACME registration +ACME_AGREE=${ACME_AGREE:-} ACME_EMAIL="${ACME_EMAIL:-}" -./telebit --acme-agree=true \ - --admin-hostname $ADMIN_HOSTNAME \ +./telebit \ + --api-hostname $API_HOSTNAME \ --auth-url $AUTH_URL \ + --acme-agree "$ACME_AGREE" \ --acme-email "$ACME_EMAIL" \ - --secret "$SECRET" \ - --listen 3020,3030 + --acme-relay-url "$ACME_RELAY_URL" \ + --listen "$LISTEN"