Tcp多路复用

pull/1219/head v.0.0.6
刘河 2019-01-06 03:16:46 +08:00
parent ade3bb0c71
commit 9bec5366a6
14 changed files with 271 additions and 187 deletions

View File

@ -1,3 +1,3 @@
0,hostServer,,ts08z6vk5nc72fs8,aaa,bbb,,1,0
0,hostServer,,7n7bxc2bm1fyjfab,a,b,,1,0
8001,tunnelServer,127.0.0.1:88,jq5i7n0sjs1h0jje,aaa,bbb,,1,1
8001,tunnelServer,127.0.0.1:88,jq5i7n0sjs1h0jje,aaa,bbb,,1,0,0,0,1
0,hostServer,,ts08z6vk5nc72fs8,aaac,bbb,snappy,1,0,1,2,3
0,hostServer,,7n7bxc2bm1fyjfab,ab,b,,1,1,1,0,1

1 8001 hostServer tunnelServer 127.0.0.1:88 ts08z6vk5nc72fs8 jq5i7n0sjs1h0jje aaa bbb 1 0 0 0 1
2 0 hostServer hostServer 7n7bxc2bm1fyjfab ts08z6vk5nc72fs8 a aaac b bbb snappy 1 0 0 1 2 3
3 0 tunnelServer hostServer jq5i7n0sjs1h0jje 7n7bxc2bm1fyjfab aaa ab bbb b 127.0.0.1:88 1 8001 1 1 0 1

View File

