WIP: track connection table

This commit is contained in:
AJ ONeal 2020-06-22 00:34:42 -06:00
parent 2b48a8b8b9
commit 36a3650080
25 changed files with 625 additions and 24 deletions

2
.gitignore vendored
View File

@ -4,7 +4,7 @@
certs
acme.d
xversion.go
assets_vfsdata.go
*_vfsdata.go
mgmt-server-linux
mgmt-server-macos

View File

@ -158,7 +158,12 @@ func handleDeviceRoutes(r chi.Router) {
http.Error(w, msg, http.StatusInternalServerError)
return
}
if err := store.Delete(auth); nil != err {
msg := `{"error":"not really sure what happened, but it didn't go well (check the logs)"}`
log.Printf("/api/devices/%s\n", slug)
log.Println(err)
http.Error(w, msg, http.StatusInternalServerError)
}
w.Write([]byte(`{"success":true}` + "\n"))
})
})

View File

@ -93,6 +93,10 @@ func routeAll() chi.Router {
return nil, fmt.Errorf("extra jwt payload 'slug' (unknown)")
}
claims.Slug = auth.Slug
if "" != claims.Subject && auth.Slug != claims.Subject {
return nil, fmt.Errorf("invalid jwt payload 'sub' (mismatch)")
}
claims.Issuer = primaryDomain
/*
// a little misdirection there
@ -102,7 +106,7 @@ func routeAll() chi.Router {
return []byte(auth.SharedKey), nil
*/
fmt.Println("ppid:", auth.MachinePPID)
//fmt.Println("ppid:", auth.MachinePPID)
return []byte(auth.MachinePPID), nil
},
@ -141,7 +145,12 @@ func routeAll() chi.Router {
return
}
w.Write([]byte(fmt.Sprintf(`{ "domains": [ "%s.%s" ] }`+"\n", claims.Slug, primaryDomain)))
w.Write([]byte(fmt.Sprintf(
`{ "sub": "%s", "domains": [ "%s.%s" ], "ports": [] }`+"\n",
claims.Subject,
claims.Slug,
primaryDomain,
)))
})
r.Route("/register-device", func(r chi.Router) {

View File

@ -253,8 +253,12 @@ func main() {
tokenString = auth[1]
}
if "" == tokenString {
// Browsers do not allow Authorization Headers and must use access_token query string
tokenString = r.URL.Query().Get("access_token")
}
if "" != r.URL.Query().Get("access_token") {
r.URL.Query().Set("access_token", "[redacted]")
}
grants, err := telebit.Inspect(authURL, tokenString)
/*
@ -266,6 +270,10 @@ func main() {
fmt.Println("return an error, do not go on")
return nil, err
}
if "" != r.URL.Query().Get("access_token") {
r.URL.Query().Set("access_token", "[redacted:"+grants.Subject+"]")
}
/*
fmt.Printf("client claims:\n%+v\n", tok.Claims)
*/

320
cmd/telebit/admin.go Normal file
View File

@ -0,0 +1,320 @@
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"log"
"net"
"net/http"
"strconv"
"strings"
"sync"
telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer"
"git.coolaj86.com/coolaj86/go-telebitd/mplexer/admin"
"github.com/go-chi/chi"
"github.com/gorilla/websocket"
)
var httpsrv *http.Server
// Servers represent actual connections
var Servers *sync.Map
// Table makes sense to be in-memory, but it could be serialized if needed
var Table *sync.Map
func init() {
Servers = &sync.Map{}
Table = &sync.Map{}
r := chi.NewRouter()
r.HandleFunc("/ws", upgradeWebsocket)
r.Route("/api", func(r chi.Router) {
// TODO token needs a globally unique subject
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
grants, err := authorizer(r)
if nil != err {
log.Println("authorization failed", err)
w.Write(apiNotAuthorizedContent)
return
}
// TODO define Admins in a better way
if "*" != grants.Subject {
log.Println("only admins allowed", err)
w.Write(apiNotAuthorizedContent)
}
next.ServeHTTP(w, r)
})
})
r.Get("/subscribers", getSubscribers)
r.Delete("/subscribers/{subject}", delSubscribers)
r.NotFound(apiNotFoundHandler)
})
adminUI := http.FileServer(admin.AdminFS)
r.Get("/", adminUI.ServeHTTP)
httpsrv = &http.Server{
Handler: r,
}
}
var apiNotFoundContent = []byte("{ \"error\": \"not found\" }\n")
var apiNotAuthorizedContent = []byte("{ \"error\": \"not authorized\" }\n")
func apiNotFoundHandler(w http.ResponseWriter, r *http.Request) {
w.Write(apiNotFoundContent)
}
type SubscriberStatus struct {
Subject string
Tunnels int
Clients int
// TODO bytes read
}
func getSubscribers(w http.ResponseWriter, r *http.Request) {
statuses := []*SubscriberStatus{}
Servers.Range(func(key, value interface{}) bool {
tunnels := 0
clients := 0
//subject := key.(string)
srvMap := value.(*sync.Map)
srvMap.Range(func(k, v interface{}) bool {
tunnels += 1
srv := v.(*SubscriberConn)
srv.clients.Range(func(k, v interface{}) bool {
clients += 1
return true
})
statuses = append(statuses, &SubscriberStatus{
Subject: k.(string),
Tunnels: tunnels,
Clients: clients,
})
return true
})
return true
})
_ = json.NewEncoder(w).Encode(&struct {
Success bool `json:"success"`
Subscribers []*SubscriberStatus `json:"subscribers"`
}{
Success: true,
Subscribers: statuses,
})
}
func delSubscribers(w http.ResponseWriter, r *http.Request) {
subject := chi.URLParam(r, "subject")
srvMapX, ok := Servers.Load(subject)
if !ok {
// TODO should this be an error?
_ = json.NewEncoder(w).Encode(&struct {
Success bool `json:"success"`
}{
Success: true,
})
return
}
srvMap := srvMapX.(*sync.Map)
srvMap.Range(func(k, v interface{}) bool {
srv := v.(*SubscriberConn)
srv.clients.Range(func(k, v interface{}) bool {
conn := v.(net.Conn)
_ = conn.Close()
return true
})
srv.wsConn.Close()
return true
})
Servers.Delete(subject)
_ = json.NewEncoder(w).Encode(&struct {
Success bool `json:"success"`
}{
Success: true,
})
}
// SubscriberConn represents a tunneled server, its grants, and its clients
type SubscriberConn struct {
remoteAddr string
wsConn *websocket.Conn
wsTun net.Conn // *telebit.WebsocketTunnel
grants *telebit.Grants
clients *sync.Map
// TODO is this the right codec type?
multiEncoder *telebit.Encoder
multiDecoder *telebit.Decoder
// to fulfill Router interface
}
func (s *SubscriberConn) RouteBytes(src, dst telebit.Addr, payload []byte) {
id := src.String()
fmt.Println("Routing some more bytes:")
fmt.Println("src", id, src)
fmt.Println("dst", dst)
clientX, ok := s.clients.Load(id)
if !ok {
// TODO send back closed client error
return
}
client, _ := clientX.(net.Conn)
for {
n, err := client.Write(payload)
if nil != err {
if n > 0 && io.ErrShortWrite == err {
payload = payload[n:]
continue
}
// TODO send back closed client error
break
}
}
}
func (s *SubscriberConn) Serve(client net.Conn) error {
var wconn *telebit.ConnWrap
switch conn := client.(type) {
case *telebit.ConnWrap:
wconn = conn
default:
// this probably isn't strictly necessary
panic("*SubscriberConn.Serve is special in that it must receive &ConnWrap{ Conn: conn }")
}
id := client.RemoteAddr().String()
s.clients.Store(id, client)
fmt.Println("[debug] cancel all the clients")
_ = client.Close()
// TODO
// - Encode each client to the tunnel
// - Find the right client for decoded messages
// TODO which order is remote / local?
srcParts := strings.Split(client.RemoteAddr().String(), ":")
srcAddr := srcParts[0]
srcPort, _ := strconv.Atoi(srcParts[1])
dstParts := strings.Split(client.LocalAddr().String(), ":")
dstAddr := dstParts[0]
dstPort, _ := strconv.Atoi(dstParts[1])
termination := telebit.Unknown
scheme := telebit.None
if 80 == dstPort {
// TODO dstAddr = wconn.Servername()
scheme = telebit.HTTP
} else if 443 == dstPort {
dstAddr = wconn.Servername()
scheme = telebit.HTTPS
}
src := telebit.NewAddr(
scheme,
termination,
srcAddr,
srcPort,
)
dst := telebit.NewAddr(
scheme,
termination,
dstAddr,
dstPort,
)
err := s.multiEncoder.Encode(wconn, *src, *dst)
s.clients.Delete(id)
return err
}
func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
log.Println("websocket opening ", r.RemoteAddr, " ", r.Host)
w.Header().Set("Content-Type", "application/json")
if "Upgrade" != r.Header.Get("Connection") && "WebSocket" != r.Header.Get("Upgrade") {
w.Write(apiNotFoundContent)
return
}
grants, err := authorizer(r)
if nil != err {
log.Println("WebSocket authorization failed", err)
w.Write(apiNotAuthorizedContent)
return
}
upgrader := websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println("WebSocket upgrade failed", err)
return
}
wsTun := telebit.NewWebsocketTunnel(conn)
server := SubscriberConn{
remoteAddr: r.RemoteAddr,
wsConn: conn,
wsTun: wsTun,
grants: grants,
clients: &sync.Map{},
multiEncoder: telebit.NewEncoder(context.TODO(), wsTun),
multiDecoder: telebit.NewDecoder(wsTun),
}
go func() {
// (this listener is also a telebit.Router)
err := server.multiDecoder.Decode(&server)
// The tunnel itself must be closed explicitly because
// there's an encoder with a callback between the websocket
// and the multiplexer, so it doesn't know to stop listening otherwise
_ = wsTun.Close()
fmt.Printf("a subscriber stream is done: %q\n", err)
}()
var srvMap *sync.Map
srvMapX, ok := Servers.Load(grants.Subject)
if ok {
srvMap = srvMapX.(*sync.Map)
} else {
srvMap = &sync.Map{}
}
srvMap.Store(r.RemoteAddr, server)
Servers.Store(grants.Subject, srvMap)
// Add this server to the domain name matrix
for _, name := range grants.Domains {
var srvMap *sync.Map
srvMapX, ok := Table.Load(name)
if ok {
srvMap = srvMapX.(*sync.Map)
} else {
srvMap = &sync.Map{}
}
srvMap.Store(r.RemoteAddr, server)
Table.Store(name, srvMap)
}
}

