Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>
This commit is contained in:
@ -1,6 +1,8 @@
|
||||
proxy更新日志
|
||||
v3.4
|
||||
1.socks5代理新增了用户名密码验证支持.
|
||||
2.socks5,http(s)代理增加了kcp传输协议支持.
|
||||
3.优化了内网穿透的心跳机制.
|
||||
|
||||
v3.3
|
||||
1.修复了socks代理模式对证书文件的判断逻辑.
|
||||
|
||||
15
config.go
15
config.go
@ -41,8 +41,8 @@ func initConfig() (err error) {
|
||||
httpArgs.Parent = http.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
|
||||
httpArgs.CertFile = http.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
httpArgs.KeyFile = http.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
httpArgs.LocalType = http.Flag("local-type", "local protocol type <tls|tcp>").Default("tcp").Short('t').Enum("tls", "tcp")
|
||||
httpArgs.ParentType = http.Flag("parent-type", "parent protocol type <tls|tcp|ssh>").Short('T').Enum("tls", "tcp", "ssh")
|
||||
httpArgs.LocalType = http.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
|
||||
httpArgs.ParentType = http.Flag("parent-type", "parent protocol type <tls|tcp|ssh|kcp>").Short('T').Enum("tls", "tcp", "ssh", "kcp")
|
||||
httpArgs.Always = http.Flag("always", "always use parent proxy").Default("false").Bool()
|
||||
httpArgs.Timeout = http.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Default("2000").Int()
|
||||
httpArgs.HTTPTimeout = http.Flag("http-timeout", "check domain if blocked , http request timeout milliseconds when connect to host").Default("3000").Int()
|
||||
@ -58,6 +58,8 @@ func initConfig() (err error) {
|
||||
httpArgs.SSHKeyFile = http.Flag("ssh-key", "private key file for ssh").Short('S').Default("").String()
|
||||
httpArgs.SSHKeyFileSalt = http.Flag("ssh-keysalt", "salt of ssh private key").Short('s').Default("").String()
|
||||
httpArgs.SSHPassword = http.Flag("ssh-password", "password for ssh").Short('A').Default("").String()
|
||||
httpArgs.KCPKey = http.Flag("kcp-key", "key for kcp encrypt/decrypt data").Short('B').Default("encrypt").String()
|
||||
httpArgs.KCPMethod = http.Flag("kcp-method", "kcp encrypt/decrypt method").Short('M').Default("3des").String()
|
||||
|
||||
//########tcp#########
|
||||
tcp := app.Command("tcp", "proxy on tcp mode")
|
||||
@ -110,9 +112,11 @@ func initConfig() (err error) {
|
||||
//########ssh#########
|
||||
socks := app.Command("socks", "proxy on ssh mode")
|
||||
socksArgs.Parent = socks.Flag("parent", "parent ssh address, such as: \"23.32.32.19:22\"").Default("").Short('P').String()
|
||||
socksArgs.ParentType = socks.Flag("parent-type", "parent protocol type <tls|tcp|ssh>").Default("tcp").Short('T').Enum("tls", "tcp", "ssh")
|
||||
socksArgs.LocalType = socks.Flag("local-type", "local protocol type <tls|tcp>").Default("tcp").Short('t').Enum("tls", "tcp")
|
||||
socksArgs.ParentType = socks.Flag("parent-type", "parent protocol type <tls|tcp|kcp|ssh>").Default("tcp").Short('T').Enum("tls", "tcp", "kcp", "ssh")
|
||||
socksArgs.LocalType = socks.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
|
||||
socksArgs.Local = socks.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
socksArgs.UDPParent = socks.Flag("udp-parent", "udp parent address, such as: \"23.32.32.19:33090\"").Default("").Short('X').String()
|
||||
socksArgs.UDPLocal = socks.Flag("udp-local", "udp local ip:port to listen").Short('x').Default(":33090").String()
|
||||
socksArgs.CertFile = socks.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
socksArgs.KeyFile = socks.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
socksArgs.SSHUser = socks.Flag("ssh-user", "user for ssh").Short('u').Default("").String()
|
||||
@ -126,6 +130,9 @@ func initConfig() (err error) {
|
||||
socksArgs.Direct = socks.Flag("direct", "direct domain file , one domain each line").Default("direct").Short('d').String()
|
||||
socksArgs.AuthFile = socks.Flag("auth-file", "http basic auth file,\"username:password\" each line in file").Short('F').String()
|
||||
socksArgs.Auth = socks.Flag("auth", "socks auth username and password, mutiple user repeat -a ,such as: -a user1:pass1 -a user2:pass2").Short('a').Strings()
|
||||
socksArgs.KCPKey = socks.Flag("kcp-key", "key for kcp encrypt/decrypt data").Short('B').Default("encrypt").String()
|
||||
socksArgs.KCPMethod = socks.Flag("kcp-method", "kcp encrypt/decrypt method").Short('M').Default("3des").String()
|
||||
|
||||
//parse args
|
||||
serviceName := kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||
flags := log.Ldate
|
||||
|
||||
@ -10,6 +10,7 @@ const (
|
||||
TYPE_UDP = "udp"
|
||||
TYPE_HTTP = "http"
|
||||
TYPE_TLS = "tls"
|
||||
TYPE_KCP = "kcp"
|
||||
CONN_CLIENT_CONTROL = uint8(1)
|
||||
CONN_SERVER_CONTROL = uint8(2)
|
||||
CONN_SERVER = uint8(3)
|
||||
@ -87,6 +88,8 @@ type HTTPArgs struct {
|
||||
SSHUser *string
|
||||
SSHKeyBytes []byte
|
||||
SSHAuthMethod ssh.AuthMethod
|
||||
KCPMethod *string
|
||||
KCPKey *string
|
||||
}
|
||||
type UDPArgs struct {
|
||||
Parent *string
|
||||
@ -122,6 +125,10 @@ type SocksArgs struct {
|
||||
Direct *string
|
||||
AuthFile *string
|
||||
Auth *[]string
|
||||
KCPMethod *string
|
||||
KCPKey *string
|
||||
UDPParent *string
|
||||
UDPLocal *string
|
||||
}
|
||||
|
||||
func (a *TCPArgs) Protocol() string {
|
||||
|
||||
@ -120,8 +120,10 @@ func (s *HTTP) Start(args interface{}) (err error) {
|
||||
sc := utils.NewServerChannel(host, p)
|
||||
if *s.cfg.LocalType == TYPE_TCP {
|
||||
err = sc.ListenTCP(s.callback)
|
||||
} else {
|
||||
} else if *s.cfg.LocalType == TYPE_TLS {
|
||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.callback)
|
||||
} else if *s.cfg.LocalType == TYPE_KCP {
|
||||
err = sc.ListenKCP(*s.cfg.KCPMethod, *s.cfg.KCPKey, s.callback)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
@ -197,6 +199,7 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
outConn, err = s.getSSHConn(address)
|
||||
} else {
|
||||
//log.Printf("%v", s.outPool)
|
||||
_outConn, err = s.outPool.Pool.Get()
|
||||
if err == nil {
|
||||
outConn = _outConn.(net.Conn)
|
||||
@ -303,12 +306,14 @@ func (s *HTTP) ConnectSSH() (err error) {
|
||||
return
|
||||
}
|
||||
func (s *HTTP) InitOutConnPool() {
|
||||
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP {
|
||||
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP || *s.cfg.ParentType == TYPE_KCP {
|
||||
//dur int, isTLS bool, certBytes, keyBytes []byte,
|
||||
//parent string, timeout int, InitialCap int, MaxCap int
|
||||
s.outPool = utils.NewOutPool(
|
||||
*s.cfg.CheckParentInterval,
|
||||
*s.cfg.ParentType == TYPE_TLS,
|
||||
*s.cfg.ParentType,
|
||||
*s.cfg.KCPMethod,
|
||||
*s.cfg.KCPKey,
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes,
|
||||
*s.cfg.Parent,
|
||||
*s.cfg.Timeout,
|
||||
|
||||
@ -105,8 +105,8 @@ func (s *Socks) InitService() {
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
log.Println("warn: socks udp not suppored for ssh")
|
||||
} else {
|
||||
_, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
s.udpSC = utils.NewServerChannelHost(":" + port)
|
||||
|
||||
s.udpSC = utils.NewServerChannelHost(*s.cfg.UDPLocal)
|
||||
err := s.udpSC.ListenUDP(s.udpCallback)
|
||||
if err != nil {
|
||||
log.Fatalf("init udp service fail, ERR: %s", err)
|
||||
@ -133,8 +133,10 @@ func (s *Socks) Start(args interface{}) (err error) {
|
||||
sc := utils.NewServerChannelHost(*s.cfg.Local)
|
||||
if *s.cfg.LocalType == TYPE_TCP {
|
||||
err = sc.ListenTCP(s.socksConnCallback)
|
||||
} else {
|
||||
} else if *s.cfg.LocalType == TYPE_TLS {
|
||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.socksConnCallback)
|
||||
} else if *s.cfg.LocalType == TYPE_KCP {
|
||||
err = sc.ListenKCP(*s.cfg.KCPMethod, *s.cfg.KCPKey, s.socksConnCallback)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
@ -176,7 +178,11 @@ func (s *Socks) udpCallback(b []byte, localAddr, srcAddr *net.UDPAddr) {
|
||||
return
|
||||
}
|
||||
}
|
||||
dstAddr, err := net.ResolveUDPAddr("udp", *s.cfg.Parent)
|
||||
parent := *s.cfg.UDPParent
|
||||
if parent == "" {
|
||||
parent = *s.cfg.Parent
|
||||
}
|
||||
dstAddr, err := net.ResolveUDPAddr("udp", parent)
|
||||
if err != nil {
|
||||
log.Printf("can't resolve address: %s", err)
|
||||
return
|
||||
@ -382,7 +388,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque
|
||||
}
|
||||
host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String())
|
||||
_, port, _ := net.SplitHostPort(s.udpSC.UDPListener.LocalAddr().String())
|
||||
// log.Printf("proxy udp on %s", net.JoinHostPort(host, port))
|
||||
log.Printf("proxy udp on %s", net.JoinHostPort(host, port))
|
||||
request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port))
|
||||
}
|
||||
func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) {
|
||||
@ -428,15 +434,16 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque
|
||||
inLocalAddr := (*inConn).LocalAddr().String()
|
||||
|
||||
log.Printf("conn %s - %s connected [%s]", inAddr, inLocalAddr, request.Addr())
|
||||
utils.IoBind0(*inConn, outConn, func(err error) {
|
||||
utils.IoBind(*inConn, outConn, func(err error) {
|
||||
log.Printf("conn %s - %s released [%s]", inAddr, inLocalAddr, request.Addr())
|
||||
utils.CloseConn(inConn)
|
||||
utils.CloseConn(&outConn)
|
||||
})
|
||||
//}, func(i int, b bool) {}, 0)
|
||||
}
|
||||
func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn net.Conn, err interface{}) {
|
||||
switch *s.cfg.ParentType {
|
||||
case "kcp":
|
||||
fallthrough
|
||||
case "tls":
|
||||
fallthrough
|
||||
case "tcp":
|
||||
@ -444,6 +451,8 @@ func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn n
|
||||
var _outConn tls.Conn
|
||||
_outConn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes)
|
||||
outConn = net.Conn(&_outConn)
|
||||
} else if *s.cfg.ParentType == "kcp" {
|
||||
outConn, err = utils.ConnectKCPHost(*s.cfg.Parent, *s.cfg.KCPMethod, *s.cfg.KCPKey)
|
||||
} else {
|
||||
outConn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||
}
|
||||
|
||||
@ -167,7 +167,8 @@ func (s *TCP) InitOutConnPool() {
|
||||
//parent string, timeout int, InitialCap int, MaxCap int
|
||||
s.outPool = utils.NewOutPool(
|
||||
*s.cfg.CheckParentInterval,
|
||||
*s.cfg.ParentType == TYPE_TLS,
|
||||
*s.cfg.ParentType,
|
||||
"", "",
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes,
|
||||
*s.cfg.Parent,
|
||||
*s.cfg.Timeout,
|
||||
|
||||
@ -167,7 +167,7 @@ func (s *TunnelBridge) Start(args interface{}) (err error) {
|
||||
_, err = inConn.Write([]byte{0x00})
|
||||
inConn.SetWriteDeadline(time.Time{})
|
||||
if err != nil {
|
||||
log.Printf("control connection write err %s", err)
|
||||
log.Printf("server control connection write err %s", err)
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second * 3)
|
||||
@ -181,7 +181,7 @@ func (s *TunnelBridge) Start(args interface{}) (err error) {
|
||||
_, err := inConn.Read(signal)
|
||||
inConn.SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
log.Printf("control connection read err: %s", err)
|
||||
log.Printf("server control connection read err: %s", err)
|
||||
break
|
||||
} else {
|
||||
// log.Printf("heartbeat from server ,id:%s", serverID)
|
||||
|
||||
@ -207,7 +207,8 @@ func (s *UDP) InitOutConnPool() {
|
||||
//parent string, timeout int, InitialCap int, MaxCap int
|
||||
s.outPool = utils.NewOutPool(
|
||||
*s.cfg.CheckParentInterval,
|
||||
*s.cfg.ParentType == TYPE_TLS,
|
||||
*s.cfg.ParentType,
|
||||
"", "",
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes,
|
||||
*s.cfg.Parent,
|
||||
*s.cfg.Timeout,
|
||||
|
||||
@ -3,6 +3,7 @@ package utils
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/binary"
|
||||
@ -16,92 +17,50 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
kcp "github.com/xtaci/kcp-go"
|
||||
)
|
||||
|
||||
func IoBind0(dst io.ReadWriter, src io.ReadWriter, fn func(err error)) {
|
||||
go func() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("IoBind0 crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
_, err := io.Copy(dst, src)
|
||||
if err != nil {
|
||||
fn(err)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("IoBind0 crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
_, err := io.Copy(src, dst)
|
||||
if err != nil {
|
||||
fn(err)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
}
|
||||
func IoBind(dst io.ReadWriter, src io.ReadWriter, fn func(err error)) {
|
||||
var one = &sync.Once{}
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("IoBind crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
e1 := make(chan error, 1)
|
||||
e2 := make(chan error, 1)
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("IoBind crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
|
||||
_, e := io.Copy(dst, src)
|
||||
e1 <- e
|
||||
}()
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("IoBind crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
|
||||
_, e := io.Copy(src, dst)
|
||||
e2 <- e
|
||||
}()
|
||||
var err error
|
||||
_, err = ioCopy(dst, src)
|
||||
if err != nil {
|
||||
one.Do(func() {
|
||||
fn(err)
|
||||
})
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("IoBind crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
var err error
|
||||
_, err = ioCopy(src, dst)
|
||||
if err != nil {
|
||||
one.Do(func() {
|
||||
fn(err)
|
||||
})
|
||||
select {
|
||||
case err = <-e1:
|
||||
case err = <-e2:
|
||||
}
|
||||
fn(err)
|
||||
}()
|
||||
}
|
||||
func ioCopy(dst io.Writer, src io.Reader) (written int64, err error) {
|
||||
buf := make([]byte, 32*1024)
|
||||
for {
|
||||
nr, er := src.Read(buf)
|
||||
if er != nil {
|
||||
err = er
|
||||
break
|
||||
}
|
||||
nw, ew := dst.Write(buf[0:nr])
|
||||
if ew != nil {
|
||||
err = ew
|
||||
break
|
||||
}
|
||||
if nr != nw {
|
||||
err = io.ErrShortWrite
|
||||
break
|
||||
}
|
||||
written += int64(nw)
|
||||
}
|
||||
return written, err
|
||||
}
|
||||
|
||||
func TlsConnectHost(host string, timeout int, certBytes, keyBytes []byte) (conn tls.Conn, err error) {
|
||||
h := strings.Split(host, ":")
|
||||
port, _ := strconv.Atoi(h[1])
|
||||
@ -143,6 +102,10 @@ func ConnectHost(hostAndPort string, timeout int) (conn net.Conn, err error) {
|
||||
conn, err = net.DialTimeout("tcp", hostAndPort, time.Duration(timeout)*time.Millisecond)
|
||||
return
|
||||
}
|
||||
func ConnectKCPHost(hostAndPort, method, key string) (conn net.Conn, err error) {
|
||||
conn, err = kcp.DialWithOptions(hostAndPort, GetKCPBlock(method, key), 10, 3)
|
||||
return
|
||||
}
|
||||
func ListenTls(ip string, port int, certBytes, keyBytes []byte) (ln *net.Listener, err error) {
|
||||
var cert tls.Certificate
|
||||
cert, err = tls.X509KeyPair(certBytes, keyBytes)
|
||||
@ -406,6 +369,38 @@ func TlsBytes(cert, key string) (certBytes, keyBytes []byte) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func GetKCPBlock(method, key string) (block kcp.BlockCrypt) {
|
||||
pass := pbkdf2.Key([]byte(key), []byte(key), 4096, 32, sha1.New)
|
||||
switch method {
|
||||
case "sm4":
|
||||
block, _ = kcp.NewSM4BlockCrypt(pass[:16])
|
||||
case "tea":
|
||||
block, _ = kcp.NewTEABlockCrypt(pass[:16])
|
||||
case "xor":
|
||||
block, _ = kcp.NewSimpleXORBlockCrypt(pass)
|
||||
case "none":
|
||||
block, _ = kcp.NewNoneBlockCrypt(pass)
|
||||
case "aes-128":
|
||||
block, _ = kcp.NewAESBlockCrypt(pass[:16])
|
||||
case "aes-192":
|
||||
block, _ = kcp.NewAESBlockCrypt(pass[:24])
|
||||
case "blowfish":
|
||||
block, _ = kcp.NewBlowfishBlockCrypt(pass)
|
||||
case "twofish":
|
||||
block, _ = kcp.NewTwofishBlockCrypt(pass)
|
||||
case "cast5":
|
||||
block, _ = kcp.NewCast5BlockCrypt(pass[:16])
|
||||
case "3des":
|
||||
block, _ = kcp.NewTripleDESBlockCrypt(pass[:24])
|
||||
case "xtea":
|
||||
block, _ = kcp.NewXTEABlockCrypt(pass[:16])
|
||||
case "salsa20":
|
||||
block, _ = kcp.NewSalsa20BlockCrypt(pass)
|
||||
default:
|
||||
block, _ = kcp.NewAESBlockCrypt(pass)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// type sockaddr struct {
|
||||
// family uint16
|
||||
|
||||
@ -6,6 +6,8 @@ import (
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
|
||||
kcp "github.com/xtaci/kcp-go"
|
||||
)
|
||||
|
||||
type ServerChannel struct {
|
||||
@ -55,7 +57,7 @@ func (sc *ServerChannel) ListenTls(certBytes, keyBytes []byte, fn func(conn net.
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("connection handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
log.Printf("tls connection handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fn(conn)
|
||||
@ -89,7 +91,7 @@ func (sc *ServerChannel) ListenTCP(fn func(conn net.Conn)) (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("connection handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
log.Printf("tcp connection handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fn(conn)
|
||||
@ -136,3 +138,35 @@ func (sc *ServerChannel) ListenUDP(fn func(packet []byte, localAddr, srcAddr *ne
|
||||
}
|
||||
return
|
||||
}
|
||||
func (sc *ServerChannel) ListenKCP(method, key string, fn func(conn net.Conn)) (err error) {
|
||||
var l net.Listener
|
||||
l, err = kcp.ListenWithOptions(fmt.Sprintf("%s:%d", sc.ip, sc.port), GetKCPBlock(method, key), 10, 3)
|
||||
if err == nil {
|
||||
sc.Listener = &l
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("ListenKCP crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
var conn net.Conn
|
||||
conn, err = (*sc.Listener).Accept()
|
||||
if err == nil {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("kcp connection handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fn(conn)
|
||||
}()
|
||||
} else {
|
||||
sc.errAcceptHandler(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -390,19 +390,23 @@ func (req *HTTPRequest) addPortIfNot() (newHost string) {
|
||||
type OutPool struct {
|
||||
Pool ConnPool
|
||||
dur int
|
||||
isTLS bool
|
||||
typ string
|
||||
certBytes []byte
|
||||
keyBytes []byte
|
||||
kcpMethod string
|
||||
kcpKey string
|
||||
address string
|
||||
timeout int
|
||||
}
|
||||
|
||||
func NewOutPool(dur int, isTLS bool, certBytes, keyBytes []byte, address string, timeout int, InitialCap int, MaxCap int) (op OutPool) {
|
||||
func NewOutPool(dur int, typ, kcpMethod, kcpKey string, certBytes, keyBytes []byte, address string, timeout int, InitialCap int, MaxCap int) (op OutPool) {
|
||||
op = OutPool{
|
||||
dur: dur,
|
||||
isTLS: isTLS,
|
||||
typ: typ,
|
||||
certBytes: certBytes,
|
||||
keyBytes: keyBytes,
|
||||
kcpMethod: kcpMethod,
|
||||
kcpKey: kcpKey,
|
||||
address: address,
|
||||
timeout: timeout,
|
||||
}
|
||||
@ -436,12 +440,14 @@ func NewOutPool(dur int, isTLS bool, certBytes, keyBytes []byte, address string,
|
||||
return
|
||||
}
|
||||
func (op *OutPool) getConn() (conn interface{}, err error) {
|
||||
if op.isTLS {
|
||||
if op.typ == "tls" {
|
||||
var _conn tls.Conn
|
||||
_conn, err = TlsConnectHost(op.address, op.timeout, op.certBytes, op.keyBytes)
|
||||
if err == nil {
|
||||
conn = net.Conn(&_conn)
|
||||
}
|
||||
} else if op.typ == "kcp" {
|
||||
conn, err = ConnectKCPHost(op.address, op.kcpMethod, op.kcpKey)
|
||||
} else {
|
||||
conn, err = ConnectHost(op.address, op.timeout)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user