@ -43,10 +43,10 @@ func (s *IndexController) Host() {
s.display("index/list")
}
func (s *IndexController) GetTaskList() {
func (s *IndexController) GetServerConfig() {
start, length := s.GetAjaxParams()
taskType := s.GetString("type")
list, cnt := lib.CsvDb.GetTaskList(start, length, taskType)
list, cnt := lib.CsvDb.GetServerConfig(start, length, taskType)
s.AjaxTable(list, cnt, cnt)
}
@ -56,7 +56,7 @@ func (s *IndexController) Add() {
s.SetInfo("新增")
s.display()
} else {
t := &lib.TaskList{
t := &lib.ServerConfig{
TcpPort: s.GetIntNoErr("port"),
Mode: s.GetString("type"),
Target: s.GetString("target"),
@ -64,7 +64,8 @@ func (s *IndexController) Add() {
U: s.GetString("u"),
P: s.GetString("p"),
Compress: s.GetString("compress"),
Crypt: s.GetString("crypt"),
Crypt: lib.GetBoolByStr(s.GetString("crypt")),
Mux: lib.GetBoolByStr(s.GetString("mux")),
IsRun: 0,
}
lib.CsvDb.NewTask(t)
@ -97,7 +98,8 @@ func (s *IndexController) Edit() {
t.U = s.GetString("u")
t.P = s.GetString("p")
t.Compress = s.GetString("compress")
t.Crypt = s.GetString("crypt")
t.Crypt = lib.GetBoolByStr(s.GetString("crypt"))
t.Mux = lib.GetBoolByStr(s.GetString("mux"))
lib.CsvDb.UpdateTask(t)
lib.StopServer(t.VerifyKey)
lib.StartTask(t.VerifyKey)

View File

@ -141,8 +141,8 @@ retry:
}
//得到一个tcp隧道
func (s *Tunnel) GetTunnel(cFlag string, en, de int, crypt bool) (c *Conn, err error) {
if v, ok := s.tunnelList[cFlag]; !ok || v.Len() < 10 { //新建通道
func (s *Tunnel) GetTunnel(cFlag string, en, de int, crypt, mux bool) (c *Conn, err error) {
if v, ok := s.tunnelList[cFlag]; !ok || v.Len() < 3 { //新建通道
go s.newChan(cFlag)
}
retry:
@ -150,11 +150,11 @@ retry:
return
}
c = s.tunnelList[cFlag].Pop()
if _, err := c.wTest(); err != nil {
if _, err = c.wTest(); err != nil {
c.Close()
goto retry
}
c.WriteConnInfo(en, de, crypt)
c.WriteConnInfo(en, de, crypt, mux)
return
}
@ -175,6 +175,13 @@ func (s *Tunnel) ReturnSignal(conn *Conn, cFlag string) {
}
}
//重回slice 复用
func (s *Tunnel) ReturnTunnel(conn *Conn, cFlag string) {
if v, ok := s.tunnelList[cFlag]; ok {
v.Add(conn)
}
}
//删除通信通道
func (s *Tunnel) DelClientSignal(cFlag string) {
s.delClient(cFlag, s.signalList)

View File

@ -102,27 +102,43 @@ func (s *TRPClient) dealChan() error {
c.SetAlive()
//写标志
c.wChan()
re:
//获取连接的host type(tcp or udp)
typeStr, host, en, de, crypt, err := c.GetHostFromConn()
typeStr, host, en, de, crypt, mux, err := c.GetHostFromConn()
if err != nil {
log.Println("get host info error:", err)
return err
}
//与目标建立连接
server, err := net.Dial(typeStr, host)
//与目标建立连接,超时时间为3
server, err := net.DialTimeout(typeStr, host, time.Second*3)
if err != nil {
log.Println("connect to ", host, "error:", err)
log.Println("connect to ", host, "error:", err, mux)
if mux {
s.sendEof(conn, de, crypt)
goto re
}
return err
}
go relay(NewConn(server), c, de, crypt)
relay(c, NewConn(server), en, crypt)
go relay(NewConn(server), c, de, crypt, mux)
relay(c, NewConn(server), en, crypt, mux)
if mux {
goto re
}
return nil
}
func (s *TRPClient) sendEof(c net.Conn, de int, crypt bool) {
switch de {
case COMPRESS_SNAPY_DECODE:
NewSnappyConn(c, crypt).Write([]byte(IO_EOF))
case COMPRESS_NONE_DECODE:
NewCryptConn(c, crypt).Write([]byte(IO_EOF))
}
}
//http模式处理
func (s *TRPClient) dealHttp(c *Conn) error {
buf := make([]byte, 1024*32)
en, de, crypt := c.GetConnInfoFromConn()
en, de, crypt, _ := c.GetConnInfoFromConn()
n, err := c.ReadFrom(buf, de, crypt)
if err != nil {
c.wError()

View File

@ -45,6 +45,12 @@ func (s *CryptConn) Write(b []byte) (n int, err error) {
//解密读
func (s *CryptConn) Read(b []byte) (n int, err error) {
defer func() {
if string(b[:n]) == IO_EOF {
err = io.EOF
n = 0
}
}()
if s.crypt {
var lens int
var buf, bs []byte
@ -62,7 +68,8 @@ func (s *CryptConn) Read(b []byte) (n int, err error) {
copy(b, bs)
return
}
return s.conn.Read(b)
n, err = s.conn.Read(b)
return
}
type SnappyConn struct {
@ -97,6 +104,12 @@ func (s *SnappyConn) Write(b []byte) (n int, err error) {
//snappy压缩读 包含解密
func (s *SnappyConn) Read(b []byte) (n int, err error) {
defer func() {
if string(b[:n]) == IO_EOF {
err = io.EOF
n = 0
}
}()
if n, err = s.r.Read(b); err != nil {
return
}
@ -160,14 +173,14 @@ func (s *Conn) ReadFlag() (string, error) {
}
//读取host 连接地址 压缩类型
func (s *Conn) GetHostFromConn() (typeStr string, host string, en, de int, crypt bool, err error) {
func (s *Conn) GetHostFromConn() (typeStr string, host string, en, de int, crypt, mux bool, err error) {
retry:
lType, err := s.ReadLen(3)
if err != nil {
return
}
if typeStr = string(lType); typeStr == TEST_FLAG {
en, de, crypt = s.GetConnInfoFromConn()
en, de, crypt, mux = s.GetConnInfoFromConn()
goto retry
}
cLen, err := s.GetLen()
@ -245,13 +258,13 @@ func (s *Conn) WriteTo(b []byte, compress int, crypt bool) (n int, err error) {
}
//写压缩方式,加密
func (s *Conn) WriteConnInfo(en, de int, crypt bool) {
s.Write([]byte(strconv.Itoa(en) + strconv.Itoa(de) + GetStrByBool(crypt)))
func (s *Conn) WriteConnInfo(en, de int, crypt, mux bool) {
s.Write([]byte(strconv.Itoa(en) + strconv.Itoa(de) + GetStrByBool(crypt) + GetStrByBool(mux)))
}
//获取压缩方式,是否加密
func (s *Conn) GetConnInfoFromConn() (en, de int, crypt bool) {
buf, err := s.ReadLen(3)
func (s *Conn) GetConnInfoFromConn() (en, de int, crypt, mux bool) {
buf, err := s.ReadLen(4)
//TODO错误处理
if err != nil {
return
@ -259,6 +272,7 @@ func (s *Conn) GetConnInfoFromConn() (en, de int, crypt bool) {
en, _ = strconv.Atoi(string(buf[0]))
de, _ = strconv.Atoi(string(buf[1]))
crypt = GetBoolByStr(string(buf[2]))
mux = GetBoolByStr(string(buf[3]))
return
}

View File

@ -10,18 +10,21 @@ import (
"strconv"
)
type TaskList struct {
TcpPort int //服务端与客户端通信端口
Mode string //启动方式
Target string //目标
VerifyKey string //flag
U string //socks5验证用户名
P string //socks5验证密码
Compress string //压缩方式
Start int //是否开启
IsRun int //是否在运行
ClientStatus int //客户端状态
Crypt string //是否加密
type ServerConfig struct {
TcpPort int //服务端与客户端通信端口
Mode string //启动方式
Target string //目标
VerifyKey string //flag
U string //socks5验证用户名
P string //socks5验证密码
Compress string //压缩方式
Start int //是否开启
IsRun int //是否在运行
ClientStatus int //客s户端状态
Crypt bool //是否加密
Mux bool //是否加密
CompressEncode int
CompressDecode int
}
type HostList struct {
@ -39,7 +42,7 @@ func NewCsv(path string, bridge *Tunnel, runList map[string]interface{}) *Csv {
}
type Csv struct {
Tasks []*TaskList
Tasks []*ServerConfig
Path string
Bridge *Tunnel
RunList map[string]interface{}
@ -69,7 +72,10 @@ func (s *Csv) StoreTasksToCsv() {
task.P,
task.Compress,
strconv.Itoa(task.Start),
task.Crypt,
GetStrByBool(task.Crypt),
GetStrByBool(task.Mux),
strconv.Itoa(task.CompressEncode),
strconv.Itoa(task.CompressDecode),
}
err := writer.Write(record)
if err != nil {
@ -98,21 +104,24 @@ func (s *Csv) LoadTaskFromCsv() {
if err != nil {
panic(err)
}
var tasks []*TaskList
var tasks []*ServerConfig
// 将每一行数据保存到内存slice中
for _, item := range records {
tcpPort, _ := strconv.Atoi(item[0])
Start, _ := strconv.Atoi(item[7])
post := &TaskList{
TcpPort: tcpPort,
Mode: item[1],
Target: item[2],
VerifyKey: item[3],
U: item[4],
P: item[5],
Compress: item[6],
Start: Start,
Crypt: item[8],
post := &ServerConfig{
TcpPort: tcpPort,
Mode: item[1],
Target: item[2],
VerifyKey: item[3],
U: item[4],
P: item[5],
Compress: item[6],
Start: Start,
Crypt: GetBoolByStr(item[8]),
Mux: GetBoolByStr(item[9]),
CompressEncode: GetIntNoerrByStr(item[10]),
CompressDecode: GetIntNoerrByStr(item[11]),
}
tasks = append(tasks, post)
}
@ -177,8 +186,8 @@ func (s *Csv) LoadHostFromCsv() {
s.Hosts = hosts
}
func (s *Csv) GetTaskList(start, length int, typeVal string) ([]*TaskList, int) {
list := make([]*TaskList, 0)
func (s *Csv) GetServerConfig(start, length int, typeVal string) ([]*ServerConfig, int) {
list := make([]*ServerConfig, 0)
var cnt int
for _, v := range s.Tasks {
if v.Mode != typeVal {
@ -209,12 +218,12 @@ func (s *Csv) GetTaskList(start, length int, typeVal string) ([]*TaskList, int)
return list, cnt
}
func (s *Csv) NewTask(t *TaskList) {
func (s *Csv) NewTask(t *ServerConfig) {
s.Tasks = append(s.Tasks, t)
s.StoreTasksToCsv()
}
func (s *Csv) UpdateTask(t *TaskList) error {
func (s *Csv) UpdateTask(t *ServerConfig) error {
for k, v := range s.Tasks {
if v.VerifyKey == t.VerifyKey {
s.Tasks = append(s.Tasks[:k], s.Tasks[k+1:]...)
@ -246,7 +255,7 @@ func (s *Csv) DelTask(vKey string) error {
return errors.New("不存在")
}
func (s *Csv) GetTask(vKey string) (v *TaskList, err error) {
func (s *Csv) GetTask(vKey string) (v *ServerConfig, err error) {
for _, v = range s.Tasks {
if v.VerifyKey == vKey {
return

View File

@ -16,11 +16,12 @@ var (
rpMode = flag.String("mode", "client", "启动模式")
tunnelTarget = flag.String("target", "10.1.50.203:80", "远程目标")
verifyKey = flag.String("vkey", "", "验证密钥")
u = flag.String("u", "", "socks5验证用户名")
p = flag.String("p", "", "socks5验证密码")
u = flag.String("u", "", "验证用户名(socks5和web)")
p = flag.String("p", "", "验证密码(socks5和web)")
compress = flag.String("compress", "", "数据压缩方式snappy")
serverAddr = flag.String("server", "", "服务器地址ip:端口")
crypt = flag.String("crypt", "", "是否加密(1|0)")
crypt = flag.String("crypt", "false", "是否加密(true|false)")
mux = flag.String("mux", "false", "是否TCP多路复用(true|false)")
config Config
err error
RunList map[string]interface{} //运行中的任务
@ -36,7 +37,6 @@ func init() {
func InitMode() {
flag.Parse()
de, en := getCompressType(*compress)
if *rpMode == "client" {
JsonParse := NewJsonStruct()
if config, err = JsonParse.Load(*configPath); err != nil {
@ -54,7 +54,25 @@ func InitMode() {
log.Fatalln("服务端开启失败", err)
}
log.Println("服务端启动监听tcp服务端端口", *TcpPort)
if svr := newMode(*rpMode, bridge, *httpPort, *tunnelTarget, *u, *p, en, de, *verifyKey, *crypt); svr != nil {
cnf := ServerConfig{
TcpPort: *httpPort,
Mode: *rpMode,
Target: *tunnelTarget,
VerifyKey: *verifyKey,
U: *u,
P: *p,
Compress: *compress,
Start: 0,
IsRun: 0,
ClientStatus: 0,
Crypt: GetBoolByStr(*crypt),
Mux: GetBoolByStr(*mux),
CompressEncode: 0,
CompressDecode: 0,
}
cnf.CompressDecode, cnf.CompressEncode = getCompressType(cnf.Compress)
if svr := newMode(bridge, &cnf);
svr != nil {
reflect.ValueOf(svr).MethodByName("Start").Call(nil)
} else {
log.Fatalln("启动模式不正确")
@ -73,26 +91,25 @@ func InitFromCsv() {
}
}
func newMode(mode string, bridge *Tunnel, httpPort int, tunnelTarget string, u string, p string, enCompress int, deCompress int, vkey string, crypt string) interface{} {
bCrypt := GetBoolByStr(crypt)
switch mode {
func newMode(bridge *Tunnel, config *ServerConfig) interface{} {
switch config.Mode {
case "httpServer":
return NewHttpModeServer(httpPort, bridge, enCompress, deCompress, vkey, bCrypt)
return NewHttpModeServer(bridge, config)
case "tunnelServer":
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessTunnel, bridge, enCompress, deCompress, vkey, u, p, bCrypt)
case "sock5Server":
return NewSock5ModeServer(httpPort, u, p, bridge, enCompress, deCompress, vkey, bCrypt)
return NewTunnelModeServer(ProcessTunnel, bridge, config)
case "socks5Server":
return NewSock5ModeServer(bridge, config)
case "httpProxyServer":
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessHttp, bridge, enCompress, deCompress, vkey, u, p, bCrypt)
return NewTunnelModeServer(ProcessHttp, bridge, config)
case "udpServer":
return NewUdpModeServer(httpPort, tunnelTarget, bridge, enCompress, deCompress, vkey, bCrypt)
return NewUdpModeServer(bridge, config)
case "webServer":
InitCsvDb()
return NewWebServer(bridge)
case "hostServer":
return NewHostServer(bCrypt)
return NewHostServer(config)
case "httpHostServer":
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessHost, bridge, enCompress, deCompress, vkey, u, p, bCrypt)
return NewTunnelModeServer(ProcessHost, bridge, config)
}
return nil
}
@ -116,9 +133,9 @@ func StopServer(cFlag string) error {
return errors.New("未在运行中")
}
func AddTask(t *TaskList) error {
de, en := getCompressType(t.Compress)
if svr := newMode(t.Mode, bridge, t.TcpPort, t.Target, t.U, t.P, en, de, t.VerifyKey, t.Crypt); svr != nil {
func AddTask(t *ServerConfig) error {
t.CompressDecode, t.CompressEncode = getCompressType(t.Compress)
if svr := newMode(bridge, t); svr != nil {
RunList[t.VerifyKey] = svr
go func() {
err := reflect.ValueOf(svr).MethodByName("Start").Call(nil)[0]

View File

@ -44,16 +44,10 @@ const (
)
type Sock5ModeServer struct {
bridge *Tunnel
httpPort int
u string //用户名
p string //密码
enCompress int
deCompress int
isVerify bool
listener net.Listener
vKey string
crypt bool
bridge *Tunnel
isVerify bool
listener net.Listener
config *ServerConfig
}
//req
@ -140,10 +134,9 @@ func (s *Sock5ModeServer) doConnect(c net.Conn, command uint8) (proxyConn *Conn,
binary.Read(c, binary.BigEndian, &port)
// connect to host
addr := net.JoinHostPort(host, strconv.Itoa(int(port)))
client, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress, s.crypt)
client, err := s.bridge.GetTunnel(getverifyval(s.config.VerifyKey), s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
if err != nil {
log.Println(err)
client.Close()
return
}
s.sendReply(c, succeeded)
@ -164,8 +157,11 @@ func (s *Sock5ModeServer) handleConnect(c net.Conn) {
log.Println(err)
c.Close()
} else {
go relay(proxyConn, NewConn(c), s.enCompress, s.crypt)
go relay(NewConn(c), proxyConn, s.deCompress, s.crypt)
go relay(proxyConn, NewConn(c), s.config.CompressEncode, s.config.Crypt, s.config.Mux)
relay(NewConn(c), proxyConn, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
if s.config.Mux {
s.bridge.ReturnTunnel(proxyConn, getverifyval(s.config.VerifyKey))
}
}
}
@ -198,8 +194,11 @@ func (s *Sock5ModeServer) handleUDP(c net.Conn) {
if err != nil {
c.Close()
} else {
go relay(proxyConn, NewConn(c), s.enCompress, s.crypt)
go relay(NewConn(c), proxyConn, s.deCompress, s.crypt)
go relay(proxyConn, NewConn(c), s.config.CompressEncode, s.config.Crypt, s.config.Mux)
relay(NewConn(c), proxyConn, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
if s.config.Mux {
s.bridge.ReturnTunnel(proxyConn, getverifyval(s.config.VerifyKey))
}
}
}
@ -262,7 +261,7 @@ func (s *Sock5ModeServer) Auth(c net.Conn) error {
if _, err := io.ReadAtLeast(c, pass, passLen); err != nil {
return err
}
if string(pass) == s.p && string(user) == s.u {
if string(pass) == s.config.U && string(user) == s.config.P {
if _, err := c.Write([]byte{userAuthVersion, authSuccess}); err != nil {
return err
}
@ -278,7 +277,7 @@ func (s *Sock5ModeServer) Auth(c net.Conn) error {
//start
func (s *Sock5ModeServer) Start() error {
s.listener, err = net.Listen("tcp", ":"+strconv.Itoa(s.httpPort))
s.listener, err = net.Listen("tcp", ":"+strconv.Itoa(s.config.TcpPort))
if err != nil {
return err
}
@ -301,20 +300,14 @@ func (s *Sock5ModeServer) Close() error {
}
//new
func NewSock5ModeServer(httpPort int, u, p string, brige *Tunnel, enCompress int, deCompress int, vKey string, crypt bool) *Sock5ModeServer {
func NewSock5ModeServer(bridge *Tunnel, cnf *ServerConfig) *Sock5ModeServer {
s := new(Sock5ModeServer)
s.httpPort = httpPort
s.bridge = brige
if u != "" && p != "" {
s.bridge = bridge
s.config = cnf
if s.config.U != "" && s.config.P != "" {
s.isVerify = true
s.u = u
s.p = p
} else {
s.isVerify = false
}
s.enCompress = enCompress
s.deCompress = deCompress
s.vKey = vKey
s.crypt = crypt
return s
}

View File

@ -33,23 +33,15 @@ WWW-Authenticate: Basic realm="easyProxy"
type process func(c *Conn, s *TunnelModeServer) error
type HttpModeServer struct {
bridge *Tunnel
httpPort int
enCompress int
deCompress int
vKey string
crypt bool
bridge *Tunnel
config *ServerConfig
}
//http
func NewHttpModeServer(httpPort int, bridge *Tunnel, enCompress int, deCompress int, vKey string, crypt bool) *HttpModeServer {
func NewHttpModeServer(bridge *Tunnel, cnf *ServerConfig) *HttpModeServer {
s := new(HttpModeServer)
s.bridge = bridge
s.httpPort = httpPort
s.enCompress = enCompress
s.deCompress = deCompress
s.vKey = vKey
s.crypt = crypt
s.config = cnf
return s
}
@ -65,7 +57,7 @@ func (s *HttpModeServer) Start() {
w.Write([]byte("401 Unauthorized\n"))
return
}
err, conn := s.bridge.GetSignal(getverifyval(s.vKey))
err, conn := s.bridge.GetSignal(getverifyval(s.config.VerifyKey))
if err != nil {
BadRequest(w)
return
@ -83,9 +75,9 @@ func (s *HttpModeServer) Start() {
goto retry
return
}
s.bridge.ReturnSignal(conn, getverifyval(s.vKey))
s.bridge.ReturnSignal(conn, getverifyval(s.config.VerifyKey))
})
log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", s.httpPort), nil))
log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", s.config.TcpPort), nil))
}
//req转为bytes发送给client端
@ -95,8 +87,8 @@ func (s *HttpModeServer) writeRequest(r *http.Request, conn *Conn) error {
return err
}
conn.wSign()
conn.WriteConnInfo(s.enCompress, s.deCompress, s.crypt)
c, err := conn.WriteTo(raw, s.enCompress, s.crypt)
conn.WriteConnInfo(s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
c, err := conn.WriteTo(raw, s.config.CompressEncode, s.config.Crypt)
if err != nil {
return err
}
@ -115,7 +107,7 @@ func (s *HttpModeServer) writeResponse(w http.ResponseWriter, c *Conn) error {
switch flags {
case RES_SIGN:
buf := make([]byte, 1024*1024*32)
n, err := c.ReadFrom(buf, s.deCompress, s.crypt)
n, err := c.ReadFrom(buf, s.config.CompressDecode, s.config.Crypt)
if err != nil {
return err
}
@ -145,38 +137,24 @@ func (s *HttpModeServer) writeResponse(w http.ResponseWriter, c *Conn) error {
}
type TunnelModeServer struct {
httpPort int
tunnelTarget string
process process
bridge *Tunnel
listener *net.TCPListener
enCompress int
deCompress int
basicUser string
basicPassword string
vKey string
crypt bool
process process
bridge *Tunnel
config *ServerConfig
listener *net.TCPListener
}
//tcp|http|host
func NewTunnelModeServer(httpPort int, tunnelTarget string, process process, bridge *Tunnel, enCompress, deCompress int, vKey, basicUser, basicPasswd string, crypt bool) *TunnelModeServer {
func NewTunnelModeServer(process process, bridge *Tunnel, cnf *ServerConfig) *TunnelModeServer {
s := new(TunnelModeServer)
s.httpPort = httpPort
s.bridge = bridge
s.tunnelTarget = tunnelTarget
s.process = process
s.enCompress = enCompress
s.deCompress = deCompress
s.vKey = vKey
s.basicUser = basicUser
s.basicPassword = basicPasswd
s.crypt = crypt
s.config = cnf
return s
}
//开始
func (s *TunnelModeServer) Start() error {
s.listener, err = net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), s.httpPort, ""})
s.listener, err = net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), s.config.TcpPort, ""})
if err != nil {
return err
}
@ -205,14 +183,19 @@ func (s *TunnelModeServer) auth(r *http.Request, c *Conn, u, p string) error {
}
//与客户端建立通道
func (s *TunnelModeServer) dealClient(vKey string, en, de int, c *Conn, target string, method string, rb []byte) error {
link, err := s.bridge.GetTunnel(getverifyval(vKey), en, de, s.crypt)
func (s *TunnelModeServer) dealClient(c *Conn, cnf *ServerConfig, addr string, method string, rb []byte) error {
link, err := s.bridge.GetTunnel(getverifyval(cnf.VerifyKey), cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
defer func() {
if cnf.Mux {
s.bridge.ReturnTunnel(link, getverifyval(cnf.VerifyKey))
}
}()
if err != nil {
log.Println(err)
c.Close()
return err
}
if _, err := link.WriteHost(CONN_TCP, target); err != nil {
if _, err := link.WriteHost(CONN_TCP, addr); err != nil {
c.Close()
link.Close()
log.Println(err)
@ -221,10 +204,10 @@ func (s *TunnelModeServer) dealClient(vKey string, en, de int, c *Conn, target s
if method == "CONNECT" {
fmt.Fprint(c, "HTTP/1.1 200 Connection established\r\n")
} else {
link.WriteTo(rb, en, s.crypt)
link.WriteTo(rb, cnf.CompressEncode, cnf.Crypt)
}
go relay(link, c, en, s.crypt)
relay(c, link, de, s.crypt)
go relay(link, c, cnf.CompressEncode, cnf.Crypt, cnf.Mux)
relay(c, link, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
return nil
}
@ -237,11 +220,11 @@ func (s *TunnelModeServer) Close() error {
func ProcessTunnel(c *Conn, s *TunnelModeServer) error {
method, _, rb, err, r := c.GetHost()
if err == nil {
if err := s.auth(r, c, s.basicUser, s.basicPassword); err != nil {
if err := s.auth(r, c, s.config.U, s.config.P); err != nil {
return err
}
}
return s.dealClient(s.vKey, s.enCompress, s.deCompress, c, s.tunnelTarget, method, rb)
return s.dealClient(c, s.config, s.config.Target, method, rb)
}
//http代理模式
@ -251,10 +234,11 @@ func ProcessHttp(c *Conn, s *TunnelModeServer) error {
c.Close()
return err
}
if err := s.auth(r, c, s.basicUser, s.basicPassword); err != nil {
if err := s.auth(r, c, s.config.U, s.config.P); err != nil {
return err
}
return s.dealClient(s.vKey, s.enCompress, s.deCompress, c, addr, method, rb)
//TODO效率问题
return s.dealClient(c, s.config, addr, method, rb)
}
//多客户端域名代理
@ -272,8 +256,7 @@ func ProcessHost(c *Conn, s *TunnelModeServer) error {
c.Close()
return err
}
de, en := getCompressType(task.Compress)
return s.dealClient(host.Vkey, en, de, c, host.Target, method, rb)
return s.dealClient(c, task, host.Target, method, rb)
}
//web管理方式
@ -285,7 +268,7 @@ type WebServer struct {
func (s *WebServer) Start() {
InitFromCsv()
p, _ := beego.AppConfig.Int("hostPort")
t := &TaskList{
t := &ServerConfig{
TcpPort: p,
Mode: "httpHostServer",
Target: "",
@ -312,7 +295,7 @@ func NewWebServer(bridge *Tunnel) *WebServer {
//host
type HostServer struct {
crypt bool
config *ServerConfig
}
//开始
@ -321,9 +304,9 @@ func (s *HostServer) Start() error {
}
//TODOhost模式的客户端无需指定和监听端口等
func NewHostServer(crypt bool) *HostServer {
func NewHostServer(cnf *ServerConfig) *HostServer {
s := new(HostServer)
s.crypt = crypt
s.config = cnf
return s
}

View File

@ -9,33 +9,23 @@ import (
)
type UdpModeServer struct {
bridge *Tunnel
udpPort int //监听的udp端口
tunnelTarget string //udp目标地址
listener *net.UDPConn
udpMap map[string]*Conn
enCompress int
deCompress int
vKey string
crypt bool
bridge *Tunnel
listener *net.UDPConn
udpMap map[string]*Conn
config *ServerConfig
}
func NewUdpModeServer(udpPort int, tunnelTarget string, bridge *Tunnel, enCompress int, deCompress int, vKey string, crypt bool) *UdpModeServer {
func NewUdpModeServer(bridge *Tunnel, cnf *ServerConfig) *UdpModeServer {
s := new(UdpModeServer)
s.udpPort = udpPort
s.tunnelTarget = tunnelTarget
s.bridge = bridge
s.udpMap = make(map[string]*Conn)
s.enCompress = enCompress
s.deCompress = deCompress
s.vKey = vKey
s.crypt = crypt
s.config = cnf
return s
}
//开始
func (s *UdpModeServer) Start() error {
s.listener, err = net.ListenUDP("udp", &net.UDPAddr{net.ParseIP("0.0.0.0"), s.udpPort, ""})
s.listener, err = net.ListenUDP("udp", &net.UDPAddr{net.ParseIP("0.0.0.0"), s.config.TcpPort, ""})
if err != nil {
return err
}
@ -55,20 +45,25 @@ func (s *UdpModeServer) Start() error {
//TODO:效率问题有待解决
func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
conn, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress, s.crypt)
conn, err := s.bridge.GetTunnel(getverifyval(s.config.VerifyKey), s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
if err != nil {
log.Println(err)
return
}
if _, err := conn.WriteHost(CONN_UDP, s.tunnelTarget); err != nil {
if _, err := conn.WriteHost(CONN_UDP, s.config.Target); err != nil {
conn.Close()
return
}
conn.WriteTo(data, s.enCompress,s.crypt)
conn.WriteTo(data, s.config.CompressEncode, s.config.Crypt)
go func(addr *net.UDPAddr, conn *Conn) {
defer func() {
if s.config.Mux {
s.bridge.ReturnTunnel(conn, getverifyval(s.config.VerifyKey))
}
}()
buf := make([]byte, 1024)
conn.conn.SetReadDeadline(time.Now().Add(time.Duration(time.Second * 3)))
n, err := conn.ReadFrom(buf, s.deCompress,s.crypt)
n, err := conn.ReadFrom(buf, s.config.CompressDecode, s.config.Crypt)
if err != nil || err == io.EOF {
conn.Close()
return

View File

@ -27,6 +27,7 @@ const (
COMPRESS_NONE_DECODE
COMPRESS_SNAPY_ENCODE
COMPRESS_SNAPY_DECODE
IO_EOF = "EOF"
)
//error
@ -130,19 +131,35 @@ func replaceHost(resp []byte) []byte {
}
//copy
func relay(in, out *Conn, compressType int, crypt bool) {
func relay(in, out *Conn, compressType int, crypt, mux bool) {
switch compressType {
case COMPRESS_SNAPY_ENCODE:
copyBuffer(NewSnappyConn(in.conn, crypt), out)
if mux {
NewSnappyConn(in.conn, crypt).Write([]byte(IO_EOF))
out.Close()
}
case COMPRESS_SNAPY_DECODE:
copyBuffer(in, NewSnappyConn(out.conn, crypt))
if mux {
in.Close()
}
case COMPRESS_NONE_ENCODE:
copyBuffer(NewCryptConn(in.conn, crypt), out)
if mux {
NewCryptConn(in.conn, crypt).Write([]byte(IO_EOF))
out.Close()
}
case COMPRESS_NONE_DECODE:
copyBuffer(in, NewCryptConn(out.conn, crypt))
if mux {
in.Close()
}
}
if !mux {
in.Close()
out.Close()
}
out.Close()
in.Close()
}
//判断压缩方式
@ -183,7 +200,7 @@ func verify(verifyKeyMd5 string) bool {
}
//get key by host from x
func getKeyByHost(host string) (h *HostList, t *TaskList, err error) {
func getKeyByHost(host string) (h *HostList, t *ServerConfig, err error) {
for _, v := range CsvDb.Hosts {
if strings.Contains(host, v.Host) {
h = v
@ -258,6 +275,10 @@ func GetStrByBool(b bool) string {
}
return "0"
}
func GetIntNoerrByStr(str string) int {
i, _ := strconv.Atoi(str)
return i
}
// io.copy的优化版读取buffer长度原为32*1024与snappy不同导致读取出的内容存在差异不利于解密特此修改
func copyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {

View File

@ -44,6 +44,13 @@
<option value="1"></option>
</select>
</div>
<div class="form-group" id="compress">
<label class="control-label">TCP</label>
<select class="form-control" name="crypt">
<option value="0"></option>
<option value="1"></option>
</select>
</div>
<div class="form-group" id="u">
<label class="control-label">(socks5,web穿)</label>
<input class="form-control" type="text" name="u" placeholder="不填则无需验证">

View File

@ -35,8 +35,15 @@
<div class="form-group" id="compress">
<label class="control-label">()</label>
<select class="form-control" name="crypt">
<option {{if eq "0" .t.Crypt}}selected{{end}} value="0"></option>
<option {{if eq "1" .t.Crypt}}selected{{end}} value="1"></option>
<option {{if eq false .t.Crypt}}selected{{end}} value="0"></option>
<option {{if eq true .t.Crypt}}selected{{end}} value="1"></option>
</select>
</div>
<div class="form-group" id="compress">
<label class="control-label">TCP()</label>
<select class="form-control" name="mux">
<option {{if eq false .t.Mux}}selected{{end}} value="0"></option>
<option {{if eq true .t.Mux}}selected{{end}} value="1"></option>
</select>
</div>
<div class="form-group" id="u">

View File

@ -11,6 +11,7 @@
<th></th>
<th></th>
<th></th>
<th>TCP</th>
<th></th>
<th></th>
<th></th>
@ -97,7 +98,7 @@
autoWidth: false,
ordering: false,
ajax: {
url: '/index/gettasklist?type={{.type}}',
url: '/index/getserverconfig?type={{.type}}',
type: 'POST'
},
dom: '<"top"fl><"toolbar">rt<"bottom"ip><"clear">',
@ -108,6 +109,7 @@
{data: 'VerifyKey'},
{data: 'Compress'},
{data: 'Crypt'},
{data: 'Mux'},
{data: 'U'},
{data: 'P'},
{data: 'ClientStatus'},
@ -149,7 +151,7 @@
}
},
{
targets: -6,
targets: -7,
render: function (data, type, row, meta) {
if (data == "0") {
return "不加密"
@ -158,6 +160,17 @@
}
}
},
{
targets: -6,
render: function (data, type, row, meta) {
if (data == "0") {
return "不启用"
} else {
return "启用"
}
}
}
,
{
targets: 2,
render: function (data, type, row, meta) {