Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>
This commit is contained in:
@ -1,6 +1,8 @@
|
|||||||
proxy更新日志
|
proxy更新日志
|
||||||
v3.4
|
v3.4
|
||||||
1.socks5代理新增了用户名密码验证支持.
|
1.socks5代理新增了用户名密码验证支持.
|
||||||
|
2.socks5,http(s)代理增加了kcp传输协议支持.
|
||||||
|
3.优化了内网穿透的心跳机制.
|
||||||
|
|
||||||
v3.3
|
v3.3
|
||||||
1.修复了socks代理模式对证书文件的判断逻辑.
|
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.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.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.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.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>").Short('T').Enum("tls", "tcp", "ssh")
|
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.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.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()
|
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.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.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.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#########
|
||||||
tcp := app.Command("tcp", "proxy on tcp mode")
|
tcp := app.Command("tcp", "proxy on tcp mode")
|
||||||
@ -110,9 +112,11 @@ func initConfig() (err error) {
|
|||||||
//########ssh#########
|
//########ssh#########
|
||||||
socks := app.Command("socks", "proxy on ssh mode")
|
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.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.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>").Default("tcp").Short('t').Enum("tls", "tcp")
|
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.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.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.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()
|
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.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.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.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
|
//parse args
|
||||||
serviceName := kingpin.MustParse(app.Parse(os.Args[1:]))
|
serviceName := kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||||
flags := log.Ldate
|
flags := log.Ldate
|
||||||
|
|||||||
@ -10,6 +10,7 @@ const (
|
|||||||
TYPE_UDP = "udp"
|
TYPE_UDP = "udp"
|
||||||
TYPE_HTTP = "http"
|
TYPE_HTTP = "http"
|
||||||
TYPE_TLS = "tls"
|
TYPE_TLS = "tls"
|
||||||
|
TYPE_KCP = "kcp"
|
||||||
CONN_CLIENT_CONTROL = uint8(1)
|
CONN_CLIENT_CONTROL = uint8(1)
|
||||||
CONN_SERVER_CONTROL = uint8(2)
|
CONN_SERVER_CONTROL = uint8(2)
|
||||||
CONN_SERVER = uint8(3)
|
CONN_SERVER = uint8(3)
|
||||||
@ -87,6 +88,8 @@ type HTTPArgs struct {
|
|||||||
SSHUser *string
|
SSHUser *string
|
||||||
SSHKeyBytes []byte
|
SSHKeyBytes []byte
|
||||||
SSHAuthMethod ssh.AuthMethod
|
SSHAuthMethod ssh.AuthMethod
|
||||||
|
KCPMethod *string
|
||||||
|
KCPKey *string
|
||||||
}
|
}
|
||||||
type UDPArgs struct {
|
type UDPArgs struct {
|
||||||
Parent *string
|
Parent *string
|
||||||
@ -122,6 +125,10 @@ type SocksArgs struct {
|
|||||||
Direct *string
|
Direct *string
|
||||||
AuthFile *string
|
AuthFile *string
|
||||||
Auth *[]string
|
Auth *[]string
|
||||||
|
KCPMethod *string
|
||||||
|
KCPKey *string
|
||||||
|
UDPParent *string
|
||||||
|
UDPLocal *string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *TCPArgs) Protocol() string {
|
func (a *TCPArgs) Protocol() string {
|
||||||
|
|||||||
@ -120,8 +120,10 @@ func (s *HTTP) Start(args interface{}) (err error) {
|
|||||||
sc := utils.NewServerChannel(host, p)
|
sc := utils.NewServerChannel(host, p)
|
||||||
if *s.cfg.LocalType == TYPE_TCP {
|
if *s.cfg.LocalType == TYPE_TCP {
|
||||||
err = sc.ListenTCP(s.callback)
|
err = sc.ListenTCP(s.callback)
|
||||||
} else {
|
} else if *s.cfg.LocalType == TYPE_TLS {
|
||||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.callback)
|
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 {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -197,6 +199,7 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
|||||||
if *s.cfg.ParentType == "ssh" {
|
if *s.cfg.ParentType == "ssh" {
|
||||||
outConn, err = s.getSSHConn(address)
|
outConn, err = s.getSSHConn(address)
|
||||||
} else {
|
} else {
|
||||||
|
//log.Printf("%v", s.outPool)
|
||||||
_outConn, err = s.outPool.Pool.Get()
|
_outConn, err = s.outPool.Pool.Get()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
outConn = _outConn.(net.Conn)
|
outConn = _outConn.(net.Conn)
|
||||||
@ -303,12 +306,14 @@ func (s *HTTP) ConnectSSH() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *HTTP) InitOutConnPool() {
|
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,
|
//dur int, isTLS bool, certBytes, keyBytes []byte,
|
||||||
//parent string, timeout int, InitialCap int, MaxCap int
|
//parent string, timeout int, InitialCap int, MaxCap int
|
||||||
s.outPool = utils.NewOutPool(
|
s.outPool = utils.NewOutPool(
|
||||||
*s.cfg.CheckParentInterval,
|
*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.CertBytes, s.cfg.KeyBytes,
|
||||||
*s.cfg.Parent,
|
*s.cfg.Parent,
|
||||||
*s.cfg.Timeout,
|
*s.cfg.Timeout,
|
||||||
|
|||||||
@ -105,8 +105,8 @@ func (s *Socks) InitService() {
|
|||||||
if *s.cfg.ParentType == "ssh" {
|
if *s.cfg.ParentType == "ssh" {
|
||||||
log.Println("warn: socks udp not suppored for ssh")
|
log.Println("warn: socks udp not suppored for ssh")
|
||||||
} else {
|
} 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)
|
err := s.udpSC.ListenUDP(s.udpCallback)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("init udp service fail, ERR: %s", err)
|
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)
|
sc := utils.NewServerChannelHost(*s.cfg.Local)
|
||||||
if *s.cfg.LocalType == TYPE_TCP {
|
if *s.cfg.LocalType == TYPE_TCP {
|
||||||
err = sc.ListenTCP(s.socksConnCallback)
|
err = sc.ListenTCP(s.socksConnCallback)
|
||||||
} else {
|
} else if *s.cfg.LocalType == TYPE_TLS {
|
||||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.socksConnCallback)
|
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 {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -176,7 +178,11 @@ func (s *Socks) udpCallback(b []byte, localAddr, srcAddr *net.UDPAddr) {
|
|||||||
return
|
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 {
|
if err != nil {
|
||||||
log.Printf("can't resolve address: %s", err)
|
log.Printf("can't resolve address: %s", err)
|
||||||
return
|
return
|
||||||
@ -382,7 +388,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque
|
|||||||
}
|
}
|
||||||
host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String())
|
host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String())
|
||||||
_, port, _ := net.SplitHostPort(s.udpSC.UDPListener.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))
|
request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port))
|
||||||
}
|
}
|
||||||
func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) {
|
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()
|
inLocalAddr := (*inConn).LocalAddr().String()
|
||||||
|
|
||||||
log.Printf("conn %s - %s connected [%s]", inAddr, inLocalAddr, request.Addr())
|
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())
|
log.Printf("conn %s - %s released [%s]", inAddr, inLocalAddr, request.Addr())
|
||||||
utils.CloseConn(inConn)
|
utils.CloseConn(inConn)
|
||||||
utils.CloseConn(&outConn)
|
utils.CloseConn(&outConn)
|
||||||
})
|
})
|
||||||
//}, func(i int, b bool) {}, 0)
|
|
||||||
}
|
}
|
||||||
func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn net.Conn, err interface{}) {
|
func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn net.Conn, err interface{}) {
|
||||||
switch *s.cfg.ParentType {
|
switch *s.cfg.ParentType {
|
||||||
|
case "kcp":
|
||||||
|
fallthrough
|
||||||
case "tls":
|
case "tls":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "tcp":
|
case "tcp":
|
||||||
@ -444,6 +451,8 @@ func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn n
|
|||||||
var _outConn tls.Conn
|
var _outConn tls.Conn
|
||||||
_outConn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes)
|
_outConn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes)
|
||||||
outConn = net.Conn(&_outConn)
|
outConn = net.Conn(&_outConn)
|
||||||
|
} else if *s.cfg.ParentType == "kcp" {
|
||||||
|
outConn, err = utils.ConnectKCPHost(*s.cfg.Parent, *s.cfg.KCPMethod, *s.cfg.KCPKey)
|
||||||
} else {
|
} else {
|
||||||
outConn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
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
|
//parent string, timeout int, InitialCap int, MaxCap int
|
||||||
s.outPool = utils.NewOutPool(
|
s.outPool = utils.NewOutPool(
|
||||||
*s.cfg.CheckParentInterval,
|
*s.cfg.CheckParentInterval,
|
||||||
*s.cfg.ParentType == TYPE_TLS,
|
*s.cfg.ParentType,
|
||||||
|
"", "",
|
||||||
s.cfg.CertBytes, s.cfg.KeyBytes,
|
s.cfg.CertBytes, s.cfg.KeyBytes,
|
||||||
*s.cfg.Parent,
|
*s.cfg.Parent,
|
||||||
*s.cfg.Timeout,
|
*s.cfg.Timeout,
|
||||||
|
|||||||
@ -167,7 +167,7 @@ func (s *TunnelBridge) Start(args interface{}) (err error) {
|
|||||||
_, err = inConn.Write([]byte{0x00})
|
_, err = inConn.Write([]byte{0x00})
|
||||||
inConn.SetWriteDeadline(time.Time{})
|
inConn.SetWriteDeadline(time.Time{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("control connection write err %s", err)
|
log.Printf("server control connection write err %s", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second * 3)
|
time.Sleep(time.Second * 3)
|
||||||
@ -181,7 +181,7 @@ func (s *TunnelBridge) Start(args interface{}) (err error) {
|
|||||||
_, err := inConn.Read(signal)
|
_, err := inConn.Read(signal)
|
||||||
inConn.SetReadDeadline(time.Time{})
|
inConn.SetReadDeadline(time.Time{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("control connection read err: %s", err)
|
log.Printf("server control connection read err: %s", err)
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
// log.Printf("heartbeat from server ,id:%s", serverID)
|
// log.Printf("heartbeat from server ,id:%s", serverID)
|
||||||
|
|||||||
@ -207,7 +207,8 @@ func (s *UDP) InitOutConnPool() {
|
|||||||
//parent string, timeout int, InitialCap int, MaxCap int
|
//parent string, timeout int, InitialCap int, MaxCap int
|
||||||
s.outPool = utils.NewOutPool(
|
s.outPool = utils.NewOutPool(
|
||||||
*s.cfg.CheckParentInterval,
|
*s.cfg.CheckParentInterval,
|
||||||
*s.cfg.ParentType == TYPE_TLS,
|
*s.cfg.ParentType,
|
||||||
|
"", "",
|
||||||
s.cfg.CertBytes, s.cfg.KeyBytes,
|
s.cfg.CertBytes, s.cfg.KeyBytes,
|
||||||
*s.cfg.Parent,
|
*s.cfg.Parent,
|
||||||
*s.cfg.Timeout,
|
*s.cfg.Timeout,
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/sha1"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@ -16,92 +17,50 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"sync"
|
|
||||||
|
"golang.org/x/crypto/pbkdf2"
|
||||||
|
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"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)) {
|
func IoBind(dst io.ReadWriter, src io.ReadWriter, fn func(err error)) {
|
||||||
var one = &sync.Once{}
|
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
e1 := make(chan error, 1)
|
||||||
if e := recover(); e != nil {
|
e2 := make(chan error, 1)
|
||||||
log.Printf("IoBind crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
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
|
var err error
|
||||||
_, err = ioCopy(dst, src)
|
select {
|
||||||
if err != nil {
|
case err = <-e1:
|
||||||
one.Do(func() {
|
case err = <-e2:
|
||||||
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)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
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) {
|
func TlsConnectHost(host string, timeout int, certBytes, keyBytes []byte) (conn tls.Conn, err error) {
|
||||||
h := strings.Split(host, ":")
|
h := strings.Split(host, ":")
|
||||||
port, _ := strconv.Atoi(h[1])
|
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)
|
conn, err = net.DialTimeout("tcp", hostAndPort, time.Duration(timeout)*time.Millisecond)
|
||||||
return
|
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) {
|
func ListenTls(ip string, port int, certBytes, keyBytes []byte) (ln *net.Listener, err error) {
|
||||||
var cert tls.Certificate
|
var cert tls.Certificate
|
||||||
cert, err = tls.X509KeyPair(certBytes, keyBytes)
|
cert, err = tls.X509KeyPair(certBytes, keyBytes)
|
||||||
@ -406,6 +369,38 @@ func TlsBytes(cert, key string) (certBytes, keyBytes []byte) {
|
|||||||
}
|
}
|
||||||
return
|
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 {
|
// type sockaddr struct {
|
||||||
// family uint16
|
// family uint16
|
||||||
|
|||||||
@ -6,6 +6,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
kcp "github.com/xtaci/kcp-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServerChannel struct {
|
type ServerChannel struct {
|
||||||
@ -55,7 +57,7 @@ func (sc *ServerChannel) ListenTls(certBytes, keyBytes []byte, fn func(conn net.
|
|||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
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)
|
fn(conn)
|
||||||
@ -89,7 +91,7 @@ func (sc *ServerChannel) ListenTCP(fn func(conn net.Conn)) (err error) {
|
|||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
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)
|
fn(conn)
|
||||||
@ -136,3 +138,35 @@ func (sc *ServerChannel) ListenUDP(fn func(packet []byte, localAddr, srcAddr *ne
|
|||||||
}
|
}
|
||||||
return
|
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 {
|
type OutPool struct {
|
||||||
Pool ConnPool
|
Pool ConnPool
|
||||||
dur int
|
dur int
|
||||||
isTLS bool
|
typ string
|
||||||
certBytes []byte
|
certBytes []byte
|
||||||
keyBytes []byte
|
keyBytes []byte
|
||||||
|
kcpMethod string
|
||||||
|
kcpKey string
|
||||||
address string
|
address string
|
||||||
timeout int
|
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{
|
op = OutPool{
|
||||||
dur: dur,
|
dur: dur,
|
||||||
isTLS: isTLS,
|
typ: typ,
|
||||||
certBytes: certBytes,
|
certBytes: certBytes,
|
||||||
keyBytes: keyBytes,
|
keyBytes: keyBytes,
|
||||||
|
kcpMethod: kcpMethod,
|
||||||
|
kcpKey: kcpKey,
|
||||||
address: address,
|
address: address,
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
}
|
}
|
||||||
@ -436,12 +440,14 @@ func NewOutPool(dur int, isTLS bool, certBytes, keyBytes []byte, address string,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (op *OutPool) getConn() (conn interface{}, err error) {
|
func (op *OutPool) getConn() (conn interface{}, err error) {
|
||||||
if op.isTLS {
|
if op.typ == "tls" {
|
||||||
var _conn tls.Conn
|
var _conn tls.Conn
|
||||||
_conn, err = TlsConnectHost(op.address, op.timeout, op.certBytes, op.keyBytes)
|
_conn, err = TlsConnectHost(op.address, op.timeout, op.certBytes, op.keyBytes)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
conn = net.Conn(&_conn)
|
conn = net.Conn(&_conn)
|
||||||
}
|
}
|
||||||
|
} else if op.typ == "kcp" {
|
||||||
|
conn, err = ConnectKCPHost(op.address, op.kcpMethod, op.kcpKey)
|
||||||
} else {
|
} else {
|
||||||
conn, err = ConnectHost(op.address, op.timeout)
|
conn, err = ConnectHost(op.address, op.timeout)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user