diff --git a/rvpn/genericlistener/conn_wedge.go b/rvpn/genericlistener/conn_wedge.go new file mode 100644 index 0000000..64dce2b --- /dev/null +++ b/rvpn/genericlistener/conn_wedge.go @@ -0,0 +1,43 @@ +package genericlistener + +import ( + "bufio" + "encoding/hex" + "net" +) + +//WedgeConn -- A buffered IO infront of a connection allowing peeking, and switching connections. +type WedgeConn struct { + reader *bufio.Reader + net.Conn +} + +//NewWedgeConn -- Constructor +func NewWedgeConn(c net.Conn) (p *WedgeConn) { + p = new(WedgeConn) + p.reader = bufio.NewReader(c) + p.Conn = c + return +} + +//NewWedgeConnSize -- Constructor +func NewWedgeConnSize(c net.Conn, size int) (p *WedgeConn) { + p = new(WedgeConn) + p.reader = bufio.NewReaderSize(c, size) + p.Conn = c + return +} + +//Peek - Get a number of bytes outof the buffer, but allow the buffer to be repled once read +func (w *WedgeConn) Peek(n int) ([]byte, error) { + return w.reader.Peek(n) +} + +//Read -- A normal reader. +func (w *WedgeConn) Read(p []byte) (int, error) { + loginfo.Println("read", w.Conn) + cnt, err := w.reader.Read(p) + loginfo.Println("read", hex.Dump(p[0:cnt])) + loginfo.Println(cnt, err) + return cnt, err +} diff --git a/rvpn/genericlistener/handle_wss_client.go b/rvpn/genericlistener/handle_wss_client.go new file mode 100644 index 0000000..298eb54 --- /dev/null +++ b/rvpn/genericlistener/handle_wss_client.go @@ -0,0 +1,115 @@ +package genericlistener + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + + jwt "github.com/dgrijalva/jwt-go" + "github.com/gorilla/mux" + "github.com/gorilla/websocket" + + "git.daplie.com/Daplie/go-rvpn-server/rvpn/admin" + "git.daplie.com/Daplie/go-rvpn-server/rvpn/connection" +) + +//LaunchWssListener - obtains a onetime connection from wedge listener +func LaunchWssListener(connectionTable *connection.Table, secretKey string, serverBind string, certfile string, keyfile string) (err error) { + loginfo.Println("starting LaunchWssListener ") + + router := mux.NewRouter().StrictSlash(true) + + router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + loginfo.Println("HandleFunc /") + switch url := r.URL.Path; url { + case "/": + // check to see if we are using the administrative Host + if strings.Contains(r.Host, "rvpn.daplie.invalid") { + http.Redirect(w, r, "/admin", 301) + } + + handleConnectionWebSocket(connectionTable, w, r, secretKey, false) + + default: + http.Error(w, "Not Found", 404) + } + }) + + router.HandleFunc("/admin", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "Welcome!") + }) + + router.HandleFunc("/api/servers", func(w http.ResponseWriter, r *http.Request) { + fmt.Println("here") + serverContainer := admin.NewServerAPIContainer() + + for c := range connectionTable.Connections() { + serverAPI := admin.NewServerAPI(c) + serverContainer.Servers = append(serverContainer.Servers, serverAPI) + + } + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + json.NewEncoder(w).Encode(serverContainer) + + }) + + s := &http.Server{ + Addr: serverBind, + Handler: router, + } + + err = s.ListenAndServeTLS(certfile, keyfile) + if err != nil { + loginfo.Println("ListenAndServeTLS: ", err) + } + return +} + +// handleConnectionWebSocket handles websocket requests from the peer. +func handleConnectionWebSocket(connectionTable *connection.Table, w http.ResponseWriter, r *http.Request, secretKey string, admin bool) { + 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) +} diff --git a/rvpn/genericlistener/listener_generic.go b/rvpn/genericlistener/listener_generic.go new file mode 100644 index 0000000..bd07374 --- /dev/null +++ b/rvpn/genericlistener/listener_generic.go @@ -0,0 +1,89 @@ +package genericlistener + +import ( + "net" + + "crypto/tls" + + "git.daplie.com/Daplie/go-rvpn-server/rvpn/connection" +) + +//LaunchGenericServer -- used to lisen for any https traffic on 443 (8443) +//used to make sure customer devices can reach 443. wss or client +func LaunchGenericServer(connectionTable *connection.Table, secretKey string, serverBinding string, certbundle tls.Certificate) { + + config := &tls.Config{Certificates: []tls.Certificate{certbundle}} + + listener, err := tls.Listen("tcp", serverBinding, config) + if err != nil { + loginfo.Println("unable to bind ", serverBinding) + return + } + + defer listener.Close() + + for { + conn, err := listener.Accept() + if err != nil { + loginfo.Println("Bad accept ", err) + continue + } + + go handleConnection(conn, connectionTable, secretKey) + } +} + +type protocol int + +//Family -- ENUM for Address Family +const ( + protoHTTP protocol = iota + 1 + protoHTTPS + protoSSLV3 + protoTLSV1 + protoTLSV11 + protoTLSV2 +) + +//State -- state of connection +type State struct { + Protocol protocol +} + +//NewState -- Constructor +func NewState() (p *State) { + p = new(State) + return +} + +func handleConnection(conn net.Conn, connectionTable *connection.Table, secretKey string) { + defer conn.Close() + + loginfo.Println("conn", conn) + loginfo.Println("hank") + loginfo.Println("here", conn.LocalAddr().String(), conn.RemoteAddr().String()) + + //state := NewState() + //wConn := NewWedgeConnSize(conn, 512) + //var buffer [512]byte + + // Peek for data to figure out what connection we have + //peekcnt := 32 + //peek, err := wConn.Peek(peekcnt) + + //if err != nil { + // loginfo.Println("error while peeking") + // return + // } + //loginfo.Println(hex.Dump(peek[0:peekcnt])) + //loginfo.Println("after peek") + + // assume http websocket. + + //loginfo.Println("wConn", wConn) + + //wedgeListener := &WedgeListener{conn: conn} + //LaunchWssListener(connectionTable, &secretKey, wedgeListener) + + return +} diff --git a/rvpn/genericlistener/listener_wedge.go b/rvpn/genericlistener/listener_wedge.go new file mode 100644 index 0000000..f7df647 --- /dev/null +++ b/rvpn/genericlistener/listener_wedge.go @@ -0,0 +1,58 @@ +package genericlistener + +import ( + "encoding/hex" + "io" + "net" + "sync" +) + +//WedgeListener -- used to hand off connections to other protocols via Listen +type WedgeListener struct { + 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() +} diff --git a/rvpn/genericlistener/setup.go b/rvpn/genericlistener/setup.go new file mode 100644 index 0000000..5353fd7 --- /dev/null +++ b/rvpn/genericlistener/setup.go @@ -0,0 +1,17 @@ +package genericlistener + +import ( + "log" + "os" +) + +var ( + loginfo *log.Logger + logdebug *log.Logger + logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile +) + +func init() { + loginfo = log.New(os.Stdout, "INFO: external: ", logFlags) + logdebug = log.New(os.Stdout, "DEBUG: external:", logFlags) +} diff --git a/rvpn/rvpnmain/run.go b/rvpn/rvpnmain/run.go index 0064e5d..caf2eae 100644 --- a/rvpn/rvpnmain/run.go +++ b/rvpn/rvpnmain/run.go @@ -6,11 +6,8 @@ import ( "log" "os" - "git.daplie.com/Daplie/go-rvpn-server/rvpn/admin" - "git.daplie.com/Daplie/go-rvpn-server/rvpn/client" "git.daplie.com/Daplie/go-rvpn-server/rvpn/connection" - "git.daplie.com/Daplie/go-rvpn-server/rvpn/external" - "git.daplie.com/Daplie/go-rvpn-server/rvpn/packer" + "git.daplie.com/Daplie/go-rvpn-server/rvpn/genericlistener" "git.daplie.com/Daplie/go-rvpn-server/rvpn/xlate" ) @@ -18,6 +15,8 @@ var ( loginfo *log.Logger logdebug *log.Logger logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile + argWssClientListener string + argGenericBinding string argServerBinding string argServerAdminBinding string argServerExternalBinding string @@ -27,7 +26,8 @@ var ( ) func init() { - flag.StringVar(&argServerBinding, "server-port", ":3502", "server Bind listener") + flag.StringVar(&argGenericBinding, "ssl-listener", ":8443", "generic SSL Listener") + flag.StringVar(&argWssClientListener, "wss-client-listener", ":3502", "wss client listener address:port") flag.StringVar(&argServerAdminBinding, "admin-server-port", "127.0.0.2:8000", "admin server Bind listener") flag.StringVar(&argServerExternalBinding, "external-server-port", "127.0.0.1:8080", "external server Bind listener") @@ -42,24 +42,28 @@ func Run() { loginfo.Println("startup") - p := packer.NewPacker() - p.Header.SetAddress("127.0.0.2") - p.Header.Port = 32768 - p.Data.AppendString("A test message") - p.PackV1() - fmt.Println("-=-=-=-=-=-=-=-=-=-=") + // certbundle, err := tls.LoadX509KeyPair("certs/fullchain.pem", "certs/privkey.pem") + // if err != nil { + // loginfo.Println(err) + // return + // } + // loginfo.Println(certbundle) + wssMapping = xlate.NewwssMapping() go wssMapping.Run() connectionTable = connection.NewTable() go connectionTable.Run() - go client.LaunchClientListener(connectionTable, &secretKey, &argServerBinding) + + //go client.LaunchClientListener(connectionTable, &secretKey, &argServerBinding) //go external.LaunchWebRequestExternalListener(&argServerExternalBinding, connectionTable) - go external.LaunchExternalServer(argServerExternalBinding, connectionTable) - err := admin.LaunchAdminListener(&argServerAdminBinding, connectionTable) - if err != nil { - loginfo.Println("LauchAdminListener failed: ", err) - } + //go external.LaunchExternalServer(argServerExternalBinding, connectionTable) + //err = admin.LaunchAdminListener(&argServerAdminBinding, connectionTable) + //if err != nil { + // loginfo.Println("LauchAdminListener failed: ", err) + //} + + genericlistener.LaunchWssListener(connectionTable, secretKey, argWssClientListener, "certs/fullchain.pem", "certs/privkey.pem") }