Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>

This commit is contained in:
arraykeys@gmail.com
2017-12-01 18:01:59 +08:00
parent 0247c4701d
commit 4b35219c27
4 changed files with 165 additions and 274 deletions

View File

@ -103,17 +103,17 @@ func initConfig() (err error) {
udpArgs.Local = udp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String() udpArgs.Local = udp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
//########mux-server######### //########mux-server#########
muxServer := app.Command("server", "proxy on mux server mode") muxServer := app.Command("server", "proxy on mux server mode").Hidden()
muxServerArgs.Parent = muxServer.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String() muxServerArgs.Parent = muxServer.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
muxServerArgs.CertFile = muxServer.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() muxServerArgs.CertFile = muxServer.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
muxServerArgs.KeyFile = muxServer.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() muxServerArgs.KeyFile = muxServer.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
muxServerArgs.Timeout = muxServer.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int() muxServerArgs.Timeout = muxServer.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
muxServerArgs.IsUDP = muxServer.Flag("udp", "proxy on udp mux server mode").Default("false").Bool() muxServerArgs.IsUDP = muxServer.Flag("udp", "proxy on udp mux server mode").Default("false").Bool()
muxServerArgs.Key = muxServer.Flag("k", "client key").Default("default").String() muxServerArgs.Key = muxServer.Flag("k", "client key").Default("default").String()
muxServerArgs.Route = muxServer.Flag("route", "local route to client's network, such as :PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings() muxServerArgs.Route = muxServer.Flag("route", "local route to client's network, such as: PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings()
//########mux-client######### //########mux-client#########
muxClient := app.Command("client", "proxy on mux client mode") muxClient := app.Command("client", "proxy on mux client mode").Hidden()
muxClientArgs.Parent = muxClient.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String() muxClientArgs.Parent = muxClient.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
muxClientArgs.CertFile = muxClient.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() muxClientArgs.CertFile = muxClient.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
muxClientArgs.KeyFile = muxClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() muxClientArgs.KeyFile = muxClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
@ -121,7 +121,7 @@ func initConfig() (err error) {
muxClientArgs.Key = muxClient.Flag("k", "key same with server").Default("default").String() muxClientArgs.Key = muxClient.Flag("k", "key same with server").Default("default").String()
//########mux-bridge######### //########mux-bridge#########
muxBridge := app.Command("bridge", "proxy on mux bridge mode") muxBridge := app.Command("bridge", "proxy on mux bridge mode").Hidden()
muxBridgeArgs.CertFile = muxBridge.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() muxBridgeArgs.CertFile = muxBridge.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
muxBridgeArgs.KeyFile = muxBridge.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() muxBridgeArgs.KeyFile = muxBridge.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
muxBridgeArgs.Timeout = muxBridge.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int() muxBridgeArgs.Timeout = muxBridge.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
@ -135,7 +135,7 @@ func initConfig() (err error) {
tunnelServerArgs.Timeout = tunnelServer.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int() tunnelServerArgs.Timeout = tunnelServer.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
tunnelServerArgs.IsUDP = tunnelServer.Flag("udp", "proxy on udp tunnel server mode").Default("false").Bool() tunnelServerArgs.IsUDP = tunnelServer.Flag("udp", "proxy on udp tunnel server mode").Default("false").Bool()
tunnelServerArgs.Key = tunnelServer.Flag("k", "client key").Default("default").String() tunnelServerArgs.Key = tunnelServer.Flag("k", "client key").Default("default").String()
tunnelServerArgs.Route = tunnelServer.Flag("route", "local route to client's network, such as :PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings() tunnelServerArgs.Route = tunnelServer.Flag("route", "local route to client's network, such as: PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings()
//########tunnel-client######### //########tunnel-client#########
tunnelClient := app.Command("tclient", "proxy on tunnel client mode") tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
@ -259,7 +259,7 @@ func initConfig() (err error) {
log.Printf("ERR:%s,restarting...", err) log.Printf("ERR:%s,restarting...", err)
continue continue
} }
log.Printf("%s [PID] %d unexpected exited, restarting...\n", os.Args[0], pid) log.Printf("worker %s [PID] %d unexpected exited, restarting...\n", os.Args[0], pid)
time.Sleep(time.Second * 5) time.Sleep(time.Second * 5)
} }
}() }()

