22 Commits
v3.4 ... v3.5

Author SHA1 Message Date
arraykeys@gmail.com
319affa43f Merge branch 'master' of https://github.com/snail007/goproxy.git 2017-11-03 13:30:06 +08:00
arraykeys@gmail.com
14f43a5976 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-03 13:27:36 +08:00
arraykeys@gmail.com
9e9a9ac6de Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-03 12:50:50 +08:00
arraykeys@gmail.com
cc24cfc26f Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-03 11:11:53 +08:00
arraykeys@gmail.com
712f7dae4a Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-02 17:52:41 +08:00
arraykeys@gmail.com
6d20908465 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-01 11:20:25 +08:00
arraykeys@gmail.com
e2f0fe71f4 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-30 14:20:13 +08:00
arraykeys@gmail.com
1241b74562 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-27 18:35:39 +08:00
arraykeys@gmail.com
2d610003d5 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-27 18:34:36 +08:00
arraykeys@gmail.com
7b2952f4d6 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-27 18:33:00 +08:00
arraykeys@gmail.com
b18c5e08bb Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-27 18:31:39 +08:00
arraykeys@gmail.com
63cb67f009 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-27 18:30:32 +08:00
arraykeys@gmail.com
cd212cb978 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-27 18:29:37 +08:00
arraykeys@gmail.com
d934c1fb4a Merge branch 'dev' of https://github.com/snail007/goproxy.git into dev 2017-10-27 16:53:59 +08:00
arraykeys@gmail.com
c8327b4075 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-27 16:52:54 +08:00
snail007
8410930d2d Update README.md 2017-10-27 16:29:52 +08:00
arraykeys@gmail.com
f5218a93f6 Merge branch 'dev' of https://github.com/snail007/goproxy.git into dev 2017-10-27 16:06:41 +08:00
arraykeys@gmail.com
ca2f367950 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-27 15:59:49 +08:00
snail007
c8559b757f Merge pull request #9 from snail007/dev
Update README.md
2017-10-26 20:01:14 +08:00
snail007
db620ebe83 Update README.md 2017-10-26 19:59:45 +08:00
arraykeys@gmail.com
abc7a4fa42 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-26 17:13:02 +08:00
arraykeys@gmail.com
b02d75eb3a Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-10-26 15:45:24 +08:00
13 changed files with 206 additions and 78 deletions

View File

@ -1,4 +1,13 @@
proxy更新日志
v3.5
1.优化了kcp参数,速度有所提升.
2.修复了socks无法正常工作的问题.
3.修正了文档中的一些描述.
4.tcp代理增加了kcp协议传输数据.
5.优化了死循环检查,增加了添加本地IP参数,当VPS在nat设备后面,
vps上网卡IP都是内网IP,这个时候可以通过-g参数添加vps的外网ip防止死循环.
6.增加了--daemon参数,可以后台运行程序哟.
v3.4
1.socks5代理新增了用户名密码验证支持.
2.socks5,http(s)代理增加了kcp传输协议支持.

View File

