diff --git a/cmd/telebitd/telebitd.go b/cmd/telebitd/telebitd.go index 2b1c2b1..20013b4 100644 --- a/cmd/telebitd/telebitd.go +++ b/cmd/telebitd/telebitd.go @@ -12,7 +12,6 @@ import ( "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" @@ -46,7 +45,7 @@ var ( connectionTable *api.Table secretKey string wssHostName = "localhost.rootprojects.org" - adminHostName = telebit.InvalidAdminDomain + adminHostName string idle int dwell int cancelcheck int diff --git a/dump/admin.html b/dump/admin.html deleted file mode 100755 index 830b681..0000000 --- a/dump/admin.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - Websock VPN Instrumentation - - -
-
VPN Instrumentation
-
-
-
Control Plane
-
-
- -
-
- - - - -
-
-
- -
- -
-
-
- - - - -
-
-
-
-
-
-
Data
-
-

{[{text}]}

-
-
-
-
- - - - - - - - - - diff --git a/dump/client.html b/dump/client.html deleted file mode 100755 index ed31ccc..0000000 --- a/dump/client.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - Websock VPN Test Client - - -
-
WebSocket Client Test
-
-
-
Control Plane
-
-
- -
-
- - - - -
-
-
- -
- -
-
-
- - - - -
-
-
- -
- -
-
-
- - - - -
-
-
-
-
-
-
Messages
-
-

{[{text}]}

-
-
-
-
- - - - - - - - - - diff --git a/relay/admin/admin.go b/relay/admin/admin.go index 7641d12..d3de63c 100644 --- a/relay/admin/admin.go +++ b/relay/admin/admin.go @@ -8,7 +8,6 @@ import ( "strconv" "strings" - telebit "git.coolaj86.com/coolaj86/go-telebitd" "git.coolaj86.com/coolaj86/go-telebitd/relay/api" "git.coolaj86.com/coolaj86/go-telebitd/relay/mplexy" @@ -48,13 +47,23 @@ func ListenAndServe(mx *mplexy.MPlexy, adminListener net.Listener) error { switch url := r.URL.Path; url { case "/": - // check to see if we are using the administrative Host - if strings.Contains(r.Host, telebit.InvalidAdminDomain) { - http.Redirect(w, r, "/admin", 301) - serverStatus.AdminStats.IncResponses() - + var hostname string + host := strings.Split(r.Host, ":") + if len(host) > 0 { + hostname = host[0] } + // check to see if we are using the administrative Host + if hostname == mplexy.InvalidAdminDomain { + http.Redirect(w, r, "/admin", 301) + serverStatus.AdminStats.IncResponses() + return + } + if hostname == mx.AdminDomain() { + http.Redirect(w, r, "/admin", 301) + serverStatus.AdminStats.IncResponses() + return + } default: http.Error(w, "Not Found", 404) } diff --git a/relay/api/status_traffic_connections.go b/relay/api/connection-stats.go similarity index 100% rename from relay/api/status_traffic_connections.go rename to relay/api/connection-stats.go diff --git a/relay/api/api_collect_connections.go b/relay/api/connections-api.go similarity index 100% rename from relay/api/api_collect_connections.go rename to relay/api/connections-api.go diff --git a/relay/api/api_collect_status_dead_time.go b/relay/api/deadtime.go similarity index 100% rename from relay/api/api_collect_status_dead_time.go rename to relay/api/deadtime.go diff --git a/relay/api/api_collect_domains.go b/relay/api/domains.go similarity index 100% rename from relay/api/api_collect_domains.go rename to relay/api/domains.go diff --git a/relay/api/domain_loadbalance.go b/relay/api/loadbalance.go similarity index 100% rename from relay/api/domain_loadbalance.go rename to relay/api/loadbalance.go diff --git a/relay/api/domain_mapping.go b/relay/api/mapping.go similarity index 100% rename from relay/api/domain_mapping.go rename to relay/api/mapping.go diff --git a/relay/api/connection_registration.go b/relay/api/registration.go similarity index 100% rename from relay/api/connection_registration.go rename to relay/api/registration.go diff --git a/relay/api/status_req_type.go b/relay/api/req-type.go similarity index 100% rename from relay/api/status_req_type.go rename to relay/api/req-type.go diff --git a/relay/api/send_track.go b/relay/api/send.go similarity index 100% rename from relay/api/send_track.go rename to relay/api/send.go diff --git a/relay/api/api_collect_server_domains.go b/relay/api/server-domains.go similarity index 100% rename from relay/api/api_collect_server_domains.go rename to relay/api/server-domains.go diff --git a/relay/api/api_collect_server.go b/relay/api/server.go similarity index 100% rename from relay/api/api_collect_server.go rename to relay/api/server.go diff --git a/relay/api/api_collect_servers.go b/relay/api/servers.go similarity index 100% rename from relay/api/api_collect_servers.go rename to relay/api/servers.go diff --git a/relay/api/status_traffic_stats.go b/relay/api/stats.go similarity index 100% rename from relay/api/status_traffic_stats.go rename to relay/api/stats.go diff --git a/relay/api/api_collect_status.go b/relay/api/status-api.go similarity index 100% rename from relay/api/api_collect_status.go rename to relay/api/status-api.go diff --git a/relay/api/status_dead_time.go b/relay/api/status-deadtime.go similarity index 100% rename from relay/api/status_dead_time.go rename to relay/api/status-deadtime.go diff --git a/relay/api/status.go b/relay/api/status.go index cec684b..1e713c7 100644 --- a/relay/api/status.go +++ b/relay/api/status.go @@ -4,7 +4,7 @@ import ( "context" "time" - "git.coolaj86.com/coolaj86/go-telebitd/tunnel" + "git.coolaj86.com/coolaj86/go-telebitd/relay/tunnel" ) //Status -- diff --git a/relay/api/domain_track.go b/relay/api/track.go similarity index 100% rename from relay/api/domain_track.go rename to relay/api/track.go diff --git a/relay/api/conn_tracking.go b/relay/api/tracking.go similarity index 100% rename from relay/api/conn_tracking.go rename to relay/api/tracking.go diff --git a/relay/api/api_collect_status_traffic.go b/relay/api/traffic.go similarity index 100% rename from relay/api/api_collect_status_traffic.go rename to relay/api/traffic.go diff --git a/relay/mplexy/listener.go b/relay/mplexy/listener.go index 4386ade..224aeda 100644 --- a/relay/mplexy/listener.go +++ b/relay/mplexy/listener.go @@ -13,11 +13,10 @@ import ( "strings" "time" - telebit "git.coolaj86.com/coolaj86/go-telebitd" "git.coolaj86.com/coolaj86/go-telebitd/packer" "git.coolaj86.com/coolaj86/go-telebitd/relay/api" + "git.coolaj86.com/coolaj86/go-telebitd/relay/tunnel" "git.coolaj86.com/coolaj86/go-telebitd/sni" - "git.coolaj86.com/coolaj86/go-telebitd/tunnel" ) type contextKey string @@ -29,7 +28,6 @@ const ( ctxListenerRegistration contextKey = "listenerRegistration" ctxConnectionTrack contextKey = "connectionTrack" ctxWssHostName contextKey = "wsshostname" - ctxAdminHostName contextKey = "adminHostName" ctxCancelCheck contextKey = "cancelcheck" ctxLoadbalanceDefaultMethod contextKey = "lbdefaultmethod" //ctxConnectionTable contextKey = "connectionTable" @@ -55,19 +53,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 @@ -80,7 +78,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)) @@ -91,7 +89,7 @@ func (mx *MPlexy) multiListenAndServe(ctx context.Context, listenerRegistration if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() { continue } - Loginfo.Println(err) + loginfo.Println(err) return } @@ -114,10 +112,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 } @@ -131,7 +129,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 @@ -145,19 +143,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) } @@ -166,21 +164,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 @@ -194,7 +192,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") } @@ -207,13 +205,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 } @@ -233,17 +231,23 @@ 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") + var hostname string + host := strings.Split(r.Host, ":") + if len(host) > 0 { + hostname = host[0] + } + + if hostname == InvalidAdminDomain { + loginfo.Println("admin.invalid") // TODO mx.Admin.CheckRemoteIP(conn) here // handle admin path mx.AcceptAdminClient(wConn) @@ -251,19 +255,24 @@ func (mx *MPlexy) acceptPlainStream(ctx context.Context, wConn *tunnel.WedgeConn } - // TODO add newtypes - // TODO check if this is a websocket - _, err = mx.AuthorizeTarget(r) - if err == nil { - Loginfo.Println("Valid WSS dected...sending to handler") + if hostname == mx.adminHostName { + loginfo.Println("admin") + // TODO mx.Admin.CheckRemoteIP(conn) here + // handle admin path + mx.AcceptAdminClient(wConn) + return + } + + if "Upgrade" == r.Header.Get("Connection") || "WebSocket" == r.Header.Get("Upgrade") { + loginfo.Println("WebSocket Upgrade is in order...") 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") @@ -271,7 +280,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") } @@ -293,7 +302,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 } @@ -302,15 +311,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 { @@ -320,17 +329,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) @@ -338,7 +347,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/relay/mplexy/mplexy.go b/relay/mplexy/mplexy.go index 2e8e4d9..92660bf 100644 --- a/relay/mplexy/mplexy.go +++ b/relay/mplexy/mplexy.go @@ -10,7 +10,10 @@ import ( "git.coolaj86.com/coolaj86/go-telebitd/relay/api" ) -var Loginfo = log.Loginfo +// InvalidAdminDomain is for bootstrapping the setup of a relay device +var InvalidAdminDomain = "admin.telebit.invalid" + +var loginfo = log.Loginfo var connectionID int64 = 0 //ListenerRegistrationStatus - post registration status @@ -112,13 +115,18 @@ func New( return mx } +// AdminDomain returns the Admin Domain as set on startup +func (mx *MPlexy) AdminDomain() string { + return mx.adminHostName +} + //Run -- Execute // - 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 @@ -129,7 +137,6 @@ func (mx *MPlexy) Run() error { 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.Status) @@ -138,29 +145,30 @@ 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("[track]", 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) } } } @@ -168,6 +176,7 @@ func (mx *MPlexy) Run() error { return nil } +// Start calls go Run() func (mx *MPlexy) Start() { go mx.Run() } diff --git a/relay/relay.go b/relay/relay.go index 5f66e63..ab1c829 100644 --- a/relay/relay.go +++ b/relay/relay.go @@ -10,7 +10,7 @@ import ( "git.coolaj86.com/coolaj86/go-telebitd/relay/admin" "git.coolaj86.com/coolaj86/go-telebitd/relay/api" "git.coolaj86.com/coolaj86/go-telebitd/relay/mplexy" - "git.coolaj86.com/coolaj86/go-telebitd/tunnel" + "git.coolaj86.com/coolaj86/go-telebitd/relay/tunnel" "github.com/gorilla/mux" "github.com/gorilla/websocket" @@ -78,7 +78,7 @@ func (r *Relay) ListenAndServe(port int) error { return r.mx.Run() } -func listenAndServeTargets(mx *mplexy.MPlexy, handler net.Listener) error { +func listenAndServeTargets(mx *mplexy.MPlexy, listener net.Listener) error { serverStatus := mx.Status router := mux.NewRouter().StrictSlash(true) @@ -121,5 +121,5 @@ func listenAndServeTargets(mx *mplexy.MPlexy, handler net.Listener) error { Addr: ":80", Handler: router, } - return s.Serve(handler) + return s.Serve(listener) } diff --git a/tunnel/conn_wedge.go b/relay/tunnel/conn_wedge.go similarity index 100% rename from tunnel/conn_wedge.go rename to relay/tunnel/conn_wedge.go diff --git a/tunnel/tunnel.go b/relay/tunnel/tunnel.go similarity index 100% rename from tunnel/tunnel.go rename to relay/tunnel/tunnel.go diff --git a/sni/tls_get_hostname.go b/sni/sni.go similarity index 95% rename from sni/tls_get_hostname.go rename to sni/sni.go index 606fdf7..47b7d16 100644 --- a/sni/tls_get_hostname.go +++ b/sni/sni.go @@ -1,5 +1,7 @@ package sni +// TODO this was probably copied from somewhere that deserves attribution + import ( "errors" ) diff --git a/telebit.go b/telebit.go deleted file mode 100644 index 1b075d5..0000000 --- a/telebit.go +++ /dev/null @@ -1,8 +0,0 @@ -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 = "chilly-bobcat-15.telebit.io" - -//var InvalidAdminDomain = "invalid.rootprojects.org" -//var InvalidAdminDomain = "rvpn.rootprojects.invalid"