40
cmd/telebit/authorizer.go Normal file
View File

@ -0,0 +1,40 @@
package main
import (
"fmt"
"net/http"
"strings"
telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer"
)
func NewAuthorizer(authURL string) telebit.Authorizer {
return func(r *http.Request) (*telebit.Grants, error) {
// do we have a valid wss_client?
var tokenString string
if auth := strings.Split(r.Header.Get("Authorization"), " "); len(auth) > 1 {
// TODO handle Basic auth tokens as well
tokenString = auth[1]
}
if "" == tokenString {
// Browsers do not allow Authorization Headers and must use access_token query string
tokenString = r.URL.Query().Get("access_token")
}
if "" != r.URL.Query().Get("access_token") {
r.URL.Query().Set("access_token", "[redacted]")
}
grants, err := telebit.Inspect(authURL, tokenString)
if nil != err {
fmt.Println("return an error, do not go on")
return nil, err
}
if "" != r.URL.Query().Get("access_token") {
r.URL.Query().Set("access_token", "[redacted:"+grants.Subject+"]")
}
return grants, err
}
}

View File

@ -8,18 +8,22 @@ import (
"encoding/hex"
"flag"
"fmt"
"io"
"log"
"net"
"net/url"
"os"
"regexp"
"strconv"
"strings"
"sync"
"time"
"git.coolaj86.com/coolaj86/go-telebitd/mgmt"
"git.coolaj86.com/coolaj86/go-telebitd/mgmt/authstore"
telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer"
"git.coolaj86.com/coolaj86/go-telebitd/mplexer/dns01"
httpshim "git.coolaj86.com/coolaj86/go-telebitd/relay/tunnel"
"github.com/caddyserver/certmagic"
"github.com/denisbrodbeck/machineid"
@ -45,6 +49,10 @@ type Forward struct {
port string
}
var authorizer telebit.Authorizer
var isHostname = regexp.MustCompile(`^[A-Za-z0-9_\.\-]+$`).MatchString
func main() {
var domains []string
var forwards []Forward
@ -62,6 +70,7 @@ func main() {
acmeRelay := flag.String("acme-relay", "", "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")
relay := flag.String("relay", "", "the domain (or ip address) at which the relay server is running")
apiHostname := flag.String("admin-hostname", "", "the hostname used to manage clients")
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)")
bindAddrsStr := flag.String("listen", "", "list of bind addresses on which to listen, such as localhost:80, or :443")
@ -69,6 +78,8 @@ func main() {
portToPorts := flag.String("port-forward", "", "a list of <from-port>:<to-port> for raw port-forwarding")
flag.Parse()
authorizer = NewAuthorizer(*authURL)
if len(os.Args) >= 2 {
if "version" == os.Args[1] {
fmt.Printf("telebit %s %s %s", GitVersion, GitRev[:7], GitTimestamp)
@ -206,7 +217,25 @@ func main() {
fmt.Println("Fwd:", fwd.pattern, fwd.port)
mux.ForwardTCP(fwd.pattern, "localhost:"+fwd.port, 120*time.Second)
}
// TODO close connection on invalid hostname
mux.HandleTCP("*", telebit.HandlerFunc(routeSubscribersAndClients))
mux.HandleTLS("*", acme, mux)
if 0 == len(*apiHostname) {
*apiHostname = os.Getenv("API_HOSTNAME")
}
if "" != *apiHostname {
listener := httpshim.NewListener()
go func() {
httpsrv.Serve(listener)
}()
mux.HandleTCP(*apiHostname, telebit.HandlerFunc(func(client net.Conn) error {
listener.Feed(client)
// TODO use a more correct non-error error?
// or perhaps (ok, error) or (handled, error)?
return io.EOF
}))
}
for _, fwd := range forwards {
//mux.ForwardTCP("*", "localhost:"+fwd.port, 120*time.Second)
mux.ForwardTCP(fwd.pattern, "localhost:"+fwd.port, 120*time.Second)
@ -278,6 +307,96 @@ func main() {
}
}
func routeSubscribersAndClients(client net.Conn) error {
var wconn *telebit.ConnWrap
switch conn := client.(type) {
case *telebit.ConnWrap:
wconn = conn
default:
panic("HandleTun is special in that it must receive &ConnWrap{ Conn: conn }")
}
// We know this to be two parts "ip:port"
dstParts := strings.Split(client.LocalAddr().String(), ":")
//dstAddr := dstParts[0]
dstPort, _ := strconv.Atoi(dstParts[1])
if 80 != dstPort && 443 != dstPort {
// TODO handle by port without peeking at Servername / Hostname
// if tryToServePort(client.LocalAddr().String(), wconn) {
// return io.EOF
// }
}
// TODO hostname for plain http?
servername := strings.ToLower(wconn.Servername())
if "" != servername && !isHostname(servername) {
_ = client.Close()
return fmt.Errorf("invalid servername")
}
// Match full servername "sub.domain.example.com"
if tryToServeName(servername, wconn) {
// TODO better non-error
return io.EOF
}
// Match wild names
// - "*.domain.example.com"
// - "*.example.com"
// - (skip)
labels := strings.Split(servername, ".")
n := len(labels)
if n < 3 {
return nil
}
for i := 1; i < n-1; i++ {
wildname := "*." + strings.Join(labels[1:], ".")
if tryToServeName(wildname, wconn) {
return io.EOF
}
}
// skip
return nil
}
// tryToServeName picks the server tunnel with the least connections, if any
func tryToServeName(servername string, wconn *telebit.ConnWrap) bool {
var srv *SubscriberConn
load := -1
srvMapX, ok := Table.Load(servername)
if !ok {
return false
}
srvMap := srvMapX.(*sync.Map)
srvMap.Range(func(k, v interface{}) bool {
myLoad := 0
mySrv := v.(*SubscriberConn)
mySrv.clients.Range(func(k, v interface{}) bool {
load += 1
return true
})
// pick the least loaded server
if -1 == load || myLoad < load {
load = myLoad
srv = mySrv
}
return true
})
// async so that the call stack can complete and be released
//srv.clients.Store(wconn.LocalAddr().String(), wconn)
go func() {
err := srv.Serve(wconn)
fmt.Printf("a browser client stream is done: %q\n", err)
//srv.clients.Delete(wconn.LocalAddr().String())
}()
return true
}
func parsePortForwards(portToPorts *string) ([]Forward, error) {
var portForwards []Forward

View File

@ -55,6 +55,8 @@ func HMACToken(secret string) (token string, err error) {
_, _ = rand.Read(b)
claims := &jwt.StandardClaims{
Id: base64.RawURLEncoding.EncodeToString(b),
Subject: "", // TODO
Issuer: "", // TODO
IssuedAt: time.Now().Unix(),
ExpiresAt: time.Now().Add(5 * time.Minute).Unix(),
}

View File

@ -64,6 +64,12 @@ func TestStore(t *testing.T) {
return
}
auth, err := store.Get(slug)
if nil == err {
t.Fatal("should get nothing back")
return
}
store.Close()
fmt.Printf("%#v\n", auth)

View File

@ -5,6 +5,7 @@ import "fmt"
type Scheme string
const (
None = Scheme("")
HTTPS = Scheme("https")
HTTP = Scheme("http")
SSH = Scheme("ssh")
@ -14,20 +15,22 @@ const (
type Termination string
const (
TCP = Termination("none")
TLS = Termination("tls")
Unknown = Termination("")
TCP = Termination("none")
TLS = Termination("tls")
)
type Addr struct {
family string // TODO what should be the format? "tcpv6"?
scheme Scheme
termination Termination
family string // TODO what should be the format? "tcpv6"?
addr string
port int
}
func NewAddr(s Scheme, t Termination, a string, p int) *Addr {
return &Addr{
family: "tun",
scheme: s,
termination: t,
addr: a,

4
mplexer/admin/assets.go Normal file
View File

@ -0,0 +1,4 @@
// +build !dev
//go:generate go run -mod vendor github.com/shurcooL/vfsgen/cmd/vfsgendev -source="git.coolaj86.com/coolaj86/go-telebitd/mplexer/admin".AdminFS
package admin

View File

@ -0,0 +1,2 @@
Contact: mailto:security@therootcompany.com
Preferred-Languages: en, lv, sq

View File

@ -0,0 +1,32 @@
/* TEAM */
Gopher: AJ ONeal
Site: https://coolaj86.com
Twitter: @coolaj86
Location: Provo, UT, USA.
Permanent Beta Tester: Ryan Burnette
Site: https://ryanburnette.com
Twitter: @ryanburnette
Location: GA, USA.
Moral Support: John Shaver
Site: https://jshaver.net
Twitter: @thejshaver
Location: USA.
/* THANKS */
Name: Brian Turley
Name: Seth Gibelyou
Name: Henry Camacho
/* SITE */
Last update: 2020/06/10
Standards: HTML5, WebSockets.
Components: Chi, Cert Magic, vfsgen.
Software: Golang
IDE: vim

View File

@ -0,0 +1,11 @@
<html>
<head>
<title>Telebit Local Admin</title>
<link rel="author" href="humans.txt" />
</head>
<body>
<h1>Hello, World!</h1>
<p>with love,</p>
<p>Telebit</p>
</body>
</html>

View File

@ -0,0 +1,3 @@
# Do not crawl the admin interface
User-agent: *
Disallow: /

View File

@ -0,0 +1,7 @@
// +build dev
package admin
import "net/http"
var AdminFS http.FileSystem = http.Dir("assets")

View File

@ -18,6 +18,7 @@ type ConnWrap struct {
scheme string
Conn net.Conn
Plain net.Conn
encrypted *bool
}
type Peeker interface {
@ -114,6 +115,9 @@ func (c *ConnWrap) Servername() string {
//c.servername = string(conn.relayTargetAddr.addr)
return string(conn.relayTargetAddr.addr)
}
// this will get the servername
c.isTerminated()
return c.servername
}
@ -126,6 +130,9 @@ func (c *ConnWrap) isTerminated() bool {
return true
}
*/
if nil != c.encrypted {
return !*c.encrypted
}
// how to know how many bytes to read? really needs timeout
c.SetDeadline(time.Now().Add(5 * time.Second))
@ -146,13 +153,16 @@ func (c *ConnWrap) isTerminated() bool {
length := (int(b[3]) << 8) + int(b[4])
b, err := c.Peek(n - 1 + length)
if nil != err {
return true
*c.encrypted = false
return !*c.encrypted
}
c.servername, _ = sni.GetHostname(b)
return false
*c.encrypted = true
return !*c.encrypted
}
}
return true
*c.encrypted = false
return !*c.encrypted
/*
if nil != err {
return true

View File

@ -48,12 +48,13 @@ func Listen(tun net.Conn) *Listener {
decoder := NewDecoder(tun)
go func() {
// TODO pass error to Accept()
// (this listener is also a telebit.Router)
err := decoder.Decode(listener)
// The listener itself must be closed explicitly because
// there's an encoder with a callback between the websocket
// and the multiplexer, so it doesn't know to stop listening otherwise
listener.Close()
_ = listener.Close()
fmt.Printf("the main stream is done: %q\n", err)
}()

View File

@ -66,9 +66,8 @@ func (m *RouteMux) Serve(client net.Conn) error {
for _, meta := range m.routes {
// TODO '*.example.com'
if meta.terminate && "" == servername {
wconn.isTerminated()
servername = wconn.servername
if meta.terminate {
servername = wconn.Servername()
}
fmt.Println("Meta:", meta.addr, servername)
if servername == meta.addr || "*" == meta.addr || port == meta.addr {

View File

@ -0,0 +1,9 @@
#!/bin/bash
go run cmd/telebit/*.go --acme-agree=true \
--acme-relay http://devices.rootprojects.org:3010/api/dns \
--auth-url http://devices.rootprojects.org:3010/api \
--relay wss://devices.rootprojects.org:8443/api/ws \
--app-id test-id \
--secret k7nsLSwNKbOeBhDFpbhwGHv \
--listen 3443

View File

@ -0,0 +1,9 @@
#!/bin/bash
go run cmd/telebit/*.go --acme-agree=true \
--acme-relay http://devices.rootprojects.org:3010/api/dns \
--auth-url http://devices.rootprojects.org:3010/api \
--relay wss://devices.rootprojects.org:8443/ws \
--app-id test-id \
--secret xxxxyyyyssss8347 \
--listen 3443

View File

@ -1 +0,0 @@
go run cmd/telebit/*.go --acme-agree=true --acme-relay http://devices.rootprojects.org:3010/api/dns --auth-url http://devices.rootprojects.org:3010/api --app-id test-id --secret k7nsLSwNKbOeBhDFpbhwGHv --listen 3443

View File

@ -35,12 +35,16 @@ var errNetClosing = "use of closed network connection"
// A Handler routes, proxies, terminates, or responds to a net.Conn.
type Handler interface {
// TODO ServeTCP
Serve(net.Conn) error
}
// HandlerFunc should handle, proxy, or terminate the connection
type HandlerFunc func(net.Conn) error
// Authorizer is called when a new client connects and we need to know something about it
type Authorizer func(*http.Request) (*Grants, error)
// Serve calls f(conn).
func (f HandlerFunc) Serve(conn net.Conn) error {
return f(conn)
@ -313,7 +317,9 @@ func newCertMagic(acme *ACME) (*certmagic.Config, error) {
}
type Grants struct {
Subject string `json:"sub"`
Domains []string `json:"domains"`
Ports []int `json:"ports"`
}
func Inspect(authURL, token string) (*Grants, error) {

View File

@ -4,7 +4,6 @@ import (
"context"
"crypto/tls"
"net"
"net/http"
"git.coolaj86.com/coolaj86/go-telebitd/log"
telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer"
@ -34,9 +33,6 @@ type Authz struct {
Domains []string
}
// Authorizer is called when a new client connects and we need to know something about it
type Authorizer func(*http.Request) (*telebit.Grants, error)
const (
listenerAdded ListenerRegistrationStatus = iota
listenerExists
@ -77,8 +73,8 @@ type MPlexy struct {
ctx context.Context
connnectionTable *api.Table
connectionTracking *api.Tracking
AuthorizeTarget Authorizer
AuthorizeAdmin Authorizer
AuthorizeTarget telebit.Authorizer
AuthorizeAdmin telebit.Authorizer
tlsConfig *tls.Config
register chan *ListenerRegistration
wssHostName string
@ -94,8 +90,8 @@ type MPlexy struct {
func New(
ctx context.Context,
tlsConfig *tls.Config,
authAdmin Authorizer,
authz Authorizer,
authAdmin telebit.Authorizer,
authz telebit.Authorizer,
serverStatus *api.Status,
) (mx *MPlexy) {
mx = &MPlexy{

View File

@ -7,6 +7,7 @@ import (
"net"
"net/http"
telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer"
"git.coolaj86.com/coolaj86/go-telebitd/relay/admin"
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
"git.coolaj86.com/coolaj86/go-telebitd/relay/mplexy"
@ -25,7 +26,7 @@ type Relay struct {
}
// New initializes and returns a relay service
func New(ctx context.Context, tlsConfig *tls.Config, authz mplexy.Authorizer, status *api.Status, table *api.Table) *Relay {
func New(ctx context.Context, tlsConfig *tls.Config, authz telebit.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