Port mux| https|tls crypt

This commit is contained in:
刘河
2019-03-05 09:23:18 +08:00
parent a29a7d4923
commit f81fb7760e
39 changed files with 706 additions and 251 deletions

63
lib/mux/pconn.go Normal file
View File

@@ -0,0 +1,63 @@
package mux
import (
"net"
"time"
)
type PortConn struct {
Conn net.Conn
rs []byte
start int
}
func newPortConn(conn net.Conn, rs []byte) *PortConn {
return &PortConn{
Conn: conn,
rs: rs,
}
}
func (pConn *PortConn) Read(b []byte) (n int, err error) {
if len(b) < len(pConn.rs)-pConn.start {
defer func() {
pConn.start = pConn.start + len(b)
}()
return copy(b, pConn.rs), nil
}
if pConn.start < len(pConn.rs) {
defer func() {
pConn.start = len(pConn.rs)
}()
return copy(b, pConn.rs[pConn.start:]), nil
}
return pConn.Conn.Read(b)
}
func (pConn *PortConn) Write(b []byte) (n int, err error) {
return pConn.Conn.Write(b)
}
func (pConn *PortConn) Close() error {
return pConn.Conn.Close()
}
func (pConn *PortConn) LocalAddr() net.Addr {
return pConn.Conn.LocalAddr()
}
func (pConn *PortConn) RemoteAddr() net.Addr {
return pConn.Conn.RemoteAddr()
}
func (pConn *PortConn) SetDeadline(t time.Time) error {
return pConn.Conn.SetDeadline(t)
}
func (pConn *PortConn) SetReadDeadline(t time.Time) error {
return pConn.Conn.SetReadDeadline(t)
}
func (pConn *PortConn) SetWriteDeadline(t time.Time) error {
return pConn.Conn.SetWriteDeadline(t)
}

44
lib/mux/plistener.go Normal file
View File

@@ -0,0 +1,44 @@
package mux
import (
"errors"
"net"
)
type PortListener struct {
net.Listener
connCh chan *PortConn
addr net.Addr
isClose bool
}
func NewPortListener(connCh chan *PortConn, addr net.Addr) *PortListener {
return &PortListener{
connCh: connCh,
addr: addr,
}
}
func (pListener *PortListener) Accept() (net.Conn, error) {
if pListener.isClose {
return nil, errors.New("the listener has closed")
}
conn := <-pListener.connCh
if conn != nil {
return conn, nil
}
return nil, errors.New("the listener has closed")
}
func (pListener *PortListener) Close() error {
//close
if pListener.isClose {
return errors.New("the listener has closed")
}
pListener.isClose = true
return nil
}
func (pListener *PortListener) Addr() net.Addr {
return pListener.addr
}

163
lib/mux/pmux.go Normal file
View File

