fix 1 => i bug, improve logging, update some ENVs and --args
This commit is contained in:
parent
f362427e7b
commit
2229f62e5f
|
@ -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 {
|
||||||
fmt.Printf("[debug] Accepting API or WebSocket client %q\n", *apiHostname)
|
if dbg.Debug {
|
||||||
|
fmt.Printf("[debug] Accepting API or WebSocket client %q\n", *apiHostname)
|
||||||
|
}
|
||||||
listener.Feed(client)
|
listener.Feed(client)
|
||||||
fmt.Printf("[debug] done with %q client\n", *apiHostname)
|
if dbg.Debug {
|
||||||
|
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])
|
||||||
|
|
||||||
fmt.Printf("[debug] wconn.LocalAddr() %+v\n", wconn.LocalAddr())
|
if dbg.Debug {
|
||||||
fmt.Printf("[debug] wconn.RemoteAddr() %+v\n", wconn.RemoteAddr())
|
fmt.Printf("[debug] wconn.LocalAddr() %+v\n", wconn.LocalAddr())
|
||||||
|
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()
|
||||||
fmt.Println("[debug] invalid servername")
|
|
||||||
|
if dbg.Debug {
|
||||||
|
fmt.Println("[debug] invalid servername")
|
||||||
|
}
|
||||||
return fmt.Errorf("invalid servername")
|
return fmt.Errorf("invalid servername")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("[debug] wconn.Servername() %+v\n", servername)
|
if dbg.Debug {
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
fmt.Println("[debug] no server to server", servername)
|
if dbg.Debug {
|
||||||
|
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() {
|
||||||
fmt.Printf("[debug] found server to handle client:\n%#v\n", srv)
|
if dbg.Debug {
|
||||||
|
fmt.Printf("[debug] found server to handle client:\n%#v\n", srv)
|
||||||
|
}
|
||||||
err := srv.Serve(wconn)
|
err := srv.Serve(wconn)
|
||||||
fmt.Printf("[debug] a browser client stream is done: %v\n", err)
|
if dbg.Debug {
|
||||||
|
fmt.Printf("[debug] a browser client stream is done: %v\n", err)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue