WSS Client now working with protocol detection
- added support for PeekAll…still not working 100%. - passing important values inside the context, no longer on arguments - stream handler now detects wss_client, validates the token to make sure. - then passes to was handler which invokes http.Server with oneConnListener - removing listener wedge, going to stay with oneConnListener. It is working.
This commit is contained in:
parent
ebafa277df
commit
9e2a04c8a7
|
@ -2,7 +2,6 @@ package genericlistener
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/hex"
|
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,16 +27,45 @@ func NewWedgeConnSize(c net.Conn, size int) (p *WedgeConn) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//Peek - Get a number of bytes outof the buffer, but allow the buffer to be repled once read
|
//Peek - Get a number of bytes outof the buffer, but allow the buffer to be replayed once read
|
||||||
func (w *WedgeConn) Peek(n int) ([]byte, error) {
|
func (w *WedgeConn) Peek(n int) ([]byte, error) {
|
||||||
|
loginfo.Println("Peek")
|
||||||
|
loginfo.Println("buffered=", w.reader.Buffered())
|
||||||
return w.reader.Peek(n)
|
return w.reader.Peek(n)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read -- A normal reader.
|
//Read -- A normal reader.
|
||||||
func (w *WedgeConn) Read(p []byte) (int, error) {
|
func (w *WedgeConn) Read(p []byte) (int, error) {
|
||||||
loginfo.Println("read", w.Conn)
|
loginfo.Println("read", w.Conn)
|
||||||
cnt, err := w.reader.Read(p)
|
cnt, err := w.reader.Read(p)
|
||||||
loginfo.Println("read", hex.Dump(p[0:cnt]))
|
|
||||||
loginfo.Println(cnt, err)
|
|
||||||
return cnt, err
|
return cnt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Buffered --
|
||||||
|
func (w *WedgeConn) Buffered() int {
|
||||||
|
return w.reader.Buffered()
|
||||||
|
}
|
||||||
|
|
||||||
|
//PeekAll --
|
||||||
|
// - get all the chars available
|
||||||
|
// - pass then back
|
||||||
|
func (w *WedgeConn) PeekAll() (buf []byte, err error) {
|
||||||
|
loginfo.Println("PeekAll")
|
||||||
|
|
||||||
|
var peek []byte
|
||||||
|
for {
|
||||||
|
b, err := w.reader.Peek(1)
|
||||||
|
if err != nil {
|
||||||
|
if len(peek) > 0 {
|
||||||
|
return peek, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var t byte
|
||||||
|
t = b[0]
|
||||||
|
|
||||||
|
peek = append(peek, t)
|
||||||
|
loginfo.Println("len", len(peek))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,9 +9,25 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"bufio"
|
||||||
|
|
||||||
"git.daplie.com/Daplie/go-rvpn-server/rvpn/connection"
|
"git.daplie.com/Daplie/go-rvpn-server/rvpn/connection"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type contextKey string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ctxSecretKey contextKey = "secretKey"
|
||||||
|
ctxConnectionTable contextKey = "connectionTable"
|
||||||
|
ctxConfig contextKey = "config"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
encryptNone int = iota
|
encryptNone int = iota
|
||||||
encryptSSLV2
|
encryptSSLV2
|
||||||
|
@ -29,6 +45,10 @@ const (
|
||||||
func GenericListenAndServe(ctx context.Context, connectionTable *connection.Table, secretKey string, serverBinding string, certbundle tls.Certificate, deadTime int) {
|
func GenericListenAndServe(ctx context.Context, connectionTable *connection.Table, secretKey string, serverBinding string, certbundle tls.Certificate, deadTime int) {
|
||||||
config := &tls.Config{Certificates: []tls.Certificate{certbundle}}
|
config := &tls.Config{Certificates: []tls.Certificate{certbundle}}
|
||||||
|
|
||||||
|
ctx = context.WithValue(ctx, ctxSecretKey, secretKey)
|
||||||
|
ctx = context.WithValue(ctx, ctxConnectionTable, connectionTable)
|
||||||
|
ctx = context.WithValue(ctx, ctxConfig, config)
|
||||||
|
|
||||||
listenAddr, err := net.ResolveTCPAddr("tcp", serverBinding)
|
listenAddr, err := net.ResolveTCPAddr("tcp", serverBinding)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
loginfo.Println(err)
|
loginfo.Println(err)
|
||||||
|
@ -62,7 +82,7 @@ func GenericListenAndServe(ctx context.Context, connectionTable *connection.Tabl
|
||||||
}
|
}
|
||||||
|
|
||||||
wedgeConn := NewWedgeConn(conn)
|
wedgeConn := NewWedgeConn(conn)
|
||||||
go handleConnection(ctx, wedgeConn, connectionTable, secretKey, config)
|
go handleConnection(ctx, wedgeConn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,8 +90,9 @@ func GenericListenAndServe(ctx context.Context, connectionTable *connection.Tabl
|
||||||
//handleConnection -
|
//handleConnection -
|
||||||
// - accept a wedgeConnection along with all the other required attritvues
|
// - accept a wedgeConnection along with all the other required attritvues
|
||||||
// - peek into the buffer, determine TLS or unencrypted
|
// - peek into the buffer, determine TLS or unencrypted
|
||||||
|
// - if TSL, then terminate with a TLS endpoint, pass to handleStream
|
||||||
func handleConnection(ctx context.Context, wConn *WedgeConn, connectionTable *connection.Table, secretKey string, config *tls.Config) {
|
// - if clearText, pass to handleStream
|
||||||
|
func handleConnection(ctx context.Context, wConn *WedgeConn) {
|
||||||
defer wConn.Close()
|
defer wConn.Close()
|
||||||
peekCnt := 10
|
peekCnt := 10
|
||||||
|
|
||||||
|
@ -107,6 +128,7 @@ func handleConnection(ctx context.Context, wConn *WedgeConn, connectionTable *co
|
||||||
}
|
}
|
||||||
|
|
||||||
oneConn := &oneConnListener{wConn}
|
oneConn := &oneConnListener{wConn}
|
||||||
|
config := ctx.Value(ctxConfig).(*tls.Config)
|
||||||
|
|
||||||
if encryptMode == encryptSSLV2 {
|
if encryptMode == encryptSSLV2 {
|
||||||
loginfo.Println("SSLv2 is not accepted")
|
loginfo.Println("SSLv2 is not accepted")
|
||||||
|
@ -121,47 +143,150 @@ func handleConnection(ctx context.Context, wConn *WedgeConn, connectionTable *co
|
||||||
loginfo.Println(err)
|
loginfo.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
loginfo.Println(conn)
|
|
||||||
handleStream(conn)
|
tlsWedgeConn := NewWedgeConn(conn)
|
||||||
|
handleStream(ctx, tlsWedgeConn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
loginfo.Println("Handle Unencrypted")
|
loginfo.Println("Handle Unencrypted")
|
||||||
handleStream(wConn)
|
handleStream(ctx, wConn)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleStream(conn net.Conn) {
|
//handleStream --
|
||||||
var buf [512]byte
|
// - we have an unencrypted stream connection with the ability to peek
|
||||||
cnt, err := conn.Read(buf[0:])
|
// - attempt to identify HTTP
|
||||||
|
// - handle http
|
||||||
|
// - attempt to identify as WSS session
|
||||||
|
// - attempt to identify as ADMIN/API session
|
||||||
|
// - else handle as raw https
|
||||||
|
// - handle other?
|
||||||
|
func handleStream(ctx context.Context, wConn *WedgeConn) {
|
||||||
|
loginfo.Println("handle Stream")
|
||||||
|
loginfo.Println("conn", wConn, wConn.LocalAddr().String(), wConn.RemoteAddr().String())
|
||||||
|
|
||||||
|
//peek for one byte to get the readers to converge
|
||||||
|
//look at buffer
|
||||||
|
//get the realrequest
|
||||||
|
peek, err := wConn.Peek(1)
|
||||||
|
loginfo.Println(hex.Dump(peek[0:]))
|
||||||
|
peek, err = wConn.Peek(wConn.Buffered())
|
||||||
|
loginfo.Println(hex.Dump(peek[0:]))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loginfo.Println(err)
|
loginfo.Println("error while peeking")
|
||||||
|
loginfo.Println(hex.Dump(peek[0:]))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
loginfo.Println(hex.Dump(buf[0:cnt]))
|
// HTTP Identifcation
|
||||||
|
if bytes.Contains(peek[:], []byte{0x0d, 0x0a}) {
|
||||||
|
//string protocol
|
||||||
|
if bytes.ContainsAny(peek[:], "HTTP/") {
|
||||||
|
loginfo.Println("identifed HTTP")
|
||||||
|
|
||||||
|
r, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(peek)))
|
||||||
|
if err != nil {
|
||||||
|
loginfo.Println("identifed as HTTP, failed request", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//state := NewState()
|
loginfo.Println(r)
|
||||||
//wConn := NewWedgeConnSize(conn, 512)
|
|
||||||
//var buffer [512]byte
|
|
||||||
|
|
||||||
// Peek for data to figure out what connection we have
|
//now we have a request. Check to see if it is one of our own
|
||||||
//peekcnt := 32
|
secretKey := ctx.Value(ctxSecretKey).(string)
|
||||||
//peek, err := wConn.Peek(peekcnt)
|
tokenString := r.URL.Query().Get("access_token")
|
||||||
|
result, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return []byte(secretKey), nil
|
||||||
|
})
|
||||||
|
|
||||||
//if err != nil {
|
if err == nil && result.Valid {
|
||||||
// loginfo.Println("error while peeking")
|
loginfo.Println("Valid WSS dected...sending to handler")
|
||||||
// return
|
oneConn := &oneConnListener{wConn}
|
||||||
// }
|
handleWssClient(ctx, oneConn)
|
||||||
//loginfo.Println(hex.Dump(peek[0:peekcnt]))
|
} else {
|
||||||
//loginfo.Println("after peek")
|
loginfo.Println("not a valid WSS connection")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// assume http websocket.
|
loginfo.Println(hex.Dump(peek[0:]))
|
||||||
|
}
|
||||||
|
|
||||||
//loginfo.Println("wConn", wConn)
|
//handleWssClient -
|
||||||
|
// - expecting an existing oneConnListener with a qualified wss client connected.
|
||||||
|
// - auth will happen again since we were just peeking at the token.
|
||||||
|
func handleWssClient(ctx context.Context, oneConn *oneConnListener) {
|
||||||
|
secretKey := ctx.Value(ctxSecretKey).(string)
|
||||||
|
connectionTable := ctx.Value(ctxConnectionTable).(*connection.Table)
|
||||||
|
|
||||||
//wedgeListener := &WedgeListener{conn: conn}
|
router := mux.NewRouter().StrictSlash(true)
|
||||||
//LaunchWssListener(connectionTable, &secretKey, wedgeListener)
|
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
loginfo.Println("HandleFunc /")
|
||||||
|
switch url := r.URL.Path; url {
|
||||||
|
case "/":
|
||||||
|
loginfo.Println("websocket opening ", r.RemoteAddr, " ", r.Host)
|
||||||
|
|
||||||
|
tokenString := r.URL.Query().Get("access_token")
|
||||||
|
result, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return []byte(secretKey), nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil || !result.Valid {
|
||||||
|
w.WriteHeader(http.StatusForbidden)
|
||||||
|
w.Write([]byte("Not Authorized"))
|
||||||
|
loginfo.Println("access_token invalid...closing connection")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loginfo.Println("help access_token valid")
|
||||||
|
|
||||||
|
claims := result.Claims.(jwt.MapClaims)
|
||||||
|
domains, ok := claims["domains"].([]interface{})
|
||||||
|
|
||||||
|
var upgrader = websocket.Upgrader{
|
||||||
|
ReadBufferSize: 1024,
|
||||||
|
WriteBufferSize: 1024,
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := upgrader.Upgrade(w, r, nil)
|
||||||
|
if err != nil {
|
||||||
|
loginfo.Println("WebSocket upgrade failed", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loginfo.Println("before connection table")
|
||||||
|
|
||||||
|
//newConnection := connection.NewConnection(connectionTable, conn, r.RemoteAddr, domains)
|
||||||
|
|
||||||
|
newRegistration := connection.NewRegistration(conn, r.RemoteAddr, domains)
|
||||||
|
connectionTable.Register() <- newRegistration
|
||||||
|
ok = <-newRegistration.CommCh()
|
||||||
|
if !ok {
|
||||||
|
loginfo.Println("connection registration failed ", newRegistration)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loginfo.Println("connection registration accepted ", newRegistration)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
s := &http.Server{
|
||||||
|
Addr: ":80",
|
||||||
|
Handler: router,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.Serve(oneConn)
|
||||||
|
if err != nil {
|
||||||
|
loginfo.Println("Serve error: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
loginfo.Println("Cancel signal hit")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
package genericlistener
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
//WedgeListener -- used to hand off connections to other protocols via Listen
|
|
||||||
type WedgeListener struct {
|
|
||||||
net.Listener
|
|
||||||
conn net.Conn
|
|
||||||
once sync.Once
|
|
||||||
}
|
|
||||||
|
|
||||||
//Accept --
|
|
||||||
func (s *WedgeListener) Accept() (net.Conn, error) {
|
|
||||||
var c net.Conn
|
|
||||||
|
|
||||||
loginfo.Println("Accept")
|
|
||||||
|
|
||||||
if 1 == 2 {
|
|
||||||
|
|
||||||
var buffer [512]byte
|
|
||||||
cnt, err := s.conn.Read(buffer[0:])
|
|
||||||
if err != nil {
|
|
||||||
loginfo.Println("Errpr radomg")
|
|
||||||
}
|
|
||||||
loginfo.Println("buffer")
|
|
||||||
loginfo.Println(hex.Dump(buffer[0:cnt]))
|
|
||||||
}
|
|
||||||
|
|
||||||
s.once.Do(func() {
|
|
||||||
loginfo.Println("Do Once")
|
|
||||||
c = s.conn
|
|
||||||
})
|
|
||||||
|
|
||||||
if c != nil {
|
|
||||||
loginfo.Println("accepted")
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
return nil, io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
//Close --
|
|
||||||
func (s *WedgeListener) Close() error {
|
|
||||||
s.once.Do(func() {
|
|
||||||
loginfo.Println("close called")
|
|
||||||
s.conn.Close()
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//Addr --
|
|
||||||
func (s *WedgeListener) Addr() net.Addr {
|
|
||||||
loginfo.Println("Add Called", s.conn.LocalAddr())
|
|
||||||
return s.conn.LocalAddr()
|
|
||||||
}
|
|
|
@ -72,7 +72,7 @@ func Run() {
|
||||||
|
|
||||||
go genericlistener.GenericListenAndServe(ctx, connectionTable, secretKey, argGenericBinding, certbundle, argDeadTime)
|
go genericlistener.GenericListenAndServe(ctx, connectionTable, secretKey, argGenericBinding, certbundle, argDeadTime)
|
||||||
|
|
||||||
time.Sleep(300 * time.Second)
|
time.Sleep(20 * time.Second)
|
||||||
cancelContext()
|
cancelContext()
|
||||||
time.Sleep(60 * time.Second)
|
time.Sleep(60 * time.Second)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue