diff --git a/cmd/mgmt/route.go b/cmd/mgmt/route.go index 0929b0b..c3d1a6f 100644 --- a/cmd/mgmt/route.go +++ b/cmd/mgmt/route.go @@ -139,7 +139,7 @@ func routeAll() chi.Router { ctx := r.Context() claims, ok := ctx.Value(MWKey("claims")).(*MgmtClaims) if !ok { - msg := `{"error":"failure to ping: 1"}` + msg := `{"error":"failure to ping: 3"}` fmt.Println("touch no claims", claims) http.Error(w, msg+"\n", http.StatusBadRequest) return diff --git a/cmd/telebit/admin.go b/cmd/telebit/admin.go index 81591f9..f2395cc 100644 --- a/cmd/telebit/admin.go +++ b/cmd/telebit/admin.go @@ -21,7 +21,20 @@ var httpsrv *http.Server func init() { r := chi.NewRouter() - r.HandleFunc("/ws", upgradeWebsocket) + r.Use(func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Println("[debug] should be handled by API or websocket upgrade") + next.ServeHTTP(w, r) + }) + }) + + r.Mount("/ws", http.HandlerFunc(upgradeWebsocket)) + + r.HandleFunc("/api/ping", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Printf("[debug] hit /api/ping and replying\n") + w.Header().Set("Content-Type", "application/json") + w.Write(apiPingContent) + })) r.Route("/api", func(r chi.Router) { // TODO token needs a globally unique subject @@ -40,6 +53,7 @@ func init() { if "*" != grants.Subject { log.Println("only admins allowed", err) w.Write(apiNotAuthorizedContent) + return } next.ServeHTTP(w, r) @@ -59,6 +73,7 @@ func init() { } } +var apiPingContent = []byte("{ \"success\": true, \"error\": \"\" }\n") var apiNotFoundContent = []byte("{ \"error\": \"not found\" }\n") var apiNotAuthorizedContent = []byte("{ \"error\": \"not authorized\" }\n") @@ -146,6 +161,7 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) { ReadBufferSize: 1024, WriteBufferSize: 1024, } + fmt.Println("[debug] grants", grants) conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Println("WebSocket upgrade failed", err) diff --git a/cmd/telebit/authorizer.go b/cmd/telebit/authorizer.go index 5f96682..07eeeb1 100644 --- a/cmd/telebit/authorizer.go +++ b/cmd/telebit/authorizer.go @@ -12,6 +12,7 @@ func NewAuthorizer(authURL string) telebit.Authorizer { return func(r *http.Request) (*telebit.Grants, error) { // do we have a valid wss_client? + fmt.Printf("[authz] Authorization = %s\n", r.Header.Get("Authorization")) var tokenString string if auth := strings.Split(r.Header.Get("Authorization"), " "); len(auth) > 1 { // TODO handle Basic auth tokens as well @@ -25,10 +26,12 @@ func NewAuthorizer(authURL string) telebit.Authorizer { r.URL.Query().Set("access_token", "[redacted]") } + fmt.Printf("[authz] authURL = %s\n", authURL) + fmt.Printf("[authz] token = %s\n", tokenString) grants, err := telebit.Inspect(authURL, tokenString) if nil != err { - fmt.Println("return an error, do not go on") + fmt.Printf("[authorizer] error inspecting %q: %s\ntoken: %s\n", authURL, err, tokenString) return nil, err } if "" != r.URL.Query().Get("access_token") { diff --git a/cmd/telebit/telebit.go b/cmd/telebit/telebit.go index 28be566..265ee82 100644 --- a/cmd/telebit/telebit.go +++ b/cmd/telebit/telebit.go @@ -21,9 +21,10 @@ import ( "git.coolaj86.com/coolaj86/go-telebitd/mgmt" "git.coolaj86.com/coolaj86/go-telebitd/mgmt/authstore" telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer" - "git.coolaj86.com/coolaj86/go-telebitd/mplexer/dns01" + tbDns01 "git.coolaj86.com/coolaj86/go-telebitd/mplexer/dns01" httpshim "git.coolaj86.com/coolaj86/go-telebitd/relay/tunnel" "git.coolaj86.com/coolaj86/go-telebitd/table" + legoDns01 "github.com/go-acme/lego/v3/challenge/dns01" "github.com/caddyserver/certmagic" "github.com/denisbrodbeck/machineid" @@ -78,8 +79,6 @@ func main() { portToPorts := flag.String("port-forward", "", "a list of : for raw port-forwarding") flag.Parse() - authorizer = NewAuthorizer(*authURL) - if len(os.Args) >= 2 { if "version" == os.Args[1] { fmt.Printf("telebit %s %s %s", GitVersion, GitRev[:7], GitTimestamp) @@ -164,14 +163,21 @@ func main() { *relay = os.Getenv("RELAY") // "wss://example.com:443" } if 0 == len(*relay) { - fmt.Fprintf(os.Stderr, "Missing relay url\n") - os.Exit(1) - return + 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") + os.Exit(1) + return + } } if 0 == len(*acmeRelay) { *acmeRelay = strings.Replace(*relay, "ws", "http", 1) // "https://example.com:443" } + if 0 == len(*authURL) { + *authURL = os.Getenv("AUTH_URL") + } if len(*relay) > 0 || len(*acmeRelay) > 0 { if "" == *authURL { *authURL = strings.Replace(*relay, "ws", "http", 1) // "https://example.com:443" @@ -192,6 +198,7 @@ func main() { } fmt.Println("grants", grants) } + authorizer = NewAuthorizer(*authURL) provider, err := getACMEProvider(acmeRelay, token) if nil != err { @@ -199,12 +206,22 @@ func main() { os.Exit(1) return } + fmt.Printf("Email: %q\n", *email) acme := &telebit.ACME{ - Email: *email, - StoragePath: *certpath, - Agree: *acmeAgree, - Directory: *acmeDirectory, - DNSProvider: provider, + Email: *email, + StoragePath: *certpath, + Agree: *acmeAgree, + Directory: *acmeDirectory, + DNSProvider: provider, + //DNSChallengeOption: legoDns01.DNSProviderOption, + DNSChallengeOption: legoDns01.WrapPreCheck(func(domain, fqdn, value string, orig legoDns01.PreCheckFunc) (bool, error) { + ok, err := orig(fqdn, value) + if ok { + fmt.Println("[Telebit-ACME-DNS] sleeping an additional 5 seconds") + time.Sleep(5 * time.Second) + } + return ok, err + }), EnableHTTPChallenge: *enableHTTP01, EnableTLSALPNChallenge: *enableTLSALPN01, } @@ -229,8 +246,11 @@ func main() { go func() { httpsrv.Serve(listener) }() + fmt.Printf("Will respond to Websocket and API requests to %q\n", *apiHostname) mux.HandleTCP(*apiHostname, telebit.HandlerFunc(func(client net.Conn) error { + fmt.Printf("[debug] Accepting API or WebSocket client %q\n", *apiHostname) listener.Feed(client) + fmt.Printf("[debug] done with %q client\n", *apiHostname) // TODO use a more correct non-error error? // or perhaps (ok, error) or (handled, error)? return io.EOF @@ -332,6 +352,7 @@ func routeSubscribersAndClients(client net.Conn) error { servername := strings.ToLower(wconn.Servername()) if "" != servername && !isHostname(servername) { _ = client.Close() + fmt.Println("[debug] invalid servername") return fmt.Errorf("invalid servername") } @@ -365,6 +386,7 @@ func routeSubscribersAndClients(client net.Conn) error { func tryToServeName(servername string, wconn *telebit.ConnWrap) bool { srv, ok := table.GetServer(servername) if !ok { + fmt.Println("[debug] no server to server", servername) return false } @@ -493,15 +515,15 @@ func newGoDaddyDNSProvider(id, secret string) (*godaddy.DNSProvider, error) { } // newAPIDNSProvider is for the sake of demoing the tunnel -func newAPIDNSProvider(baseURL string, token string) (*dns01.DNSProvider, error) { - config := dns01.NewDefaultConfig() +func newAPIDNSProvider(baseURL string, token string) (*tbDns01.DNSProvider, error) { + config := tbDns01.NewDefaultConfig() config.Token = token endpoint, err := url.Parse(baseURL) if nil != err { return nil, err } config.Endpoint = endpoint - return dns01.NewDNSProviderConfig(config) + return tbDns01.NewDNSProviderConfig(config) } /* diff --git a/mplexer/connwrap.go b/mplexer/connwrap.go index 7b41485..7e8beba 100644 --- a/mplexer/connwrap.go +++ b/mplexer/connwrap.go @@ -138,8 +138,9 @@ func (c *ConnWrap) isTerminated() bool { c.SetDeadline(time.Now().Add(5 * time.Second)) n := 6 b, _ := c.Peek(n) - fmt.Println("Peek(n)", b) + fmt.Println("Peek(n)", b, string(b)) defer c.SetDeadline(time.Time{}) + var encrypted bool if len(b) >= n { // SSL v3.x / TLS v1.x // 0: TLS Byte @@ -153,15 +154,16 @@ func (c *ConnWrap) isTerminated() bool { length := (int(b[3]) << 8) + int(b[4]) b, err := c.Peek(n - 1 + length) if nil != err { - *c.encrypted = false + c.encrypted = &encrypted return !*c.encrypted } c.servername, _ = sni.GetHostname(b) - *c.encrypted = true + encrypted = true + c.encrypted = &encrypted return !*c.encrypted } } - *c.encrypted = false + c.encrypted = &encrypted return !*c.encrypted /* if nil != err { diff --git a/mplexer/telebit.go b/mplexer/telebit.go index d52ce20..aa3f5aa 100644 --- a/mplexer/telebit.go +++ b/mplexer/telebit.go @@ -16,6 +16,7 @@ import ( "github.com/caddyserver/certmagic" "github.com/go-acme/lego/v3/challenge" + "github.com/go-acme/lego/v3/challenge/dns01" ) // Note: 64k is the TCP max, but 1460b is the 100mbit Ethernet max (1500 MTU - overhead), @@ -176,6 +177,7 @@ type ACME struct { Email string Directory string DNSProvider challenge.Provider + DNSChallengeOption dns01.ChallengeOption Storage certmagic.Storage StoragePath string EnableHTTPChallenge bool @@ -205,7 +207,7 @@ func TerminateTLS(client net.Conn, acme *ACME) net.Conn { } var err error - magic, err = newCertMagic(acme) + magic, err = NewCertMagic(acme) if nil != err { fmt.Fprintf( os.Stderr, @@ -276,7 +278,7 @@ func TerminateTLS(client net.Conn, acme *ACME) net.Conn { } } -func newCertMagic(acme *ACME) (*certmagic.Config, error) { +func NewCertMagic(acme *ACME) (*certmagic.Config, error) { if !acme.Agree { fmt.Fprintf( os.Stderr, @@ -304,8 +306,10 @@ func newCertMagic(acme *ACME) (*certmagic.Config, error) { }, }) // yes, a circular reference, passing `magic` to its own Issuer + fmt.Printf("[debug] ACME Email: %q\n", acme.Email) magic.Issuer = certmagic.NewACMEManager(magic, certmagic.ACMEManager{ DNSProvider: acme.DNSProvider, + DNSChallengeOption: acme.DNSChallengeOption, CA: acme.Directory, Email: acme.Email, Agreed: acme.Agree,