telebit/rvpn/external/server.go

175 lines
3.9 KiB
Go

package external
import (
"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
}
}
}
}