@ -13,10 +13,11 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
- 跨平台性,无论你是widows,linux,还是mac,甚至是树莓派,都可以很好的运行proxy.
- 多协议支持,支持HTTP(S),TCP,UDP,Websocket,SOCKS5代理.
- 支持内网穿透,协议支持TCP和UDP.
- HTTP(S),SOCKS5代理支持SSH中转,上级Linux服务器不需要任何服务端,本地一个proxy即可开心上网.
- SSH中转,HTTP(S),SOCKS5代理支持SSH中转,上级Linux服务器不需要任何服务端,本地一个proxy即可开心上网.
- 支持[KCP](https://github.com/xtaci/kcp-go)协议,HTTP(S),SOCKS5代理支持KCP协议传输数据,降低延迟,提升浏览体验.
### Why need these?
- 当由于安全因素或者限制,我们不能顺畅的访问我们在其它地方的服务,我们可以通过多个相连的proxy节点建立起一个安全的隧道,顺畅的访问我们的服务.
- 当由于某某原因,我们不能访问我们在其它地方的服务,我们可以通过多个相连的proxy节点建立起一个安全的隧道访问我们的服务.  
- 微信接口本地开发,方便调试.
- 远程访问内网机器.
- 和小伙伴一起玩局域网游戏.
@ -37,9 +38,11 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
1. [手动安装](#手动安装)
### 首次使用必看
- [环境](#使用教程)
- [环境](#首次使用必看-1)
- [使用配置文件](#使用配置文件)
- [后台运行](#后台运行)
- [生成通讯证书文件](#生成加密通讯需要的证书文件)
- [安全建议](#安全建议)
### 手册目录
- [1. HTTP代理](#1http代理)
@ -52,7 +55,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
- [1.7 通过SSH中转](#17https通过ssh中转)
- [1.7.1 用户名和密码的方式](#171-ssh用户名和密码的方式)
- [1.7.2 用户名和密钥的方式](#172-ssh用户名和密钥的方式)
- [1.8 KCP协议传输](#18KCP协议传输)
- [1.8 KCP协议传输](#18kcp协议传输)
- [1.9 查看帮助](#19查看帮助)
- [2. TCP代理](#2tcp代理)
- [2.1 普通一级TCP代理](#21普通一级tcp代理)
@ -87,7 +90,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
- [5.6.1 用户名和密码的方式](#561-ssh用户名和密码的方式)
- [5.6.2 用户名和密钥的方式](#562-ssh用户名和密钥的方式)
- [5.7 认证](#57认证)
- [5.8 KCP协议传输](#58KCP协议传输)
- [5.8 KCP协议传输](#58kcp协议传输)
- [5.9 查看帮助](#59查看帮助)
### Fast Start
@ -114,7 +117,7 @@ wget https://github.com/reddec/monexec/releases/download/v0.1.1/monexec_0.1.1_li
下载地址:https://github.com/snail007/goproxy/releases
```shell
cd /root/proxy/
wget https://github.com/snail007/goproxy/releases/download/v3.1fix/proxy-linux-amd64.tar.gz
wget https://github.com/snail007/goproxy/releases/download/v3.4/proxy-linux-amd64.tar.gz
```
#### **3.下载自动安装脚本**
```shell
@ -124,9 +127,9 @@ chmod +x install.sh
./install.sh
```
## 使用教程
## 首次使用必看
#### **提示**
#### **环境**
接下来的教程,默认系统是linux,程序是proxy所有操作需要root权限
如果你的是windows,请使用windows版本的proxy.exe即可.
@ -141,13 +144,25 @@ http
--local-type=tcp
--local=:33080
```
### 0.生成加密通讯需要的证书文件
### 生成加密通讯需要的证书文件
http,tcp,udp代理过程会和上级通讯,为了安全我们采用加密通讯,当然可以选择不加密通信通讯,本教程所有和上级通讯都采用加密,需要证书文件.
在linux上并安装了openssl命令可以直接通过下面的命令生成证书和key文件.
`./proxy keygen`
默认会在当前程序目录下面生成证书文件proxy.crt和key文件proxy.key。
### 后台运行
默认执行proxy之后,如果要保持proxy运行,不能关闭命令行.
如果想在后台运行proxy,命令行可以关闭,只需要在命令最后加上--daemon参数即可.
比如:
`./proxy http -t tcp -p "0.0.0.0:38080" --daemon`
更推荐用monexec守护运行proxy比较好.
### 安全建议
当VPS在nat设备后面,vps上网卡IP都是内网IP,这个时候可以通过-g参数添加vps的外网ip防止死循环.
假设你的vps外网ip是23.23.23.23,下面命令通过-g参数设置23.23.23.23
`./proxy http -g "23.23.23.23"`
### 1.HTTP代理
#### **1.1.普通HTTP代理**
`./proxy http -t tcp -p "0.0.0.0:38080"`
@ -211,7 +226,7 @@ http,tcp,udp代理过程会和上级通讯,为了安全我们采用加密通讯,
KCP协议需要-B参数设置一个密码用于加密解密数据
一级HTTP代理(VPS,IP:22.22.22.22)
`./proxy http -t kcp -p ":38080" -B mypassword
`./proxy http -t kcp -p ":38080" -B mypassword`
二级HTTP代理(本地Linux)
`./proxy http -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" -B mypassword`
@ -439,7 +454,7 @@ server连接到bridge的时候,如果同时有多个client连接到同一个brid
`./proxy help tserver`
### 5.SOCKS5代理
提示:SOCKS5代理,只支持TCP协议,不支持UDP协议,不支持用户名密码认证.
提示:SOCKS5代理,支持CONNECT,UDP协议,不支持BIND,支持用户名密码认证.
#### **5.1.普通SOCKS5代理**
`./proxy socks -t tcp -p "0.0.0.0:38080"`
@ -501,7 +516,7 @@ server连接到bridge的时候,如果同时有多个client连接到同一个brid
KCP协议需要-B参数设置一个密码用于加密解密数据
一级HTTP代理(VPS,IP:22.22.22.22)
`./proxy socks -t kcp -p ":38080" -B mypassword
`./proxy socks -t kcp -p ":38080" -B mypassword`
二级HTTP代理(本地Linux)
`./proxy socks -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" -B mypassword`

View File

@ -4,6 +4,7 @@ import (
"fmt"
"log"
"os"
"os/exec"
"proxy/services"
"proxy/utils"
@ -36,6 +37,7 @@ func initConfig() (err error) {
app = kingpin.New("proxy", "happy with proxy")
app.Author("snail").Version(APP_VERSION)
debug := app.Flag("debug", "debug log output").Default("false").Bool()
daemon := app.Flag("daemon", "run proxy in background").Default("false").Bool()
//########http#########
http := app.Command("http", "proxy on http mode")
httpArgs.Parent = http.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
@ -60,18 +62,21 @@ func initConfig() (err error) {
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()
httpArgs.LocalIPS = http.Flag("local bind ips", "if your host behind a nat,set your public ip here avoid dead loop").Short('g').Strings()
//########tcp#########
tcp := app.Command("tcp", "proxy on tcp mode")
tcpArgs.Parent = tcp.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
tcpArgs.CertFile = tcp.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
tcpArgs.KeyFile = tcp.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('t').Default("2000").Int()
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|udp>").Short('T').Enum("tls", "tcp", "udp")
tcpArgs.IsTLS = tcp.Flag("tls", "proxy on tls mode").Default("false").Bool()
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('e').Default("2000").Int()
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|kcp|udp>").Short('T').Enum("tls", "tcp", "udp", "kcp")
tcpArgs.LocalType = tcp.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
tcpArgs.PoolSize = tcp.Flag("pool-size", "conn pool size , which connect to parent proxy, zero: means turn off pool").Short('L').Default("0").Int()
tcpArgs.CheckParentInterval = tcp.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
tcpArgs.Local = tcp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
tcpArgs.KCPKey = tcp.Flag("kcp-key", "key for kcp encrypt/decrypt data").Short('B').Default("encrypt").String()
tcpArgs.KCPMethod = tcp.Flag("kcp-method", "kcp encrypt/decrypt method").Short('M').Default("3des").String()
//########udp#########
udp := app.Command("udp", "proxy on udp mode")
@ -132,10 +137,23 @@ func initConfig() (err error) {
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()
socksArgs.LocalIPS = socks.Flag("local bind ips", "if your host behind a nat,set your public ip here avoid dead loop").Short('g').Strings()
//parse args
serviceName := kingpin.MustParse(app.Parse(os.Args[1:]))
flags := log.Ldate
if *daemon {
args := []string{}
for _, arg := range os.Args[1:] {
if arg != "--daemon" {
args = append(args, arg)
}
}
cmd := exec.Command(os.Args[0], args...)
cmd.Start()
fmt.Printf("%s [PID] %d running...\n", os.Args[0], cmd.Process.Pid)
os.Exit(0)
}
if *debug {
flags |= log.Lshortfile | log.Lmicroseconds
} else {

View File

@ -9,7 +9,7 @@ import (
"syscall"
)
const APP_VERSION = "3.4"
const APP_VERSION = "3.5"
func main() {
err := initConfig()

View File

@ -1,5 +1,5 @@
#!/bin/bash
VER="3.4"
VER="3.5"
RELEASE="release-${VER}"
rm -rf .cert
mkdir .cert
@ -9,7 +9,7 @@ cd .cert
cd ..
rm -rf ${RELEASE}
mkdir ${RELEASE}
set CGO_ENABLED=0
export CGO_ENABLED=0
#linux
GOOS=linux GOARCH=386 go build && tar zcfv "${RELEASE}/proxy-linux-386.tar.gz" proxy direct blocked
GOOS=linux GOARCH=amd64 go build && tar zcfv "${RELEASE}/proxy-linux-amd64.tar.gz" proxy direct blocked
@ -61,3 +61,9 @@ GOOS=windows GOARCH=386 go build && tar zcfv "${RELEASE}/proxy-windows-386.tar.g
GOOS=windows GOARCH=amd64 go build && tar zcfv "${RELEASE}/proxy-windows-amd64.tar.gz" proxy.exe direct blocked .cert/proxy.crt .cert/proxy.key
rm -rf proxy proxy.exe .cert
#todo
#1.release.sh VER="xxx"
#2.main.go APP_VERSION="xxx"
#3.install_auto.sh goproxy/releases/download/vxxx
#4.README goproxy/releases/download/vxxx

View File

@ -58,10 +58,12 @@ type TCPArgs struct {
KeyBytes []byte
Local *string
ParentType *string
IsTLS *bool
LocalType *string
Timeout *int
PoolSize *int
CheckParentInterval *int
KCPMethod *string
KCPKey *string
}
type HTTPArgs struct {
@ -91,6 +93,7 @@ type HTTPArgs struct {
SSHAuthMethod ssh.AuthMethod
KCPMethod *string
KCPKey *string
LocalIPS *[]string
}
type UDPArgs struct {
Parent *string
@ -130,11 +133,17 @@ type SocksArgs struct {
KCPKey *string
UDPParent *string
UDPLocal *string
LocalIPS *[]string
}
func (a *TCPArgs) Protocol() string {
if *a.IsTLS {
return "tls"
switch *a.LocalType {
case TYPE_TLS:
return TYPE_TLS
case TYPE_TCP:
return TYPE_TCP
case TYPE_KCP:
return TYPE_KCP
}
return "tcp"
return "unknown"
}

View File

@ -223,7 +223,7 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
}
outAddr := outConn.RemoteAddr().String()
outLocalAddr := outConn.LocalAddr().String()
//outLocalAddr := outConn.LocalAddr().String()
if req.IsHTTPS() && (!useProxy || *s.cfg.ParentType == "ssh") {
//https无上级或者上级非代理,proxy需要响应connect请求,并直连目标
@ -238,12 +238,10 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
}
}
utils.IoBind((*inConn), outConn, func(err error) {
log.Printf("conn %s - %s - %s - %s released [%s]", inAddr, inLocalAddr, outLocalAddr, outAddr, req.Host)
utils.CloseConn(inConn)
utils.CloseConn(&outConn)
utils.IoBind((*inConn), outConn, func(err interface{}) {
log.Printf("conn %s - %s released [%s]", inAddr, outAddr, req.Host)
})
log.Printf("conn %s - %s - %s - %s connected [%s]", inAddr, inLocalAddr, outLocalAddr, outAddr, req.Host)
log.Printf("conn %s - %s connected [%s]", inAddr, outAddr, req.Host)
return
}
@ -362,6 +360,9 @@ func (s *HTTP) IsDeadLoop(inLocalAddr string, host string) bool {
}
}
interfaceIPs, err := utils.GetAllInterfaceAddr()
for _, ip := range *s.cfg.LocalIPS {
interfaceIPs = append(interfaceIPs, net.ParseIP(ip).To4())
}
if err == nil {
for _, localIP := range interfaceIPs {
for _, outIP := range outIPs {

View File

@ -167,6 +167,11 @@ func (s *Socks) udpCallback(b []byte, localAddr, srcAddr *net.UDPAddr) {
log.Printf("parse udp packet fail, ERR:%s", err)
return
}
//防止死循环
if s.IsDeadLoop((*localAddr).String(), p.Host()) {
log.Printf("dead loop detected , %s", p.Host())
return
}
//log.Printf("##########udp to -> %s:%s###########", p.Host(), p.Port())
if *s.cfg.Parent != "" {
//有上级代理,转发给上级
@ -288,8 +293,8 @@ func (s *Socks) socksConnCallback(inConn net.Conn) {
defer func() {
if err := recover(); err != nil {
log.Printf("socks conn handler crashed with err : %s \nstack: %s", err, string(debug.Stack()))
inConn.Close()
}
utils.CloseConn(&inConn)
}()
//协商开始
@ -393,11 +398,17 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque
}
func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) {
var outConn net.Conn
defer utils.CloseConn(&outConn)
var err interface{}
useProxy := true
tryCount := 0
maxTryCount := 5
//防止死循环
if s.IsDeadLoop((*inConn).LocalAddr().String(), request.Host()) {
utils.CloseConn(inConn)
log.Printf("dead loop detected , %s", request.Host())
utils.CloseConn(inConn)
return
}
for {
if *s.cfg.Always {
outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr())
@ -412,10 +423,11 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque
}
} else {
outConn, err = utils.ConnectHost(request.Addr(), *s.cfg.Timeout)
useProxy = false
}
}
tryCount++
if err == nil || tryCount > maxTryCount {
if err == nil || tryCount > maxTryCount || *s.cfg.Parent == "" {
break
} else {
log.Printf("get out conn fail,%s,retrying...", err)
@ -431,13 +443,11 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque
request.TCPReply(socks.REP_SUCCESS)
inAddr := (*inConn).RemoteAddr().String()
inLocalAddr := (*inConn).LocalAddr().String()
//inLocalAddr := (*inConn).LocalAddr().String()
log.Printf("conn %s - %s connected [%s]", inAddr, inLocalAddr, request.Addr())
utils.IoBind(*inConn, outConn, func(err error) {
log.Printf("conn %s - %s released [%s]", inAddr, inLocalAddr, request.Addr())
utils.CloseConn(inConn)
utils.CloseConn(&outConn)
log.Printf("conn %s - %s connected", inAddr, request.Addr())
utils.IoBind(*inConn, outConn, func(err interface{}) {
log.Printf("conn %s - %s released", inAddr, request.Addr())
})
}
func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn net.Conn, err interface{}) {
@ -568,3 +578,38 @@ func (s *Socks) InitBasicAuth() (err error) {
func (s *Socks) IsBasicAuth() bool {
return *s.cfg.AuthFile != "" || len(*s.cfg.Auth) > 0
}
func (s *Socks) IsDeadLoop(inLocalAddr string, host string) bool {
inIP, inPort, err := net.SplitHostPort(inLocalAddr)
if err != nil {
return false
}
outDomain, outPort, err := net.SplitHostPort(host)
if err != nil {
return false
}
if inPort == outPort {
var outIPs []net.IP
outIPs, err = net.LookupIP(outDomain)
if err == nil {
for _, ip := range outIPs {
if ip.String() == inIP {
return true
}
}
}
interfaceIPs, err := utils.GetAllInterfaceAddr()
for _, ip := range *s.cfg.LocalIPS {
interfaceIPs = append(interfaceIPs, net.ParseIP(ip).To4())
}
if err == nil {
for _, localIP := range interfaceIPs {
for _, outIP := range outIPs {
if localIP.Equal(outIP) {
return true
}
}
}
}
}
return false
}

View File

@ -29,9 +29,9 @@ func (s *TCP) CheckArgs() {
log.Fatalf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local)
}
if *s.cfg.ParentType == "" {
log.Fatalf("parent type unkown,use -T <tls|tcp>")
log.Fatalf("parent type unkown,use -T <tls|tcp|kcp|udp>")
}
if *s.cfg.ParentType == "tls" || *s.cfg.IsTLS {
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.LocalType == TYPE_TLS {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
}
}
@ -52,10 +52,13 @@ func (s *TCP) Start(args interface{}) (err error) {
host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p)
if !*s.cfg.IsTLS {
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
@ -75,6 +78,8 @@ func (s *TCP) callback(inConn net.Conn) {
}()
var err error
switch *s.cfg.ParentType {
case TYPE_KCP:
fallthrough
case TYPE_TCP:
fallthrough
case TYPE_TLS:
@ -102,15 +107,13 @@ func (s *TCP) OutToTCP(inConn *net.Conn) (err error) {
return
}
inAddr := (*inConn).RemoteAddr().String()
inLocalAddr := (*inConn).LocalAddr().String()
//inLocalAddr := (*inConn).LocalAddr().String()
outAddr := outConn.RemoteAddr().String()
outLocalAddr := outConn.LocalAddr().String()
utils.IoBind((*inConn), outConn, func(err error) {
log.Printf("conn %s - %s - %s - %s released", inAddr, inLocalAddr, outLocalAddr, outAddr)
utils.CloseConn(inConn)
utils.CloseConn(&outConn)
//outLocalAddr := outConn.LocalAddr().String()
utils.IoBind((*inConn), outConn, func(err interface{}) {
log.Printf("conn %s - %s released", inAddr, outAddr)
})
log.Printf("conn %s - %s - %s - %s connected", inAddr, inLocalAddr, outLocalAddr, outAddr)
log.Printf("conn %s - %s connected", inAddr, outAddr)
return
}
func (s *TCP) OutToUDP(inConn *net.Conn) (err error) {
@ -162,13 +165,14 @@ func (s *TCP) OutToUDP(inConn *net.Conn) (err error) {
}
func (s *TCP) 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,
"", "",
*s.cfg.KCPMethod,
*s.cfg.KCPKey,
s.cfg.CertBytes, s.cfg.KeyBytes,
*s.cfg.Parent,
*s.cfg.Timeout,

View File

@ -112,9 +112,7 @@ func (s *TunnelBridge) Start(args interface{}) (err error) {
return
}
serverConn := serverConnItem.(ServerConn).Conn
utils.IoBind(*serverConn, inConn, func(err error) {
(*serverConn).Close()
utils.CloseConn(&inConn)
utils.IoBind(*serverConn, inConn, func(err interface{}) {
s.serverConns.Remove(ID)
s.cmClient.RemoveOne(key, ID)
s.cmServer.RemoveOne(serverID, ID)

View File

@ -72,7 +72,7 @@ func (s *TunnelClient) InitHeartbeatDeamon() {
log.Printf("heartbeat connection read err: %s", err)
break
} else {
log.Printf("heartbeat from bridge")
//log.Printf("heartbeat from bridge")
}
}
close(readDie)
@ -273,10 +273,8 @@ func (s *TunnelClient) ServeConn(localAddr, ID, serverID string) {
log.Printf("build connection error, err: %s", err)
return
}
utils.IoBind(inConn, outConn, func(err error) {
utils.IoBind(inConn, outConn, func(err interface{}) {
log.Printf("conn %s released", ID)
utils.CloseConn(&inConn)
utils.CloseConn(&outConn)
s.cm.RemoveOne(*s.cfg.Key, ID)
})
s.cm.Add(*s.cfg.Key, ID, &inConn)

View File

@ -240,9 +240,7 @@ func (s *TunnelServer) Start(args interface{}) (err error) {
break
}
}
utils.IoBind(inConn, outConn, func(err error) {
utils.CloseConn(&outConn)
utils.CloseConn(&inConn)
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)
})

View File

@ -20,7 +20,6 @@ import (
"golang.org/x/crypto/pbkdf2"
"runtime/debug"
"strconv"
"strings"
"time"
@ -28,39 +27,60 @@ import (
kcp "github.com/xtaci/kcp-go"
)
func IoBind(dst io.ReadWriter, src io.ReadWriter, fn func(err error)) {
go func() {
e1 := make(chan error, 1)
e2 := make(chan error, 1)
func IoBind(dst io.ReadWriteCloser, src io.ReadWriteCloser, fn func(err interface{})) {
go func() {
defer func() {
if e := recover(); e != nil {
log.Printf("IoBind crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
if err := recover(); err != nil {
log.Printf("bind crashed %s", err)
}
}()
_, e := io.Copy(dst, src)
e1 <- e
e1 := make(chan interface{}, 1)
e2 := make(chan interface{}, 1)
go func() {
defer func() {
if err := recover(); err != nil {
log.Printf("bind crashed %s", err)
}
}()
_, err := io.Copy(dst, src)
e1 <- err
}()
go func() {
defer func() {
if e := recover(); e != nil {
log.Printf("IoBind crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
if err := recover(); err != nil {
log.Printf("bind crashed %s", err)
}
}()
_, e := io.Copy(src, dst)
e2 <- e
_, err := io.Copy(src, dst)
e2 <- err
}()
var err error
var err interface{}
select {
case err = <-e1:
//log.Printf("e1")
case err = <-e2:
//log.Printf("e2")
}
src.Close()
dst.Close()
fn(err)
}()
}
func ioCopy(dst io.ReadWriter, src io.ReadWriter) (err error) {
buf := make([]byte, 32*1024)
n := 0
for {
n, err = src.Read(buf)
if n > 0 {
if _, e := dst.Write(buf[0:n]); e != nil {
return e
}
}
if err != nil {
return
}
}
}
func TlsConnectHost(host string, timeout int, certBytes, keyBytes []byte) (conn tls.Conn, err error) {
h := strings.Split(host, ":")
port, _ := strconv.Atoi(h[1])
@ -103,8 +123,15 @@ func ConnectHost(hostAndPort string, timeout int) (conn net.Conn, err error) {
return
}
func ConnectKCPHost(hostAndPort, method, key string) (conn net.Conn, err error) {
conn, err = kcp.DialWithOptions(hostAndPort, GetKCPBlock(method, key), 10, 3)
kcpconn, err := kcp.DialWithOptions(hostAndPort, GetKCPBlock(method, key), 10, 3)
if err != nil {
return
}
kcpconn.SetNoDelay(1, 10, 2, 1)
kcpconn.SetWindowSize(1024, 1024)
kcpconn.SetMtu(1400)
kcpconn.SetACKNoDelay(false)
return kcpconn, err
}
func ListenTls(ip string, port int, certBytes, keyBytes []byte) (ln *net.Listener, err error) {
var cert tls.Certificate