fix 1 => i bug, improve logging, update some ENVs and --args

This commit is contained in:
AJ ONeal 2020-07-17 21:51:48 -06:00
parent f362427e7b
commit 2229f62e5f
2 changed files with 64 additions and 22 deletions

View File

@ -18,6 +18,7 @@ import (
"strings" "strings"
"time" "time"
"git.coolaj86.com/coolaj86/go-telebitd/dbg"
"git.coolaj86.com/coolaj86/go-telebitd/mgmt" "git.coolaj86.com/coolaj86/go-telebitd/mgmt"
"git.coolaj86.com/coolaj86/go-telebitd/mgmt/authstore" "git.coolaj86.com/coolaj86/go-telebitd/mgmt/authstore"
telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer" telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer"
@ -54,8 +55,10 @@ var authorizer telebit.Authorizer
var isHostname = regexp.MustCompile(`^[A-Za-z0-9_\.\-]+$`).MatchString var isHostname = regexp.MustCompile(`^[A-Za-z0-9_\.\-]+$`).MatchString
// ClientID may be baked in, or may be supplied via command line // ClientID may be baked in, or supplied via ENVs or --args
var ClientID string var ClientID string
// ClientSecret may be baked in, or supplied via ENVs or --args
var ClientSecret string var ClientSecret string
func main() { func main() {
@ -64,7 +67,7 @@ func main() {
var portForwards []Forward var portForwards []Forward
// TODO replace the websocket connection with a mock server // TODO replace the websocket connection with a mock server
appID := flag.String("app-id", "telebit.io", "a unique identifier for a deploy target environment") appID := flag.String("app-id", "", "a unique identifier for a deploy target environment")
email := flag.String("acme-email", "", "email to use for Let's Encrypt / ACME registration") email := flag.String("acme-email", "", "email to use for Let's Encrypt / ACME registration")
certpath := flag.String("acme-storage", "./acme.d/", "path to ACME storage directory") certpath := flag.String("acme-storage", "./acme.d/", "path to ACME storage directory")
acmeAgree := flag.Bool("acme-agree", false, "agree to the terms of the ACME service provider (required)") acmeAgree := flag.Bool("acme-agree", false, "agree to the terms of the ACME service provider (required)")
@ -74,15 +77,21 @@ func main() {
enableTLSALPN01 := flag.Bool("acme-tls-alpn-01", false, "enable TLS-ALPN-01 ACME challenges") enableTLSALPN01 := flag.Bool("acme-tls-alpn-01", false, "enable TLS-ALPN-01 ACME challenges")
acmeRelay := flag.String("acme-relay-url", "", "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") 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") relay := flag.String("relay-url", "", "the websocket url at which to connect to the tunnel relay")
apiHostname := flag.String("api-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)") 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)") 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") bindAddrsStr := flag.String("listen", "", "list of bind addresses on which to listen, such as localhost:80, or :443")
locals := flag.String("locals", "", "a list of <from-domain>:<to-port>") locals := flag.String("locals", "", "a list of <from-domain>:<to-port>")
portToPorts := flag.String("port-forward", "", "a list of <from-port>:<to-port> for raw port-forwarding") portToPorts := flag.String("port-forward", "", "a list of <from-port>:<to-port> for raw port-forwarding")
verbose := flag.Bool("verbose", false, "log excessively")
flag.Parse() flag.Parse()
dbg.Debug = *verbose
if !dbg.Debug {
dbg.Debug = ("true" == os.Getenv("VERBOSE"))
}
if len(os.Args) >= 2 { if len(os.Args) >= 2 {
if "version" == os.Args[1] { if "version" == os.Args[1] {
fmt.Printf("telebit %s %s %s", GitVersion, GitRev[:7], GitTimestamp) fmt.Printf("telebit %s %s %s", GitVersion, GitRev[:7], GitTimestamp)
@ -208,7 +217,7 @@ func main() {
} }
} }
if 0 == len(*relay) { if 0 == len(*relay) {
*relay = os.Getenv("RELAY") // "wss://example.com:443" *relay = os.Getenv("RELAY_URL") // "wss://example.com:443"
} }
if 0 == len(*relay) { if 0 == len(*relay) {
if len(bindAddrs) > 0 { if len(bindAddrs) > 0 {
@ -284,12 +293,13 @@ func main() {
// Port forward without TerminatingTLS // Port forward without TerminatingTLS
for _, fwd := range portForwards { for _, fwd := range portForwards {
fmt.Println("Fwd:", fwd.pattern, fwd.port) msg := fmt.Sprintf("Fwd: %s %s", fwd.pattern, fwd.port)
mux.ForwardTCP(fwd.pattern, "localhost:"+fwd.port, 120*time.Second) fmt.Println(msg)
mux.ForwardTCP(fwd.pattern, "localhost:"+fwd.port, 120*time.Second, msg, "[Port Forward]")
} }
// TODO close connection on invalid hostname // TODO close connection on invalid hostname
mux.HandleTCP("*", telebit.HandlerFunc(routeSubscribersAndClients)) mux.HandleTCP("*", telebit.HandlerFunc(routeSubscribersAndClients), "[Tun => Remote Servers]")
mux.HandleTLS("*", acme, mux) mux.HandleTLS("*", acme, mux, "[Terminate TLS & Recurse]")
if 0 == len(*apiHostname) { if 0 == len(*apiHostname) {
*apiHostname = os.Getenv("API_HOSTNAME") *apiHostname = os.Getenv("API_HOSTNAME")
@ -301,20 +311,27 @@ func main() {
}() }()
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)
mux.HandleTCP(*apiHostname, telebit.HandlerFunc(func(client net.Conn) error { mux.HandleTCP(*apiHostname, telebit.HandlerFunc(func(client net.Conn) error {
if dbg.Debug {
fmt.Printf("[debug] Accepting API or WebSocket client %q\n", *apiHostname) fmt.Printf("[debug] Accepting API or WebSocket client %q\n", *apiHostname)
}
listener.Feed(client) listener.Feed(client)
if dbg.Debug {
fmt.Printf("[debug] done with %q client\n", *apiHostname) fmt.Printf("[debug] done with %q client\n", *apiHostname)
}
// nil now means handler in-progress (go routine) // nil now means handler in-progress (go routine)
// EOF now means handler finished // EOF now means handler finished
return nil return nil
})) }), "[Admin API & Server Relays]")
} }
for _, fwd := range forwards { for _, fwd := range forwards {
//mux.ForwardTCP("*", "localhost:"+fwd.port, 120*time.Second) //mux.ForwardTCP("*", "localhost:"+fwd.port, 120*time.Second)
mux.ForwardTCP(fwd.pattern, "localhost:"+fwd.port, 120*time.Second) mux.ForwardTCP(fwd.pattern, "localhost:"+fwd.port, 120*time.Second, "[Servername Forward]")
} }
done := make(chan error) done := make(chan error)
if dbg.Debug {
fmt.Println("[debug] bindAddrs", bindAddrs, *bindAddrsStr)
}
for _, addr := range bindAddrs { for _, addr := range bindAddrs {
go func(addr string) { go func(addr string) {
fmt.Printf("Listening on %s\n", addr) fmt.Printf("Listening on %s\n", addr)
@ -394,8 +411,10 @@ func routeSubscribersAndClients(client net.Conn) error {
//dstAddr := dstParts[0] //dstAddr := dstParts[0]
dstPort, _ := strconv.Atoi(dstParts[1]) dstPort, _ := strconv.Atoi(dstParts[1])
if dbg.Debug {
fmt.Printf("[debug] wconn.LocalAddr() %+v\n", wconn.LocalAddr()) fmt.Printf("[debug] wconn.LocalAddr() %+v\n", wconn.LocalAddr())
fmt.Printf("[debug] wconn.RemoteAddr() %+v\n", wconn.RemoteAddr()) fmt.Printf("[debug] wconn.RemoteAddr() %+v\n", wconn.RemoteAddr())
}
if 80 != dstPort && 443 != dstPort { if 80 != dstPort && 443 != dstPort {
// TODO handle by port without peeking at Servername / Hostname // TODO handle by port without peeking at Servername / Hostname
@ -408,11 +427,16 @@ func routeSubscribersAndClients(client net.Conn) error {
servername := strings.ToLower(wconn.Servername()) servername := strings.ToLower(wconn.Servername())
if "" != servername && !isHostname(servername) { if "" != servername && !isHostname(servername) {
_ = client.Close() _ = client.Close()
if dbg.Debug {
fmt.Println("[debug] invalid servername") fmt.Println("[debug] invalid servername")
}
return fmt.Errorf("invalid servername") return fmt.Errorf("invalid servername")
} }
if dbg.Debug {
fmt.Printf("[debug] wconn.Servername() %+v\n", servername) fmt.Printf("[debug] wconn.Servername() %+v\n", servername)
}
// Match full servername "sub.domain.example.com" // Match full servername "sub.domain.example.com"
if tryToServeName(servername, wconn) { if tryToServeName(servername, wconn) {
// TODO better non-error // TODO better non-error
@ -430,7 +454,7 @@ func routeSubscribersAndClients(client net.Conn) error {
return telebit.ErrNotHandled return telebit.ErrNotHandled
} }
for i := 1; i < n-1; i++ { for i := 1; i < n-1; i++ {
wildname := "*." + strings.Join(labels[1:], ".") wildname := "*." + strings.Join(labels[i:], ".")
if tryToServeName(wildname, wconn) { if tryToServeName(wildname, wconn) {
return io.EOF return io.EOF
} }
@ -448,16 +472,22 @@ func tryToServeName(servername string, wconn *telebit.ConnWrap) bool {
// TODO BUG: Sometimes srv=nil & ok=true, which should not be possible // TODO BUG: Sometimes srv=nil & ok=true, which should not be possible
fmt.Println("[bug] found 'srv=nil'", servername, srv) fmt.Println("[bug] found 'srv=nil'", servername, srv)
} }
if dbg.Debug {
fmt.Println("[debug] no server to server", servername) fmt.Println("[debug] no server to server", servername)
}
return false return false
} }
// async so that the call stack can complete and be released // async so that the call stack can complete and be released
//srv.clients.Store(wconn.LocalAddr().String(), wconn) //srv.clients.Store(wconn.LocalAddr().String(), wconn)
go func() { go func() {
if dbg.Debug {
fmt.Printf("[debug] found server to handle client:\n%#v\n", srv) fmt.Printf("[debug] found server to handle client:\n%#v\n", srv)
}
err := srv.Serve(wconn) err := srv.Serve(wconn)
if dbg.Debug {
fmt.Printf("[debug] a browser client stream is done: %v\n", err) fmt.Printf("[debug] a browser client stream is done: %v\n", err)
}
}() }()
return true return true

View File

@ -2,6 +2,7 @@ package telebit
import ( import (
"context" "context"
"encoding/hex"
"fmt" "fmt"
"io" "io"
"net" "net"
@ -10,6 +11,8 @@ import (
"strings" "strings"
"time" "time"
"git.coolaj86.com/coolaj86/go-telebitd/dbg"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
@ -71,9 +74,17 @@ func (wsw *WebsocketTunnel) Read(b []byte) (int, error) {
} }
n, err := wsw.tmpr.Read(b) n, err := wsw.tmpr.Read(b)
fmt.Println("[debug] [wstun] Read", n) if dbg.Debug {
logmsg := hex.EncodeToString(b[:n])
if len(logmsg) > 80 {
logmsg = logmsg[:39] + "..." + logmsg[n-38:]
}
fmt.Println("[debug] [wstun] Read", n, logmsg)
}
if nil != err { if nil != err {
fmt.Println("[debug] [wstun] Read err:", err) if dbg.Debug {
fmt.Println("[debug] [wstun] Read (EOF=WS packet complete) err:", err)
}
if io.EOF == err { if io.EOF == err {
wsw.tmpr = nil wsw.tmpr = nil
// ignore the message EOF because it's not the websocket EOF // ignore the message EOF because it's not the websocket EOF
@ -98,6 +109,7 @@ func (wsw *WebsocketTunnel) Write(b []byte) (int, error) {
fmt.Println("[debug] [wstun] Write err:", err) fmt.Println("[debug] [wstun] Write err:", err)
return n, err return n, err
} }
fmt.Println("[debug] [wstun] Write n", n, "=", len(b))
// if the message error fails, we can assume the websocket is damaged // if the message error fails, we can assume the websocket is damaged
return n, msgw.Close() return n, msgw.Close()