20 Commits
v3.6 ... v3.9

Author SHA1 Message Date
arraykeys@gmail.com
ee93171c63 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-30 15:37:27 +08:00
arraykeys@gmail.com
ddd2302cb2 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-30 15:37:01 +08:00
arraykeys@gmail.com
c96d2288b3 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-30 15:33:32 +08:00
arraykeys@gmail.com
6f5a088091 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-30 14:25:44 +08:00
arraykeys@gmail.com
9a07797e29 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-27 12:44:43 +08:00
arraykeys@gmail.com
055a020d33 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-27 12:41:12 +08:00
arraykeys@gmail.com
4681ff3827 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-27 12:21:59 +08:00
arraykeys@gmail.com
cff92faf06 Merge branch 'master' of https://github.com/snail007/goproxy.git into dev 2017-11-27 11:28:24 +08:00
arraykeys@gmail.com
890daf5489 Merge branch 'dev' of https://github.com/snail007/goproxy.git into dev 2017-11-27 11:28:17 +08:00
snail007
182bdeb766 Merge pull request #14 from snail007/dev
Update README.md
2017-11-23 19:27:53 -06:00
snail007
a4a953b167 Update README.md 2017-11-24 09:27:07 +08:00
arraykeys@gmail.com
ff37b7e18c Merge branch 'dev' 2017-11-21 14:03:24 +08:00
arraykeys@gmail.com
7aa0e78c15 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-21 14:02:28 +08:00
arraykeys@gmail.com
d798807693 Merge branch 'dev' 2017-11-14 11:58:06 +08:00
arraykeys@gmail.com
35b78c2da6 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-14 11:57:56 +08:00
arraykeys@gmail.com
66a4291c97 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-14 11:56:24 +08:00
arraykeys@gmail.com
e89a965aff Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-14 10:02:51 +08:00
arraykeys@gmail.com
85a9f10be4 Merge branch 'dev' 2017-11-09 13:11:57 +08:00
arraykeys@gmail.com
8bc6e0ffec Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-09 13:11:47 +08:00
arraykeys@gmail.com
98fc0ade4a Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2017-11-07 11:31:12 +08:00
16 changed files with 404 additions and 293 deletions

View File

@ -1,4 +1,18 @@
proxy更新日志
v3.9
1.增加了守护运行参数--forever,比如: proxy http --forever ,
proxy会fork子进程,然后监控子进程,如果子进程异常退出,5秒后重启子进程.
该参数配合后台运行参数--daemon和日志参数--log,可以保障proxy一直在后台执行不会因为意外退出,
而且可以通过日志文件看到proxy的输出日志内容.
比如: proxy http -p ":9090" --forever --log proxy.log --daemon
v3.8
1.增加了日志输出到文件--log参数,比如: --log proxy.log,日志就会输出到proxy.log方便排除问题.
v3.7
1.修复了socks代理不能正常和上级代理通讯的问题.
v3.6
1.http(s),socks代理,集成了外部HTTP API认证,可以通过外部API对用户名和密码进行认证.
2.手册http(s),socks代理认证部分增加了集成外部HTTP API认证的使用说明.

View File