View File

@ -2,6 +2,7 @@ package services
import ( import (
"bufio" "bufio"
"io"
"log" "log"
"net" "net"
"proxy/utils" "proxy/utils"
@ -11,20 +12,14 @@ import (
"github.com/xtaci/smux" "github.com/xtaci/smux"
) )
type MuxServerConn struct {
//ClientLocalAddr string //tcp:2.2.22:333@ID
Conn *net.Conn
}
type MuxBridge struct { type MuxBridge struct {
cfg MuxBridgeArgs cfg MuxBridgeArgs
serverConns utils.ConcurrentMap
clientControlConns utils.ConcurrentMap clientControlConns utils.ConcurrentMap
} }
func NewMuxBridge() Service { func NewMuxBridge() Service {
return &MuxBridge{ return &MuxBridge{
cfg: MuxBridgeArgs{}, cfg: MuxBridgeArgs{},
serverConns: utils.NewConcurrentMap(),
clientControlConns: utils.NewConcurrentMap(), clientControlConns: utils.NewConcurrentMap(),
} }
} }
@ -51,31 +46,46 @@ func (s *MuxBridge) Start(args interface{}) (err error) {
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, func(inConn net.Conn) { err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, func(inConn net.Conn) {
reader := bufio.NewReader(inConn) reader := bufio.NewReader(inConn)
var err error var err error
var connType uint8 var connType uint8
err = utils.ReadPacket(reader, &connType) var key string
err = utils.ReadPacket(reader, &connType, &key)
if err != nil { if err != nil {
log.Printf("read error,ERR:%s", err) log.Printf("read error,ERR:%s", err)
return return
} }
switch connType { switch connType {
case CONN_SERVER: case CONN_SERVER:
log.Printf("server connection %s", key)
session, err := smux.Server(inConn, nil) session, err := smux.Server(inConn, nil)
if err != nil { if err != nil {
utils.CloseConn(&inConn) utils.CloseConn(&inConn)
log.Printf("server underlayer connection error,ERR:%s", err) log.Printf("server session error,ERR:%s", err)
return return
} }
conn, err := session.AcceptStream() for {
stream, err := session.AcceptStream()
if err != nil { if err != nil {
session.Close() session.Close()
utils.CloseConn(&inConn) utils.CloseConn(&inConn)
return return
} }
log.Printf("server connection %s", conn.RemoteAddr()) go s.callback(stream, key)
//s.callback(conn)
} }
s.callback(inConn) case CONN_CLIENT:
log.Printf("client connection %s", key)
session, err := smux.Client(inConn, nil)
if err != nil {
utils.CloseConn(&inConn)
log.Printf("client session error,ERR:%s", err)
return
}
s.clientControlConns.Set(key, session)
//log.Printf("set client session,key: %s", key)
}
}) })
if err != nil { if err != nil {
return return
@ -86,86 +96,48 @@ func (s *MuxBridge) Start(args interface{}) (err error) {
func (s *MuxBridge) Clean() { func (s *MuxBridge) Clean() {
s.StopService() s.StopService()
} }
func (s *MuxBridge) callback(inConn net.Conn) { func (s *MuxBridge) callback(inConn net.Conn, key string) {
reader := bufio.NewReader(inConn) reader := bufio.NewReader(inConn)
var err error var err error
var connType uint8 var ID, clientLocalAddr, serverID string
err = utils.ReadPacket(reader, &connType) err = utils.ReadPacketData(reader, &ID, &clientLocalAddr, &serverID)
if err != nil {
log.Printf("read error,ERR:%s", err)
return
}
switch connType {
case CONN_SERVER:
var key, ID, clientLocalAddr, serverID string
err = utils.ReadPacketData(reader, &key, &ID, &clientLocalAddr, &serverID)
if err != nil { if err != nil {
log.Printf("read error,ERR:%s", err) log.Printf("read error,ERR:%s", err)
return return
} }
packet := utils.BuildPacketData(ID, clientLocalAddr, serverID) packet := utils.BuildPacketData(ID, clientLocalAddr, serverID)
log.Printf("server connection, key: %s , id: %s %s %s", key, ID, clientLocalAddr, serverID) try := 20
//addr := clientLocalAddr + "@" + ID
s.serverConns.Set(ID, MuxServerConn{
Conn: &inConn,
})
for { for {
item, ok := s.clientControlConns.Get(key) try--
if try == 0 {
break
}
session, ok := s.clientControlConns.Get(key)
if !ok { if !ok {
log.Printf("client %s control conn not exists", key) log.Printf("client %s session not exists", key)
time.Sleep(time.Second * 3) time.Sleep(time.Second * 3)
continue continue
} }
(*item.(*net.Conn)).SetWriteDeadline(time.Now().Add(time.Second * 3)) stream, err := session.(*smux.Session).OpenStream()
_, err := (*item.(*net.Conn)).Write(packet)
(*item.(*net.Conn)).SetWriteDeadline(time.Time{})
if err != nil { if err != nil {
log.Printf("%s client control conn write signal fail, err: %s, retrying...", key, err) log.Printf("%s client session open stream fail, err: %s, retrying...", key, err)
time.Sleep(time.Second * 3) time.Sleep(time.Second * 3)
continue continue
} else { } else {
_, err := stream.Write(packet)
if err != nil {
log.Printf("server %s stream write fail, err: %s, retrying...", key, err)
time.Sleep(time.Second * 3)
continue
}
log.Printf("server stream %s created", ID)
go io.Copy(stream, inConn)
io.Copy(inConn, stream)
stream.Close()
inConn.Close()
log.Printf("server stream %s released", ID)
break break
} }
} }
case CONN_CLIENT:
var key, ID, serverID string
err = utils.ReadPacketData(reader, &key, &ID, &serverID)
if err != nil {
log.Printf("read error,ERR:%s", err)
return
}
log.Printf("client connection , key: %s , id: %s, server id:%s", key, ID, serverID)
serverConnItem, ok := s.serverConns.Get(ID)
if !ok {
inConn.Close()
log.Printf("server conn %s exists", ID)
return
}
serverConn := serverConnItem.(MuxServerConn).Conn
utils.IoBind(*serverConn, inConn, func(err interface{}) {
s.serverConns.Remove(ID)
// s.cmClient.RemoveOne(key, ID)
// s.cmServer.RemoveOne(serverID, ID)
log.Printf("conn %s released", ID)
})
// s.cmClient.Add(key, ID, &inConn)
log.Printf("conn %s created", ID)
case CONN_CLIENT_CONTROL:
var key string
err = utils.ReadPacketData(reader, &key)
if err != nil {
log.Printf("read error,ERR:%s", err)
return
}
log.Printf("client control connection, key: %s", key)
if s.clientControlConns.Has(key) {
item, _ := s.clientControlConns.Get(key)
(*item.(*net.Conn)).Close()
}
s.clientControlConns.Set(key, &inConn)
log.Printf("set client %s control conn", key)
}
} }

View File

@ -2,89 +2,28 @@ package services
import ( import (
"crypto/tls" "crypto/tls"
"fmt"
"io"
"log" "log"
"net" "net"
"proxy/utils" "proxy/utils"
"time" "time"
"github.com/xtaci/smux"
) )
type MuxClient struct { type MuxClient struct {
cfg MuxClientArgs cfg MuxClientArgs
// cm utils.ConnManager
ctrlConn net.Conn
} }
func NewMuxClient() Service { func NewMuxClient() Service {
return &MuxClient{ return &MuxClient{
cfg: MuxClientArgs{}, cfg: MuxClientArgs{},
// cm: utils.NewConnManager(),
} }
} }
func (s *MuxClient) InitService() { func (s *MuxClient) InitService() {
// s.InitHeartbeatDeamon()
} }
// func (s *MuxClient) InitHeartbeatDeamon() {
// log.Printf("heartbeat started")
// go func() {
// var heartbeatConn net.Conn
// var ID = *s.cfg.Key
// for {
// //close all connection
// s.cm.RemoveAll()
// if s.ctrlConn != nil {
// s.ctrlConn.Close()
// }
// utils.CloseConn(&heartbeatConn)
// heartbeatConn, err := s.GetInConn(CONN_CLIENT_HEARBEAT, ID)
// if err != nil {
// log.Printf("heartbeat connection err: %s, retrying...", err)
// time.Sleep(time.Second * 3)
// utils.CloseConn(&heartbeatConn)
// continue
// }
// log.Printf("heartbeat connection created,id:%s", ID)
// writeDie := make(chan bool)
// readDie := make(chan bool)
// go func() {
// for {
// heartbeatConn.SetWriteDeadline(time.Now().Add(time.Second * 3))
// _, err = heartbeatConn.Write([]byte{0x00})
// heartbeatConn.SetWriteDeadline(time.Time{})
// if err != nil {
// log.Printf("heartbeat connection write err %s", err)
// break
// }
// time.Sleep(time.Second * 3)
// }
// close(writeDie)
// }()
// go func() {
// for {
// signal := make([]byte, 1)
// heartbeatConn.SetReadDeadline(time.Now().Add(time.Second * 6))
// _, err := heartbeatConn.Read(signal)
// heartbeatConn.SetReadDeadline(time.Time{})
// if err != nil {
// log.Printf("heartbeat connection read err: %s", err)
// break
// } else {
// //log.Printf("heartbeat from bridge")
// }
// }
// close(readDie)
// }()
// select {
// case <-readDie:
// case <-writeDie:
// }
// }
// }()
// }
func (s *MuxClient) CheckArgs() { func (s *MuxClient) CheckArgs() {
if *s.cfg.Parent != "" { if *s.cfg.Parent != "" {
log.Printf("use tls parent %s", *s.cfg.Parent) log.Printf("use tls parent %s", *s.cfg.Parent)
@ -97,37 +36,47 @@ func (s *MuxClient) CheckArgs() {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
} }
func (s *MuxClient) StopService() { func (s *MuxClient) StopService() {
// s.cm.RemoveAll()
} }
func (s *MuxClient) Start(args interface{}) (err error) { func (s *MuxClient) Start(args interface{}) (err error) {
s.cfg = args.(MuxClientArgs) s.cfg = args.(MuxClientArgs)
s.CheckArgs() s.CheckArgs()
s.InitService() s.InitService()
log.Printf("proxy on tunnel client mode") log.Printf("proxy on mux client mode")
for { for {
//close all conn var _conn tls.Conn
// s.cm.Remove(*s.cfg.Key) _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes)
if s.ctrlConn != nil {
s.ctrlConn.Close()
}
s.ctrlConn, err = s.GetInConn(CONN_CLIENT_CONTROL, *s.cfg.Key)
if err != nil { if err != nil {
log.Printf("control connection err: %s, retrying...", err) log.Printf("connection err: %s, retrying...", err)
time.Sleep(time.Second * 3) time.Sleep(time.Second * 3)
if s.ctrlConn != nil { continue
s.ctrlConn.Close()
} }
conn := net.Conn(&_conn)
_, err = conn.Write(utils.BuildPacket(CONN_CLIENT, *s.cfg.Key))
if err != nil {
conn.Close()
log.Printf("connection err: %s, retrying...", err)
time.Sleep(time.Second * 3)
continue
}
session, err := smux.Server(conn, nil)
if err != nil {
log.Printf("session err: %s, retrying...", err)
conn.Close()
time.Sleep(time.Second * 3)
continue continue
} }
for { for {
var ID, clientLocalAddr, serverID string stream, err := session.AcceptStream()
err = utils.ReadPacketData(s.ctrlConn, &ID, &clientLocalAddr, &serverID)
if err != nil { if err != nil {
if s.ctrlConn != nil { log.Printf("accept stream err: %s, retrying...", err)
s.ctrlConn.Close() session.Close()
time.Sleep(time.Second * 3)
break
} }
var ID, clientLocalAddr, serverID string
err = utils.ReadPacketData(stream, &ID, &clientLocalAddr, &serverID)
if err != nil {
log.Printf("read connection signal err: %s, retrying...", err) log.Printf("read connection signal err: %s, retrying...", err)
break break
} }
@ -135,78 +84,40 @@ func (s *MuxClient) Start(args interface{}) (err error) {
protocol := clientLocalAddr[:3] protocol := clientLocalAddr[:3]
localAddr := clientLocalAddr[4:] localAddr := clientLocalAddr[4:]
if protocol == "udp" { if protocol == "udp" {
go s.ServeUDP(localAddr, ID, serverID) go s.ServeUDP(stream, localAddr, ID)
} else { } else {
go s.ServeConn(localAddr, ID, serverID) go s.ServeConn(stream, localAddr, ID)
} }
} }
} }
} }
func (s *MuxClient) Clean() { func (s *MuxClient) Clean() {
s.StopService() s.StopService()
} }
func (s *MuxClient) GetInConn(typ uint8, data ...string) (outConn net.Conn, err error) {
outConn, err = s.GetConn() func (s *MuxClient) ServeUDP(inConn *smux.Stream, localAddr, ID string) {
if err != nil {
err = fmt.Errorf("connection err: %s", err)
return
}
_, err = outConn.Write(utils.BuildPacket(typ, data...))
if err != nil {
err = fmt.Errorf("write connection data err: %s ,retrying...", err)
utils.CloseConn(&outConn)
return
}
return
}
func (s *MuxClient) GetConn() (conn net.Conn, err error) {
var _conn tls.Conn
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes)
if err == nil {
conn = net.Conn(&_conn)
}
return
}
func (s *MuxClient) ServeUDP(localAddr, ID, serverID string) {
var inConn net.Conn
var err error
// for {
for {
// s.cm.RemoveOne(*s.cfg.Key, ID)
inConn, err = s.GetInConn(CONN_CLIENT, *s.cfg.Key, ID, serverID)
if err != nil {
utils.CloseConn(&inConn)
log.Printf("connection err: %s, retrying...", err)
time.Sleep(time.Second * 3)
continue
} else {
break
}
}
// s.cm.Add(*s.cfg.Key, ID, &inConn)
log.Printf("conn %s created", ID)
for { for {
srcAddr, body, err := utils.ReadUDPPacket(inConn) srcAddr, body, err := utils.ReadUDPPacket(inConn)
if err == io.EOF || err == io.ErrUnexpectedEOF { if err != nil {
log.Printf("connection %s released", ID)
utils.CloseConn(&inConn)
break
} else if err != nil {
log.Printf("udp packet revecived fail, err: %s", err) log.Printf("udp packet revecived fail, err: %s", err)
log.Printf("connection %s released", ID)
inConn.Close()
break
} else { } else {
//log.Printf("udp packet revecived:%s,%v", srcAddr, body) //log.Printf("udp packet revecived:%s,%v", srcAddr, body)
go s.processUDPPacket(&inConn, srcAddr, localAddr, body) go s.processUDPPacket(inConn, srcAddr, localAddr, body)
} }
} }
// } // }
} }
func (s *MuxClient) processUDPPacket(inConn *net.Conn, srcAddr, localAddr string, body []byte) { func (s *MuxClient) processUDPPacket(inConn *smux.Stream, srcAddr, localAddr string, body []byte) {
dstAddr, err := net.ResolveUDPAddr("udp", localAddr) dstAddr, err := net.ResolveUDPAddr("udp", localAddr)
if err != nil { if err != nil {
log.Printf("can't resolve address: %s", err) log.Printf("can't resolve address: %s", err)
utils.CloseConn(inConn) inConn.Close()
return return
} }
clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
@ -234,26 +145,14 @@ func (s *MuxClient) processUDPPacket(inConn *net.Conn, srcAddr, localAddr string
_, err = (*inConn).Write(bs) _, err = (*inConn).Write(bs)
if err != nil { if err != nil {
log.Printf("send udp response fail ,ERR:%s", err) log.Printf("send udp response fail ,ERR:%s", err)
utils.CloseConn(inConn) inConn.Close()
return return
} }
//log.Printf("send udp response success ,from:%s ,%d ,%v", dstAddr.String(), len(bs), bs) //log.Printf("send udp response success ,from:%s ,%d ,%v", dstAddr.String(), len(bs), bs)
} }
func (s *MuxClient) ServeConn(localAddr, ID, serverID string) { func (s *MuxClient) ServeConn(inConn *smux.Stream, localAddr, ID string) {
var inConn, outConn net.Conn
var err error var err error
for { var outConn net.Conn
inConn, err = s.GetInConn(CONN_CLIENT, *s.cfg.Key, ID, serverID)
if err != nil {
utils.CloseConn(&inConn)
log.Printf("connection err: %s, retrying...", err)
time.Sleep(time.Second * 3)
continue
} else {
break
}
}
i := 0 i := 0
for { for {
i++ i++
@ -269,15 +168,13 @@ func (s *MuxClient) ServeConn(localAddr, ID, serverID string) {
} }
} }
if err != nil { if err != nil {
utils.CloseConn(&inConn) inConn.Close()
utils.CloseConn(&outConn) utils.CloseConn(&outConn)
log.Printf("build connection error, err: %s", err) log.Printf("build connection error, err: %s", err)
return return
} }
utils.IoBind(inConn, outConn, func(err interface{}) { utils.IoBind(inConn, outConn, func(err interface{}) {
log.Printf("conn %s released", ID) log.Printf("conn %s released", ID)
// s.cm.RemoveOne(*s.cfg.Key, ID)
}) })
// s.cm.Add(*s.cfg.Key, ID, &inConn)
log.Printf("conn %s created", ID) log.Printf("conn %s created", ID)
} }

View File

@ -3,7 +3,6 @@ package services
import ( import (
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"io"
"log" "log"
"net" "net"
"proxy/utils" "proxy/utils"
@ -19,8 +18,8 @@ type MuxServer struct {
cfg MuxServerArgs cfg MuxServerArgs
udpChn chan MuxUDPItem udpChn chan MuxUDPItem
sc utils.ServerChannel sc utils.ServerChannel
underLayerConn net.Conn
session *smux.Session session *smux.Session
lockChn chan bool
} }
type MuxServerManager struct { type MuxServerManager struct {
@ -28,7 +27,6 @@ type MuxServerManager struct {
udpChn chan MuxUDPItem udpChn chan MuxUDPItem
sc utils.ServerChannel sc utils.ServerChannel
serverID string serverID string
// cm utils.ConnManager
} }
func NewMuxServerManager() Service { func NewMuxServerManager() Service {
@ -36,7 +34,6 @@ func NewMuxServerManager() Service {
cfg: MuxServerArgs{}, cfg: MuxServerArgs{},
udpChn: make(chan MuxUDPItem, 50000), udpChn: make(chan MuxUDPItem, 50000),
serverID: utils.Uniqueid(), serverID: utils.Uniqueid(),
// cm: utils.NewConnManager(),
} }
} }
func (s *MuxServerManager) Start(args interface{}) (err error) { func (s *MuxServerManager) Start(args interface{}) (err error) {
@ -53,6 +50,9 @@ func (s *MuxServerManager) Start(args interface{}) (err error) {
log.Printf("server id: %s", s.serverID) log.Printf("server id: %s", s.serverID)
//log.Printf("route:%v", *s.cfg.Route) //log.Printf("route:%v", *s.cfg.Route)
for _, _info := range *s.cfg.Route { for _, _info := range *s.cfg.Route {
if _info == "" {
continue
}
IsUDP := *s.cfg.IsUDP IsUDP := *s.cfg.IsUDP
if strings.HasPrefix(_info, "udp://") { if strings.HasPrefix(_info, "udp://") {
IsUDP = true IsUDP = true
@ -95,7 +95,6 @@ func (s *MuxServerManager) Clean() {
s.StopService() s.StopService()
} }
func (s *MuxServerManager) StopService() { func (s *MuxServerManager) StopService() {
// s.cm.RemoveAll()
} }
func (s *MuxServerManager) CheckArgs() { func (s *MuxServerManager) CheckArgs() {
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" { if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
@ -104,13 +103,13 @@ func (s *MuxServerManager) CheckArgs() {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
} }
func (s *MuxServerManager) InitService() { func (s *MuxServerManager) InitService() {
} }
func NewMuxServer() Service { func NewMuxServer() Service {
return &MuxServer{ return &MuxServer{
cfg: MuxServerArgs{}, cfg: MuxServerArgs{},
udpChn: make(chan MuxUDPItem, 50000), udpChn: make(chan MuxUDPItem, 50000),
lockChn: make(chan bool, 1),
} }
} }
@ -147,18 +146,18 @@ func (s *MuxServer) Start(args interface{}) (err error) {
if err != nil { if err != nil {
return return
} }
log.Printf("proxy on udp tunnel server mode %s", (*s.sc.UDPListener).LocalAddr()) log.Printf("proxy on udp mux server mode %s", (*s.sc.UDPListener).LocalAddr())
} else { } else {
err = s.sc.ListenTCP(func(inConn net.Conn) { err = s.sc.ListenTCP(func(inConn net.Conn) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
log.Printf("tserver conn handler crashed with err : %s \nstack: %s", err, string(debug.Stack())) log.Printf("server conn handler crashed with err : %s \nstack: %s", err, string(debug.Stack()))
} }
}() }()
var outConn net.Conn var outConn net.Conn
var ID string var ID string
for { for {
outConn, ID, err = s.GetOutConn(CONN_SERVER) outConn, ID, err = s.GetOutConn()
if err != nil { if err != nil {
utils.CloseConn(&outConn) utils.CloseConn(&outConn)
log.Printf("connect to %s fail, err: %s, retrying...", *s.cfg.Parent, err) log.Printf("connect to %s fail, err: %s, retrying...", *s.cfg.Parent, err)
@ -169,24 +168,22 @@ func (s *MuxServer) Start(args interface{}) (err error) {
} }
} }
utils.IoBind(inConn, outConn, func(err interface{}) { utils.IoBind(inConn, outConn, func(err interface{}) {
// s.cfg.Mgr.cm.RemoveOne(s.cfg.Mgr.serverID, ID)
log.Printf("%s conn %s released", *s.cfg.Key, ID) log.Printf("%s conn %s released", *s.cfg.Key, ID)
}) })
//add conn //add conn
// s.cfg.Mgr.cm.Add(s.cfg.Mgr.serverID, ID, &inConn)
log.Printf("%s conn %s created", *s.cfg.Key, ID) log.Printf("%s conn %s created", *s.cfg.Key, ID)
}) })
if err != nil { if err != nil {
return return
} }
log.Printf("proxy on tunnel server mode %s", (*s.sc.Listener).Addr()) log.Printf("proxy on mux server mode %s", (*s.sc.Listener).Addr())
} }
return return
} }
func (s *MuxServer) Clean() { func (s *MuxServer) Clean() {
} }
func (s *MuxServer) GetOutConn(typ uint8) (outConn net.Conn, ID string, err error) { func (s *MuxServer) GetOutConn() (outConn net.Conn, ID string, err error) {
outConn, err = s.GetConn() outConn, err = s.GetConn()
if err != nil { if err != nil {
log.Printf("connection err: %s", err) log.Printf("connection err: %s", err)
@ -197,7 +194,7 @@ func (s *MuxServer) GetOutConn(typ uint8) (outConn net.Conn, ID string, err erro
remoteAddr = "udp:" + *s.cfg.Remote remoteAddr = "udp:" + *s.cfg.Remote
} }
ID = utils.Uniqueid() ID = utils.Uniqueid()
_, err = outConn.Write(utils.BuildPacket(typ, *s.cfg.Key, ID, remoteAddr, s.cfg.Mgr.serverID)) _, err = outConn.Write(utils.BuildPacketData(ID, remoteAddr, s.cfg.Mgr.serverID))
if err != nil { if err != nil {
log.Printf("write connection data err: %s ,retrying...", err) log.Printf("write connection data err: %s ,retrying...", err)
utils.CloseConn(&outConn) utils.CloseConn(&outConn)
@ -206,11 +203,43 @@ func (s *MuxServer) GetOutConn(typ uint8) (outConn net.Conn, ID string, err erro
return return
} }
func (s *MuxServer) GetConn() (conn net.Conn, err error) { func (s *MuxServer) GetConn() (conn net.Conn, err error) {
select {
case s.lockChn <- true:
default:
err = fmt.Errorf("can not connect at same time")
return
}
defer func() {
<-s.lockChn
}()
if s.session == nil {
var _conn tls.Conn var _conn tls.Conn
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes) _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes)
if err == nil { if err != nil {
conn = net.Conn(&_conn) s.session = nil
return
} }
c := net.Conn(&_conn)
_, err = c.Write(utils.BuildPacket(CONN_SERVER, *s.cfg.Key))
if err != nil {
c.Close()
s.session = nil
return
}
if err == nil {
s.session, err = smux.Client(c, nil)
if err != nil {
s.session = nil
return
}
}
}
conn, err = s.session.OpenStream()
if err != nil {
s.session.Close()
s.session = nil
}
return return
} }
func (s *MuxServer) UDPConnDeamon() { func (s *MuxServer) UDPConnDeamon() {
@ -221,18 +250,15 @@ func (s *MuxServer) UDPConnDeamon() {
} }
}() }()
var outConn net.Conn var outConn net.Conn
// var hb utils.HeartbeatReadWriter
var ID string var ID string
// var cmdChn = make(chan bool, 1000)
var err error var err error
for { for {
item := <-s.udpChn item := <-s.udpChn
RETRY: RETRY:
if outConn == nil { if outConn == nil {
for { for {
outConn, ID, err = s.GetOutConn(CONN_SERVER) outConn, ID, err = s.GetOutConn()
if err != nil { if err != nil {
// cmdChn <- true
outConn = nil outConn = nil
utils.CloseConn(&outConn) utils.CloseConn(&outConn)
log.Printf("connect to %s fail, err: %s, retrying...", *s.cfg.Parent, err) log.Printf("connect to %s fail, err: %s, retrying...", *s.cfg.Parent, err)
@ -241,18 +267,14 @@ func (s *MuxServer) UDPConnDeamon() {
} else { } else {
go func(outConn net.Conn, ID string) { go func(outConn net.Conn, ID string) {
go func() { go func() {
// <-cmdChn
// outConn.Close() // outConn.Close()
}() }()
for { for {
srcAddrFromConn, body, err := utils.ReadUDPPacket(outConn) srcAddrFromConn, body, err := utils.ReadUDPPacket(outConn)
if err == io.EOF || err == io.ErrUnexpectedEOF {
log.Printf("UDP deamon connection %s exited", ID)
break
}
if err != nil { if err != nil {
log.Printf("parse revecived udp packet fail, err: %s ,%v", err, body) log.Printf("parse revecived udp packet fail, err: %s ,%v", err, body)
continue log.Printf("UDP deamon connection %s exited", ID)
break
} }
//log.Printf("udp packet revecived over parent , local:%s", srcAddrFromConn) //log.Printf("udp packet revecived over parent , local:%s", srcAddrFromConn)
_srcAddr := strings.Split(srcAddrFromConn, ":") _srcAddr := strings.Split(srcAddrFromConn, ":")