diff --git a/cmd/telebitd/telebitd.go b/cmd/telebitd/telebitd.go index a6c382a..2b1c2b1 100644 --- a/cmd/telebitd/telebitd.go +++ b/cmd/telebitd/telebitd.go @@ -7,15 +7,16 @@ import ( "fmt" "io" "io/ioutil" - "log" + golog "log" "net/http" "os" "strings" telebit "git.coolaj86.com/coolaj86/go-telebitd" + "git.coolaj86.com/coolaj86/go-telebitd/log" "git.coolaj86.com/coolaj86/go-telebitd/relay" "git.coolaj86.com/coolaj86/go-telebitd/relay/api" - "git.coolaj86.com/coolaj86/go-telebitd/server" + "git.coolaj86.com/coolaj86/go-telebitd/relay/mplexy" jwt "github.com/dgrijalva/jwt-go" "github.com/spf13/viper" @@ -24,14 +25,18 @@ import ( _ "github.com/joho/godotenv/autoload" ) +var Loginfo = log.Loginfo +var Logdebug = log.Logdebug + +func init() { + log.LogFlags = golog.Ldate | golog.Lmicroseconds | golog.Lshortfile +} + var ( logfile = "stdout" configPath = "./" configFile = "telebit-relay" - loginfo *log.Logger - logdebug *log.Logger - logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile argWssClientListener string tcpPort int argServerBinding string @@ -86,10 +91,7 @@ func main() { } // send the output io.Writing to the other packages - server.InitLogging(logoutput) - - loginfo = log.New(logoutput, "INFO: main: ", logFlags) - logdebug = log.New(logoutput, "DEBUG: main:", logFlags) + log.InitLogging(logoutput) viper.SetConfigName(configFile) viper.AddConfigPath(configPath) @@ -111,7 +113,7 @@ func main() { lbDefaultMethod = viper.Get("rvpn.loadbalancing.defaultmethod").(string) nickname = viper.Get("rvpn.serverName").(string) - loginfo.Println("startup") + Loginfo.Println("startup") ctx, cancelContext := context.WithCancel(context.Background()) defer cancelContext() @@ -139,7 +141,7 @@ func main() { }, } - authorizer := func(r *http.Request) (*server.Authz, error) { + authorizer := func(r *http.Request) (*mplexy.Authz, error) { // do we have a valid wss_client? var tokenString string @@ -158,7 +160,7 @@ func main() { return nil, err } - authz := &server.Authz{ + authz := &mplexy.Authz{ Domains: []string{ "target.rootprojects.org", }, @@ -174,7 +176,7 @@ func main() { if err != nil || !result.Valid { w.WriteHeader(http.StatusForbidden) w.Write([]byte("Not Authorized")) - loginfo.Println("access_token invalid...closing connection") + Loginfo.Println("access_token invalid...closing connection") return } diff --git a/server/setup.go b/log/log.go similarity index 55% rename from server/setup.go rename to log/log.go index c906f8a..fbf03e4 100644 --- a/server/setup.go +++ b/log/log.go @@ -1,4 +1,4 @@ -package server +package log import ( "io" @@ -8,22 +8,19 @@ import ( var ( //Logoutput -- passing the output writer from main - loginfo *log.Logger - logdebug *log.Logger - logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile - connectionID int64 + Loginfo *log.Logger + Logdebug *log.Logger + LogFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile ) func init() { - loginfo = log.New(os.Stdout, "INFO: server: ", logFlags) - logdebug = log.New(os.Stdout, "DEBUG: server:", logFlags) - connectionID = 0 + Loginfo = log.New(os.Stdout, "INFO: ", LogFlags) + Logdebug = log.New(os.Stdout, "DEBUG: ", LogFlags) } //InitLogging -- after main sets up output, it will init all packages InitLogging //I am sure I am doing this wrong, but I could not find a way to have package level //logging with the flags I wanted and the ability to run lumberjack file management func InitLogging(logoutput io.Writer) { - loginfo.SetOutput(logoutput) - + Loginfo.SetOutput(logoutput) } diff --git a/relay/admin/admin.go b/relay/admin/admin.go index dd7378f..7641d12 100644 --- a/relay/admin/admin.go +++ b/relay/admin/admin.go @@ -10,7 +10,7 @@ import ( telebit "git.coolaj86.com/coolaj86/go-telebitd" "git.coolaj86.com/coolaj86/go-telebitd/relay/api" - "git.coolaj86.com/coolaj86/go-telebitd/server" + "git.coolaj86.com/coolaj86/go-telebitd/relay/mplexy" "github.com/gorilla/mux" ) @@ -26,7 +26,7 @@ var serverStatusAPI *api.Status //ListenAndServe - // - expecting an existing oneConnListener with a qualified wss client connected. // - auth will happen again since we were just peeking at the token. -func ListenAndServe(mx *server.MPlexy, adminListener net.Listener) error { +func ListenAndServe(mx *mplexy.MPlexy, adminListener net.Listener) error { //serverStatus = mx.ctx.Value(ctxServerStatus).(*Status) connectionTable = mx.Status.ConnectionTable diff --git a/server/listener_generic.go b/relay/mplexy/listener.go similarity index 82% rename from server/listener_generic.go rename to relay/mplexy/listener.go index c809636..4386ade 100644 --- a/server/listener_generic.go +++ b/relay/mplexy/listener.go @@ -1,4 +1,4 @@ -package server +package mplexy import ( "bufio" @@ -7,7 +7,6 @@ import ( "crypto/tls" "encoding/hex" "fmt" - "log" "net" "net/http" "strconv" @@ -56,19 +55,19 @@ const ( // - if TLS, consume connection with TLS certbundle, pass to request identifier // - else, just pass to the request identififer func (mx *MPlexy) multiListenAndServe(ctx context.Context, listenerRegistration *ListenerRegistration) { - loginfo.Println(":" + string(listenerRegistration.port)) + Loginfo.Println(":" + string(listenerRegistration.port)) cancelCheck := ctx.Value(ctxCancelCheck).(int) listenAddr, err := net.ResolveTCPAddr("tcp", ":"+strconv.Itoa(listenerRegistration.port)) if nil != err { - loginfo.Println(err) + Loginfo.Println(err) return } ln, err := net.ListenTCP("tcp", listenAddr) if err != nil { - loginfo.Println("unable to bind", err) + Loginfo.Println("unable to bind", err) listenerRegistration.status = listenerFault listenerRegistration.err = err listenerRegistration.commCh <- listenerRegistration @@ -81,7 +80,7 @@ func (mx *MPlexy) multiListenAndServe(ctx context.Context, listenerRegistration for { select { case <-ctx.Done(): - loginfo.Println("Cancel signal hit") + Loginfo.Println("Cancel signal hit") return default: ln.SetDeadline(time.Now().Add(time.Duration(cancelCheck) * time.Second)) @@ -92,7 +91,7 @@ func (mx *MPlexy) multiListenAndServe(ctx context.Context, listenerRegistration if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() { continue } - log.Println(err) + Loginfo.Println(err) return } @@ -115,10 +114,10 @@ func (mx *MPlexy) accept(ctx context.Context, wConn *tunnel.WedgeConn) { encryptMode := encryptNone - loginfo.Println("new conn", wConn, wConn.LocalAddr().String(), wConn.RemoteAddr().String()) + Loginfo.Println("new conn", wConn, wConn.LocalAddr().String(), wConn.RemoteAddr().String()) peek, err := wConn.Peek(peekCnt) if err != nil { - loginfo.Println("error while peeking") + Loginfo.Println("error while peeking") wConn.Close() return } @@ -132,7 +131,7 @@ func (mx *MPlexy) accept(ctx context.Context, wConn *tunnel.WedgeConn) { } else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x01}) { encryptMode = encryptTLS10 - loginfo.Println("TLS10") + Loginfo.Println("TLS10") } else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x02}) { encryptMode = encryptTLS11 @@ -146,19 +145,19 @@ func (mx *MPlexy) accept(ctx context.Context, wConn *tunnel.WedgeConn) { } if encryptMode == encryptSSLV2 { - loginfo.Println("<= SSLv2 is not accepted") + Loginfo.Println("<= SSLv2 is not accepted") wConn.Close() return } if encryptMode == encryptNone { - loginfo.Println("Handle Unencrypted") + Loginfo.Println("Handle Unencrypted") mx.acceptPlainStream(ctx, wConn, false) return } - loginfo.Println("Handle Encryption") + Loginfo.Println("Handle Encryption") mx.acceptEncryptedStream(ctx, wConn) } @@ -167,21 +166,21 @@ func (mx *MPlexy) acceptEncryptedStream(ctx context.Context, wConn *tunnel.Wedge peek, err := wConn.PeekAll() if err != nil { - loginfo.Println("Bad socket: read error from", wConn.RemoteAddr(), err) - loginfo.Println(hex.Dump(peek[0:])) + Loginfo.Println("Bad socket: read error from", wConn.RemoteAddr(), err) + Loginfo.Println(hex.Dump(peek[0:])) wConn.Close() return } sniHostName, err := sni.GetHostname(peek) if err != nil { - loginfo.Println("Bad socket: no SNI from", wConn.RemoteAddr(), err) - loginfo.Println(err) + Loginfo.Println("Bad socket: no SNI from", wConn.RemoteAddr(), err) + Loginfo.Println(err) wConn.Close() return } - loginfo.Println("SNI:", sniHostName) + Loginfo.Println("SNI:", sniHostName) if sniHostName == mx.wssHostName || sniHostName == mx.adminHostName { // The TLS should be terminated and handled internally @@ -195,7 +194,7 @@ func (mx *MPlexy) acceptEncryptedStream(ctx context.Context, wConn *tunnel.Wedge //oneConn := &oneConnListener{wConn} // TLS remains intact and shall be routed downstream, wholesale - loginfo.Println("processing non terminating traffic", mx.wssHostName, sniHostName) + Loginfo.Println("processing non terminating traffic", mx.wssHostName, sniHostName) go mx.routeToTarget(ctx, wConn, sniHostName, "https") } @@ -208,13 +207,13 @@ func (mx *MPlexy) acceptEncryptedStream(ctx context.Context, wConn *tunnel.Wedge // - else handle as raw http // - handle other? func (mx *MPlexy) acceptPlainStream(ctx context.Context, wConn *tunnel.WedgeConn, encrypted bool) { - loginfo.Println("Plain Conn", wConn.LocalAddr().String(), wConn.RemoteAddr().String()) + Loginfo.Println("Plain Conn", wConn.LocalAddr().String(), wConn.RemoteAddr().String()) // TODO couldn't reading everything be dangerous? Or is it limited to a single packet? peek, err := wConn.PeekAll() if err != nil { - loginfo.Println("error while peeking", err) - loginfo.Println(hex.Dump(peek[0:])) + Loginfo.Println("error while peeking", err) + Loginfo.Println(hex.Dump(peek[0:])) wConn.Close() return } @@ -234,17 +233,17 @@ func (mx *MPlexy) acceptPlainStream(ctx context.Context, wConn *tunnel.WedgeConn return } - loginfo.Println("identified HTTP") + Loginfo.Println("identified HTTP") r, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(peek))) if err != nil { - loginfo.Println("identified as HTTP, failed request parsing", err) + Loginfo.Println("identified as HTTP, failed request parsing", err) wConn.Close() return } if strings.Contains(r.Host, telebit.InvalidAdminDomain) { - loginfo.Println("admin") + Loginfo.Println("admin") // TODO mx.Admin.CheckRemoteIP(conn) here // handle admin path mx.AcceptAdminClient(wConn) @@ -256,15 +255,15 @@ func (mx *MPlexy) acceptPlainStream(ctx context.Context, wConn *tunnel.WedgeConn // TODO check if this is a websocket _, err = mx.AuthorizeTarget(r) if err == nil { - loginfo.Println("Valid WSS dected...sending to handler") + Loginfo.Println("Valid WSS dected...sending to handler") mx.AcceptTargetServer(wConn) return } // TODO sniHostName is the key to the route, which could also be a port or hostname //traffic not terminating on the rvpn do not decrypt - loginfo.Println("processing non terminating traffic", mx.wssHostName, r.Host) - loginfo.Println(hex.Dump(peek)) + Loginfo.Println("processing non terminating traffic", mx.wssHostName, r.Host) + Loginfo.Println(hex.Dump(peek)) if !encrypted { // TODO request and cache http resources as a feature?? go mx.routeToTarget(ctx, wConn, r.Host, "http") @@ -272,7 +271,7 @@ func (mx *MPlexy) acceptPlainStream(ctx context.Context, wConn *tunnel.WedgeConn } // This is not presently possible - loginfo.Println("impossible condition: local decryption of routable client", mx.wssHostName, r.Host) + Loginfo.Println("impossible condition: local decryption of routable client", mx.wssHostName, r.Host) go mx.routeToTarget(ctx, wConn, r.Host, "https") } @@ -294,7 +293,7 @@ func (mx *MPlexy) routeToTarget(ctx context.Context, extConn *tunnel.WedgeConn, conn, ok := serverStatus.ConnectionTable.ConnByDomain(hostname) if !ok { //matching connection can not be found based on ConnByDomain - loginfo.Println("unable to match ", hostname, " to an existing connection") + Loginfo.Println("unable to match ", hostname, " to an existing connection") //http.Error(, "Domain not supported", http.StatusBadRequest) return } @@ -303,15 +302,15 @@ func (mx *MPlexy) routeToTarget(ctx context.Context, extConn *tunnel.WedgeConn, serverStatus.ExtConnectionRegister(track) remoteStr := extConn.RemoteAddr().String() - loginfo.Println("Domain Accepted", hostname, remoteStr) + Loginfo.Println("Domain Accepted", hostname, remoteStr) var header *packer.Header if rAddr, rPort, err := net.SplitHostPort(remoteStr); err != nil { - loginfo.Println("unable to decode hostport", remoteStr, err) + Loginfo.Println("unable to decode hostport", remoteStr, err) } else if port, err := strconv.Atoi(rPort); err != nil { - loginfo.Printf("unable to parse port string %q: %v\n", rPort, err) + Loginfo.Printf("unable to parse port string %q: %v\n", rPort, err) } else if header, err = packer.NewHeader(rAddr, port, service); err != nil { - loginfo.Println("unable to create packer header", err) + Loginfo.Println("unable to create packer header", err) } if header == nil { @@ -321,17 +320,17 @@ func (mx *MPlexy) routeToTarget(ctx context.Context, extConn *tunnel.WedgeConn, for { buffer, err := extConn.PeekAll() if err != nil { - loginfo.Println("unable to peekAll", err) + Loginfo.Println("unable to peekAll", err) return } - loginfo.Println("Before Packer", hex.Dump(buffer)) + Loginfo.Println("Before Packer", hex.Dump(buffer)) p := packer.NewPacker(header) p.Data.AppendBytes(buffer) buf := p.PackV1() - //loginfo.Println(hex.Dump(buf.Bytes())) + //Loginfo.Println(hex.Dump(buf.Bytes())) //Bundle up the send request and dispatch sendTrack := api.NewSendTrack(buf.Bytes(), hostname) @@ -339,7 +338,7 @@ func (mx *MPlexy) routeToTarget(ctx context.Context, extConn *tunnel.WedgeConn, cnt := len(buffer) if _, err = extConn.Discard(cnt); err != nil { - loginfo.Println("unable to discard", cnt, err) + Loginfo.Println("unable to discard", cnt, err) return } diff --git a/server/manager.go b/relay/mplexy/mplexy.go similarity index 89% rename from server/manager.go rename to relay/mplexy/mplexy.go index e47d01b..2e8e4d9 100644 --- a/server/manager.go +++ b/relay/mplexy/mplexy.go @@ -1,4 +1,4 @@ -package server +package mplexy import ( "context" @@ -6,9 +6,13 @@ import ( "net" "net/http" + "git.coolaj86.com/coolaj86/go-telebitd/log" "git.coolaj86.com/coolaj86/go-telebitd/relay/api" ) +var Loginfo = log.Loginfo +var connectionID int64 = 0 + //ListenerRegistrationStatus - post registration status type ListenerRegistrationStatus int @@ -112,9 +116,9 @@ func New( // - execute the GenericLister // - pass initial port, we'll announce that func (mx *MPlexy) Run() error { - loginfo.Println("ConnectionTable starting") + Loginfo.Println("ConnectionTable starting") - loginfo.Println(mx.connectionTracking) + Loginfo.Println(mx.connectionTracking) ctx := mx.ctx @@ -134,29 +138,29 @@ func (mx *MPlexy) Run() error { select { case <-ctx.Done(): - loginfo.Println("Cancel signal hit") + Loginfo.Println("Cancel signal hit") return nil case registration := <-mx.register: - loginfo.Println("register fired", registration.port) + Loginfo.Println("register fired", registration.port) // check to see if port is already running for listener := range mx.listeners { if mx.listeners[listener] == registration.port { - loginfo.Println("listener already running", registration.port) + Loginfo.Println("listener already running", registration.port) registration.status = listenerExists registration.commCh <- registration } } - loginfo.Println("listener starting up ", registration.port) - loginfo.Println(ctx.Value(ctxConnectionTrack).(*api.Tracking)) + Loginfo.Println("listener starting up ", registration.port) + Loginfo.Println(ctx.Value(ctxConnectionTrack).(*api.Tracking)) go mx.multiListenAndServe(ctx, registration) status := <-registration.commCh if status.status == listenerAdded { mx.listeners[status.listener] = status.port } else if status.status == listenerFault { - loginfo.Println("Unable to create a new listerer", registration.port) + Loginfo.Println("Unable to create a new listerer", registration.port) } } } diff --git a/relay/relay.go b/relay/relay.go index 612b207..5f66e63 100644 --- a/relay/relay.go +++ b/relay/relay.go @@ -9,7 +9,7 @@ import ( "git.coolaj86.com/coolaj86/go-telebitd/relay/admin" "git.coolaj86.com/coolaj86/go-telebitd/relay/api" - "git.coolaj86.com/coolaj86/go-telebitd/server" + "git.coolaj86.com/coolaj86/go-telebitd/relay/mplexy" "git.coolaj86.com/coolaj86/go-telebitd/tunnel" "github.com/gorilla/mux" @@ -20,12 +20,12 @@ import ( type Relay struct { ctx context.Context status *api.Status - mx *server.MPlexy + mx *mplexy.MPlexy table *api.Table } // New initializes and returns a relay service -func New(ctx context.Context, tlsConfig *tls.Config, authz server.Authorizer, status *api.Status, table *api.Table) *Relay { +func New(ctx context.Context, tlsConfig *tls.Config, authz mplexy.Authorizer, status *api.Status, table *api.Table) *Relay { // TODO do we need this already setup here? or is it just for logging? status.ConnectionTracking = api.NewTracking() status.ConnectionTable = table @@ -34,7 +34,7 @@ func New(ctx context.Context, tlsConfig *tls.Config, authz server.Authorizer, st ctx: ctx, status: status, table: table, - mx: server.New(ctx, tlsConfig, authAdmin, authz, status), // TODO Accept + mx: mplexy.New(ctx, tlsConfig, authAdmin, authz, status), // TODO Accept } return r } @@ -78,7 +78,7 @@ func (r *Relay) ListenAndServe(port int) error { return r.mx.Run() } -func listenAndServeTargets(mx *server.MPlexy, handler net.Listener) error { +func listenAndServeTargets(mx *mplexy.MPlexy, handler net.Listener) error { serverStatus := mx.Status router := mux.NewRouter().StrictSlash(true) diff --git a/server/one_conn.go b/server/one_conn.go deleted file mode 100644 index f8e09de..0000000 --- a/server/one_conn.go +++ /dev/null @@ -1,32 +0,0 @@ -package server - -import ( - "io" - "net" -) - -type oneConnListener struct { - conn net.Conn -} - -func (l *oneConnListener) Accept() (net.Conn, error) { - if l.conn == nil { - loginfo.Println("oneConnListener Accept EOF") - return nil, io.EOF - } - - c := l.conn - l.conn = nil - loginfo.Println("Accept", c.LocalAddr().String(), c.RemoteAddr().String()) - return c, nil -} - -func (l *oneConnListener) Close() error { - loginfo.Println("oneConnListener close") - return nil -} - -func (l *oneConnListener) Addr() net.Addr { - loginfo.Println("oneConnLister addr") - return nil -}