@ -14,7 +14,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
- 多协议支持,支持HTTP(S),TCP,UDP,Websocket,SOCKS5代理.
- 支持内网穿透,协议支持TCP和UDP.
- SSH中转,HTTP(S),SOCKS5代理支持SSH中转,上级Linux服务器不需要任何服务端,本地一个proxy即可开心上网.
- 支持[KCP](https://github.com/xtaci/kcp-go)协议,HTTP(S),SOCKS5代理支持KCP协议传输数据,降低延迟,提升浏览体验.
- [KCP](https://github.com/xtaci/kcp-go)协议支持,HTTP(S),SOCKS5代理支持KCP协议传输数据,降低延迟,提升浏览体验.
- 集成外部APIHTTP(S),SOCKS5代理认证功能可以与外部HTTP API集成可以方便的通过外部系统控制代理用户
### Why need these?
- 当由于某某原因,我们不能访问我们在其它地方的服务,我们可以通过多个相连的proxy节点建立起一个安全的隧道访问我们的服务.  
@ -26,7 +27,9 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
- ...  
本页是v3.6手册,其他版本手册请点击下面链接查看.
本页是v3.9手册,其他版本手册请点击下面链接查看.
- [v3.8手册](https://github.com/snail007/goproxy/tree/v3.8)
- [v3.6-v3.7手册](https://github.com/snail007/goproxy/tree/v3.6)
- [v3.5手册](https://github.com/snail007/goproxy/tree/v3.5)
- [v3.4手册](https://github.com/snail007/goproxy/tree/v3.4)
- [v3.3手册](https://github.com/snail007/goproxy/tree/v3.3)
@ -35,6 +38,9 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
- [v3.0手册](https://github.com/snail007/goproxy/tree/v3.0)
- [v2.x手册](https://github.com/snail007/goproxy/tree/v2.2)
### 怎么找到组织?
[点击加入交流组织](https://gitter.im/go-proxy/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link)
### 安装
1. [快速安装](#自动安装)
1. [手动安装](#手动安装)
@ -42,7 +48,10 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
### 首次使用必看
- [环境](#首次使用必看-1)
- [使用配置文件](#使用配置文件)
- [调试输出](#调试输出)
- [使用日志文件](#使用日志文件)
- [后台运行](#后台运行)
- [守护运行](#守护运行)
- [生成通讯证书文件](#生成加密通讯需要的证书文件)
- [安全建议](#安全建议)
@ -106,22 +115,14 @@ curl -L https://raw.githubusercontent.com/snail007/goproxy/master/install_auto.s
如果安装失败或者你的vps不是linux64位系统,请按照下面的半自动步骤安装:
#### 手动安装
#### **1.登录你的VPS,下载守护进程monexec,选择合适你的版本,vps一般选择"linux_amd64.tar.gz"的即可.**
下载地址:https://github.com/reddec/monexec/releases
比如下载到/root/proxy/
执行:
```shell
mkdir /root/proxy/
cd /root/proxy/
wget https://github.com/reddec/monexec/releases/download/v0.1.1/monexec_0.1.1_linux_amd64.tar.gz
```
#### **2.下载proxy**
#### **1.下载proxy**
下载地址:https://github.com/snail007/goproxy/releases
```shell
cd /root/proxy/
wget https://github.com/snail007/goproxy/releases/download/v3.6/proxy-linux-amd64.tar.gz
wget https://github.com/snail007/goproxy/releases/download/v3.9/proxy-linux-amd64.tar.gz
```
#### **3.下载自动安装脚本**
#### **2.下载自动安装脚本**
```shell
cd /root/proxy/
wget https://raw.githubusercontent.com/snail007/goproxy/master/install.sh
@ -129,7 +130,7 @@ chmod +x install.sh
./install.sh
```
## 首次使用必看
## **首次使用必看**
#### **环境**
接下来的教程,默认系统是linux,程序是proxy所有操作需要root权限
@ -146,26 +147,40 @@ http
--local-type=tcp
--local=:33080
```
### 生成加密通讯需要的证书文件
### **调试输出**
默认情况下,日志输出的信息不包含文件行数,某些情况下为了排除程序问题,快速定位问题,
可以使用--debug参数,输出代码行数和毫秒时间.
### **使用日志文件**
默认情况下,日志是直接在控制台显示出来的,如果要保存到文件,可以使用--log参数,
比如: --log proxy.log,日志就会输出到proxy.log方便排除问题.
### **生成加密通讯需要的证书文件**
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比较好.
### 安全建议
### **守护运行**
守护运行参数--forever,比如: `proxy http --forever` ,
proxy会fork子进程,然后监控子进程,如果子进程异常退出,5秒后重启子进程.
该参数配合后台运行参数--daemon和日志参数--log,可以保障proxy一直在后台执行不会因为意外退出,
而且可以通过日志文件看到proxy的输出日志内容.
比如: `proxy http -p ":9090" --forever --log proxy.log --daemon`
### **安全建议**
当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.HTTP代理**
#### **1.1.普通HTTP代理**
`./proxy http -t tcp -p "0.0.0.0:38080"`
@ -251,7 +266,7 @@ KCP协议需要-B参数设置一个密码用于加密解密数据
#### **1.9.查看帮助**
`./proxy help http`
### 2.TCP代理
### **2.TCP代理**
#### **2.1.普通一级TCP代理**
本地执行:
@ -293,7 +308,7 @@ VPS(IP:22.22.22.33)执行:
#### **2.6.查看帮助**
`./proxy help tcp`
### 3.UDP代理
### **3.UDP代理**
#### **3.1.普通一级UDP代理**
本地执行:
@ -335,7 +350,7 @@ VPS(IP:22.22.22.33)执行:
#### **3.6.查看帮助**
`./proxy help udp`
### 4.内网穿透
### **4.内网穿透**
#### **4.1、原理说明**
内网穿透,由三部分组成:client端,server端,bridge端client和server主动连接bridge端进行桥接.
当用户访问server端,流程是:
@ -399,7 +414,7 @@ VPS(IP:22.22.22.33)执行:
`./proxy tserver --udp -r ":53@:53" -P "127.0.0.1:33080" -C proxy.crt -K proxy.key`
1. 在公司机器A上面执行
`./proxy tclient --udp -P "22.22.22.22:33080" -C proxy.crt -K proxy.key`
`./proxy tclient -P "22.22.22.22:33080" -C proxy.crt -K proxy.key`
1. 完成
@ -469,7 +484,7 @@ server连接到bridge的时候,如果同时有多个client连接到同一个brid
`./proxy help tserver`
`./proxy help tserver`
### 5.SOCKS5代理
### **5.SOCKS5代理**
提示:SOCKS5代理,支持CONNECT,UDP协议,不支持BIND,支持用户名密码认证.
#### **5.1.普通SOCKS5代理**
`./proxy socks -t tcp -p "0.0.0.0:38080"`
@ -556,7 +571,7 @@ KCP协议需要-B参数设置一个密码用于加密解密数据
### TODO
- http,socks代理多个上级负载均衡?
- 内网穿透server<->bridge心跳机制?
- 内网穿透增加multiplexing模式?
- 欢迎加群反馈...
### 如何使用源码?

View File

@ -1,12 +1,14 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
"os/exec"
"proxy/services"
"proxy/utils"
"time"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
@ -14,6 +16,7 @@ import (
var (
app *kingpin.Application
service *services.ServiceItem
cmd *exec.Cmd
)
func initConfig() (err error) {
@ -38,6 +41,9 @@ func initConfig() (err error) {
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()
forever := app.Flag("forever", "run proxy in forever,fail and retry").Default("false").Bool()
logfile := app.Flag("log", "log file path").Default("").String()
//########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()
@ -102,6 +108,7 @@ func initConfig() (err error) {
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.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.Mux = tunnelServer.Flag("mux", "use multiplexing mode").Default("false").Bool()
//########tunnel-client#########
tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
@ -110,6 +117,7 @@ func initConfig() (err error) {
tunnelClientArgs.KeyFile = tunnelClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
tunnelClientArgs.Timeout = tunnelClient.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
tunnelClientArgs.Key = tunnelClient.Flag("k", "key same with server").Default("default").String()
tunnelClientArgs.Mux = tunnelClient.Flag("mux", "use multiplexing mode").Default("false").Bool()
//########tunnel-bridge#########
tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode")
@ -117,6 +125,7 @@ func initConfig() (err error) {
tunnelBridgeArgs.KeyFile = tunnelBridge.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
tunnelBridgeArgs.Timeout = tunnelBridge.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
tunnelBridgeArgs.Local = tunnelBridge.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
tunnelBridgeArgs.Mux = tunnelBridge.Flag("mux", "use multiplexing mode").Default("false").Bool()
//########ssh#########
socks := app.Command("socks", "proxy on ssh mode")
@ -150,6 +159,20 @@ func initConfig() (err error) {
//parse args
serviceName := kingpin.MustParse(app.Parse(os.Args[1:]))
flags := log.Ldate
if *debug {
flags |= log.Lshortfile | log.Lmicroseconds
} else {
flags |= log.Ltime
}
log.SetFlags(flags)
if *logfile != "" {
f, e := os.OpenFile(*logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
if e != nil {
log.Fatal(e)
}
log.SetOutput(f)
}
if *daemon {
args := []string{}
for _, arg := range os.Args[1:] {
@ -157,18 +180,69 @@ func initConfig() (err error) {
args = append(args, arg)
}
}
cmd := exec.Command(os.Args[0], args...)
cmd = exec.Command(os.Args[0], args...)
cmd.Start()
fmt.Printf("%s [PID] %d running...\n", os.Args[0], cmd.Process.Pid)
f := ""
if *forever {
f = "forever "
}
log.Printf("%s%s [PID] %d running...\n", f, os.Args[0], cmd.Process.Pid)
os.Exit(0)
}
if *debug {
flags |= log.Lshortfile | log.Lmicroseconds
} else {
flags |= log.Ltime
if *forever {
args := []string{}
for _, arg := range os.Args[1:] {
if arg != "--forever" {
args = append(args, arg)
}
}
go func() {
for {
if cmd != nil {
cmd.Process.Kill()
}
cmd = exec.Command(os.Args[0], args...)
cmdReaderStderr, err := cmd.StderrPipe()
if err != nil {
log.Printf("ERR:%s,restarting...\n", err)
continue
}
cmdReader, err := cmd.StdoutPipe()
if err != nil {
log.Printf("ERR:%s,restarting...\n", err)
continue
}
scanner := bufio.NewScanner(cmdReader)
scannerStdErr := bufio.NewScanner(cmdReaderStderr)
go func() {
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}()
go func() {
for scannerStdErr.Scan() {
fmt.Println(scannerStdErr.Text())
}
}()
if err := cmd.Start(); err != nil {
log.Printf("ERR:%s,restarting...\n", err)
continue
}
pid := cmd.Process.Pid
log.Printf("worker %s [PID] %d running...\n", os.Args[0], pid)
if err := cmd.Wait(); err != nil {
log.Printf("ERR:%s,restarting...", err)
continue
}
log.Printf("%s [PID] %d unexpected exited, restarting...\n", os.Args[0], pid)
time.Sleep(time.Second * 5)
}
}()
return
}
if *logfile == "" {
poster()
}
log.SetFlags(flags)
poster()
//regist services and run service
services.Regist("http", services.NewHTTP(), httpArgs)
services.Regist("tcp", services.NewTCP(), tcpArgs)

View File

@ -1,12 +1,6 @@
#!/bin/bash
set -e
# install monexec
tar zxvf monexec_0.1.1_linux_amd64.tar.gz
cd monexec_0.1.1_linux_amd64
cp monexec /usr/bin/
chmod +x /usr/bin/monexec
cd ..
# #install proxy
tar zxvf proxy-linux-amd64.tar.gz
cp proxy /usr/bin/

View File

@ -5,15 +5,8 @@ if [ -e /tmp/proxy ]; then
fi
mkdir /tmp/proxy
cd /tmp/proxy
wget https://github.com/reddec/monexec/releases/download/v0.1.1/monexec_0.1.1_linux_amd64.tar.gz
wget https://github.com/snail007/goproxy/releases/download/v3.6/proxy-linux-amd64.tar.gz
wget https://github.com/snail007/goproxy/releases/download/v3.9/proxy-linux-amd64.tar.gz
# install monexec
tar zxvf monexec_0.1.1_linux_amd64.tar.gz
cd monexec_0.1.1_linux_amd64
cp monexec /usr/bin/
chmod +x /usr/bin/monexec
cd ..
# #install proxy
tar zxvf proxy-linux-amd64.tar.gz
cp proxy /usr/bin/

19
main.go
View File

@ -1,7 +1,6 @@
package main
import (
"fmt"
"log"
"os"
"os/signal"
@ -9,14 +8,18 @@ import (
"syscall"
)
const APP_VERSION = "3.6"
const APP_VERSION = "3.9"
func main() {
err := initConfig()
if err != nil {
log.Fatalf("err : %s", err)
}
Clean(&service.S)
if service != nil && service.S != nil {
Clean(&service.S)
} else {
Clean(nil)
}
}
func Clean(s *services.Service) {
signalChan := make(chan os.Signal, 1)
@ -29,8 +32,14 @@ func Clean(s *services.Service) {
syscall.SIGQUIT)
go func() {
for _ = range signalChan {
fmt.Println("\nReceived an interrupt, stopping services...")
(*s).Clean()
log.Println("Received an interrupt, stopping services...")
if s != nil && *s != nil {
(*s).Clean()
}
if cmd != nil {
log.Printf("clean process %d", cmd.Process.Pid)
cmd.Process.Kill()
}
cleanupDone <- true
}
}()

View File

@ -1,5 +1,5 @@
#!/bin/bash
VER="3.6"
VER="3.9"
RELEASE="release-${VER}"
rm -rf .cert
mkdir .cert

View File

@ -16,6 +16,8 @@ const (
CONN_SERVER_HEARBEAT = uint8(3)
CONN_SERVER = uint8(4)
CONN_CLIENT = uint8(5)
CONN_SERVER_MUX = uint8(6)
CONN_CLIENT_MUX = uint8(7)
)
type TunnelServerArgs struct {
@ -31,6 +33,7 @@ type TunnelServerArgs struct {
Timeout *int
Route *[]string
Mgr *TunnelServerManager
Mux *bool
}
type TunnelClientArgs struct {
Parent *string
@ -40,6 +43,7 @@ type TunnelClientArgs struct {
KeyBytes []byte
Key *string
Timeout *int
Mux *bool
}
type TunnelBridgeArgs struct {
Parent *string
@ -49,6 +53,7 @@ type TunnelBridgeArgs struct {
KeyBytes []byte
Local *string
Timeout *int
Mux *bool
}
type TCPArgs struct {
Parent *string

1
services/mux_bridge.go Normal file
View File

@ -0,0 +1 @@
package services

1
services/mux_client.go Normal file
View File

@ -0,0 +1 @@
package services

1
services/mux_server.go Normal file
View File

@ -0,0 +1 @@
package services

View File

@ -492,11 +492,11 @@ func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn n
err = fmt.Errorf("write req detail fail,%s", err)
return
}
// _, err = outConn.Read(buf)
// if err != nil {
// err = fmt.Errorf("read req reply fail,%s", err)
// return
// }
_, err = outConn.Read(buf)
if err != nil {
err = fmt.Errorf("read req reply fail,%s", err)
return
}
//result := buf[:n]
//log.Printf("result:%v", result)

View File

@ -17,8 +17,8 @@ type TunnelBridge struct {
cfg TunnelBridgeArgs
serverConns utils.ConcurrentMap
clientControlConns utils.ConcurrentMap
cmServer utils.ConnManager
cmClient utils.ConnManager
// cmServer utils.ConnManager
// cmClient utils.ConnManager
}
func NewTunnelBridge() Service {
@ -26,8 +26,8 @@ func NewTunnelBridge() Service {
cfg: TunnelBridgeArgs{},
serverConns: utils.NewConcurrentMap(),
clientControlConns: utils.NewConcurrentMap(),
cmServer: utils.NewConnManager(),
cmClient: utils.NewConnManager(),
// cmServer: utils.NewConnManager(),
// cmClient: utils.NewConnManager(),
}
}
@ -92,7 +92,7 @@ func (s *TunnelBridge) Start(args interface{}) (err error) {
time.Sleep(time.Second * 3)
continue
} else {
s.cmServer.Add(serverID, ID, &inConn)
// s.cmServer.Add(serverID, ID, &inConn)
break
}
}
@ -114,11 +114,11 @@ func (s *TunnelBridge) Start(args interface{}) (err error) {
serverConn := serverConnItem.(ServerConn).Conn
utils.IoBind(*serverConn, inConn, func(err interface{}) {
s.serverConns.Remove(ID)
s.cmClient.RemoveOne(key, ID)
s.cmServer.RemoveOne(serverID, ID)
// s.cmClient.RemoveOne(key, ID)
// s.cmServer.RemoveOne(serverID, ID)
log.Printf("conn %s released", ID)
})
s.cmClient.Add(key, ID, &inConn)
// s.cmClient.Add(key, ID, &inConn)
log.Printf("conn %s created", ID)
case CONN_CLIENT_CONTROL:
@ -136,101 +136,101 @@ func (s *TunnelBridge) Start(args interface{}) (err error) {
s.clientControlConns.Set(key, &inConn)
log.Printf("set client %s control conn", key)
case CONN_SERVER_HEARBEAT:
var serverID string
err = utils.ReadPacketData(reader, &serverID)
if err != nil {
log.Printf("read error,ERR:%s", err)
return
}
log.Printf("server heartbeat connection, id: %s", serverID)
writeDie := make(chan bool)
readDie := make(chan bool)
go func() {
for {
inConn.SetWriteDeadline(time.Now().Add(time.Second * 3))
_, err = inConn.Write([]byte{0x00})
inConn.SetWriteDeadline(time.Time{})
if err != nil {
log.Printf("server heartbeat connection write err %s", err)
break
}
time.Sleep(time.Second * 3)
}
close(writeDie)
}()
go func() {
for {
signal := make([]byte, 1)
inConn.SetReadDeadline(time.Now().Add(time.Second * 6))
_, err := inConn.Read(signal)
inConn.SetReadDeadline(time.Time{})
if err != nil {
log.Printf("server heartbeat connection read err: %s", err)
break
} else {
// log.Printf("heartbeat from server ,id:%s", serverID)
}
}
close(readDie)
}()
select {
case <-readDie:
case <-writeDie:
}
utils.CloseConn(&inConn)
s.cmServer.Remove(serverID)
log.Printf("server heartbeat conn %s released", serverID)
case CONN_CLIENT_HEARBEAT:
var clientID string
err = utils.ReadPacketData(reader, &clientID)
if err != nil {
log.Printf("read error,ERR:%s", err)
return
}
log.Printf("client heartbeat connection, id: %s", clientID)
writeDie := make(chan bool)
readDie := make(chan bool)
go func() {
for {
inConn.SetWriteDeadline(time.Now().Add(time.Second * 3))
_, err = inConn.Write([]byte{0x00})
inConn.SetWriteDeadline(time.Time{})
if err != nil {
log.Printf("client heartbeat connection write err %s", err)
break
}
time.Sleep(time.Second * 3)
}
close(writeDie)
}()
go func() {
for {
signal := make([]byte, 1)
inConn.SetReadDeadline(time.Now().Add(time.Second * 6))
_, err := inConn.Read(signal)
inConn.SetReadDeadline(time.Time{})
if err != nil {
log.Printf("client control connection read err: %s", err)
break
} else {
// log.Printf("heartbeat from client ,id:%s", clientID)
}
}
close(readDie)
}()
select {
case <-readDie:
case <-writeDie:
}
utils.CloseConn(&inConn)
s.cmClient.Remove(clientID)
if s.clientControlConns.Has(clientID) {
item, _ := s.clientControlConns.Get(clientID)
(*item.(*net.Conn)).Close()
}
s.clientControlConns.Remove(clientID)
log.Printf("client heartbeat conn %s released", clientID)
// case CONN_SERVER_HEARBEAT:
// var serverID string
// err = utils.ReadPacketData(reader, &serverID)
// if err != nil {
// log.Printf("read error,ERR:%s", err)
// return
// }
// log.Printf("server heartbeat connection, id: %s", serverID)
// writeDie := make(chan bool)
// readDie := make(chan bool)
// go func() {
// for {
// inConn.SetWriteDeadline(time.Now().Add(time.Second * 3))
// _, err = inConn.Write([]byte{0x00})
// inConn.SetWriteDeadline(time.Time{})
// if err != nil {
// log.Printf("server heartbeat connection write err %s", err)
// break
// }
// time.Sleep(time.Second * 3)
// }
// close(writeDie)
// }()
// go func() {
// for {
// signal := make([]byte, 1)
// inConn.SetReadDeadline(time.Now().Add(time.Second * 6))
// _, err := inConn.Read(signal)
// inConn.SetReadDeadline(time.Time{})
// if err != nil {
// log.Printf("server heartbeat connection read err: %s", err)
// break
// } else {
// // log.Printf("heartbeat from server ,id:%s", serverID)
// }
// }
// close(readDie)
// }()
// select {
// case <-readDie:
// case <-writeDie:
// }
// utils.CloseConn(&inConn)
// s.cmServer.Remove(serverID)
// log.Printf("server heartbeat conn %s released", serverID)
// case CONN_CLIENT_HEARBEAT:
// var clientID string
// err = utils.ReadPacketData(reader, &clientID)
// if err != nil {
// log.Printf("read error,ERR:%s", err)
// return
// }
// log.Printf("client heartbeat connection, id: %s", clientID)
// writeDie := make(chan bool)
// readDie := make(chan bool)
// go func() {
// for {
// inConn.SetWriteDeadline(time.Now().Add(time.Second * 3))
// _, err = inConn.Write([]byte{0x00})
// inConn.SetWriteDeadline(time.Time{})
// if err != nil {
// log.Printf("client heartbeat connection write err %s", err)
// break
// }
// time.Sleep(time.Second * 3)
// }
// close(writeDie)
// }()
// go func() {
// for {
// signal := make([]byte, 1)
// inConn.SetReadDeadline(time.Now().Add(time.Second * 6))
// _, err := inConn.Read(signal)
// inConn.SetReadDeadline(time.Time{})
// if err != nil {
// log.Printf("client control connection read err: %s", err)
// break
// } else {
// // log.Printf("heartbeat from client ,id:%s", clientID)
// }
// }
// close(readDie)
// }()
// select {
// case <-readDie:
// case <-writeDie:
// }
// utils.CloseConn(&inConn)
// s.cmClient.Remove(clientID)
// if s.clientControlConns.Has(clientID) {
// item, _ := s.clientControlConns.Get(clientID)
// (*item.(*net.Conn)).Close()
// }
// s.clientControlConns.Remove(clientID)
// log.Printf("client heartbeat conn %s released", clientID)
}
})
if err != nil {

View File

@ -11,79 +11,80 @@ import (
)
type TunnelClient struct {
cfg TunnelClientArgs
cm utils.ConnManager
cfg TunnelClientArgs
// cm utils.ConnManager
ctrlConn net.Conn
}
func NewTunnelClient() Service {
return &TunnelClient{
cfg: TunnelClientArgs{},
cm: utils.NewConnManager(),
// cm: utils.NewConnManager(),
}
}
func (s *TunnelClient) InitService() {
s.InitHeartbeatDeamon()
// s.InitHeartbeatDeamon()
}
func (s *TunnelClient) 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 *TunnelClient) 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 *TunnelClient) CheckArgs() {
if *s.cfg.Parent != "" {
log.Printf("use tls parent %s", *s.cfg.Parent)
@ -96,7 +97,7 @@ func (s *TunnelClient) CheckArgs() {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
}
func (s *TunnelClient) StopService() {
s.cm.RemoveAll()
// s.cm.RemoveAll()
}
func (s *TunnelClient) Start(args interface{}) (err error) {
s.cfg = args.(TunnelClientArgs)
@ -106,7 +107,7 @@ func (s *TunnelClient) Start(args interface{}) (err error) {
for {
//close all conn
s.cm.Remove(*s.cfg.Key)
// s.cm.Remove(*s.cfg.Key)
if s.ctrlConn != nil {
s.ctrlConn.Close()
}
@ -171,7 +172,7 @@ func (s *TunnelClient) ServeUDP(localAddr, ID, serverID string) {
var err error
// for {
for {
s.cm.RemoveOne(*s.cfg.Key, ID)
// s.cm.RemoveOne(*s.cfg.Key, ID)
inConn, err = s.GetInConn(CONN_CLIENT, *s.cfg.Key, ID, serverID)
if err != nil {
utils.CloseConn(&inConn)
@ -182,7 +183,7 @@ func (s *TunnelClient) ServeUDP(localAddr, ID, serverID string) {
break
}
}
s.cm.Add(*s.cfg.Key, ID, &inConn)
// s.cm.Add(*s.cfg.Key, ID, &inConn)
log.Printf("conn %s created", ID)
for {
@ -275,8 +276,8 @@ func (s *TunnelClient) ServeConn(localAddr, ID, serverID string) {
}
utils.IoBind(inConn, outConn, func(err interface{}) {
log.Printf("conn %s released", ID)
s.cm.RemoveOne(*s.cfg.Key, ID)
// s.cm.RemoveOne(*s.cfg.Key, ID)
})
s.cm.Add(*s.cfg.Key, ID, &inConn)
// s.cm.Add(*s.cfg.Key, ID, &inConn)
log.Printf("conn %s created", ID)
}

View File

@ -24,7 +24,7 @@ type TunnelServerManager struct {
udpChn chan UDPItem
sc utils.ServerChannel
serverID string
cm utils.ConnManager
// cm utils.ConnManager
}
func NewTunnelServerManager() Service {
@ -32,7 +32,7 @@ func NewTunnelServerManager() Service {
cfg: TunnelServerArgs{},
udpChn: make(chan UDPItem, 50000),
serverID: utils.Uniqueid(),
cm: utils.NewConnManager(),
// cm: utils.NewConnManager(),
}
}
func (s *TunnelServerManager) Start(args interface{}) (err error) {
@ -91,7 +91,7 @@ func (s *TunnelServerManager) Clean() {
s.StopService()
}
func (s *TunnelServerManager) StopService() {
s.cm.RemoveAll()
// s.cm.RemoveAll()
}
func (s *TunnelServerManager) CheckArgs() {
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
@ -100,62 +100,63 @@ func (s *TunnelServerManager) CheckArgs() {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
}
func (s *TunnelServerManager) InitService() {
s.InitHeartbeatDeamon()
}
func (s *TunnelServerManager) InitHeartbeatDeamon() {
log.Printf("heartbeat started")
go func() {
var heartbeatConn net.Conn
var ID string
for {
//close all connection
s.cm.Remove(ID)
utils.CloseConn(&heartbeatConn)
heartbeatConn, ID, err := s.GetOutConn(CONN_SERVER_HEARBEAT)
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:
}
}
}()
// s.InitHeartbeatDeamon()
}
// func (s *TunnelServerManager) InitHeartbeatDeamon() {
// log.Printf("heartbeat started")
// go func() {
// var heartbeatConn net.Conn
// var ID string
// for {
// //close all connection
// s.cm.Remove(ID)
// utils.CloseConn(&heartbeatConn)
// heartbeatConn, ID, err := s.GetOutConn(CONN_SERVER_HEARBEAT)
// 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 *TunnelServerManager) GetOutConn(typ uint8) (outConn net.Conn, ID string, err error) {
outConn, err = s.GetConn()
if err != nil {
@ -241,11 +242,11 @@ func (s *TunnelServer) Start(args interface{}) (err error) {
}
}
utils.IoBind(inConn, outConn, func(err interface{}) {
s.cfg.Mgr.cm.RemoveOne(s.cfg.Mgr.serverID, ID)
// s.cfg.Mgr.cm.RemoveOne(s.cfg.Mgr.serverID, ID)
log.Printf("%s conn %s released", *s.cfg.Key, ID)
})
//add conn
s.cfg.Mgr.cm.Add(s.cfg.Mgr.serverID, ID, &inConn)
// s.cfg.Mgr.cm.Add(s.cfg.Mgr.serverID, ID, &inConn)
log.Printf("%s conn %s created", *s.cfg.Key, ID)
})
if err != nil {

View File

@ -42,7 +42,8 @@ func IoBind(dst io.ReadWriteCloser, src io.ReadWriteCloser, fn func(err interfac
log.Printf("bind crashed %s", err)
}
}()
_, err := io.Copy(dst, src)
//_, err := io.Copy(dst, src)
err := ioCopy(dst, src)
e1 <- err
}()
go func() {
@ -51,7 +52,8 @@ func IoBind(dst io.ReadWriteCloser, src io.ReadWriteCloser, fn func(err interfac
log.Printf("bind crashed %s", err)
}
}()
_, err := io.Copy(src, dst)
//_, err := io.Copy(src, dst)
err := ioCopy(src, dst)
e2 <- err
}()
var err interface{}