From d0b6a899f255ed87d4b209716f3c820c4fed686d Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 17 Jul 2020 23:28:12 -0600 Subject: [PATCH] consolidate ENVs for remote server, truncate debug output, add --verbose option --- cmd/telebit/telebit.go | 5 ++- cmd/wsconnect/wsconnect.go | 2 +- dbg/dbg.go | 55 ++++++++++++++++++++++++++++++++ examples/client.env | 6 +++- examples/mgmt.env | 3 +- examples/register-new-device.sh | 5 +-- examples/run-as-client.sh | 56 +++++++++++++++++++++++++++------ mgmt/auth.go | 12 ++++--- mgmt/authstore/authstore.go | 5 +++ mplexer/decoder.go | 11 +++++-- mplexer/encoder.go | 18 ++++++++--- mplexer/parser.go | 10 ++++-- mplexer/v1.go | 13 ++++++-- mplexer/websockettunnel.go | 7 +---- table/table.go | 10 ++++-- 15 files changed, 175 insertions(+), 43 deletions(-) create mode 100644 dbg/dbg.go diff --git a/cmd/telebit/telebit.go b/cmd/telebit/telebit.go index c7fbd92..e41d0ae 100644 --- a/cmd/telebit/telebit.go +++ b/cmd/telebit/telebit.go @@ -87,9 +87,8 @@ func main() { verbose := flag.Bool("verbose", false, "log excessively") flag.Parse() - dbg.Debug = *verbose if !dbg.Debug { - dbg.Debug = ("true" == os.Getenv("VERBOSE")) + dbg.Debug = *verbose } if len(os.Args) >= 2 { @@ -217,7 +216,7 @@ func main() { } } if 0 == len(*relay) { - *relay = os.Getenv("RELAY_URL") // "wss://example.com:443" + *relay = os.Getenv("TUNNEL_RELAY_URL") // "wss://example.com:443" } if 0 == len(*relay) { if len(bindAddrs) > 0 { diff --git a/cmd/wsconnect/wsconnect.go b/cmd/wsconnect/wsconnect.go index fb04b99..3c92d38 100644 --- a/cmd/wsconnect/wsconnect.go +++ b/cmd/wsconnect/wsconnect.go @@ -58,7 +58,7 @@ func main() { } } if 0 == len(*relay) { - *relay = os.Getenv("RELAY") // "wss://example.com:443" + *relay = os.Getenv("TUNNEL_RELAY_URL") // "wss://example.com:443" } if 0 == len(*relay) { fmt.Fprintf(os.Stderr, "Missing relay url\n") diff --git a/dbg/dbg.go b/dbg/dbg.go new file mode 100644 index 0000000..096664a --- /dev/null +++ b/dbg/dbg.go @@ -0,0 +1,55 @@ +package dbg + +import ( + "encoding/hex" + "fmt" + "os" +) + +// Debug is a flag for whether or not verbose logging should be activated +var Debug bool + +var rawBytes bool +var allBytes bool + +func init() { + Init() +} + +// Init will set debug vars from ENVs and print out whatever is set +func Init() { + if !Debug { + Debug = ("true" == os.Getenv("VERBOSE")) + } + if !allBytes { + allBytes = ("true" == os.Getenv("VERBOSE_BYTES")) + } + if !rawBytes { + rawBytes = ("true" == os.Getenv("VERBOSE_RAW")) + } + + if Debug { + fmt.Fprintf(os.Stderr, "DEBUG=true\n") + } + if allBytes || rawBytes { + fmt.Fprintf(os.Stderr, "VERBOSE_BYTES=true\n") + } + if rawBytes { + fmt.Fprintf(os.Stderr, "VERBOSE_RAW=true\n") + } +} + +// Trunc will take up to the first and last 20 bytes of the input to product 80 char hex output +func Trunc(b []byte, n int) string { + bin := b[:n] + if allBytes || rawBytes { + if rawBytes { + return string(bin) + } + return hex.EncodeToString(bin) + } + if n > 40 { + return hex.EncodeToString(bin[:19]) + ".." + hex.EncodeToString(bin[n-19:]) + } + return hex.EncodeToString(bin) +} diff --git a/examples/client.env b/examples/client.env index 287397a..4e4e30f 100644 --- a/examples/client.env +++ b/examples/client.env @@ -1,4 +1,8 @@ CLIENT_SUBJECT=newbie -RELAY=wss://devices.example.com:8443 +ACME_RELAY_URL=https://mgmt.example.com/api/dns +AUTH_URL=https://devices.example.com/api +TUNNEL_RELAY_URL=wss://devices.example.com CLIENT_SECRET=xxxxxxxxxxxxxxxx LOCALS=https:$CLIENT_SUBJECT.devices.example.com:3000,http:$CLIENT_SUBJECT.devices.example.com:3000 +#PORT_FORWARDS=3443:3001,8443:3002 +#DUCKDNS_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx diff --git a/examples/mgmt.env b/examples/mgmt.env index f06dd22..6159372 100644 --- a/examples/mgmt.env +++ b/examples/mgmt.env @@ -1,4 +1,5 @@ -SECRET=xxxxxxxxxxxxxxxx +MGMT_SECRET=xxxxxxxxxxxxxxxx +AUTH_BASEURL=https://devices.example.com DUCKDNS_TOKEN=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX GODADDY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx GODADDY_API_SECRET=XXXXXXXXXXXXXXXXXXXXXX diff --git a/examples/register-new-device.sh b/examples/register-new-device.sh index 8e6cc25..3415732 100644 --- a/examples/register-new-device.sh +++ b/examples/register-new-device.sh @@ -1,9 +1,10 @@ source .env + TOKEN=$(go run -mod=vendor cmd/signjwt/*.go $SECRET) -AUTH_URL=${AUTH_URL:-"http://mgmt.example.com:3010"} +AUTH_URL=${AUTH_URL:-"http://mgmt.example.com:3010/api"} CLIENT_SUBJECT=${CLIENT_SUBJECT:-"newbie"} -curl -X POST $AUTH_URL/api/devices \ +curl -X POST $AUTH_URL/devices \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "slug": "'$CLIENT_SUBJECT'" }' diff --git a/examples/run-as-client.sh b/examples/run-as-client.sh index 348bdec..c8ca700 100644 --- a/examples/run-as-client.sh +++ b/examples/run-as-client.sh @@ -3,16 +3,52 @@ set -e set -u -go generate -mod=vendor ./... -go build -mod=vendor -o telebit cmd/telebit/*.go - source .env -ACME_RELAY_URL=${ACME_RELAY_URL:-"https://devices.examples.com"} -AUTH_URL=${AUTH_URL:-"https://devices.examples.com"} -CLIENT_SECRET=${CLIENT_SECRET:-"yyyyyyyyyyyyyyyy"} +#go generate -mod=vendor ./... +CLIENT_ID="${CLIENT_ID:-"${APP_ID:-"test-id"}"}" +CLIENT_SECRET="${CLIENT_SECRET:-}" +go build -mod=vendor -o ./telebit \ + -ldflags="-X 'main.ClientID=$CLIENT_ID' -X 'main.ClientSecret=$CLIENT_SECRET'" \ + cmd/telebit/*.go +#go build -mod=vendor -o telebit \ +# cmd/telebit/*.go -./telebit --acme-agree=true \ - --acme-relay-url $ACME_RELAY_URL/api \ - --auth-url $AUTH_URL/api \ - --app-id test-id --secret "$CLIENT_SECRET" +# For Device Authorization across services +AUTH_URL=${AUTH_URL:-"https://devices.examples.com/api"} +APP_ID="$CLIENT_ID" +SECRET="${CLIENT_SECRET:-"xxxxxxxxxxxxxxxx"}" +#CLIENT_SECRET=${CLIENT_SECRET:-"yyyyyyyyyyyyyyyy"} +LOCALS="${LOCALS:-"https:newbie.devices.examples.com:3000,http:newbie.devices.examples.com:3000"}" + +# For the Remote Server (Tunnel Client) +TUNNEL_RELAY_URL=${TUNNEL_RELAY_URL:-"wss://devices.example.com"} +LISTEN=":3080" + +# For Let's Encrypt / ACME registration +ACME_AGREE=${ACME_AGREE:-} +ACME_EMAIL=${ACME_EMAIL:-"me@example.com"} + +# For Let's Encrypt / ACME challenges +ACME_RELAY_URL=${ACME_RELAY_URL:-"https://devices.examples.com/api/dns"} + +VERBOSE=${VERBOSE:-} +VERBOSE_BYTES=${VERBOSE_BYTES:-} +VERBOSE_RAW=${VERBOSE_RAW:-} + + +./telebit \ + --auth-url $AUTH_URL \ + --app-id "$APP_ID" \ + --secret "$CLIENT_SECRET" \ + --relay-url $TUNNEL_RELAY_URL \ + --listen "$LISTEN" \ + --locals "$LOCALS" \ + --acme-agree=${ACME_AGREE} \ + --acme-email "$ACME_EMAIL" \ + --acme-relay-url $ACME_RELAY_URL \ + --verbose=$VERBOSE + +# --subject "$CLIENT_SUBJECT" \ + +#PORT_FORWARDS=3443:3001,8443:3002 diff --git a/mgmt/auth.go b/mgmt/auth.go index 3593e63..820ad29 100644 --- a/mgmt/auth.go +++ b/mgmt/auth.go @@ -6,6 +6,7 @@ import ( "fmt" "io/ioutil" + "git.coolaj86.com/coolaj86/go-telebitd/dbg" "git.coolaj86.com/coolaj86/go-telebitd/mgmt/authstore" telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer" ) @@ -35,10 +36,13 @@ func Ping(authURL, token string) error { func Register(authURL, secret, ppid string) (kid string, err error) { pub := authstore.ToPublicKeyString(ppid) - jsonb := bytes.NewBuffer([]byte( - fmt.Sprintf(`{ "machine_ppid": "%s", "public_key": "%s" }`, ppid, pub), - )) - msg, err := telebit.Request("POST", authURL+"/register-device/"+secret, "", jsonb) + jsons := fmt.Sprintf(`{ "machine_ppid": "%s", "public_key": "%s" }`, ppid, pub) + jsonb := bytes.NewBuffer([]byte(jsons)) + fullURL := authURL + "/register-device/" + secret + if dbg.Debug { + fmt.Println("[debug] authURL, secret, ppid", fullURL, secret, jsons) + } + msg, err := telebit.Request("POST", fullURL, "", jsonb) if nil != err { return "", err } diff --git a/mgmt/authstore/authstore.go b/mgmt/authstore/authstore.go index 1e925db..f901b94 100644 --- a/mgmt/authstore/authstore.go +++ b/mgmt/authstore/authstore.go @@ -5,8 +5,10 @@ import ( "crypto/sha256" "encoding/base64" "errors" + "fmt" "time" + "git.coolaj86.com/coolaj86/go-telebitd/dbg" jwt "github.com/dgrijalva/jwt-go" ) @@ -50,6 +52,9 @@ func ToPublicKeyString(secret string) string { func HMACToken(secret string) (token string, err error) { keyID := ToPublicKeyString(secret) + if dbg.Debug { + fmt.Printf("[debug] keyID=%s\n", keyID) + } b := make([]byte, 16) _, _ = rand.Read(b) diff --git a/mplexer/decoder.go b/mplexer/decoder.go index 52a2ef0..4327ec0 100644 --- a/mplexer/decoder.go +++ b/mplexer/decoder.go @@ -1,10 +1,11 @@ package telebit import ( - "encoding/hex" "fmt" "io" "log" + + "git.coolaj86.com/coolaj86/go-telebitd/dbg" ) // Decoder handles a Reader stream containing mplexy-encoded clients @@ -33,7 +34,9 @@ func (d *Decoder) Decode(out Router) error { for { b := make([]byte, d.bufferSize) n, err := d.in.Read(b) - log.Println("[debug] [decoder] [srv] Tunnel read", n, string(b[:n])) + if dbg.Debug { + log.Println("[debug] [decoder] [srv] Tunnel read", n, dbg.Trunc(b, n)) + } if n > 0 { rx <- b[:n] } @@ -49,7 +52,9 @@ func (d *Decoder) Decode(out Router) error { select { case b := <-rx: n, err := p.Write(b) - fmt.Println("[debug] [decoder] [srv] Tunnel write", n, len(b), hex.EncodeToString(b)) + if dbg.Debug { + fmt.Println("[debug] [decoder] [srv] Tunnel write", n, len(b), dbg.Trunc(b, len(b))) + } // TODO BUG: handle when 'n' bytes written is less than len(b) if nil != err { fmt.Println("[debug] [decoder] [srv] Tunnel write error") diff --git a/mplexer/encoder.go b/mplexer/encoder.go index 0b3f387..cafd67a 100644 --- a/mplexer/encoder.go +++ b/mplexer/encoder.go @@ -2,11 +2,13 @@ package telebit import ( "context" - "encoding/hex" "errors" "fmt" "io" + "strings" "sync" + + "git.coolaj86.com/coolaj86/go-telebitd/dbg" ) // TODO: try to be more like encoding/csv, or more like encoding/pem and encoding/json? @@ -73,7 +75,9 @@ func (enc *Encoder) Encode(rin io.Reader, src, dst Addr) error { b := make([]byte, enc.bufferSize) //fmt.Println("loopers gonna loop") n, err := rin.Read(b) - fmt.Println("[debug] [encoder] [srv] Browser read", n, hex.EncodeToString(b[:n])) + if dbg.Debug { + fmt.Println("[debug] [encoder] [srv] Browser read", n, dbg.Trunc(b, n)) + } if n > 0 { rx <- b[:n] } @@ -94,7 +98,9 @@ func (enc *Encoder) Encode(rin io.Reader, src, dst Addr) error { case <-enc.ctx.Done(): // TODO: verify that closing the reader will cause the goroutine to be released //rin.Close() - fmt.Println("[debug] [encoder] [srv] Browser ctx.Done()") + if dbg.Debug { + fmt.Println("[debug] [encoder] [srv] Browser ctx.Done()") + } return errors.New("cancelled by encoder read or parent context") /* case <-enc.subctx.Done(): @@ -113,8 +119,10 @@ func (enc *Encoder) Encode(rin io.Reader, src, dst Addr) error { //fmt.Println("[debug] encode payload:", string(b)) _, err = enc.write(header, b) - fmt.Println("[debug] [encoder] [srv] Browser-to-tun write", len(header), string(header)) - fmt.Println("[debug] [encoder] [srv]", len(b), hex.EncodeToString(b)) + if dbg.Debug { + fmt.Println("[debug] [encoder] [srv] Browser-to-tun write", len(header), strings.TrimSpace(string(header))) + fmt.Println("[debug] [encoder] [srv]", len(b), dbg.Trunc(b, len(b))) + } if nil != err { fmt.Println("[debug] [encoder] [srv] Browser-to-tun write err", err) //rin.Close() diff --git a/mplexer/parser.go b/mplexer/parser.go index 8ee1f49..d96970c 100644 --- a/mplexer/parser.go +++ b/mplexer/parser.go @@ -3,6 +3,8 @@ package telebit import ( "errors" "fmt" + + "git.coolaj86.com/coolaj86/go-telebitd/dbg" ) type Parser struct { @@ -69,7 +71,9 @@ func (p *Parser) Write(b []byte) (int, error) { switch p.parseState { case VersionState: - fmt.Println("[debug] version state", b[0]) + if dbg.Debug { + fmt.Println("[debug] MPLEXY version byte", b[0], string(b)) + } p.state.version = b[0] b = b[1:] p.consumed++ @@ -80,7 +84,9 @@ func (p *Parser) Write(b []byte) (int, error) { switch p.state.version { case V1: - fmt.Println("[debug] v1 unmarshal") + if dbg.Debug { + fmt.Println("[debug] MPLEXY packet is of type v1") + } return p.unpackV1(b) default: return 0, errors.New("incorrect version or version not implemented") diff --git a/mplexer/v1.go b/mplexer/v1.go index 97bd4cd..fa84d6b 100644 --- a/mplexer/v1.go +++ b/mplexer/v1.go @@ -5,6 +5,8 @@ import ( "fmt" "strconv" "strings" + + "git.coolaj86.com/coolaj86/go-telebitd/dbg" ) const ( @@ -182,7 +184,9 @@ func (p *Parser) unpackV1Header(b []byte, n int) ([]byte, error) { } */ p.parseState++ - fmt.Printf("[debug] unpackV1 parse state: %v\n", p.parseState) + if dbg.Debug { + fmt.Printf("[debug] unpackV1 parse state: %v\n", p.parseState) + } if "end" == service { fmt.Println("[debug] unpackV1 end") @@ -192,7 +196,9 @@ func (p *Parser) unpackV1Header(b []byte, n int) ([]byte, error) { } func (p *Parser) unpackV1Payload(b []byte, n int) ([]byte, error) { - fmt.Printf("[debug] unpackV1 payload state: %+v\n", p.state) + if dbg.Debug { + fmt.Printf("[debug] unpackV1 payload state: %+v\n", p.state) + } // Handle "connect" and "end" if 0 == p.state.payloadLen { /* @@ -241,6 +247,9 @@ func (p *Parser) unpackV1Payload(b []byte, n int) ([]byte, error) { if p.state.payloadWritten == p.state.payloadLen { p.state = ParserState{} p.parseState = 0 + if dbg.Debug { + fmt.Println("[debug] MPLEXY completed packet and reset state") + } } return b, nil } diff --git a/mplexer/websockettunnel.go b/mplexer/websockettunnel.go index 03c1d76..d68a98a 100644 --- a/mplexer/websockettunnel.go +++ b/mplexer/websockettunnel.go @@ -2,7 +2,6 @@ package telebit import ( "context" - "encoding/hex" "fmt" "io" "net" @@ -75,11 +74,7 @@ func (wsw *WebsocketTunnel) Read(b []byte) (int, error) { n, err := wsw.tmpr.Read(b) 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) + fmt.Println("[debug] [wstun] Read", n, dbg.Trunc(b, n)) } if nil != err { if dbg.Debug { diff --git a/table/table.go b/table/table.go index 57032eb..c465324 100644 --- a/table/table.go +++ b/table/table.go @@ -1,7 +1,6 @@ package table import ( - "encoding/hex" "fmt" "net" "sync" @@ -10,6 +9,7 @@ import ( "strconv" "strings" + "git.coolaj86.com/coolaj86/go-telebitd/dbg" telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer" "github.com/gorilla/websocket" ) @@ -114,7 +114,9 @@ type SubscriberConn struct { func (s *SubscriberConn) RouteBytes(src, dst telebit.Addr, payload []byte) { id := fmt.Sprintf("%s:%d", src.Hostname(), src.Port()) - fmt.Println("[debug] Routing some more bytes:", len(payload)) + if dbg.Debug { + fmt.Println("[debug] Routing some more bytes:", dbg.Trunc(payload, len(payload))) + } fmt.Printf("id %s\nsrc %+v\n", id, src) fmt.Printf("dst %s %+v\n", dst.Scheme(), dst) clientX, ok := s.Clients.Load(id) @@ -133,7 +135,9 @@ func (s *SubscriberConn) RouteBytes(src, dst telebit.Addr, payload []byte) { for { n, err := client.Write(payload) - fmt.Println("[debug] table Write", len(payload), hex.EncodeToString(payload)) + if dbg.Debug { + fmt.Println("[debug] table Write", dbg.Trunc(payload, len(payload))) + } if nil == err || io.EOF == err { break }