update URLs

This commit is contained in:
AJ ONeal 2020-07-21 22:42:21 -06:00
parent ecbaf4dfd0
commit 0089dec42e
4 changed files with 138 additions and 16 deletions

View File

@ -24,7 +24,7 @@ import (
"git.rootprojects.org/root/telebit/mgmt" "git.rootprojects.org/root/telebit/mgmt"
"git.rootprojects.org/root/telebit/mgmt/authstore" "git.rootprojects.org/root/telebit/mgmt/authstore"
"git.rootprojects.org/root/telebit/table" "git.rootprojects.org/root/telebit/table"
httpshim "git.rootprojects.org/root/telebit/tunnel" "git.rootprojects.org/root/telebit/tunnel"
legoDns01 "github.com/go-acme/lego/v3/challenge/dns01" legoDns01 "github.com/go-acme/lego/v3/challenge/dns01"
"github.com/caddyserver/certmagic" "github.com/caddyserver/certmagic"
@ -113,6 +113,10 @@ func main() {
*acmeAgree = true *acmeAgree = true
} }
} }
if 0 == len(*acmeRelay) {
*acmeRelay = os.Getenv("ACME_RELAY_URL")
}
if 0 == len(*email) { if 0 == len(*email) {
*email = os.Getenv("ACME_EMAIL") *email = os.Getenv("ACME_EMAIL")
} }
@ -234,21 +238,32 @@ func main() {
return return
} }
} }
if 0 == len(*acmeRelay) {
*acmeRelay = os.Getenv("ACME_RELAY_URL")
}
if 0 == len(*acmeRelay) {
*acmeRelay = strings.Replace(*relay, "ws", "http", 1) + "/dns" // "https://example.com:443"
}
if 0 == len(*authURL) { if 0 == len(*authURL) {
*authURL = os.Getenv("AUTH_URL") *authURL = os.Getenv("AUTH_URL")
} }
var grants *telebit.Grants var grants *telebit.Grants
if len(*relay) > 0 /* || len(*acmeRelay) > 0 */ { if len(*relay) > 0 /* || len(*acmeRelay) > 0 */ {
if "" == *authURL { directory, err := tunnel.Discover(*relay)
*authURL = strings.Replace(*relay, "ws", "http", 1) + "/api" // "https://example.com:443" if nil != err {
fmt.Fprintf(os.Stderr, "Error: invalid Tunnel Relay URL %q: %s\n", *relay, err)
os.Exit(1)
} }
fmt.Printf("[Directory] %s\n\t%#v\n", *relay, directory)
if "" == *authURL {
*authURL = directory.Authenticate.URL
} else {
fmt.Println("Suggested Auth URL:", directory.Authenticate.URL)
fmt.Println("--auth-url Auth URL:", *authURL)
}
if "" == *authURL {
fmt.Fprintf(os.Stderr, "Discovered Directory Endpoints: %+v\n", directory)
fmt.Fprintf(os.Stderr, "No Auth URL detected, no supplied\n")
os.Exit(1)
return
}
// TODO look at relay rather than authURL? // TODO look at relay rather than authURL?
fmt.Println("Auth URL", *authURL) fmt.Println("Auth URL", *authURL)
authorizer = NewAuthorizer(*authURL) authorizer = NewAuthorizer(*authURL)
@ -265,7 +280,8 @@ func main() {
os.Exit(1) os.Exit(1)
} }
} }
fmt.Println("grants", grants) fmt.Printf("[Grants]\n\t%#v\n", grants)
*relay = grants.Audience
} }
authorizer = NewAuthorizer(*authURL) authorizer = NewAuthorizer(*authURL)
@ -388,7 +404,8 @@ func muxAll(
*apiHostname = os.Getenv("API_HOSTNAME") *apiHostname = os.Getenv("API_HOSTNAME")
} }
if "" != *apiHostname { if "" != *apiHostname {
apiListener := httpshim.NewListener() // this is a generic net listener
apiListener := tunnel.NewListener()
go func() { go func() {
httpsrv.Serve(apiListener) httpsrv.Serve(apiListener)
}() }()
@ -416,7 +433,7 @@ func muxAll(
} }
for i, fwd := range forwards { for i, fwd := range forwards {
fmt.Printf("[%d] Will decrypt local requests to %q\n", i, fwd.pattern) fmt.Printf("[%d] Will decrypt local requests to \"%s://%s\"\n", i, fwd.scheme, fwd.pattern)
mux.HandleTLS(fwd.pattern, acme, mux, "[Terminate TLS & Recurse] for (local) "+fwd.pattern) mux.HandleTLS(fwd.pattern, acme, mux, "[Terminate TLS & Recurse] for (local) "+fwd.pattern)
} }

View File

@ -365,12 +365,13 @@ func NewCertMagic(acme *ACME) (*certmagic.Config, error) {
type Grants struct { type Grants struct {
Subject string `json:"sub"` Subject string `json:"sub"`
Audience string `json:"aud"`
Domains []string `json:"domains"` Domains []string `json:"domains"`
Ports []int `json:"ports"` Ports []int `json:"ports"`
} }
func Inspect(authURL, token string) (*Grants, error) { func Inspect(authURL, token string) (*Grants, error) {
inspectURL := authURL + "/inspect" inspectURL := strings.TrimSuffix(authURL, "/inspect") + "/inspect"
//fmt.Fprintf(os.Stderr, "[debug] telebit.Inspect(\n\tinspectURL = %s,\n\ttoken = %s,\n)", inspectURL, token) //fmt.Fprintf(os.Stderr, "[debug] telebit.Inspect(\n\tinspectURL = %s,\n\ttoken = %s,\n)", inspectURL, token)
msg, err := Request("GET", inspectURL, token, nil) msg, err := Request("GET", inspectURL, token, nil)
if nil != err { if nil != err {

103
tunnel/discover.go Normal file
View File

@ -0,0 +1,103 @@
package tunnel
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
)
// Endpoints represents the endpoints listed in the API service directory.
// Ideally the Relay URL is discoverable and will provide the authn endpoint,
// which will provide the tunnel endpoint. However, for the sake of testing,
// these things may happen out-of-order.
type Endpoints struct {
ToS string `json:"terms_of_service"`
APIHost string `json:"api_host"`
Tunnel Endpoint `json:"tunnel"`
Authenticate Endpoint `json:"authn"`
/*
{
"terms_of_service": ":hostname/tos/",
"api_host": ":hostname/api",
"pair_request": {
"method": "POST",
"pathname": "api/telebit.app/pair_request"
}
}
*/
}
// Endpoint represents a URL Request
type Endpoint struct {
URL string `json:"-"`
Method string `json:"method"`
Scheme string `json:"scheme"`
Host string `json:"host"`
Pathname string `json:"pathname"`
}
// Discover checks the .well-known directory for service endpoints
func Discover(relay string) (*Endpoints, error) {
directives := &Endpoints{}
relayURL, err := url.Parse(relay)
if nil != err {
fmt.Fprintf(os.Stderr, "Error: invalid Tunnel Relay URL %q: %s\n", relay, err)
os.Exit(1)
}
if "ws" != relayURL.Scheme[:2] {
if '/' != relayURL.Path[len(relayURL.Path)-1] {
relayURL.Path += "/"
}
resp, err := http.Get(relayURL.String() + ".well-known/telebit.app/index.json")
if nil != err {
fmt.Fprintf(os.Stderr, "Error: invalid Tunnel Relay URL %q: %s\n", relay, err)
os.Exit(1)
}
b, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if nil != err {
return nil, err
}
body := strings.Replace(string(b), ":hostname", relayURL.Host, -1)
err = json.Unmarshal([]byte(body), directives)
if nil != err {
return nil, err
}
directives.Tunnel.URL = endpointToURLString(directives.APIHost, directives.Tunnel)
} else {
directives.Tunnel.URL = relayURL.String()
directives.APIHost = relayURL.Host
}
directives.Authenticate.URL = endpointToURLString(directives.APIHost, directives.Authenticate)
return directives, nil
}
func endpointToURLString(apiHost string, endpoint Endpoint) string {
pathname := endpoint.Pathname
if "" == pathname {
return ""
}
host := endpoint.Host
if "" == host {
host = apiHost
}
scheme := endpoint.Scheme
if "" == scheme {
scheme = "https:"
}
return fmt.Sprintf("%s//%s/%s", scheme, host, pathname)
}

View File

@ -100,6 +100,7 @@ func DialWebsocketTunnel(ctx context.Context, relay, authz string) (net.Conn, er
if dbg.Debug { if dbg.Debug {
fmt.Fprintf(os.Stderr, "[debug] [wstun] simple dial failed %q %v %v\n", err, wsconn, ctx) fmt.Fprintf(os.Stderr, "[debug] [wstun] simple dial failed %q %v %v\n", err, wsconn, ctx)
} }
return nil, err
} }
return NewWebsocketTunnel(wsconn), err return NewWebsocketTunnel(wsconn), err
} }