From e740d2ca0f4eda19efbf76468e78377656e2fe0f Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 30 Apr 2020 04:43:36 -0600 Subject: [PATCH] heavier refactoring --- .gitignore | 2 + README.md | 7 +- cmd/telebitd/telebitd.go | 87 +++++++------ go.mod | 1 + go.sum | 2 + relay/relay.go | 52 ++++++++ rvpn-docker/README.md | 4 +- rvpn-docker/rvpn/Dockerfile | 6 +- server/connection_table.go | 8 +- server/listener_generic.go | 99 ++++++++------ server/manager.go | 151 +++++++++++++--------- server/status.go | 6 +- go-rvpn-server.yaml => telebit-relay.yaml | 0 telebit.go | 5 +- 14 files changed, 276 insertions(+), 154 deletions(-) create mode 100644 relay/relay.go rename go-rvpn-server.yaml => telebit-relay.yaml (100%) diff --git a/.gitignore b/.gitignore index 612eeb0..136a8fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.env +.env.* certs *.exe /telebitd diff --git a/README.md b/README.md index ac49d24..10af9d8 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,12 @@ tmp $ serve-https -p 8080 -d /tmp --servername hfc.rootprojects.org --agree-tos ### Start Tunnel Client ```bash -node-tunnel-client $ bin/stunnel.js --locals http://hfc.rootprojects.org:8080,http://test1.hfc.rootprojects.org:8080 --stunneld wss://localhost.rootprojects.org:8443 --secret abc123 +# For .env +TELEBIT_SECRET=abcdef1234567890 +``` + +```bash +node-tunnel-client $ bin/stunnel.js --locals http://hfc.rootprojects.org:8080,http://test1.hfc.rootprojects.org:8080 --stunneld wss://localhost.rootprojects.org:8443 --secret abcdef1234567890 ``` ### Execute RVPN diff --git a/cmd/telebitd/telebitd.go b/cmd/telebitd/telebitd.go index a513360..059ff87 100644 --- a/cmd/telebitd/telebitd.go +++ b/cmd/telebitd/telebitd.go @@ -8,46 +8,49 @@ import ( "io" "io/ioutil" "log" + "net/http" "os" - "time" + telebit "git.coolaj86.com/coolaj86/go-telebitd" + "git.coolaj86.com/coolaj86/go-telebitd/relay" + "git.coolaj86.com/coolaj86/go-telebitd/server" + + jwt "github.com/dgrijalva/jwt-go" "github.com/spf13/viper" lumberjack "gopkg.in/natefinch/lumberjack.v2" - telebit "git.coolaj86.com/coolaj86/go-telebitd" - "git.coolaj86.com/coolaj86/go-telebitd/server" + _ "github.com/joho/godotenv/autoload" ) var ( logfile = "stdout" configPath = "./" - configFile = "go-rvpn-server" + configFile = "telebit-relay" loginfo *log.Logger logdebug *log.Logger logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile argWssClientListener string - argGenericBinding int + tcpPort int argServerBinding string argServerAdminBinding string argServerExternalBinding string argDeadTime int connectionTable *server.Table - secretKey = "abc123" + secretKey string wssHostName = "localhost.rootprojects.org" adminHostName = telebit.InvalidAdminDomain idle int dwell int cancelcheck int lbDefaultMethod string - serverName string + nickname string ) func init() { flag.StringVar(&logfile, "log", logfile, "Log file (or stdout/stderr; empty for none)") flag.StringVar(&configPath, "config-path", configPath, "Configuration File Path") - flag.StringVar(&configFile, "config-file", configFile, "Configuration File Name") - + flag.StringVar(&secretKey, "secret", "", "a >= 16-character random string for JWT key signing") } var logoutput io.Writer @@ -55,6 +58,15 @@ var logoutput io.Writer //Main -- main entry point func main() { flag.Parse() + + if "" == secretKey { + secretKey = os.Getenv("TELEBIT_SECRET") + } + if len(secretKey) < 16 { + fmt.Fprintf(os.Stderr, "Invalid secret: %q. See --help for details.\n", secretKey) + os.Exit(1) + } + switch logfile { case "stdout": logoutput = os.Stdout @@ -89,54 +101,51 @@ func main() { wssHostName = viper.Get("rvpn.wssdomain").(string) adminHostName = viper.Get("rvpn.admindomain").(string) - argGenericBinding = viper.GetInt("rvpn.genericlistener") + tcpPort = viper.GetInt("rvpn.port") deadtime := viper.Get("rvpn.deadtime").(map[string]interface{}) idle = deadtime["idle"].(int) dwell = deadtime["dwell"].(int) cancelcheck = deadtime["cancelcheck"].(int) lbDefaultMethod = viper.Get("rvpn.loadbalancing.defaultmethod").(string) - serverName = viper.Get("rvpn.serverName").(string) + nickname = viper.Get("rvpn.serverName").(string) loginfo.Println("startup") - certbundle, err := tls.LoadX509KeyPair("certs/fullchain.pem", "certs/privkey.pem") - if err != nil { - loginfo.Println(err) - return - } - ctx, cancelContext := context.WithCancel(context.Background()) defer cancelContext() serverStatus := server.NewStatus(ctx) serverStatus.AdminDomain = adminHostName serverStatus.WssDomain = wssHostName - serverStatus.Name = serverName - serverStatus.StartTime = time.Now() + serverStatus.Name = nickname serverStatus.DeadTime = server.NewStatusDeadTime(dwell, idle, cancelcheck) serverStatus.LoadbalanceDefaultMethod = lbDefaultMethod - // Setup for GenericListenServe. - // - establish context for the generic listener - // - startup listener - // - accept with peek buffer. - // - peek at the 1st 30 bytes. - // - check for tls - // - if tls, establish, protocol peek buffer, else decrypted - // - match protocol + connectionTable := server.NewTable(dwell, idle, lbDefaultMethod) - connectionTracking := server.NewTracking() - serverStatus.ConnectionTracking = connectionTracking - go connectionTracking.Run(ctx) + tlsConfig := &tls.Config{ + GetCertificate: func(*tls.ClientHelloInfo) (*tls.Certificate, error) { + // TODO + // 1. call out to greenlock for validation + // 2. push challenges through http channel + // 3. receive certificates (or don't) + certbundle, err := tls.LoadX509KeyPair("certs/fullchain.pem", "certs/privkey.pem") + if err != nil { + return nil, err + } + return &certbundle, nil + }, + } - connectionTable = server.NewTable(dwell, idle) - serverStatus.ConnectionTable = connectionTable - go connectionTable.Run(ctx, lbDefaultMethod) + authorizer := func(r *http.Request) (*server.Authz, error) { + // do we have a valid wss_client? + tokenString := r.URL.Query().Get("access_token") + _, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { + return []byte(secretKey), nil + }) + return nil, err + } - genericListeners := server.NewGenerListeners(ctx, secretKey, certbundle, serverStatus) - //serverStatus.GenericListeners = genericListeners - - go genericListeners.Run(ctx, argGenericBinding) - - select {} + r := relay.New(ctx, tlsConfig, authorizer, serverStatus, connectionTable) + r.ListenAndServe(tcpPort) } diff --git a/go.mod b/go.mod index 62ccd32..d0dcbe5 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gorilla/mux v1.7.4 github.com/gorilla/websocket v1.4.2 + github.com/joho/godotenv v1.3.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.6.3 gopkg.in/natefinch/lumberjack.v2 v2.0.0 diff --git a/go.sum b/go.sum index da35738..104c871 100644 --- a/go.sum +++ b/go.sum @@ -49,6 +49,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= diff --git a/relay/relay.go b/relay/relay.go new file mode 100644 index 0000000..a86e9f9 --- /dev/null +++ b/relay/relay.go @@ -0,0 +1,52 @@ +package relay + +import ( + "context" + "crypto/tls" + + "git.coolaj86.com/coolaj86/go-telebitd/server" +) + +type Relay struct { + ctx context.Context + status *server.Status + mx *server.MPlexy + table *server.Table +} + +func New(ctx context.Context, tlsConfig *tls.Config, authz server.Authorizer, status *server.Status, table *server.Table) *Relay { + return &Relay{ + ctx: ctx, + status: status, + table: table, + mx: server.New(ctx, tlsConfig, authz, status), + } +} + +func (r *Relay) ListenAndServe(port int) error { + + serverStatus := r.status + + // Setup for GenericListenServe. + // - establish context for the generic listener + // - startup listener + // - accept with peek buffer. + // - peek at the 1st 30 bytes. + // - check for tls + // - if tls, establish, protocol peek buffer, else decrypted + // - match protocol + + connectionTracking := server.NewTracking() + serverStatus.ConnectionTracking = connectionTracking + go connectionTracking.Run(r.ctx) + + serverStatus.ConnectionTable = r.table + go serverStatus.ConnectionTable.Run(r.ctx) + + //serverStatus.GenericListeners = genericListeners + + // blocks until it can listen, which it can't until started + go r.mx.MultiListenAndServe(port) + + return r.mx.Run() +} diff --git a/rvpn-docker/README.md b/rvpn-docker/README.md index 568a2da..7797c64 100644 --- a/rvpn-docker/README.md +++ b/rvpn-docker/README.md @@ -17,7 +17,7 @@ Docker version 17.03.0-ce, build 60ccb22 cd $GOPATH/src/git.coolaj86.com/coolaj86 git clone git@git.coolaj86.com:coolaj86/go-telebitd.git -cd go-rvpn-server +cd telebit-relay go get ``` @@ -36,7 +36,7 @@ Step 2/3 : LABEL maintainer "henry.f.camacho@gmail.com" ---> Running in 5cdffef8e33d ---> f7e09c097612 Removing intermediate container 5cdffef8e33d -Step 3/3 : WORKDIR "/go-rvpn-server" +Step 3/3 : WORKDIR "/telebit-relay" ---> 182aa9c814f2 Removing intermediate container f136550d6d48 Successfully built 182aa9c814f2 diff --git a/rvpn-docker/rvpn/Dockerfile b/rvpn-docker/rvpn/Dockerfile index 839adf8..ab55bf7 100644 --- a/rvpn-docker/rvpn/Dockerfile +++ b/rvpn-docker/rvpn/Dockerfile @@ -1,5 +1,5 @@ -FROM golang:1.7.5 -LABEL maintainer "henry.f.camacho@gmail.com" +FROM golang:1.14 +LABEL maintainer "aj@therootcompany.com" -WORKDIR "/go-rvpn-server" +WORKDIR "/telebit-relay" diff --git a/server/connection_table.go b/server/connection_table.go index 4dac70a..c8d552e 100755 --- a/server/connection_table.go +++ b/server/connection_table.go @@ -21,10 +21,11 @@ type Table struct { domainRevoke chan *DomainMapping dwell int idle int + balanceMethod string } //NewTable -- consructor -func NewTable(dwell, idle int) (p *Table) { +func NewTable(dwell, idle int, balanceMethod string) (p *Table) { p = new(Table) p.connections = make(map[*Connection][]string) p.domains = make(map[string]*DomainLoadBalance) @@ -34,6 +35,7 @@ func NewTable(dwell, idle int) (p *Table) { p.domainRevoke = make(chan *DomainMapping) p.dwell = dwell p.idle = idle + p.balanceMethod = balanceMethod return } @@ -88,7 +90,7 @@ func (c *Table) GetConnection(serverID int64) (*Connection, error) { } //Run -- Execute -func (c *Table) Run(ctx context.Context, defaultMethod string) { +func (c *Table) Run(ctx context.Context) { loginfo.Println("ConnectionTable starting") go c.reaper(c.dwell, c.idle) @@ -122,7 +124,7 @@ func (c *Table) Run(ctx context.Context, defaultMethod string) { c.domains[newDomain].AddConnection(connection) } else { //if not, then add as the 1st to the list of connections - c.domains[newDomain] = NewDomainLoadBalance(defaultMethod) + c.domains[newDomain] = NewDomainLoadBalance(c.balanceMethod) c.domains[newDomain].AddConnection(connection) } diff --git a/server/listener_generic.go b/server/listener_generic.go index 38e5f83..7aadb37 100644 --- a/server/listener_generic.go +++ b/server/listener_generic.go @@ -6,6 +6,7 @@ import ( "context" "crypto/tls" "encoding/hex" + "fmt" "log" "net" "net/http" @@ -31,7 +32,7 @@ const ( //ctxConnectionTable contextKey = "connectionTable" - ctxConfig contextKey = "config" + ctxConfig contextKey = "tlsConfig" ctxListenerRegistration contextKey = "listenerRegistration" ctxConnectionTrack contextKey = "connectionTrack" ctxWssHostName contextKey = "wsshostname" @@ -40,21 +41,26 @@ const ( ctxLoadbalanceDefaultMethod contextKey = "lbdefaultmethod" ) +// TODO isn't this restriction in the TLS lib? +// or are we just pre-checking for remote hosts? +type tlsScheme int + const ( - encryptNone int = iota + encryptNone tlsScheme = iota encryptSSLV2 encryptSSLV3 encryptTLS10 encryptTLS11 encryptTLS12 + encryptTLS13 ) -//GenericListenAndServe -- used to lisen for any https traffic on 443 (8443) +// multiListenAndServe -- used to lisen for any https traffic on 443 (8443) // - setup generic TCP listener, unencrypted TCP, with a Deadtime out // - leaverage the wedgeConn to peek into the buffer. // - if TLS, consume connection with TLS certbundle, pass to request identifier // - else, just pass to the request identififer -func GenericListenAndServe(ctx context.Context, listenerRegistration *ListenerRegistration) { +func (mx *MPlexy) multiListenAndServe(ctx context.Context, listenerRegistration *ListenerRegistration) { loginfo.Println(":" + string(listenerRegistration.port)) cancelCheck := ctx.Value(ctxCancelCheck).(int) @@ -95,18 +101,24 @@ func GenericListenAndServe(ctx context.Context, listenerRegistration *ListenerRe return } + fmt.Println("New connection from %v on %v", conn.LocalAddr(), conn.RemoteAddr()) + + // TODO maybe put these into something like mx.newConnCh and have an mx.Accept()? wedgeConn := NewWedgeConn(conn) - go acceptTCPOrTLS(ctx, wedgeConn) + go mx.accept(ctx, wedgeConn) } } } -//acceptTCPOrTLS - +//accept - // - accept a wedgeConnection along with all the other required attritvues // - peek into the buffer, determine TLS or unencrypted // - if TSL, then terminate with a TLS endpoint, pass to handleStream // - if clearText, pass to handleStream -func acceptTCPOrTLS(ctx context.Context, wConn *WedgeConn) { +func (mx *MPlexy) accept(ctx context.Context, wConn *WedgeConn) { + // TODO shouldn't this responsibility fall elsewhere? + // (otherwise I think we're keeping this function in memory while something else fails to end) + // (i.e. something, somewhere is missing a `go doStuff()` defer wConn.Close() peekCnt := 10 @@ -136,20 +148,24 @@ func acceptTCPOrTLS(ctx context.Context, wConn *WedgeConn) { } else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x03}) { encryptMode = encryptTLS12 + + } else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x04}) { + encryptMode = encryptTLS13 + } oneConn := &oneConnListener{wConn} - config := ctx.Value(ctxConfig).(*tls.Config) + tlsConfig := ctx.Value(ctxConfig).(*tls.Config) if encryptMode == encryptSSLV2 { - loginfo.Println("SSLv2 is not accepted") + loginfo.Println("<= SSLv2 is not accepted") return } if encryptMode == encryptNone { loginfo.Println("Handle Unencrypted") - handleStream(ctx, wConn) + mx.handleStream(ctx, wConn) return } @@ -177,9 +193,10 @@ func acceptTCPOrTLS(ctx context.Context, wConn *WedgeConn) { loginfo.Println("sni:", sniHostName) + // This is where a target device connects to receive traffic if sniHostName == wssHostName { //handle WSS Path - tlsListener := tls.NewListener(oneConn, config) + tlsListener := tls.NewListener(oneConn, tlsConfig) conn, err := tlsListener.Accept() if err != nil { @@ -188,30 +205,31 @@ func acceptTCPOrTLS(ctx context.Context, wConn *WedgeConn) { } tlsWedgeConn := NewWedgeConn(conn) - handleStream(ctx, tlsWedgeConn) + mx.handleStream(ctx, tlsWedgeConn) return - - } else if sniHostName == adminHostName { - // handle admin path - tlsListener := tls.NewListener(oneConn, config) - - conn, err := tlsListener.Accept() - if err != nil { - loginfo.Println(err) - return - } - - tlsWedgeConn := NewWedgeConn(conn) - handleStream(ctx, tlsWedgeConn) - return - - } else { - //traffic not terminating on the rvpn do not decrypt - loginfo.Println("processing non terminating traffic", wssHostName, sniHostName) - handleExternalHTTPRequest(ctx, wConn, sniHostName, "https") } - return + // This is where an admin of the relay manages it + if sniHostName == adminHostName { + // TODO mx.Admin.CheckRemoteIP(conn) here + + // handle admin path + tlsListener := tls.NewListener(oneConn, tlsConfig) + + conn, err := tlsListener.Accept() + if err != nil { + loginfo.Println(err) + return + } + + tlsWedgeConn := NewWedgeConn(conn) + mx.handleStream(ctx, tlsWedgeConn) + return + } + + //traffic not terminating on the rvpn do not decrypt + loginfo.Println("processing non terminating traffic", wssHostName, sniHostName) + handleExternalHTTPRequest(ctx, wConn, sniHostName, "https") } //handleStream -- @@ -222,7 +240,7 @@ func acceptTCPOrTLS(ctx context.Context, wConn *WedgeConn) { // - attempt to identify as ADMIN/API session // - else handle as raw http // - handle other? -func handleStream(ctx context.Context, wConn *WedgeConn) { +func (mx *MPlexy) handleStream(ctx context.Context, wConn *WedgeConn) { loginfo.Println("handle Stream") loginfo.Println("conn", wConn.LocalAddr().String(), wConn.RemoteAddr().String()) @@ -234,6 +252,9 @@ func handleStream(ctx context.Context, wConn *WedgeConn) { return } + // TODO handle by TCP port as well + // (which needs a short read timeout since servers expect clients to say hello) + // HTTP Identifcation // CRLF if !bytes.Contains(peek[:], []byte{0x0d, 0x0a}) { return @@ -252,14 +273,11 @@ func handleStream(ctx context.Context, wConn *WedgeConn) { return } - // do we have a valid wss_client? - secretKey := ctx.Value(ctxSecretKey).(string) - tokenString := r.URL.Query().Get("access_token") - result, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { - return []byte(secretKey), nil - }) + // TODO add newtypes + // TODO check if this is a websocket + _, err = mx.authorize(r) - if err == nil && result.Valid { + if err == nil { loginfo.Println("Valid WSS dected...sending to handler") oneConn := &oneConnListener{wConn} handleWssClient(ctx, oneConn) @@ -268,6 +286,7 @@ func handleStream(ctx context.Context, wConn *WedgeConn) { //if yes, prep the oneConn and send it to the handler return } + if strings.Contains(r.Host, telebit.InvalidAdminDomain) { loginfo.Println("admin") oneConn := &oneConnListener{wConn} diff --git a/server/manager.go b/server/manager.go index bf9d853..7fbf9e8 100644 --- a/server/manager.go +++ b/server/manager.go @@ -4,11 +4,28 @@ import ( "context" "crypto/tls" "net" + "net/http" ) //ListenerRegistrationStatus - post registration status type ListenerRegistrationStatus int +// Authz represents grants or privileges of a client +// clientID +// domains that may be forwarded +// # of domains that may be forwarded +// ports that may be forwarded (i.e. allow special ports < 1024, exclude 443, 25, etc) +// # of ports that may be forwarded +// # of concurrent conections +// # bandwith rate (i.e. 5 mbps) +// # bandwith cap per time period (i.e. 100 MB / hour) +// # throttled rate (i.e. 0 (kill), or 1 mbps) +type Authz struct { +} + +// Authorizer is called when a new client connects and we need to know something about it +type Authorizer func(*http.Request) (*Authz, error) + const ( listenerAdded ListenerRegistrationStatus = iota listenerExists @@ -40,99 +57,107 @@ func NewListenerRegistration(port int) (p *ListenerRegistration) { p = new(ListenerRegistration) p.port = port p.commCh = make(chan *ListenerRegistration) - return + return p } -// Servers - -type Servers struct { +// MPlexy - +type MPlexy struct { listeners map[*net.Listener]int ctx context.Context connnectionTable *Table connectionTracking *Tracking - secretKey string - certbundle tls.Certificate + authorize Authorizer + tlsConfig *tls.Config register chan *ListenerRegistration - servers *Servers wssHostName string adminHostName string cancelCheck int lbDefaultMethod string serverStatus *Status + //xservers *MPlexy } -// NewGenerListeners creates tcp (and https and wss?) listeners -func NewGenerListeners(ctx context.Context, secretKey string, certbundle tls.Certificate, serverStatus *Status) (p *Servers) { - p = &Servers{} - p.listeners = make(map[*net.Listener]int) - p.ctx = ctx - p.connnectionTable = serverStatus.ConnectionTable - p.connectionTracking = serverStatus.ConnectionTracking - p.secretKey = secretKey - p.certbundle = certbundle - p.register = make(chan *ListenerRegistration) - p.wssHostName = serverStatus.WssDomain - p.adminHostName = serverStatus.AdminDomain - p.cancelCheck = serverStatus.DeadTime.cancelcheck - p.lbDefaultMethod = serverStatus.LoadbalanceDefaultMethod - p.serverStatus = serverStatus - return +// New creates tcp (and https and wss?) listeners +func New(ctx context.Context, tlsConfig *tls.Config, authz Authorizer, serverStatus *Status) (mx *MPlexy) { + mx = &MPlexy{ + listeners: make(map[*net.Listener]int), + ctx: ctx, + connnectionTable: serverStatus.ConnectionTable, + connectionTracking: serverStatus.ConnectionTracking, + authorize: authz, + tlsConfig: tlsConfig, + register: make(chan *ListenerRegistration), + wssHostName: serverStatus.WssDomain, + adminHostName: serverStatus.AdminDomain, + cancelCheck: serverStatus.DeadTime.cancelcheck, + lbDefaultMethod: serverStatus.LoadbalanceDefaultMethod, + serverStatus: serverStatus, + } + return mx } //Run -- Execute // - execute the GenericLister // - pass initial port, we'll announce that -func (gl *Servers) Run(ctx context.Context, initialPort int) { +func (mx *MPlexy) Run() error { loginfo.Println("ConnectionTable starting") - config := &tls.Config{Certificates: []tls.Certificate{gl.certbundle}} + loginfo.Println(mx.connectionTracking) - ctx = context.WithValue(ctx, ctxSecretKey, gl.secretKey) + ctx := mx.ctx - loginfo.Println(gl.connectionTracking) + // For just this bit + ctx = context.WithValue(ctx, ctxConnectionTrack, mx.connectionTracking) - ctx = context.WithValue(ctx, ctxConnectionTrack, gl.connectionTracking) - ctx = context.WithValue(ctx, ctxConfig, config) - ctx = context.WithValue(ctx, ctxListenerRegistration, gl.register) - ctx = context.WithValue(ctx, ctxWssHostName, gl.wssHostName) - ctx = context.WithValue(ctx, ctxAdminHostName, gl.adminHostName) - ctx = context.WithValue(ctx, ctxCancelCheck, gl.cancelCheck) - ctx = context.WithValue(ctx, ctxLoadbalanceDefaultMethod, gl.lbDefaultMethod) - ctx = context.WithValue(ctx, ctxServerStatus, gl.serverStatus) + // For all Listeners + ctx = context.WithValue(ctx, ctxConfig, mx.tlsConfig) + ctx = context.WithValue(ctx, ctxListenerRegistration, mx.register) + ctx = context.WithValue(ctx, ctxWssHostName, mx.wssHostName) + ctx = context.WithValue(ctx, ctxAdminHostName, mx.adminHostName) + ctx = context.WithValue(ctx, ctxCancelCheck, mx.cancelCheck) + ctx = context.WithValue(ctx, ctxLoadbalanceDefaultMethod, mx.lbDefaultMethod) + ctx = context.WithValue(ctx, ctxServerStatus, mx.serverStatus) - go func(ctx context.Context) { - for { - select { + for { + select { - case <-ctx.Done(): - loginfo.Println("Cancel signal hit") - return + case <-ctx.Done(): + loginfo.Println("Cancel signal hit") + return nil - case registration := <-gl.register: - loginfo.Println("register fired", registration.port) + case registration := <-mx.register: + loginfo.Println("register fired", registration.port) - // check to see if port is already running - for listener := range gl.listeners { - if gl.listeners[listener] == 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).(*Tracking)) - go GenericListenAndServe(ctx, registration) - - status := <-registration.commCh - if status.status == listenerAdded { - gl.listeners[status.listener] = status.port - } else if status.status == listenerFault { - loginfo.Println("Unable to create a new listerer", 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) + registration.status = listenerExists + registration.commCh <- registration } } + loginfo.Println("listener starting up ", registration.port) + loginfo.Println(ctx.Value(ctxConnectionTrack).(*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) + } } + } - }(ctx) - - newListener := NewListenerRegistration(initialPort) - gl.register <- newListener + return nil +} + +func (mx *MPlexy) Start() { + go mx.Run() +} + +// MultiListenAndServe starts another listener (to the same application) on a new port +func (mx *MPlexy) MultiListenAndServe(port int) { + // TODO how to associate a listening device with a given plain port + mx.register <- NewListenerRegistration(port) } diff --git a/server/status.go b/server/status.go index fbd0fde..3fd8add 100644 --- a/server/status.go +++ b/server/status.go @@ -15,13 +15,13 @@ type Status struct { DeadTime *StatusDeadTime ConnectionTracking *Tracking ConnectionTable *Table - servers *Servers LoadbalanceDefaultMethod string AdminStats *TrafficStats AdminReqTyoe *AdminReqType TrafficStats *TrafficStats ExtConnections *ConnectionStats WSSConnections *ConnectionStats + //servers *MPlexy } //NewStatus -- @@ -32,7 +32,9 @@ func NewStatus(ctx context.Context) (p *Status) { p.TrafficStats = new(TrafficStats) p.ExtConnections = new(ConnectionStats) p.WSSConnections = new(ConnectionStats) - return + // TODO any reason not to set StartTime like this? + p.StartTime = time.Now() + return p } // South Facing Functions diff --git a/go-rvpn-server.yaml b/telebit-relay.yaml similarity index 100% rename from go-rvpn-server.yaml rename to telebit-relay.yaml diff --git a/telebit.go b/telebit.go index 26ced0b..1b075d5 100644 --- a/telebit.go +++ b/telebit.go @@ -2,4 +2,7 @@ package telebit // InvalidAdminDomain is a domain that can only be accessed by Domain Fronting // (i.e. trixy clients sending fake headers), not browsers -var InvalidAdminDomain = "rvpn.rootprojects.invalid" +var InvalidAdminDomain = "chilly-bobcat-15.telebit.io" + +//var InvalidAdminDomain = "invalid.rootprojects.org" +//var InvalidAdminDomain = "rvpn.rootprojects.invalid"