diff --git a/rvpn/admin/domain_api.go b/rvpn/admin/domain_api.go index 8813ee2..3e3ee0d 100644 --- a/rvpn/admin/domain_api.go +++ b/rvpn/admin/domain_api.go @@ -2,9 +2,9 @@ package admin //DomainAPI -- Structure to hold the domain tracking for JSON type DomainAPI struct { - Domain string - BytesIn int64 - BytesOut int64 + Domain string `json:"domain"` + BytesIn int64 `json:"bytes_in"` + BytesOut int64 `json:"bytes_out"` } //NewDomainAPI - Constructor diff --git a/rvpn/admin/server_api.go b/rvpn/admin/server_api.go index f95e350..c1b9562 100644 --- a/rvpn/admin/server_api.go +++ b/rvpn/admin/server_api.go @@ -9,11 +9,11 @@ import ( //ServerAPI -- Structure to support the server API type ServerAPI struct { - ServerName string - Domains []*DomainAPI - Duration float64 - BytesIn int64 - BytesOut int64 + ServerName string `json:"server_name"` + Domains []*DomainAPI `json:"domains"` + Duration float64 `json:"duration"` + BytesIn int64 `json:"bytes_in"` + BytesOut int64 `json:"bytes_out"` } //NewServerAPI - Constructor @@ -35,7 +35,7 @@ func NewServerAPI(c *connection.Connection) (s *ServerAPI) { //ServerAPIContainer -- Holder for all the Servers type ServerAPIContainer struct { - Servers []*ServerAPI + Servers []*ServerAPI `json:"servers"` } //NewServerAPIContainer -- Constructor diff --git a/rvpn/external/listener_webrequest.go b/rvpn/external/listener_webrequest.go index 251d3d6..9175c05 100644 --- a/rvpn/external/listener_webrequest.go +++ b/rvpn/external/listener_webrequest.go @@ -47,10 +47,13 @@ func LaunchWebRequestExternalListener(serverBinding *string, connectionTable *co http.Error(w, "Domain not supported", http.StatusBadRequest) } else { + loginfo.Println("Domain Accepted") loginfo.Println(conn, rAddr, rPort) p := packer.NewPacker() p.Header.SetAddress(rAddr) p.Header.Port, err = strconv.Atoi(rPort) + p.Header.Port = 8080 + p.Header.Service = "http" p.Data.AppendBytes(dump) buf := p.PackV1() diff --git a/rvpn/external/server.go b/rvpn/external/server.go new file mode 100644 index 0000000..37077be --- /dev/null +++ b/rvpn/external/server.go @@ -0,0 +1,175 @@ +package external + +import ( + "encoding/hex" + "net" + "net/http" + "strconv" + "strings" + + "bytes" + + "bufio" + + "git.daplie.com/Daplie/go-rvpn-server/rvpn/connection" + "git.daplie.com/Daplie/go-rvpn-server/rvpn/packer" +) + +//LaunchExternalServer -- used to listen for external connections destin for WSS +func LaunchExternalServer(serverBinding string, connectionTable *connection.Table) { + addr, err := net.ResolveTCPAddr("tcp4", serverBinding) + if err != nil { + loginfo.Println("Unabled to resolve ", serverBinding, " in launchExternalServer") + loginfo.Println(err) + return + } + + loginfo.Println("passed ResolveTCPAddr") + + listener, err := net.ListenTCP("tcp", addr) + if err != nil { + loginfo.Println("unable to bind ", serverBinding) + return + } + + loginfo.Println("listening") + + for { + conn, err := listener.AcceptTCP() + if err != nil { + loginfo.Println("Bad accept ", err) + continue + } + + go handleConnection(conn, connectionTable) + } +} + +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) { + defer conn.Close() + + state := NewState() + + var buffer [512]byte + + for { + cnt, err := conn.Read(buffer[0:]) + if err != nil { + return + } + loginfo.Println("state ", state, " ", state.Protocol) + loginfo.Println("conn ", conn) + loginfo.Println("byte read", cnt) + loginfo.Println("buffer") + loginfo.Println(hex.Dump(buffer[0:cnt])) + + if state.Protocol == 0 { + //attempt to discover protocol + + // HTTP Identifcation + if bytes.Contains(buffer[:], []byte{0x0d, 0x0a}) { + //string protocol + if bytes.ContainsAny(buffer[:], "HTTP/") { + loginfo.Println("identifed HTTP") + state.Protocol = protoHTTP + } + + } else if bytes.Contains(buffer[:], []byte{0x16, 0x03, 0x00}) { + loginfo.Println("identifed SSLV3") + state.Protocol = protoSSLV3 + + } else if bytes.Contains(buffer[:], []byte{0x16, 0x03, 0x01}) { + loginfo.Println("identifed TLSV1") + state.Protocol = protoTLSV1 + + } else if bytes.Contains(buffer[:], []byte{0x16, 0x03, 0x02}) { + loginfo.Println("identifed TLSV1.1") + state.Protocol = protoTLSV11 + + } else if bytes.Contains(buffer[:], []byte{0x16, 0x03, 0x03}) { + loginfo.Println("identifed TLSV2") + state.Protocol = protoTLSV2 + + } else { + loginfo.Println("Protocol not identified", conn) + return + } + } + + if state.Protocol == 0 { + loginfo.Println("Making sure protocol is set") + loginfo.Println(state) + return + } else if state.Protocol == protoHTTP { + readBuffer := bytes.NewBuffer(buffer[0:cnt]) + reader := bufio.NewReader(readBuffer) + r, err := http.ReadRequest(reader) + + loginfo.Println(r) + + if err != nil { + loginfo.Println("error parsing request") + return + } + + hostname := r.Host + loginfo.Println("Host: ", hostname) + + if strings.Contains(hostname, ":") { + arr := strings.Split(hostname, ":") + hostname = arr[0] + } + + loginfo.Println("Remote: ", conn.RemoteAddr().String()) + + remoteSplit := strings.Split(conn.RemoteAddr().String(), ":") + rAddr := remoteSplit[0] + rPort := remoteSplit[1] + + if conn, ok := connectionTable.ConnByDomain(hostname); !ok { + //matching connection can not be found based on ConnByDomain + loginfo.Println("unable to match ", hostname, " to an existing connection") + //http.Error(, "Domain not supported", http.StatusBadRequest) + + } else { + + loginfo.Println("Domain Accepted") + loginfo.Println(conn, rAddr, rPort) + p := packer.NewPacker() + p.Header.SetAddress(rAddr) + p.Header.Port, err = strconv.Atoi(rPort) + p.Header.Port = 8080 + p.Header.Service = "http" + p.Data.AppendBytes(buffer[0:cnt]) + buf := p.PackV1() + + sendTrack := connection.NewSendTrack(buf.Bytes(), hostname) + conn.SendCh() <- sendTrack + } + } + + } +} diff --git a/rvpn/matching/protocol.go b/rvpn/matching/protocol.go new file mode 100644 index 0000000..d337e1f --- /dev/null +++ b/rvpn/matching/protocol.go @@ -0,0 +1,62 @@ +package matching + +type headerTerm int +type matchType int +type protocolType int + +//headerTerm -- ENUM for header terminator +const ( + CRLF2 headerTerm = iota + ZER0 +) + +//Family -- ENUM for Address Family +const ( + BYTES matchType = iota + REGEX +) + +const ( + pHTTP = iota + 1 + pTLS + pSSH +) + +//Protocol -- +type Protocol struct { + HeaderTerm headerTerm + MatchType matchType + Type protocolType + SearchRegex string + SearchBytes []byte +} + +//NewProtocol -- Constructor +func NewProtocol() (p *Protocol) { + p = new(Protocol) + return +} + +//Protocols -- +type Protocols struct { + protocols []*Protocol +} + +func (p *Protocols) add(protocol *Protocol) []*Protocol { + p.protocols = append(p.protocols, protocol) + return p.protocols +} + +//NewProtocols -- +func NewProtocols() (p *Protocols) { + p = new(Protocols) + p.protocols = make([]*Protocol, 0) + + newp := NewProtocol() + newp.MatchType = REGEX + newp.HeaderTerm = CRLF2 + newp.MatchType = pHTTP + p.add(newp) + + return +} diff --git a/rvpn/matching/setup.go b/rvpn/matching/setup.go new file mode 100644 index 0000000..4447d71 --- /dev/null +++ b/rvpn/matching/setup.go @@ -0,0 +1,13 @@ +package matching + +import "log" +import "os" + +func init() { + logFlags := log.Ldate | log.Lmicroseconds | log.Lshortfile + loginfo := log.New(os.Stdout, "INFO: matching: ", logFlags) + logdebug := log.New(os.Stdout, "DEBUG: matching:", logFlags) + + loginfo.Println("") + logdebug.Println("") +} diff --git a/rvpn/packer/packer.go b/rvpn/packer/packer.go index f3ad2f6..349556c 100644 --- a/rvpn/packer/packer.go +++ b/rvpn/packer/packer.go @@ -2,6 +2,7 @@ package packer import ( "bytes" + "encoding/hex" "fmt" ) @@ -47,6 +48,7 @@ func (p *Packer) PackV1() (b bytes.Buffer) { fmt.Println("meta: ", metaBuf) fmt.Println("Data: ", p.Data.buffer) fmt.Println("Buffer: ", buf.Bytes()) + fmt.Println("Buffer: ", hex.Dump(buf.Bytes())) fmt.Printf("Buffer %s", buf.Bytes()) b = buf diff --git a/rvpn/packer/packer_header.go b/rvpn/packer/packer_header.go index f5760be..c771f50 100644 --- a/rvpn/packer/packer_header.go +++ b/rvpn/packer/packer_header.go @@ -20,8 +20,8 @@ const ( ) var addressFamilyText = [...]string{ - "ipv4", - "ipv6", + "IPv4", + "IPv6", } func newPackerHeader() (p *packerHeader) { diff --git a/rvpn/rvpnmain/run.go b/rvpn/rvpnmain/run.go index d58832f..90c26cc 100644 --- a/rvpn/rvpnmain/run.go +++ b/rvpn/rvpnmain/run.go @@ -56,8 +56,8 @@ func Run() { connectionTable = connection.NewTable() go connectionTable.Run() go client.LaunchClientListener(connectionTable, &secretKey, &argServerBinding) - go external.LaunchWebRequestExternalListener(&argServerExternalBinding, connectionTable) - + //go external.LaunchWebRequestExternalListener(&argServerExternalBinding, connectionTable) + go external.LaunchExternalServer(argServerExternalBinding, connectionTable) err := admin.LaunchAdminListener(&argServerAdminBinding, connectionTable) if err != nil { loginfo.Println("LauchAdminListener failed: ", err)