@@ -0,0 +1,163 @@
// This module is used for port reuse
// Distinguish client, web manager , HTTP and HTTPS according to the difference of protocol
package mux
import (
"bufio"
"bytes"
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
"github.com/pkg/errors"
"io"
"net"
"strconv"
"strings"
)
const (
HTTP_GET = 716984
HTTP_POST = 807983
HTTP_HEAD = 726965
HTTP_PUT = 808585
HTTP_DELETE = 686976
HTTP_CONNECT = 677978
HTTP_OPTIONS = 798084
HTTP_TRACE = 848265
CLIENT = 848384
)
type PortMux struct {
net.Listener
port int
isClose bool
managerHost string
clientConn chan *PortConn
httpConn chan *PortConn
httpsConn chan *PortConn
managerConn chan *PortConn
}
func NewPortMux(port int, managerHost string) *PortMux {
pMux := &PortMux{
managerHost: managerHost,
port: port,
clientConn: make(chan *PortConn),
httpConn: make(chan *PortConn),
httpsConn: make(chan *PortConn),
managerConn: make(chan *PortConn),
}
pMux.Start()
return pMux
}
func (pMux *PortMux) Start() error {
// Port multiplexing is based on TCP only
tcpAddr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:"+strconv.Itoa(pMux.port))
if err != nil {
return err
}
pMux.Listener, err = net.ListenTCP("tcp", tcpAddr)
if err != nil {
return err
}
go func() {
for {
conn, err := pMux.Listener.Accept()
if err != nil {
logs.Warn(err)
//close
pMux.Close()
}
go pMux.process(conn)
}
}()
return nil
}
func (pMux *PortMux) process(conn net.Conn) {
// Recognition according to different signs
// read 3 byte
buf := make([]byte, 3)
if n, err := io.ReadFull(conn, buf); err != nil || n != 3 {
return
}
var ch chan *PortConn
var rs []byte
var buffer bytes.Buffer
switch bytesToNum(buf) {
case HTTP_CONNECT, HTTP_DELETE, HTTP_GET, HTTP_HEAD, HTTP_OPTIONS, HTTP_POST, HTTP_PUT, HTTP_TRACE: //http and manager
buffer.Reset()
r := bufio.NewReader(conn)
buffer.Write(buf)
for {
b, _, err := r.ReadLine()
if err != nil {
logs.Warn("read line error", err.Error())
conn.Close()
break
}
buffer.Write(b)
buffer.Write([]byte("\r\n"))
if strings.Index(string(b), "Host:") == 0 || strings.Index(string(b), "host:") == 0 {
// Remove host and space effects
str := strings.Replace(string(b), "Host:", "", -1)
str = strings.Replace(str, "host:", "", -1)
str = strings.TrimSpace(str)
// Determine whether it is the same as the manager domain name
if str == pMux.managerHost {
ch = pMux.managerConn
} else {
ch = pMux.httpConn
}
b, _ := r.Peek(r.Buffered())
buffer.Write(b)
rs = buffer.Bytes()
break
}
}
case CLIENT: // client connection
ch = pMux.clientConn
default: // https
ch = pMux.httpsConn
}
if len(rs) == 0 {
rs = buf
}
ch <- newPortConn(conn, rs)
}
func (pMux *PortMux) Close() error {
if pMux.isClose {
return errors.New("the port mux has closed")
}
pMux.isClose = true
close(pMux.clientConn)
close(pMux.httpsConn)
close(pMux.httpConn)
close(pMux.managerConn)
return pMux.Listener.Close()
}
func (pMux *PortMux) GetClientListener() net.Listener {
return NewPortListener(pMux.clientConn, pMux.Listener.Addr())
}
func (pMux *PortMux) GetHttpListener() net.Listener {
return NewPortListener(pMux.httpConn, pMux.Listener.Addr())
}
func (pMux *PortMux) GetHttpsListener() net.Listener {
return NewPortListener(pMux.httpsConn, pMux.Listener.Addr())
}
func (pMux *PortMux) GetManagerListener() net.Listener {
return NewPortListener(pMux.managerConn, pMux.Listener.Addr())
}
func bytesToNum(b []byte) int {
var str string
for i := 0; i < len(b); i++ {
str += strconv.Itoa(int(b[i]))
}
x, _ := strconv.Atoi(str)
return int(x)
}

39
lib/mux/pmux_test.go Normal file
View File

@@ -0,0 +1,39 @@
package mux
import (
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
"testing"
"time"
)
func TestPortMux_Close(t *testing.T) {
logs.Reset()
logs.EnableFuncCallDepth(true)
logs.SetLogFuncCallDepth(3)
pMux := NewPortMux(8888)
go func() {
if pMux.Start() != nil {
logs.Warn("Error")
}
}()
time.Sleep(time.Second * 3)
go func() {
l := pMux.GetHttpsAccept()
conn, err := l.Accept()
logs.Warn(conn, err)
}()
go func() {
l := pMux.GetHttpAccept()
conn, err := l.Accept()
logs.Warn(conn, err)
}()
go func() {
l := pMux.GetClientAccept()
conn, err := l.Accept()
logs.Warn(conn, err)
}()
l := pMux.GetManagerAccept()
conn, err := l.Accept()
logs.Warn(conn, err)
}