diff --git a/rvpn/connection/connection_table.go b/rvpn/connection/connection_table.go index f814fa5..4b752a5 100755 --- a/rvpn/connection/connection_table.go +++ b/rvpn/connection/connection_table.go @@ -2,6 +2,7 @@ package connection import "fmt" import "time" +import "context" const ( initialDomains = 0 @@ -62,13 +63,18 @@ func (c *Table) reaper(delay int, idle int) { } //Run -- Execute -func (c *Table) Run() { +func (c *Table) Run(ctx context.Context) { loginfo.Println("ConnectionTable starting") go c.reaper(300, 60) for { select { + + case <-ctx.Done(): + loginfo.Println("Cancel signal hit") + return + case registration := <-c.register: loginfo.Println("register fired") diff --git a/rvpn/genericlistener/listener_generic.go b/rvpn/genericlistener/listener_generic.go index bd07374..993b83e 100644 --- a/rvpn/genericlistener/listener_generic.go +++ b/rvpn/genericlistener/listener_generic.go @@ -1,89 +1,167 @@ package genericlistener import ( - "net" - + "bytes" + "context" "crypto/tls" + "encoding/hex" + "log" + "net" + "time" "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) { +const ( + encryptNone int = iota + encryptSSLV2 + encryptSSLV3 + encryptTLS10 + encryptTLS11 + encryptTLS12 +) +//GenericListenAndServe -- 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, connectionTable *connection.Table, secretKey string, serverBinding string, certbundle tls.Certificate, deadTime int) { config := &tls.Config{Certificates: []tls.Certificate{certbundle}} - listener, err := tls.Listen("tcp", serverBinding, config) - if err != nil { - loginfo.Println("unable to bind ", serverBinding) + listenAddr, err := net.ResolveTCPAddr("tcp", serverBinding) + if nil != err { + loginfo.Println(err) return } - defer listener.Close() + ln, err := net.ListenTCP("tcp", listenAddr) + if err != nil { + loginfo.Println("unable to bind", err) + return + } for { - conn, err := listener.Accept() - if err != nil { - loginfo.Println("Bad accept ", err) - continue - } + select { + case <-ctx.Done(): + loginfo.Println("Cancel signal hit") + return + default: + ln.SetDeadline(time.Now().Add(time.Duration(deadTime) * time.Second)) - go handleConnection(conn, connectionTable, secretKey) + conn, err := ln.Accept() + + loginfo.Println("Deadtime reached") + + if nil != err { + if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() { + continue + } + log.Println(err) + return + } + + wedgeConn := NewWedgeConn(conn) + go handleConnection(ctx, wedgeConn, connectionTable, secretKey, config) + } } } -type protocol int +//handleConnection - +// - accept a wedgeConnection along with all the other required attritvues +// - peek into the buffer, determine TLS or unencrypted -//Family -- ENUM for Address Family -const ( - protoHTTP protocol = iota + 1 - protoHTTPS - protoSSLV3 - protoTLSV1 - protoTLSV11 - protoTLSV2 -) +func handleConnection(ctx context.Context, wConn *WedgeConn, connectionTable *connection.Table, secretKey string, config *tls.Config) { + defer wConn.Close() + peekCnt := 10 -//State -- state of connection -type State struct { - Protocol protocol -} + encryptMode := encryptNone -//NewState -- Constructor -func NewState() (p *State) { - p = new(State) - return -} + loginfo.Println("conn", wConn, wConn.LocalAddr().String(), wConn.RemoteAddr().String()) + peek, err := wConn.Peek(peekCnt) -func handleConnection(conn net.Conn, connectionTable *connection.Table, secretKey string) { - defer conn.Close() + if err != nil { + loginfo.Println("error while peeking") + return + } + loginfo.Println(hex.Dump(peek[0:peekCnt])) + loginfo.Println(hex.Dump(peek[2:4])) + loginfo.Println("after peek") - loginfo.Println("conn", conn) - loginfo.Println("hank") - loginfo.Println("here", conn.LocalAddr().String(), conn.RemoteAddr().String()) + //take a look for a TLS header. + if bytes.Contains(peek[0:0], []byte{0x80}) && bytes.Contains(peek[2:4], []byte{0x01, 0x03}) { + encryptMode = encryptSSLV2 - //state := NewState() - //wConn := NewWedgeConnSize(conn, 512) - //var buffer [512]byte + } else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x00}) { + encryptMode = encryptSSLV3 - // Peek for data to figure out what connection we have - //peekcnt := 32 - //peek, err := wConn.Peek(peekcnt) + } else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x01}) { + encryptMode = encryptTLS10 + loginfo.Println("TLS10") - //if err != nil { - // loginfo.Println("error while peeking") - // return - // } - //loginfo.Println(hex.Dump(peek[0:peekcnt])) - //loginfo.Println("after peek") + } else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x02}) { + encryptMode = encryptTLS11 - // assume http websocket. + } else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x03}) { + encryptMode = encryptTLS12 + } - //loginfo.Println("wConn", wConn) + oneConn := &oneConnListener{wConn} - //wedgeListener := &WedgeListener{conn: conn} - //LaunchWssListener(connectionTable, &secretKey, wedgeListener) + if encryptMode == encryptSSLV2 { + loginfo.Println("SSLv2 is not accepted") + return + + } else if encryptMode != encryptNone { + loginfo.Println("Handle Encryption") + tlsListener := tls.NewListener(oneConn, config) + + conn, err := tlsListener.Accept() + if err != nil { + loginfo.Println(err) + return + } + loginfo.Println(conn) + handleStream(conn) + return + } + + loginfo.Println("Handle Unencrypted") + handleStream(wConn) return } + +func handleStream(conn net.Conn) { + var buf [512]byte + cnt, err := conn.Read(buf[0:]) + if err != nil { + loginfo.Println(err) + return + } + + loginfo.Println(hex.Dump(buf[0:cnt])) + +} + +//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) diff --git a/rvpn/genericlistener/listener_wedge.go b/rvpn/genericlistener/listener_wedge.go index f7df647..62a6316 100644 --- a/rvpn/genericlistener/listener_wedge.go +++ b/rvpn/genericlistener/listener_wedge.go @@ -9,6 +9,7 @@ import ( //WedgeListener -- used to hand off connections to other protocols via Listen type WedgeListener struct { + net.Listener conn net.Conn once sync.Once } diff --git a/rvpn/genericlistener/one_conn.go b/rvpn/genericlistener/one_conn.go new file mode 100644 index 0000000..1e9b104 --- /dev/null +++ b/rvpn/genericlistener/one_conn.go @@ -0,0 +1,34 @@ +package genericlistener + +import ( + "io" + "net" +) + +type oneConnListener struct { + conn net.Conn +} + +func (l *oneConnListener) Accept() (c net.Conn, err error) { + c = l.conn + + if c == nil { + err = io.EOF + loginfo.Println("Accept") + return + } + err = nil + l.conn = nil + loginfo.Println("Accept", c.LocalAddr().String(), c.RemoteAddr().String()) + return +} + +func (l *oneConnListener) Close() error { + loginfo.Println("close") + return nil +} + +func (l *oneConnListener) Addr() net.Addr { + loginfo.Println("addr") + return nil +} diff --git a/rvpn/rvpnmain/run.go b/rvpn/rvpnmain/run.go index caf2eae..a39b3fa 100644 --- a/rvpn/rvpnmain/run.go +++ b/rvpn/rvpnmain/run.go @@ -1,10 +1,14 @@ package rvpnmain import ( + "crypto/tls" "flag" "fmt" "log" "os" + "time" + + "context" "git.daplie.com/Daplie/go-rvpn-server/rvpn/connection" "git.daplie.com/Daplie/go-rvpn-server/rvpn/genericlistener" @@ -20,17 +24,18 @@ var ( argServerBinding string argServerAdminBinding string argServerExternalBinding string + argDeadTime int connectionTable *connection.Table wssMapping *xlate.WssMapping secretKey = "abc123" ) func init() { - flag.StringVar(&argGenericBinding, "ssl-listener", ":8443", "generic SSL Listener") + flag.IntVar(&argDeadTime, "dead-time-counter", 5, "deadtime counter in seconds") + flag.StringVar(&argGenericBinding, "generic-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") - } //Run -- main entry point @@ -44,18 +49,35 @@ func Run() { fmt.Println("-=-=-=-=-=-=-=-=-=-=") - // certbundle, err := tls.LoadX509KeyPair("certs/fullchain.pem", "certs/privkey.pem") - // if err != nil { - // loginfo.Println(err) - // return - // } - // loginfo.Println(certbundle) + certbundle, err := tls.LoadX509KeyPair("certs/fullchain.pem", "certs/privkey.pem") + if err != nil { + loginfo.Println(err) + return + } - wssMapping = xlate.NewwssMapping() - go wssMapping.Run() + ctx, cancelContext := context.WithCancel(context.Background()) + defer cancelContext() connectionTable = connection.NewTable() - go connectionTable.Run() + go connectionTable.Run(ctx) + + // 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 + + go genericlistener.GenericListenAndServe(ctx, connectionTable, secretKey, argGenericBinding, certbundle, argDeadTime) + + time.Sleep(300 * time.Second) + cancelContext() + time.Sleep(60 * time.Second) + + //wssMapping = xlate.NewwssMapping() + //go wssMapping.Run() //go client.LaunchClientListener(connectionTable, &secretKey, &argServerBinding) //go external.LaunchWebRequestExternalListener(&argServerExternalBinding, connectionTable) @@ -65,5 +87,5 @@ func Run() { // loginfo.Println("LauchAdminListener failed: ", err) //} - genericlistener.LaunchWssListener(connectionTable, secretKey, argWssClientListener, "certs/fullchain.pem", "certs/privkey.pem") + //genericlistener.LaunchWssListener(connectionTable, secretKey, argWssClientListener, "certs/fullchain.pem", "certs/privkey.pem") }