mirror of https://github.com/ehang-io/nps
很多修改
parent
c34e5e1a7d
commit
0b90bf3a18
124
README.md
124
README.md
|
@ -1,7 +1,7 @@
|
||||||
# easyProxy
|
# easyProxy
|
||||||
  
|
  
|
||||||
|
|
||||||
easyProxy是一款轻量级、高性能、功能最为强大的**内网穿透**代理服务器。目前支持**tcp、udp流量转发**,可支持任何tcp、udp上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析等等……),此外还**支持内网http代理、内网socks5代理**,可实现在非内网环境下如同使用vpn一样访问内网资源和设备的效果,同时**支持socks5验证,snnapy压缩(节省带宽和流量)、站点保护、加密传输、多路复用、host修改、自定义header**。
|
easyProxy是一款轻量级、高性能、功能最为强大的**内网穿透**代理服务器。目前支持**tcp、udp流量转发**,可支持任何tcp、udp上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析等等……),此外还**支持内网http代理、内网socks5代理**,可实现在非内网环境下如同使用vpn一样访问内网资源和设备的效果。
|
||||||
|
|
||||||
目前市面上提供类似服务的有花生壳、TeamView、GoToMyCloud等等,但要使用第三方的公网服务器就必须为第三方付费,并且这些服务都有各种各样的限制,此外,由于数据包会流经第三方,因此对数据安全也是一大隐患。
|
目前市面上提供类似服务的有花生壳、TeamView、GoToMyCloud等等,但要使用第三方的公网服务器就必须为第三方付费,并且这些服务都有各种各样的限制,此外,由于数据包会流经第三方,因此对数据安全也是一大隐患。
|
||||||
|
|
||||||
|
@ -38,33 +38,47 @@ easyProxy是一款轻量级、高性能、功能最为强大的**内网穿透**
|
||||||
- [x] 支持一个服务端,多个客户端模式
|
- [x] 支持一个服务端,多个客户端模式
|
||||||
- [x] host修改支持
|
- [x] host修改支持
|
||||||
- [x] 自定义设置header支持
|
- [x] 自定义设置header支持
|
||||||
|
- [x] 流量统计
|
||||||
|
- [x] 自动义404页面
|
||||||
|
- [x] 热更新支持
|
||||||
|
|
||||||
## 目录
|
## 目录
|
||||||
|
|
||||||
1. [安装](#安装)
|
* [安装](#安装)
|
||||||
2. [web管理模式](#web管理模式)(多隧道时推荐)
|
* [编译安装](#源码安装)
|
||||||
3. [tcp隧道模式](#tcp隧道模式)
|
* [release安装](#release安装)
|
||||||
4. [udp隧道模式](#udp隧道模式)
|
* [web管理](#web管理模式)(多隧道时推荐)
|
||||||
5. [socks5代理模式](#socks5代理模式)
|
* [启动](#启动)
|
||||||
6. [http代理模式](#http代理模式)
|
* [配置文件说明](#服务端配置文件)
|
||||||
7. [数据压缩支持](#数据压缩支持)
|
* 单隧道模式及介绍
|
||||||
8. [站点密码保护](#站点保护)
|
* [tcp隧道模式](#tcp隧道模式)
|
||||||
9. [加密传输](#加密传输)
|
* [udp隧道模式](#udp隧道模式)
|
||||||
10. [TCP多路复用](#多路复用)
|
* [socks5代理模式](#socks5代理模式)
|
||||||
11. [host修改](#host修改)
|
* [http代理模式](#http代理模式)
|
||||||
12. [自定义header](#自定义header)
|
|
||||||
13. [获取用户真实ip](#获取用户真实ip)
|
|
||||||
|
|
||||||
|
* [相关功能](#相关功能)
|
||||||
|
* [数据压缩支持](#数据压缩支持)
|
||||||
|
* [站点密码保护](#站点保护)
|
||||||
|
* [加密传输](#加密传输)
|
||||||
|
* [TCP多路复用](#多路复用)
|
||||||
|
* [host修改](#host修改)
|
||||||
|
* [自定义header](#自定义header)
|
||||||
|
* [获取用户真实ip](#获取用户真实ip)
|
||||||
|
* [热更新支持](#热更新支持)
|
||||||
|
* [客户端地址显示](#客户端地址显示)
|
||||||
|
* [自定义404页面](#404页面配置)
|
||||||
|
* [流量统计](#流量统计)
|
||||||
|
* [连接池](#连接池)
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
1. release安装
|
### release安装
|
||||||
> https://github.com/cnlh/easyProxy/releases
|
> https://github.com/cnlh/easyProxy/releases
|
||||||
|
|
||||||
下载对应的系统版本即可,服务端和客户端是单独的,go语言开发,无需任何第三方依赖
|
下载对应的系统版本即可,服务端和客户端是单独的,go语言开发,无需任何第三方依赖
|
||||||
|
|
||||||
2. 源码安装
|
### 源码安装
|
||||||
- 安装源码
|
- 安装源码(另有snappy、beego包)
|
||||||
> go get github.com/cnlh/easyProxy
|
> go get github.com/cnlh/easyProxy
|
||||||
- 编译
|
- 编译
|
||||||
> go build cmd/server/proxy_server.go
|
> go build cmd/server/proxy_server.go
|
||||||
|
@ -89,35 +103,7 @@ tcpport | 服务端客户端通信端口
|
||||||
|
|
||||||
**提示:使用web模式时,服务端执行文件必须在项目根目录,否则无法正确加载配置文件**
|
**提示:使用web模式时,服务端执行文件必须在项目根目录,否则无法正确加载配置文件**
|
||||||
|
|
||||||
### 使用
|
### 启动
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**有两种模式:**
|
|
||||||
|
|
||||||
1、单客户端模式,所有的隧道流量均从这个单客户端转发。
|
|
||||||
|
|
||||||
|
|
||||||
- 服务端
|
|
||||||
|
|
||||||
```
|
|
||||||
./proxy_server -vkey=DKibZF5TXvic1g3kY
|
|
||||||
```
|
|
||||||
名称 | 含义
|
|
||||||
---|---
|
|
||||||
vkey | 验证密钥
|
|
||||||
|
|
||||||
|
|
||||||
- 客户端
|
|
||||||
|
|
||||||
```
|
|
||||||
./proxy_client -server=ip:port -vkey=DKibZF5TXvic1g3kY
|
|
||||||
```
|
|
||||||
- 配置
|
|
||||||
|
|
||||||
进入web界面,公网ip:web界面端口(默认8080),密码默认为123
|
|
||||||
|
|
||||||
2、多客户端模式,不同的隧道流量均从不同的客户端转发。
|
|
||||||
|
|
||||||
|
|
||||||
- 服务端
|
- 服务端
|
||||||
|
@ -125,10 +111,11 @@ vkey | 验证密钥
|
||||||
```
|
```
|
||||||
./proxy_server
|
./proxy_server
|
||||||
```
|
```
|
||||||
名称 | 含义
|
|
||||||
---|---
|
|
||||||
mode | 运行模式
|
|
||||||
- 客户端
|
- 客户端
|
||||||
|
```
|
||||||
|
./proxy_server -server=ip:port -vkey=web界面中显示的
|
||||||
|
```
|
||||||
|
|
||||||
进入web管理界面,有详细的命令
|
进入web管理界面,有详细的命令
|
||||||
|
|
||||||
|
@ -316,30 +303,31 @@ httpport | http代理连接端口
|
||||||
配置HTTP代理即可,ip为外网服务器ip,端口为httpport,即可在外网环境访问内网啦!
|
配置HTTP代理即可,ip为外网服务器ip,端口为httpport,即可在外网环境访问内网啦!
|
||||||
```
|
```
|
||||||
|
|
||||||
## 数据压缩支持
|
## 相关功能
|
||||||
|
|
||||||
|
### 数据压缩支持
|
||||||
|
|
||||||
由于是内网穿透,内网客户端与服务端之间的隧道存在大量的数据交换,为节省流量,加快传输速度,由此本程序支持SNNAPY形式的压缩。
|
由于是内网穿透,内网客户端与服务端之间的隧道存在大量的数据交换,为节省流量,加快传输速度,由此本程序支持SNNAPY形式的压缩。
|
||||||
|
|
||||||
|
|
||||||
- 所有模式均支持数据压缩,可以与加密同时使用
|
- 所有模式均支持数据压缩,可以与加密同时使用
|
||||||
|
- 开启此功能会增加cpu和内存消耗
|
||||||
|
|
||||||
- 在server端加上参数 -compress=snappy(或在web管理中设置)
|
- 在server端加上参数 -compress=snappy(或在web管理中设置)
|
||||||
```
|
```
|
||||||
-compress=snappy
|
-compress=snappy
|
||||||
```
|
```
|
||||||
|
|
||||||
## 加密传输
|
### 加密传输
|
||||||
|
|
||||||
如果公司内网防火墙对外网访问进行了流量识别与屏蔽,例如禁止了ssh协议等,通过设置 配置文件,将服务端与客户端之间的通信内容加密传输,将会有效防止流量被拦截。
|
如果公司内网防火墙对外网访问进行了流量识别与屏蔽,例如禁止了ssh协议等,通过设置 配置文件,将服务端与客户端之间的通信内容加密传输,将会有效防止流量被拦截。
|
||||||
|
|
||||||
|
- 开启此功能会增加cpu和内存消耗
|
||||||
- 在server端加上参数 -crypt=true(或在web管理中设置)
|
- 在server端加上参数 -crypt=true(或在web管理中设置)
|
||||||
```
|
```
|
||||||
-crypt=true
|
-crypt=true
|
||||||
```
|
```
|
||||||
|
|
||||||
## 多路复用
|
### 多路复用
|
||||||
|
|
||||||
客户端和服务器端之间的连接支持多路复用,不再需要为每一个用户请求创建一个连接,使连接建立的延迟降低,并且避免了大量文件描述符的占用。
|
客户端和服务器端之间的连接支持多路复用,不再需要为每一个用户请求创建一个连接,使连接建立的延迟降低,并且避免了大量文件描述符的占用。
|
||||||
|
|
||||||
|
@ -351,7 +339,7 @@ httpport | http代理连接端口
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## 站点保护
|
### 站点保护
|
||||||
由于所有客户端共用一个 http 服务端口,任何知道你的域名和 url 的人都能访问到你部署在内网的 web 服务,但是在某些场景下需要确保只有限定的用户才能访问。
|
由于所有客户端共用一个 http 服务端口,任何知道你的域名和 url 的人都能访问到你部署在内网的 web 服务,但是在某些场景下需要确保只有限定的用户才能访问。
|
||||||
|
|
||||||
easyProxy支持通过 HTTP Basic Auth 来保护你的 web 服务,使用户需要通过用户名和密码才能访问到你的服务。
|
easyProxy支持通过 HTTP Basic Auth 来保护你的 web 服务,使用户需要通过用户名和密码才能访问到你的服务。
|
||||||
|
@ -361,25 +349,37 @@ easyProxy支持通过 HTTP Basic Auth 来保护你的 web 服务,使用户需
|
||||||
-u=user -p=password
|
-u=user -p=password
|
||||||
```
|
```
|
||||||
|
|
||||||
web管理中也可配置
|
- web管理中也可配置
|
||||||
|
|
||||||
## host修改
|
### host修改
|
||||||
|
|
||||||
|
|
||||||
通常情况下本代理不会修改转发的任何数据。但有一些后端服务会根据 http 请求 header 中的 host 字段来展现不同的网站,例如 nginx 的虚拟主机服务,启用 host-header 的修改功能可以动态修改 http 请求中的 host 字段。该功能仅限于域名代理模式。
|
通常情况下本代理不会修改转发的任何数据。但有一些后端服务会根据 http 请求 header 中的 host 字段来展现不同的网站,例如 nginx 的虚拟主机服务,启用 host-header 的修改功能可以动态修改 http 请求中的 host 字段。该功能仅限于域名代理模式。
|
||||||
|
|
||||||
**使用方法:在web管理中设置**
|
**使用方法:在web管理中设置**
|
||||||
|
|
||||||
## 自定义header
|
### 自定义header
|
||||||
|
|
||||||
支持对header进行新增或者修改,以配合服务的需要
|
支持对header进行新增或者修改,以配合服务的需要
|
||||||
|
|
||||||
## 获取用户真实ip
|
### 获取用户真实ip
|
||||||
|
|
||||||
目前只有域名模式的代理支持这一功能,可以通过用户请求的 header 中的 X-Forwarded-For 和 X-Real-IP 来获取用户真实 IP。
|
目前只有域名模式的代理支持这一功能,可以通过用户请求的 header 中的 X-Forwarded-For 和 X-Real-IP 来获取用户真实 IP。
|
||||||
|
|
||||||
**本代理前会在每一个请求中添加了这两个 header。**
|
**本代理前会在每一个请求中添加了这两个 header。**
|
||||||
|
|
||||||
|
### 热更新支持
|
||||||
|
在web管理中的修改将实时使用,无需重启客户端或者服务端
|
||||||
|
|
||||||
|
### 客户端地址显示
|
||||||
|
在web管理中将显示客户端的连接地址
|
||||||
|
|
||||||
|
### 404页面配置
|
||||||
|
支持域名解析模式的自定义404页面,修改/web/static/page/error.html中内容即可,暂不支持静态文件等内容
|
||||||
|
|
||||||
|
### 流量统计
|
||||||
|
可统计显示每个代理使用的流量,由于压缩和加密等原因,会和实际环境中的略有差异
|
||||||
|
|
||||||
|
### 连接池
|
||||||
|
easyProxy会预先和后端服务建立起指定数量的连接,每次接收到用户请求后,会从连接池中取出一个连接和用户连接关联起来,避免了等待与后端服务建立连接时间。
|
||||||
|
|
||||||
## 操作系统支持
|
|
||||||
支持Windows、Linux、MacOSX等,无第三方依赖库。
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ func newList() *list {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tunnel struct {
|
type Bridge struct {
|
||||||
TunnelPort int //通信隧道端口
|
TunnelPort int //通信隧道端口
|
||||||
listener *net.TCPListener //server端监听
|
listener *net.TCPListener //server端监听
|
||||||
SignalList map[int]*list //通信
|
SignalList map[int]*list //通信
|
||||||
|
@ -41,8 +41,8 @@ type Tunnel struct {
|
||||||
tunnelLock sync.Mutex
|
tunnelLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTunnel(tunnelPort int, runList map[int]interface{}) *Tunnel {
|
func NewTunnel(tunnelPort int, runList map[int]interface{}) *Bridge {
|
||||||
t := new(Tunnel)
|
t := new(Bridge)
|
||||||
t.TunnelPort = tunnelPort
|
t.TunnelPort = tunnelPort
|
||||||
t.SignalList = make(map[int]*list)
|
t.SignalList = make(map[int]*list)
|
||||||
t.TunnelList = make(map[int]*list)
|
t.TunnelList = make(map[int]*list)
|
||||||
|
@ -50,7 +50,7 @@ func NewTunnel(tunnelPort int, runList map[int]interface{}) *Tunnel {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Tunnel) StartTunnel() error {
|
func (s *Bridge) StartTunnel() error {
|
||||||
var err error
|
var err error
|
||||||
s.listener, err = net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), s.TunnelPort, ""})
|
s.listener, err = net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), s.TunnelPort, ""})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -61,7 +61,7 @@ func (s *Tunnel) StartTunnel() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
//tcp server
|
//tcp server
|
||||||
func (s *Tunnel) tunnelProcess() error {
|
func (s *Bridge) tunnelProcess() error {
|
||||||
var err error
|
var err error
|
||||||
for {
|
for {
|
||||||
conn, err := s.listener.Accept()
|
conn, err := s.listener.Accept()
|
||||||
|
@ -75,12 +75,12 @@ func (s *Tunnel) tunnelProcess() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
//验证失败,返回错误验证flag,并且关闭连接
|
//验证失败,返回错误验证flag,并且关闭连接
|
||||||
func (s *Tunnel) verifyError(c *utils.Conn) {
|
func (s *Bridge) verifyError(c *utils.Conn) {
|
||||||
c.Conn.Write([]byte(utils.VERIFY_EER))
|
c.Conn.Write([]byte(utils.VERIFY_EER))
|
||||||
c.Conn.Close()
|
c.Conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Tunnel) cliProcess(c *utils.Conn) error {
|
func (s *Bridge) cliProcess(c *utils.Conn) error {
|
||||||
c.Conn.(*net.TCPConn).SetReadDeadline(time.Now().Add(time.Duration(5) * time.Second))
|
c.Conn.(*net.TCPConn).SetReadDeadline(time.Now().Add(time.Duration(5) * time.Second))
|
||||||
vval := make([]byte, 32)
|
vval := make([]byte, 32)
|
||||||
if _, err := c.Conn.Read(vval); err != nil {
|
if _, err := c.Conn.Read(vval); err != nil {
|
||||||
|
@ -104,7 +104,7 @@ func (s *Tunnel) cliProcess(c *utils.Conn) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
//tcp连接类型区分
|
//tcp连接类型区分
|
||||||
func (s *Tunnel) typeDeal(typeVal string, c *utils.Conn, id int) error {
|
func (s *Bridge) typeDeal(typeVal string, c *utils.Conn, id int) error {
|
||||||
switch typeVal {
|
switch typeVal {
|
||||||
case utils.WORK_MAIN:
|
case utils.WORK_MAIN:
|
||||||
log.Println("客户端连接成功", c.Conn.RemoteAddr())
|
log.Println("客户端连接成功", c.Conn.RemoteAddr())
|
||||||
|
@ -119,7 +119,7 @@ func (s *Tunnel) typeDeal(typeVal string, c *utils.Conn, id int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
//加到对应的list中
|
//加到对应的list中
|
||||||
func (s *Tunnel) addList(m map[int]*list, c *utils.Conn, id int) {
|
func (s *Bridge) addList(m map[int]*list, c *utils.Conn, id int) {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
if v, ok := m[id]; ok {
|
if v, ok := m[id]; ok {
|
||||||
v.Add(c)
|
v.Add(c)
|
||||||
|
@ -132,7 +132,7 @@ func (s *Tunnel) addList(m map[int]*list, c *utils.Conn, id int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//新建隧道
|
//新建隧道
|
||||||
func (s *Tunnel) newChan(id int) error {
|
func (s *Bridge) newChan(id int) error {
|
||||||
var connPass *utils.Conn
|
var connPass *utils.Conn
|
||||||
var err error
|
var err error
|
||||||
retry:
|
retry:
|
||||||
|
@ -148,7 +148,7 @@ retry:
|
||||||
|
|
||||||
//得到一个tcp隧道
|
//得到一个tcp隧道
|
||||||
//TODO 超时问题 锁机制问题 对单个客户端加锁
|
//TODO 超时问题 锁机制问题 对单个客户端加锁
|
||||||
func (s *Tunnel) GetTunnel(id int, en, de int, crypt, mux bool) (c *utils.Conn, err error) {
|
func (s *Bridge) GetTunnel(id int, en, de int, crypt, mux bool) (c *utils.Conn, err error) {
|
||||||
retry:
|
retry:
|
||||||
if c, err = s.waitAndPop(s.TunnelList, id); err != nil {
|
if c, err = s.waitAndPop(s.TunnelList, id); err != nil {
|
||||||
return
|
return
|
||||||
|
@ -162,7 +162,7 @@ retry:
|
||||||
}
|
}
|
||||||
|
|
||||||
//得到一个通信通道
|
//得到一个通信通道
|
||||||
func (s *Tunnel) GetSignal(id int) (err error, conn *utils.Conn) {
|
func (s *Bridge) GetSignal(id int) (err error, conn *utils.Conn) {
|
||||||
if v, ok := s.SignalList[id]; !ok || v.Len() == 0 {
|
if v, ok := s.SignalList[id]; !ok || v.Len() == 0 {
|
||||||
err = errors.New("客户端未连接")
|
err = errors.New("客户端未连接")
|
||||||
return
|
return
|
||||||
|
@ -172,14 +172,14 @@ func (s *Tunnel) GetSignal(id int) (err error, conn *utils.Conn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//重回slice 复用
|
//重回slice 复用
|
||||||
func (s *Tunnel) ReturnSignal(conn *utils.Conn, id int) {
|
func (s *Bridge) ReturnSignal(conn *utils.Conn, id int) {
|
||||||
if v, ok := s.SignalList[id]; ok {
|
if v, ok := s.SignalList[id]; ok {
|
||||||
v.Add(conn)
|
v.Add(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//重回slice 复用
|
//重回slice 复用
|
||||||
func (s *Tunnel) ReturnTunnel(conn *utils.Conn, id int) {
|
func (s *Bridge) ReturnTunnel(conn *utils.Conn, id int) {
|
||||||
if v, ok := s.TunnelList[id]; ok {
|
if v, ok := s.TunnelList[id]; ok {
|
||||||
utils.FlushConn(conn.Conn)
|
utils.FlushConn(conn.Conn)
|
||||||
v.Add(conn)
|
v.Add(conn)
|
||||||
|
@ -187,16 +187,16 @@ func (s *Tunnel) ReturnTunnel(conn *utils.Conn, id int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除通信通道
|
//删除通信通道
|
||||||
func (s *Tunnel) DelClientSignal(id int) {
|
func (s *Bridge) DelClientSignal(id int) {
|
||||||
s.delClient(id, s.SignalList)
|
s.delClient(id, s.SignalList)
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除隧道
|
//删除隧道
|
||||||
func (s *Tunnel) DelClientTunnel(id int) {
|
func (s *Bridge) DelClientTunnel(id int) {
|
||||||
s.delClient(id, s.TunnelList)
|
s.delClient(id, s.TunnelList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Tunnel) delClient(id int, l map[int]*list) {
|
func (s *Bridge) delClient(id int, l map[int]*list) {
|
||||||
if t := l[id]; t != nil {
|
if t := l[id]; t != nil {
|
||||||
for {
|
for {
|
||||||
if t.Len() <= 0 {
|
if t.Len() <= 0 {
|
||||||
|
@ -209,7 +209,7 @@ func (s *Tunnel) delClient(id int, l map[int]*list) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//等待
|
//等待
|
||||||
func (s *Tunnel) waitAndPop(m map[int]*list, id int) (c *utils.Conn, err error) {
|
func (s *Bridge) waitAndPop(m map[int]*list, id int) (c *utils.Conn, err error) {
|
||||||
ticker := time.NewTicker(time.Millisecond * 100)
|
ticker := time.NewTicker(time.Millisecond * 100)
|
||||||
stop := time.After(time.Second * 3)
|
stop := time.After(time.Second * 3)
|
||||||
for {
|
for {
|
||||||
|
@ -231,7 +231,7 @@ func (s *Tunnel) waitAndPop(m map[int]*list, id int) (c *utils.Conn, err error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Tunnel) verify(id int) bool {
|
func (s *Bridge) verify(id int) bool {
|
||||||
for k := range s.RunList {
|
for k := range s.RunList {
|
||||||
if k == id {
|
if k == id {
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -24,22 +24,32 @@ var (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
server.VerifyKey = *VerifyKey
|
task := &utils.Tunnel{
|
||||||
cnf := &utils.ServerConfig{
|
TcpPort: *httpPort,
|
||||||
TcpPort: *httpPort,
|
Mode: *rpMode,
|
||||||
Mode: *rpMode,
|
Target: *tunnelTarget,
|
||||||
Target: *tunnelTarget,
|
Config: &utils.Config{
|
||||||
VerifyKey: *VerifyKey,
|
U: *u,
|
||||||
U: *u,
|
P: *p,
|
||||||
P: *p,
|
Compress: *compress,
|
||||||
Compress: *compress,
|
Crypt: utils.GetBoolByStr(*crypt),
|
||||||
Start: 0,
|
Mux: utils.GetBoolByStr(*mux),
|
||||||
IsRun: 0,
|
},
|
||||||
ClientStatus: 0,
|
Flow: &utils.Flow{},
|
||||||
Crypt: utils.GetBoolByStr(*crypt),
|
UseClientCnf: false,
|
||||||
Mux: utils.GetBoolByStr(*mux),
|
}
|
||||||
CompressEncode: 0,
|
if *VerifyKey != "" {
|
||||||
CompressDecode: 0,
|
c := &utils.Client{
|
||||||
|
Id: 0,
|
||||||
|
VerifyKey: *VerifyKey,
|
||||||
|
Addr: "",
|
||||||
|
Remark: "",
|
||||||
|
Status: true,
|
||||||
|
IsConnect: false,
|
||||||
|
}
|
||||||
|
c.Cnf.CompressDecode, c.Cnf.CompressEncode = utils.GetCompressType(c.Cnf.Compress)
|
||||||
|
server.CsvDb.Clients[0] = c
|
||||||
|
task.Client = c
|
||||||
}
|
}
|
||||||
if *TcpPort == 0 {
|
if *TcpPort == 0 {
|
||||||
p, err := beego.AppConfig.Int("tcpport")
|
p, err := beego.AppConfig.Int("tcpport")
|
||||||
|
@ -50,6 +60,6 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Println("服务端启动,监听tcp服务端端口:", *TcpPort)
|
log.Println("服务端启动,监听tcp服务端端口:", *TcpPort)
|
||||||
cnf.CompressDecode, cnf.CompressEncode = utils.GetCompressType(cnf.Compress)
|
task.Config.CompressDecode, task.Config.CompressEncode = utils.GetCompressType(task.Config.Compress)
|
||||||
server.StartNewServer(*TcpPort, cnf)
|
server.StartNewServer(*TcpPort, task)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
2,zl4p3da659qa9rh3,127.0.0.1:58000,测试2,true,,,0,0,
|
|
||||||
1,rfd0tl1anega0d0g,127.0.0.1:53603,测试,true,1,1,1,1,snappy
|
1,rfd0tl1anega0d0g,127.0.0.1:53603,测试,true,1,1,1,1,snappy
|
||||||
|
2,zl4p3da659qa9rh3,127.0.0.1:52096,测试2,true,1,1,1,1,snappy
|
||||||
|
|
|
|
@ -1,2 +1,2 @@
|
||||||
a.o.com,127.0.0.1:8080,1,,,测试2
|
|
||||||
b.o.com,127.0.0.1:8082,2,,,测试
|
b.o.com,127.0.0.1:8082,2,,,测试
|
||||||
|
a.o.com,127.0.0.1:8080,1,Connection: close,,测试2
|
||||||
|
|
|
|
@ -1,4 +1,5 @@
|
||||||
9001,tunnelServer,127.0.0.1:8080,,,,1,0,0,0,0,1,1,true,test
|
53,udpServer,114.114.114.114:53,,,,1,0,0,0,1,2,2,true,udp测试
|
||||||
53,udpServer,114.114.114.114:53,,,,1,0,0,0,0,2,2,true,udp测试
|
9001,tunnelServer,127.0.0.1:8080,1,1,snappy,1,1,1,0,0,1,1,false,test
|
||||||
8024,socks5Server,,,,,1,0,0,0,0,3,2,true,socks5测试
|
9009,tunnelServer,127.0.0.1:5900,,,,1,0,0,0,0,5,2,true,vnc
|
||||||
8025,httpProxyServer,,,,,1,0,0,0,0,4,2,true,http测试
|
8025,httpProxyServer,,2,2,snappy,1,1,1,0,0,4,2,false,http测试
|
||||||
|
8024,socks5Server,,,,,1,0,0,0,0,3,2,false,socks5测试
|
||||||
|
|
|
BIN
image/web.png
BIN
image/web.png
Binary file not shown.
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 233 KiB |
BIN
image/web2.png
BIN
image/web2.png
Binary file not shown.
Before Width: | Height: | Size: 280 KiB After Width: | Height: | Size: 281 KiB |
|
@ -8,53 +8,47 @@ import (
|
||||||
|
|
||||||
//server base struct
|
//server base struct
|
||||||
type server struct {
|
type server struct {
|
||||||
bridge *bridge.Tunnel
|
bridge *bridge.Bridge
|
||||||
config *utils.ServerConfig
|
task *utils.Tunnel
|
||||||
|
config *utils.Config
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) GetTunnelAndWriteHost(connType string, cnf *utils.ServerConfig, addr string) (*utils.Conn, error) {
|
func (s *server) GetTunnelAndWriteHost(connType string, clientId int, cnf *utils.Config, addr string) (link *utils.Conn, err error) {
|
||||||
var err error
|
if link, err = s.bridge.GetTunnel(clientId, cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, cnf.Mux); err != nil {
|
||||||
link, err := s.bridge.GetTunnel(cnf.ClientId, cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
return
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
if _, err = link.WriteHost(connType, addr); err != nil {
|
if _, err = link.WriteHost(connType, addr); err != nil {
|
||||||
link.Close()
|
link.Close()
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
return link, nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) FlowAdd(in, out int64) {
|
func (s *server) FlowAdd(in, out int64) {
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
if s.config.Flow == nil {
|
s.task.Flow.ExportFlow += out
|
||||||
s.config.Flow = new(utils.Flow)
|
s.task.Flow.InletFlow += in
|
||||||
}
|
|
||||||
s.config.Flow.ExportFlow += out
|
|
||||||
s.config.Flow.InletFlow += in
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) FlowAddHost(host *utils.HostList, in, out int64) {
|
func (s *server) FlowAddHost(host *utils.Host, in, out int64) {
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
if s.config.Flow == nil {
|
|
||||||
s.config.Flow = new(utils.Flow)
|
|
||||||
}
|
|
||||||
host.Flow.ExportFlow += out
|
host.Flow.ExportFlow += out
|
||||||
host.Flow.InletFlow += in
|
host.Flow.InletFlow += in
|
||||||
}
|
}
|
||||||
|
|
||||||
//热更新配置
|
//热更新配置
|
||||||
func (s *server) ResetConfig() {
|
func (s *server) ResetConfig() {
|
||||||
task, err := CsvDb.GetTask(s.config.Id)
|
//获取最新数据
|
||||||
|
task, err := CsvDb.GetTask(s.task.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.config.UseClientCnf = task.UseClientCnf
|
s.task.UseClientCnf = task.UseClientCnf
|
||||||
if s.config.UseClientCnf {
|
//使用客户端配置
|
||||||
client, err := CsvDb.GetClient(s.config.ClientId)
|
if s.task.UseClientCnf {
|
||||||
|
client, err := CsvDb.GetClient(s.task.Client.Id)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
s.config.U = client.Cnf.U
|
s.config.U = client.Cnf.U
|
||||||
s.config.P = client.Cnf.P
|
s.config.P = client.Cnf.P
|
||||||
|
@ -62,15 +56,14 @@ func (s *server) ResetConfig() {
|
||||||
s.config.Mux = client.Cnf.Mux
|
s.config.Mux = client.Cnf.Mux
|
||||||
s.config.Crypt = client.Cnf.Crypt
|
s.config.Crypt = client.Cnf.Crypt
|
||||||
}
|
}
|
||||||
s.config.CompressDecode, s.config.CompressEncode = utils.GetCompressType(client.Cnf.Compress)
|
|
||||||
} else {
|
} else {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
s.config.U = task.U
|
s.config.U = task.Config.U
|
||||||
s.config.P = task.P
|
s.config.P = task.Config.P
|
||||||
s.config.Compress = task.Compress
|
s.config.Compress = task.Config.Compress
|
||||||
s.config.Mux = task.Mux
|
s.config.Mux = task.Config.Mux
|
||||||
s.config.Crypt = task.Crypt
|
s.config.Crypt = task.Config.Crypt
|
||||||
}
|
}
|
||||||
s.config.CompressDecode, s.config.CompressEncode = utils.GetCompressType(task.Compress)
|
|
||||||
}
|
}
|
||||||
|
s.config.CompressDecode, s.config.CompressEncode = utils.GetCompressType(s.config.Compress)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,7 @@ type process func(c *utils.Conn, s *TunnelModeServer) error
|
||||||
|
|
||||||
//tcp隧道模式
|
//tcp隧道模式
|
||||||
func ProcessTunnel(c *utils.Conn, s *TunnelModeServer) error {
|
func ProcessTunnel(c *utils.Conn, s *TunnelModeServer) error {
|
||||||
_, _, rb, err, r := c.GetHost()
|
return s.dealClient(c, s.config, s.task.Target, "", nil)
|
||||||
if err == nil {
|
|
||||||
if err := s.auth(r, c, s.config.U, s.config.P); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s.dealClient(c, s.config, s.config.Target, "", rb)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//http代理模式
|
//http代理模式
|
||||||
|
@ -41,8 +35,7 @@ func ProcessHost(c *utils.Conn, s *TunnelModeServer) error {
|
||||||
var (
|
var (
|
||||||
isConn = true
|
isConn = true
|
||||||
link *utils.Conn
|
link *utils.Conn
|
||||||
client *utils.Client
|
host *utils.Host
|
||||||
host *utils.HostList
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
)
|
)
|
||||||
for {
|
for {
|
||||||
|
@ -52,17 +45,17 @@ func ProcessHost(c *utils.Conn, s *TunnelModeServer) error {
|
||||||
}
|
}
|
||||||
//首次获取conn
|
//首次获取conn
|
||||||
if isConn {
|
if isConn {
|
||||||
if host, client, err = GetKeyByHost(r.Host); err != nil {
|
if host, err = GetInfoByHost(r.Host); err != nil {
|
||||||
log.Printf("the host %s is not found !", r.Host)
|
log.Printf("the host %s is not found !", r.Host)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
client.Cnf.ClientId = host.ClientId
|
host.Client.Cnf.CompressDecode, host.Client.Cnf.CompressEncode = utils.GetCompressType(host.Client.Cnf.Compress)
|
||||||
client.Cnf.CompressDecode, client.Cnf.CompressEncode = utils.GetCompressType(client.Cnf.Compress)
|
|
||||||
if err = s.auth(r, c, client.Cnf.U, client.Cnf.P); err != nil {
|
if err = s.auth(r, c, host.Client.Cnf.U, host.Client.Cnf.P); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if link, err = s.GetTunnelAndWriteHost(utils.CONN_TCP, client.Cnf, host.Target); err != nil {
|
if link, err = s.GetTunnelAndWriteHost(utils.CONN_TCP, host.Client.Id, host.Client.Cnf, host.Target); err != nil {
|
||||||
log.Println("get bridge tunnel error: ", err)
|
log.Println("get bridge tunnel error: ", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -72,27 +65,28 @@ func ProcessHost(c *utils.Conn, s *TunnelModeServer) error {
|
||||||
} else {
|
} else {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
out, _ := utils.Relay(c.Conn, link.Conn, client.Cnf.CompressDecode, client.Cnf.Crypt, client.Cnf.Mux)
|
out, _ := utils.Relay(c.Conn, link.Conn, host.Client.Cnf.CompressDecode, host.Client.Cnf.Crypt, host.Client.Cnf.Mux)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
s.FlowAddHost(host, 0, out)
|
s.FlowAddHost(host, 0, out)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
isConn = false
|
isConn = false
|
||||||
}
|
}
|
||||||
|
//根据设定,修改header和host
|
||||||
utils.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String())
|
utils.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String())
|
||||||
b, err := httputil.DumpRequest(r, true)
|
b, err := httputil.DumpRequest(r, true)
|
||||||
s.FlowAddHost(host, int64(len(b)), 0)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if _, err := link.WriteTo(b, client.Cnf.CompressEncode, client.Cnf.Crypt); err != nil {
|
s.FlowAddHost(host, int64(len(b)), 0)
|
||||||
|
if _, err := link.WriteTo(b, host.Client.Cnf.CompressEncode, host.Client.Cnf.Crypt); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
if client != nil && client.Cnf != nil && client.Cnf.Mux && link != nil {
|
if host != nil && host.Client.Cnf != nil && host.Client.Cnf.Mux && link != nil {
|
||||||
link.WriteTo([]byte(utils.IO_EOF), client.Cnf.CompressEncode, client.Cnf.Crypt)
|
link.WriteTo([]byte(utils.IO_EOF), host.Client.Cnf.CompressEncode, host.Client.Cnf.Crypt)
|
||||||
s.bridge.ReturnTunnel(link, client.Id)
|
s.bridge.ReturnTunnel(link, host.Client.Id)
|
||||||
} else if link != nil {
|
} else if link != nil {
|
||||||
link.Close()
|
link.Close()
|
||||||
}
|
}
|
||||||
|
@ -103,5 +97,3 @@ func ProcessHost(c *utils.Conn, s *TunnelModeServer) error {
|
||||||
c.Close()
|
c.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,9 @@ type RunServer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Bridge *bridge.Tunnel
|
Bridge *bridge.Bridge
|
||||||
RunList map[int]interface{} //运行中的任务
|
RunList map[int]interface{} //运行中的任务
|
||||||
CsvDb = utils.GetCsvDb()
|
CsvDb = utils.GetCsvDb()
|
||||||
VerifyKey string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -33,7 +32,7 @@ func init() {
|
||||||
//从csv文件中恢复任务
|
//从csv文件中恢复任务
|
||||||
func InitFromCsv() {
|
func InitFromCsv() {
|
||||||
for _, v := range CsvDb.Tasks {
|
for _, v := range CsvDb.Tasks {
|
||||||
if v.Start == 1 {
|
if v.Status {
|
||||||
log.Println("启动模式:", v.Mode, "监听端口:", v.TcpPort)
|
log.Println("启动模式:", v.Mode, "监听端口:", v.TcpPort)
|
||||||
AddTask(v)
|
AddTask(v)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +40,7 @@ func InitFromCsv() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//start a new server
|
//start a new server
|
||||||
func StartNewServer(bridgePort int, cnf *utils.ServerConfig) {
|
func StartNewServer(bridgePort int, cnf *utils.Tunnel) {
|
||||||
Bridge = bridge.NewTunnel(bridgePort, RunList)
|
Bridge = bridge.NewTunnel(bridgePort, RunList)
|
||||||
if err := Bridge.StartTunnel(); err != nil {
|
if err := Bridge.StartTunnel(); err != nil {
|
||||||
log.Fatalln("服务端开启失败", err)
|
log.Fatalln("服务端开启失败", err)
|
||||||
|
@ -58,37 +57,32 @@ func StartNewServer(bridgePort int, cnf *utils.ServerConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//new a server by mode name
|
//new a server by mode name
|
||||||
func NewMode(Bridge *bridge.Tunnel, c *utils.ServerConfig) interface{} {
|
func NewMode(Bridge *bridge.Bridge, c *utils.Tunnel) interface{} {
|
||||||
config := utils.DeepCopyConfig(c)
|
switch c.Mode {
|
||||||
switch config.Mode {
|
|
||||||
case "tunnelServer":
|
case "tunnelServer":
|
||||||
return NewTunnelModeServer(ProcessTunnel, Bridge, config)
|
return NewTunnelModeServer(ProcessTunnel, Bridge, c)
|
||||||
case "socks5Server":
|
case "socks5Server":
|
||||||
return NewSock5ModeServer(Bridge, config)
|
return NewSock5ModeServer(Bridge, c)
|
||||||
case "httpProxyServer":
|
case "httpProxyServer":
|
||||||
return NewTunnelModeServer(ProcessHttp, Bridge, config)
|
return NewTunnelModeServer(ProcessHttp, Bridge, c)
|
||||||
case "udpServer":
|
case "udpServer":
|
||||||
return NewUdpModeServer(Bridge, config)
|
return NewUdpModeServer(Bridge, c)
|
||||||
case "webServer":
|
case "webServer":
|
||||||
InitFromCsv()
|
InitFromCsv()
|
||||||
p, _ := beego.AppConfig.Int("hostPort")
|
p, _ := beego.AppConfig.Int("hostPort")
|
||||||
t := &utils.ServerConfig{
|
t := &utils.Tunnel{
|
||||||
TcpPort: p,
|
TcpPort: p,
|
||||||
Mode: "httpHostServer",
|
Mode: "httpHostServer",
|
||||||
Target: "",
|
Target: "",
|
||||||
U: "",
|
Config: &utils.Config{},
|
||||||
P: "",
|
Status: true,
|
||||||
Compress: "",
|
|
||||||
Start: 1,
|
|
||||||
IsRun: 0,
|
|
||||||
ClientStatus: 0,
|
|
||||||
}
|
}
|
||||||
AddTask(t)
|
AddTask(t)
|
||||||
return NewWebServer(Bridge)
|
return NewWebServer(Bridge)
|
||||||
case "hostServer":
|
case "hostServer":
|
||||||
return NewHostServer(config)
|
return NewHostServer(c)
|
||||||
case "httpHostServer":
|
case "httpHostServer":
|
||||||
return NewTunnelModeServer(ProcessHost, Bridge, config)
|
return NewTunnelModeServer(ProcessHost, Bridge, c)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -100,7 +94,7 @@ func StopServer(id int) error {
|
||||||
if t, err := CsvDb.GetTask(id); err != nil {
|
if t, err := CsvDb.GetTask(id); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
t.Start = 0
|
t.Status = false
|
||||||
CsvDb.UpdateTask(t)
|
CsvDb.UpdateTask(t)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -109,7 +103,7 @@ func StopServer(id int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
//add task
|
//add task
|
||||||
func AddTask(t *utils.ServerConfig) error {
|
func AddTask(t *utils.Tunnel) error {
|
||||||
if svr := NewMode(Bridge, t); svr != nil {
|
if svr := NewMode(Bridge, t); svr != nil {
|
||||||
RunList[t.Id] = svr
|
RunList[t.Id] = svr
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -131,7 +125,7 @@ func StartTask(id int) error {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
AddTask(t)
|
AddTask(t)
|
||||||
t.Start = 1
|
t.Status = true
|
||||||
CsvDb.UpdateTask(t)
|
CsvDb.UpdateTask(t)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -146,12 +140,11 @@ func DelTask(id int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
//get key by host from x
|
//get key by host from x
|
||||||
func GetKeyByHost(host string) (h *utils.HostList, t *utils.Client, err error) {
|
func GetInfoByHost(host string) (h *utils.Host, err error) {
|
||||||
for _, v := range CsvDb.Hosts {
|
for _, v := range CsvDb.Hosts {
|
||||||
s := strings.Split(host, ":")
|
s := strings.Split(host, ":")
|
||||||
if s[0] == v.Host {
|
if s[0] == v.Host {
|
||||||
h = v
|
h = v
|
||||||
t, err = CsvDb.GetClient(v.ClientId)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,39 +153,25 @@ func GetKeyByHost(host string) (h *utils.HostList, t *utils.Client, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//get task list by page num
|
//get task list by page num
|
||||||
func GetServerConfig(start, length int, typeVal string, clientId int) ([]*utils.ServerConfig, int) {
|
func GetTunnel(start, length int, typeVal string, clientId int) ([]*utils.Tunnel, int) {
|
||||||
list := make([]*utils.ServerConfig, 0)
|
list := make([]*utils.Tunnel, 0)
|
||||||
var cnt int
|
var cnt int
|
||||||
for _, v := range CsvDb.Tasks {
|
for _, v := range CsvDb.Tasks {
|
||||||
if (typeVal != "" && v.Mode != typeVal) || (typeVal == "" && clientId != v.ClientId) {
|
if (typeVal != "" && v.Mode != typeVal) || (typeVal == "" && clientId != v.Client.Id) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if v.UseClientCnf {
|
|
||||||
v = utils.DeepCopyConfig(v)
|
|
||||||
if c, err := CsvDb.GetClient(v.ClientId); err == nil {
|
|
||||||
v.Compress = c.Cnf.Compress
|
|
||||||
v.Mux = c.Cnf.Mux
|
|
||||||
v.Crypt = c.Cnf.Crypt
|
|
||||||
v.U = c.Cnf.U
|
|
||||||
v.P = c.Cnf.P
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cnt++
|
cnt++
|
||||||
|
if _, ok := Bridge.SignalList[v.Client.Id]; ok {
|
||||||
|
v.Client.IsConnect = true
|
||||||
|
} else {
|
||||||
|
v.Client.IsConnect = false
|
||||||
|
}
|
||||||
if start--; start < 0 {
|
if start--; start < 0 {
|
||||||
if length--; length > 0 {
|
if length--; length > 0 {
|
||||||
if _, ok := RunList[v.Id]; ok {
|
if _, ok := RunList[v.Id]; ok {
|
||||||
v.IsRun = 1
|
v.Client.Status = true
|
||||||
} else {
|
} else {
|
||||||
v.IsRun = 0
|
v.Client.Status = false
|
||||||
}
|
|
||||||
if s, ok := Bridge.SignalList[v.ClientId]; ok {
|
|
||||||
if s.Len() > 0 {
|
|
||||||
v.ClientStatus = 1
|
|
||||||
} else {
|
|
||||||
v.ClientStatus = 0
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
v.ClientStatus = 0
|
|
||||||
}
|
}
|
||||||
list = append(list, v)
|
list = append(list, v)
|
||||||
}
|
}
|
||||||
|
@ -218,13 +197,13 @@ func dealClientData(list []*utils.Client) {
|
||||||
v.Flow.InletFlow = 0
|
v.Flow.InletFlow = 0
|
||||||
v.Flow.ExportFlow = 0
|
v.Flow.ExportFlow = 0
|
||||||
for _, h := range CsvDb.Hosts {
|
for _, h := range CsvDb.Hosts {
|
||||||
if h.ClientId == v.Id {
|
if h.Client.Id == v.Id {
|
||||||
v.Flow.InletFlow += h.Flow.InletFlow
|
v.Flow.InletFlow += h.Flow.InletFlow
|
||||||
v.Flow.ExportFlow += h.Flow.ExportFlow
|
v.Flow.ExportFlow += h.Flow.ExportFlow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, t := range CsvDb.Tasks {
|
for _, t := range CsvDb.Tasks {
|
||||||
if t.ClientId == v.Id {
|
if t.Client.Id == v.Id {
|
||||||
v.Flow.InletFlow += t.Flow.InletFlow
|
v.Flow.InletFlow += t.Flow.InletFlow
|
||||||
v.Flow.ExportFlow += t.Flow.ExportFlow
|
v.Flow.ExportFlow += t.Flow.ExportFlow
|
||||||
}
|
}
|
||||||
|
@ -236,12 +215,12 @@ func dealClientData(list []*utils.Client) {
|
||||||
//根据客户端id删除其所属的所有隧道和域名
|
//根据客户端id删除其所属的所有隧道和域名
|
||||||
func DelTunnelAndHostByClientId(clientId int) {
|
func DelTunnelAndHostByClientId(clientId int) {
|
||||||
for _, v := range CsvDb.Tasks {
|
for _, v := range CsvDb.Tasks {
|
||||||
if v.ClientId == clientId {
|
if v.Client.Id == clientId {
|
||||||
DelTask(v.Id)
|
DelTask(v.Id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, v := range CsvDb.Hosts {
|
for _, v := range CsvDb.Hosts {
|
||||||
if v.ClientId == clientId {
|
if v.Client.Id == clientId {
|
||||||
CsvDb.DelHost(v.Host)
|
CsvDb.DelHost(v.Host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,7 @@ func (s *Sock5ModeServer) doConnect(c net.Conn, command uint8) (proxyConn *utils
|
||||||
} else {
|
} else {
|
||||||
ltype = utils.CONN_TCP
|
ltype = utils.CONN_TCP
|
||||||
}
|
}
|
||||||
if proxyConn, err = s.GetTunnelAndWriteHost(ltype, s.config, addr); err != nil {
|
if proxyConn, err = s.GetTunnelAndWriteHost(ltype, s.task.Client.Id, s.config, addr); err != nil {
|
||||||
log.Println("get bridge tunnel error: ", err)
|
log.Println("get bridge tunnel error: ", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ func (s *Sock5ModeServer) handleConnect(c net.Conn) {
|
||||||
proxyConn, err := s.doConnect(c, connectMethod)
|
proxyConn, err := s.doConnect(c, connectMethod)
|
||||||
defer func() {
|
defer func() {
|
||||||
if s.config.Mux && proxyConn != nil {
|
if s.config.Mux && proxyConn != nil {
|
||||||
s.bridge.ReturnTunnel(proxyConn, s.config.ClientId)
|
s.bridge.ReturnTunnel(proxyConn, s.task.Client.Id)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -198,7 +198,7 @@ func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
||||||
proxyConn, err := s.doConnect(c, associateMethod)
|
proxyConn, err := s.doConnect(c, associateMethod)
|
||||||
defer func() {
|
defer func() {
|
||||||
if s.config.Mux && proxyConn != nil {
|
if s.config.Mux && proxyConn != nil {
|
||||||
s.bridge.ReturnTunnel(proxyConn, s.config.ClientId)
|
s.bridge.ReturnTunnel(proxyConn, s.task.Client.Id)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -285,7 +285,7 @@ func (s *Sock5ModeServer) Auth(c net.Conn) error {
|
||||||
//start
|
//start
|
||||||
func (s *Sock5ModeServer) Start() error {
|
func (s *Sock5ModeServer) Start() error {
|
||||||
var err error
|
var err error
|
||||||
s.listener, err = net.Listen("tcp", ":"+strconv.Itoa(s.config.TcpPort))
|
s.listener, err = net.Listen("tcp", ":"+strconv.Itoa(s.task.TcpPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -309,10 +309,11 @@ func (s *Sock5ModeServer) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
//new
|
//new
|
||||||
func NewSock5ModeServer(bridge *bridge.Tunnel, cnf *utils.ServerConfig) *Sock5ModeServer {
|
func NewSock5ModeServer(bridge *bridge.Bridge, task *utils.Tunnel) *Sock5ModeServer {
|
||||||
s := new(Sock5ModeServer)
|
s := new(Sock5ModeServer)
|
||||||
s.bridge = bridge
|
s.bridge = bridge
|
||||||
s.config = cnf
|
s.task = task
|
||||||
|
s.config = utils.DeepCopyConfig(task.Config)
|
||||||
if s.config.U != "" && s.config.P != "" {
|
if s.config.U != "" && s.config.P != "" {
|
||||||
s.isVerify = true
|
s.isVerify = true
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -20,11 +20,12 @@ type TunnelModeServer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
//tcp|http|host
|
//tcp|http|host
|
||||||
func NewTunnelModeServer(process process, bridge *bridge.Tunnel, cnf *utils.ServerConfig) *TunnelModeServer {
|
func NewTunnelModeServer(process process, bridge *bridge.Bridge, task *utils.Tunnel) *TunnelModeServer {
|
||||||
s := new(TunnelModeServer)
|
s := new(TunnelModeServer)
|
||||||
s.bridge = bridge
|
s.bridge = bridge
|
||||||
s.process = process
|
s.process = process
|
||||||
s.config = cnf
|
s.task = task
|
||||||
|
s.config = utils.DeepCopyConfig(task.Config)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ func (s *TunnelModeServer) Start() error {
|
||||||
if s.errorContent, err = utils.ReadAllFromFile(beego.AppPath + "/web/static/page/error.html"); err != nil {
|
if s.errorContent, err = utils.ReadAllFromFile(beego.AppPath + "/web/static/page/error.html"); err != nil {
|
||||||
s.errorContent = []byte("easyProxy 404")
|
s.errorContent = []byte("easyProxy 404")
|
||||||
}
|
}
|
||||||
s.listener, err = net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), s.config.TcpPort, ""})
|
s.listener, err = net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), s.task.TcpPort, ""})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -69,15 +70,15 @@ func (s *TunnelModeServer) writeConnFail(c net.Conn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//与客户端建立通道
|
//与客户端建立通道
|
||||||
func (s *TunnelModeServer) dealClient(c *utils.Conn, cnf *utils.ServerConfig, addr string, method string, rb []byte) error {
|
func (s *TunnelModeServer) dealClient(c *utils.Conn, cnf *utils.Config, addr string, method string, rb []byte) error {
|
||||||
var link *utils.Conn
|
var link *utils.Conn
|
||||||
var err error
|
var err error
|
||||||
defer func() {
|
defer func() {
|
||||||
if cnf.Mux && link != nil {
|
if cnf.Mux && link != nil {
|
||||||
s.bridge.ReturnTunnel(link, cnf.ClientId)
|
s.bridge.ReturnTunnel(link, s.task.Client.Id)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
if link, err = s.GetTunnelAndWriteHost(utils.CONN_TCP, cnf, addr); err != nil {
|
if link, err = s.GetTunnelAndWriteHost(utils.CONN_TCP, s.task.Client.Id, cnf, addr); err != nil {
|
||||||
log.Println("get bridge tunnel error: ", err)
|
log.Println("get bridge tunnel error: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -115,7 +116,7 @@ func (s *WebServer) Start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//new
|
//new
|
||||||
func NewWebServer(bridge *bridge.Tunnel) *WebServer {
|
func NewWebServer(bridge *bridge.Bridge) *WebServer {
|
||||||
s := new(WebServer)
|
s := new(WebServer)
|
||||||
s.bridge = bridge
|
s.bridge = bridge
|
||||||
return s
|
return s
|
||||||
|
@ -131,9 +132,10 @@ func (s *HostServer) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHostServer(cnf *utils.ServerConfig) *HostServer {
|
func NewHostServer(task *utils.Tunnel) *HostServer {
|
||||||
s := new(HostServer)
|
s := new(HostServer)
|
||||||
s.config = cnf
|
s.task = task
|
||||||
|
s.config = utils.DeepCopyConfig(task.Config)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,18 +15,19 @@ type UdpModeServer struct {
|
||||||
udpMap map[string]*utils.Conn
|
udpMap map[string]*utils.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUdpModeServer(bridge *bridge.Tunnel, cnf *utils.ServerConfig) *UdpModeServer {
|
func NewUdpModeServer(bridge *bridge.Bridge, task *utils.Tunnel) *UdpModeServer {
|
||||||
s := new(UdpModeServer)
|
s := new(UdpModeServer)
|
||||||
s.bridge = bridge
|
s.bridge = bridge
|
||||||
s.udpMap = make(map[string]*utils.Conn)
|
s.udpMap = make(map[string]*utils.Conn)
|
||||||
s.config = cnf
|
s.task = task
|
||||||
|
s.config = utils.DeepCopyConfig(task.Config)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
//开始
|
//开始
|
||||||
func (s *UdpModeServer) Start() error {
|
func (s *UdpModeServer) Start() error {
|
||||||
var err error
|
var err error
|
||||||
s.listener, err = net.ListenUDP("udp", &net.UDPAddr{net.ParseIP("0.0.0.0"), s.config.TcpPort, ""})
|
s.listener, err = net.ListenUDP("udp", &net.UDPAddr{net.ParseIP("0.0.0.0"), s.task.TcpPort, ""})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -45,14 +46,14 @@ func (s *UdpModeServer) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO:效率问题有待解决
|
//TODO:效率问题有待解决--->建立稳定通道,重复利用,提高效率,下个版本
|
||||||
func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
|
func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
|
||||||
conn, err := s.bridge.GetTunnel(s.config.ClientId, s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
conn, err := s.bridge.GetTunnel(s.task.Client.Id, s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := conn.WriteHost(utils.CONN_UDP, s.config.Target); err != nil {
|
if _, err := conn.WriteHost(utils.CONN_UDP, s.task.Target); err != nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -60,7 +61,7 @@ func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if conn != nil && s.config.Mux {
|
if conn != nil && s.config.Mux {
|
||||||
conn.WriteTo([]byte(utils.IO_EOF), s.config.CompressEncode, s.config.Crypt)
|
conn.WriteTo([]byte(utils.IO_EOF), s.config.CompressEncode, s.config.Crypt)
|
||||||
s.bridge.ReturnTunnel(conn, s.config.ClientId)
|
s.bridge.ReturnTunnel(conn, s.task.Client.Id)
|
||||||
} else {
|
} else {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}
|
}
|
||||||
|
@ -70,7 +71,6 @@ func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
|
||||||
buf := utils.BufPoolUdp.Get().([]byte)
|
buf := utils.BufPoolUdp.Get().([]byte)
|
||||||
out, err := conn.ReadFrom(buf, s.config.CompressDecode, s.config.Crypt)
|
out, err := conn.ReadFrom(buf, s.config.CompressDecode, s.config.Crypt)
|
||||||
if err != nil || err == io.EOF {
|
if err != nil || err == io.EOF {
|
||||||
log.Println("revieve error:", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.listener.WriteToUDP(buf[:out], addr)
|
s.listener.WriteToUDP(buf[:out], addr)
|
||||||
|
|
147
utils/file.go
147
utils/file.go
|
@ -22,7 +22,7 @@ type Flow struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Cnf *ServerConfig
|
Cnf *Config
|
||||||
Id int //id
|
Id int //id
|
||||||
VerifyKey string //验证密钥
|
VerifyKey string //验证密钥
|
||||||
Addr string //客户端ip地址
|
Addr string //客户端ip地址
|
||||||
|
@ -32,35 +32,36 @@ type Client struct {
|
||||||
Flow *Flow
|
Flow *Flow
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerConfig struct {
|
type Tunnel struct {
|
||||||
TcpPort int //服务端与客户端通信端口
|
Id int //Id
|
||||||
VerifyKey string
|
TcpPort int //服务端与客户端通信端口
|
||||||
Mode string //启动方式
|
Mode string //启动方式
|
||||||
Target string //目标
|
Target string //目标
|
||||||
|
Status bool //是否开启
|
||||||
|
Client *Client //所属客户端id
|
||||||
|
Flow *Flow
|
||||||
|
Config *Config
|
||||||
|
UseClientCnf bool //是否继承客户端配置
|
||||||
|
Remark string //备注
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
U string //socks5验证用户名
|
U string //socks5验证用户名
|
||||||
P string //socks5验证密码
|
P string //socks5验证密码
|
||||||
Compress string //压缩方式
|
Compress string //压缩方式
|
||||||
Start int //是否开启
|
|
||||||
IsRun int //是否在运行
|
|
||||||
ClientStatus int //客s户端状态
|
|
||||||
Crypt bool //是否加密
|
Crypt bool //是否加密
|
||||||
Mux bool //是否加密
|
Mux bool //是否加密
|
||||||
CompressEncode int //加密方式
|
CompressEncode int //加密方式
|
||||||
CompressDecode int //解密方式
|
CompressDecode int //解密方式
|
||||||
Id int //Id
|
|
||||||
ClientId int //所属客户端id
|
|
||||||
UseClientCnf bool //是否继承客户端配置
|
|
||||||
Flow *Flow
|
|
||||||
Remark string //备注
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostList struct {
|
type Host struct {
|
||||||
ClientId int //服务端与客户端通信端口
|
|
||||||
Host string //启动方式
|
Host string //启动方式
|
||||||
Target string //目标
|
Target string //目标
|
||||||
HeaderChange string //host修改
|
HeaderChange string //host修改
|
||||||
HostChange string //host修改
|
HostChange string //host修改
|
||||||
Flow *Flow
|
Flow *Flow
|
||||||
|
Client *Client
|
||||||
Remark string //备注
|
Remark string //备注
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,19 +71,19 @@ func NewCsv() *Csv {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Csv struct {
|
type Csv struct {
|
||||||
Tasks []*ServerConfig
|
Tasks []*Tunnel
|
||||||
Path string
|
Path string
|
||||||
Hosts []*HostList //域名列表
|
Hosts []*Host //域名列表
|
||||||
Clients []*Client //客户端
|
Clients []*Client //客户端
|
||||||
ClientIncreaseId int //客户端id
|
ClientIncreaseId int //客户端id
|
||||||
TaskIncreaseId int //任务自增ID
|
TaskIncreaseId int //任务自增ID
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) Init() {
|
func (s *Csv) Init() {
|
||||||
|
s.LoadClientFromCsv()
|
||||||
s.LoadTaskFromCsv()
|
s.LoadTaskFromCsv()
|
||||||
s.LoadHostFromCsv()
|
s.LoadHostFromCsv()
|
||||||
s.LoadClientFromCsv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) StoreTasksToCsv() {
|
func (s *Csv) StoreTasksToCsv() {
|
||||||
|
@ -98,16 +99,16 @@ func (s *Csv) StoreTasksToCsv() {
|
||||||
strconv.Itoa(task.TcpPort),
|
strconv.Itoa(task.TcpPort),
|
||||||
task.Mode,
|
task.Mode,
|
||||||
task.Target,
|
task.Target,
|
||||||
task.U,
|
task.Config.U,
|
||||||
task.P,
|
task.Config.P,
|
||||||
task.Compress,
|
task.Config.Compress,
|
||||||
strconv.Itoa(task.Start),
|
utils.GetStrByBool(task.Status),
|
||||||
GetStrByBool(task.Crypt),
|
GetStrByBool(task.Config.Crypt),
|
||||||
GetStrByBool(task.Mux),
|
GetStrByBool(task.Config.Mux),
|
||||||
strconv.Itoa(task.CompressEncode),
|
strconv.Itoa(task.Config.CompressEncode),
|
||||||
strconv.Itoa(task.CompressDecode),
|
strconv.Itoa(task.Config.CompressDecode),
|
||||||
strconv.Itoa(task.Id),
|
strconv.Itoa(task.Id),
|
||||||
strconv.Itoa(task.ClientId),
|
strconv.Itoa(task.Client.Id),
|
||||||
strconv.FormatBool(task.UseClientCnf),
|
strconv.FormatBool(task.UseClientCnf),
|
||||||
task.Remark,
|
task.Remark,
|
||||||
}
|
}
|
||||||
|
@ -143,27 +144,31 @@ func (s *Csv) LoadTaskFromCsv() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("配置文件打开错误:", path)
|
log.Fatal("配置文件打开错误:", path)
|
||||||
}
|
}
|
||||||
var tasks []*ServerConfig
|
var tasks []*Tunnel
|
||||||
// 将每一行数据保存到内存slice中
|
// 将每一行数据保存到内存slice中
|
||||||
for _, item := range records {
|
for _, item := range records {
|
||||||
post := &ServerConfig{
|
post := &Tunnel{
|
||||||
TcpPort: GetIntNoErrByStr(item[0]),
|
TcpPort: GetIntNoErrByStr(item[0]),
|
||||||
Mode: item[1],
|
Mode: item[1],
|
||||||
Target: item[2],
|
Target: item[2],
|
||||||
U: item[3],
|
Config: &Config{
|
||||||
P: item[4],
|
U: item[3],
|
||||||
Compress: item[5],
|
P: item[4],
|
||||||
Start: GetIntNoErrByStr(item[6]),
|
Compress: item[5],
|
||||||
Crypt: GetBoolByStr(item[7]),
|
Crypt: GetBoolByStr(item[7]),
|
||||||
Mux: GetBoolByStr(item[8]),
|
Mux: GetBoolByStr(item[8]),
|
||||||
CompressEncode: GetIntNoErrByStr(item[9]),
|
CompressEncode: GetIntNoErrByStr(item[9]),
|
||||||
CompressDecode: GetIntNoErrByStr(item[10]),
|
CompressDecode: GetIntNoErrByStr(item[10]),
|
||||||
Id: GetIntNoErrByStr(item[11]),
|
},
|
||||||
ClientId: GetIntNoErrByStr(item[12]),
|
Status: utils.GetBoolByStr(item[6]),
|
||||||
UseClientCnf: GetBoolByStr(item[13]),
|
Id: GetIntNoErrByStr(item[11]),
|
||||||
Remark: item[14],
|
UseClientCnf: GetBoolByStr(item[13]),
|
||||||
|
Remark: item[14],
|
||||||
}
|
}
|
||||||
post.Flow = new(Flow)
|
post.Flow = new(Flow)
|
||||||
|
if post.Client, err = s.GetClient(GetIntNoErrByStr(item[12])); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
tasks = append(tasks, post)
|
tasks = append(tasks, post)
|
||||||
if post.Id > s.TaskIncreaseId {
|
if post.Id > s.TaskIncreaseId {
|
||||||
s.TaskIncreaseId = post.Id
|
s.TaskIncreaseId = post.Id
|
||||||
|
@ -191,13 +196,13 @@ func (s *Csv) GetIdByVerifyKey(vKey string, addr string) (int, error) {
|
||||||
return 0, errors.New("not found")
|
return 0, errors.New("not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) NewTask(t *ServerConfig) {
|
func (s *Csv) NewTask(t *Tunnel) {
|
||||||
t.Flow = new(Flow)
|
t.Flow = new(Flow)
|
||||||
s.Tasks = append(s.Tasks, t)
|
s.Tasks = append(s.Tasks, t)
|
||||||
s.StoreTasksToCsv()
|
s.StoreTasksToCsv()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) UpdateTask(t *ServerConfig) error {
|
func (s *Csv) UpdateTask(t *Tunnel) error {
|
||||||
for k, v := range s.Tasks {
|
for k, v := range s.Tasks {
|
||||||
if v.Id == t.Id {
|
if v.Id == t.Id {
|
||||||
s.Tasks = append(s.Tasks[:k], s.Tasks[k+1:]...)
|
s.Tasks = append(s.Tasks[:k], s.Tasks[k+1:]...)
|
||||||
|
@ -220,7 +225,7 @@ func (s *Csv) DelTask(id int) error {
|
||||||
return errors.New("不存在")
|
return errors.New("不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) GetTask(id int) (v *ServerConfig, err error) {
|
func (s *Csv) GetTask(id int) (v *Tunnel, err error) {
|
||||||
for _, v = range s.Tasks {
|
for _, v = range s.Tasks {
|
||||||
if v.Id == id {
|
if v.Id == id {
|
||||||
return
|
return
|
||||||
|
@ -245,7 +250,7 @@ func (s *Csv) StoreHostToCsv() {
|
||||||
record := []string{
|
record := []string{
|
||||||
host.Host,
|
host.Host,
|
||||||
host.Target,
|
host.Target,
|
||||||
strconv.Itoa(host.ClientId),
|
strconv.Itoa(host.Client.Id),
|
||||||
host.HeaderChange,
|
host.HeaderChange,
|
||||||
host.HostChange,
|
host.HostChange,
|
||||||
host.Remark,
|
host.Remark,
|
||||||
|
@ -274,7 +279,7 @@ func (s *Csv) LoadClientFromCsv() {
|
||||||
Addr: item[2],
|
Addr: item[2],
|
||||||
Remark: item[3],
|
Remark: item[3],
|
||||||
Status: GetBoolByStr(item[4]),
|
Status: GetBoolByStr(item[4]),
|
||||||
Cnf: &ServerConfig{
|
Cnf: &Config{
|
||||||
U: item[5],
|
U: item[5],
|
||||||
P: item[6],
|
P: item[6],
|
||||||
Crypt: GetBoolByStr(item[7]),
|
Crypt: GetBoolByStr(item[7]),
|
||||||
|
@ -297,17 +302,19 @@ func (s *Csv) LoadHostFromCsv() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("配置文件打开错误:", path)
|
log.Fatal("配置文件打开错误:", path)
|
||||||
}
|
}
|
||||||
var hosts []*HostList
|
var hosts []*Host
|
||||||
// 将每一行数据保存到内存slice中
|
// 将每一行数据保存到内存slice中
|
||||||
for _, item := range records {
|
for _, item := range records {
|
||||||
post := &HostList{
|
post := &Host{
|
||||||
ClientId: GetIntNoErrByStr(item[2]),
|
|
||||||
Host: item[0],
|
Host: item[0],
|
||||||
Target: item[1],
|
Target: item[1],
|
||||||
HeaderChange: item[3],
|
HeaderChange: item[3],
|
||||||
HostChange: item[4],
|
HostChange: item[4],
|
||||||
Remark: item[5],
|
Remark: item[5],
|
||||||
}
|
}
|
||||||
|
if post.Client, err = s.GetClient(GetIntNoErrByStr(item[2])); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
post.Flow = new(Flow)
|
post.Flow = new(Flow)
|
||||||
hosts = append(hosts, post)
|
hosts = append(hosts, post)
|
||||||
}
|
}
|
||||||
|
@ -325,14 +332,14 @@ func (s *Csv) DelHost(host string) error {
|
||||||
return errors.New("不存在")
|
return errors.New("不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) NewHost(t *HostList) {
|
func (s *Csv) NewHost(t *Host) {
|
||||||
t.Flow = new(Flow)
|
t.Flow = new(Flow)
|
||||||
s.Hosts = append(s.Hosts, t)
|
s.Hosts = append(s.Hosts, t)
|
||||||
s.StoreHostToCsv()
|
s.StoreHostToCsv()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) UpdateHost(t *HostList) error {
|
func (s *Csv) UpdateHost(t *Host) error {
|
||||||
for k, v := range s.Hosts {
|
for k, v := range s.Hosts {
|
||||||
if v.Host == t.Host {
|
if v.Host == t.Host {
|
||||||
s.Hosts = append(s.Hosts[:k], s.Hosts[k+1:]...)
|
s.Hosts = append(s.Hosts[:k], s.Hosts[k+1:]...)
|
||||||
|
@ -344,11 +351,11 @@ func (s *Csv) UpdateHost(t *HostList) error {
|
||||||
return errors.New("不存在")
|
return errors.New("不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) GetHostList(start, length int, id int) ([]*HostList, int) {
|
func (s *Csv) GetHost(start, length int, id int) ([]*Host, int) {
|
||||||
list := make([]*HostList, 0)
|
list := make([]*Host, 0)
|
||||||
var cnt int
|
var cnt int
|
||||||
for _, v := range s.Hosts {
|
for _, v := range s.Hosts {
|
||||||
if id == 0 || v.ClientId == id {
|
if id == 0 || v.Client.Id == id {
|
||||||
cnt++
|
cnt++
|
||||||
if start--; start < 0 {
|
if start--; start < 0 {
|
||||||
if length--; length > 0 {
|
if length--; length > 0 {
|
||||||
|
@ -461,27 +468,15 @@ func GetCsvDb() *Csv {
|
||||||
return CsvDb
|
return CsvDb
|
||||||
}
|
}
|
||||||
|
|
||||||
//深拷贝serverConfig
|
//深拷贝Tunnel
|
||||||
func DeepCopyConfig(c *ServerConfig) *ServerConfig {
|
func DeepCopyConfig(c *Config) *Config {
|
||||||
return &ServerConfig{
|
return &Config{
|
||||||
TcpPort: c.TcpPort,
|
|
||||||
VerifyKey: c.VerifyKey,
|
|
||||||
Mode: c.Mode,
|
|
||||||
Target: c.Target,
|
|
||||||
U: c.U,
|
U: c.U,
|
||||||
P: c.P,
|
P: c.P,
|
||||||
Compress: c.Compress,
|
Compress: c.Compress,
|
||||||
Start: c.Start,
|
|
||||||
IsRun: c.IsRun,
|
|
||||||
ClientStatus: c.ClientStatus,
|
|
||||||
Crypt: c.Crypt,
|
Crypt: c.Crypt,
|
||||||
Mux: c.Mux,
|
Mux: c.Mux,
|
||||||
CompressEncode: c.CompressEncode,
|
CompressEncode: c.CompressEncode,
|
||||||
CompressDecode: c.CompressDecode,
|
CompressDecode: c.CompressDecode,
|
||||||
Id: c.Id,
|
|
||||||
ClientId: c.ClientId,
|
|
||||||
UseClientCnf: c.UseClientCnf,
|
|
||||||
Flow: c.Flow,
|
|
||||||
Remark: c.Remark,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,6 +240,5 @@ func ReadAllFromFile(filePth string) ([]byte, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioutil.ReadAll(f)
|
return ioutil.ReadAll(f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ func (s *ClientController) Add() {
|
||||||
Id: server.CsvDb.GetClientId(),
|
Id: server.CsvDb.GetClientId(),
|
||||||
Status: true,
|
Status: true,
|
||||||
Remark: s.GetString("Remark"),
|
Remark: s.GetString("Remark"),
|
||||||
Cnf: &utils.ServerConfig{
|
Cnf: &utils.Config{
|
||||||
U: s.GetString("u"),
|
U: s.GetString("u"),
|
||||||
P: s.GetString("p"),
|
P: s.GetString("p"),
|
||||||
Compress: s.GetString("compress"),
|
Compress: s.GetString("compress"),
|
||||||
|
|
|
@ -57,11 +57,11 @@ func (s *IndexController) All() {
|
||||||
s.display("index/list")
|
s.display("index/list")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *IndexController) GetServerConfig() {
|
func (s *IndexController) GetTunnel() {
|
||||||
start, length := s.GetAjaxParams()
|
start, length := s.GetAjaxParams()
|
||||||
taskType := s.GetString("type")
|
taskType := s.GetString("type")
|
||||||
clientId := s.GetIntNoErr("client_id")
|
clientId := s.GetIntNoErr("client_id")
|
||||||
list, cnt := server.GetServerConfig(start, length, taskType, clientId)
|
list, cnt := server.GetTunnel(start, length, taskType, clientId)
|
||||||
s.AjaxTable(list, cnt, cnt)
|
s.AjaxTable(list, cnt, cnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,22 +72,26 @@ func (s *IndexController) Add() {
|
||||||
s.SetInfo("新增")
|
s.SetInfo("新增")
|
||||||
s.display()
|
s.display()
|
||||||
} else {
|
} else {
|
||||||
t := &utils.ServerConfig{
|
t := &utils.Tunnel{
|
||||||
TcpPort: s.GetIntNoErr("port"),
|
TcpPort: s.GetIntNoErr("port"),
|
||||||
Mode: s.GetString("type"),
|
Mode: s.GetString("type"),
|
||||||
Target: s.GetString("target"),
|
Target: s.GetString("target"),
|
||||||
U: s.GetString("u"),
|
Config: &utils.Config{
|
||||||
P: s.GetString("p"),
|
U: s.GetString("u"),
|
||||||
Compress: s.GetString("compress"),
|
P: s.GetString("p"),
|
||||||
Crypt: s.GetBoolNoErr("crypt"),
|
Compress: s.GetString("compress"),
|
||||||
Mux: s.GetBoolNoErr("mux"),
|
Crypt: s.GetBoolNoErr("crypt"),
|
||||||
IsRun: 0,
|
Mux: s.GetBoolNoErr("mux"),
|
||||||
|
},
|
||||||
Id: server.CsvDb.GetTaskId(),
|
Id: server.CsvDb.GetTaskId(),
|
||||||
ClientId: s.GetIntNoErr("client_id"),
|
|
||||||
UseClientCnf: s.GetBoolNoErr("use_client"),
|
UseClientCnf: s.GetBoolNoErr("use_client"),
|
||||||
Start: 1,
|
Status: true,
|
||||||
Remark: s.GetString("remark"),
|
Remark: s.GetString("remark"),
|
||||||
}
|
}
|
||||||
|
var err error
|
||||||
|
if t.Client, err = server.CsvDb.GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||||
|
s.AjaxErr(err.Error())
|
||||||
|
}
|
||||||
server.CsvDb.NewTask(t)
|
server.CsvDb.NewTask(t)
|
||||||
if err := server.AddTask(t); err != nil {
|
if err := server.AddTask(t); err != nil {
|
||||||
s.AjaxErr(err.Error())
|
s.AjaxErr(err.Error())
|
||||||
|
@ -115,12 +119,12 @@ func (s *IndexController) Edit() {
|
||||||
t.Mode = s.GetString("type")
|
t.Mode = s.GetString("type")
|
||||||
t.Target = s.GetString("target")
|
t.Target = s.GetString("target")
|
||||||
t.Id = id
|
t.Id = id
|
||||||
t.ClientId = s.GetIntNoErr("client_id")
|
t.Client.Id = s.GetIntNoErr("client_id")
|
||||||
t.U = s.GetString("u")
|
t.Config.U = s.GetString("u")
|
||||||
t.P = s.GetString("p")
|
t.Config.P = s.GetString("p")
|
||||||
t.Compress = s.GetString("compress")
|
t.Config.Compress = s.GetString("compress")
|
||||||
t.Crypt = s.GetBoolNoErr("crypt")
|
t.Config.Crypt = s.GetBoolNoErr("crypt")
|
||||||
t.Mux = s.GetBoolNoErr("mux")
|
t.Config.Mux = s.GetBoolNoErr("mux")
|
||||||
t.UseClientCnf = s.GetBoolNoErr("use_client")
|
t.UseClientCnf = s.GetBoolNoErr("use_client")
|
||||||
t.Remark = s.GetString("remark")
|
t.Remark = s.GetString("remark")
|
||||||
server.CsvDb.UpdateTask(t)
|
server.CsvDb.UpdateTask(t)
|
||||||
|
@ -162,7 +166,7 @@ func (s *IndexController) HostList() {
|
||||||
} else {
|
} else {
|
||||||
start, length := s.GetAjaxParams()
|
start, length := s.GetAjaxParams()
|
||||||
clientId := s.GetIntNoErr("client_id")
|
clientId := s.GetIntNoErr("client_id")
|
||||||
list, cnt := server.CsvDb.GetHostList(start, length, clientId)
|
list, cnt := server.CsvDb.GetHost(start, length, clientId)
|
||||||
s.AjaxTable(list, cnt, cnt)
|
s.AjaxTable(list, cnt, cnt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,8 +186,10 @@ func (s *IndexController) AddHost() {
|
||||||
s.SetInfo("新增")
|
s.SetInfo("新增")
|
||||||
s.display("index/hadd")
|
s.display("index/hadd")
|
||||||
} else {
|
} else {
|
||||||
h := &utils.HostList{
|
h := &utils.Host{
|
||||||
ClientId: s.GetIntNoErr("client_id"),
|
Client: &utils.Client{
|
||||||
|
Id: s.GetIntNoErr("client_id"),
|
||||||
|
},
|
||||||
Host: s.GetString("host"),
|
Host: s.GetString("host"),
|
||||||
Target: s.GetString("target"),
|
Target: s.GetString("target"),
|
||||||
HeaderChange: s.GetString("header"),
|
HeaderChange: s.GetString("header"),
|
||||||
|
@ -199,7 +205,7 @@ func (s *IndexController) EditHost() {
|
||||||
host := s.GetString("host")
|
host := s.GetString("host")
|
||||||
if s.Ctx.Request.Method == "GET" {
|
if s.Ctx.Request.Method == "GET" {
|
||||||
s.Data["menu"] = "host"
|
s.Data["menu"] = "host"
|
||||||
if h, _, err := server.GetKeyByHost(host); err != nil {
|
if h, err := server.GetInfoByHost(host); err != nil {
|
||||||
s.error()
|
s.error()
|
||||||
} else {
|
} else {
|
||||||
s.Data["h"] = h
|
s.Data["h"] = h
|
||||||
|
@ -207,10 +213,10 @@ func (s *IndexController) EditHost() {
|
||||||
s.SetInfo("修改")
|
s.SetInfo("修改")
|
||||||
s.display("index/hedit")
|
s.display("index/hedit")
|
||||||
} else {
|
} else {
|
||||||
if h, _, err := server.GetKeyByHost(host); err != nil {
|
if h, err := server.GetInfoByHost(host); err != nil {
|
||||||
s.error()
|
s.error()
|
||||||
} else {
|
} else {
|
||||||
h.ClientId = s.GetIntNoErr("client_id")
|
h.Client.Id = s.GetIntNoErr("client_id")
|
||||||
h.Host = s.GetString("nhost")
|
h.Host = s.GetString("nhost")
|
||||||
h.Target = s.GetString("target")
|
h.Target = s.GetString("target")
|
||||||
h.HeaderChange = s.GetString("header")
|
h.HeaderChange = s.GetString("header")
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" id="client_id">
|
<div class="form-group" id="client_id">
|
||||||
<label class="control-label">客户端ID</label>
|
<label class="control-label">客户端ID</label>
|
||||||
<input class="form-control" value="{{.t.ClientId}}" type="text" name="client_id"
|
<input class="form-control" value="{{.t.Client.Id}}" type="text" name="client_id"
|
||||||
placeholder="客户端id">
|
placeholder="客户端id">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" id="use_client">
|
<div class="form-group" id="use_client">
|
||||||
|
@ -44,32 +44,32 @@
|
||||||
<div class="form-group" id="compress">
|
<div class="form-group" id="compress">
|
||||||
<label class="control-label">数据压缩方式(所有模式均支持)</label>
|
<label class="control-label">数据压缩方式(所有模式均支持)</label>
|
||||||
<select class="form-control" name="compress">
|
<select class="form-control" name="compress">
|
||||||
<option {{if eq "" .t.Compress}}selected{{end}} value="">不压缩</option>
|
<option {{if eq "" .t.Config.Compress}}selected{{end}} value="">不压缩</option>
|
||||||
<option {{if eq "snappy" .t.Compress}}selected{{end}} value="snappy">snappy压缩</option>
|
<option {{if eq "snappy" .t.Config.Compress}}selected{{end}} value="snappy">snappy压缩</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" id="crypt">
|
<div class="form-group" id="crypt">
|
||||||
<label class="control-label">是否加密传输(所有模式均支持)</label>
|
<label class="control-label">是否加密传输(所有模式均支持)</label>
|
||||||
<select class="form-control" name="crypt">
|
<select class="form-control" name="crypt">
|
||||||
<option {{if eq false .t.Crypt}}selected{{end}} value="0">不加密</option>
|
<option {{if eq false .t.Config.Crypt}}selected{{end}} value="0">不加密</option>
|
||||||
<option {{if eq true .t.Crypt}}selected{{end}} value="1">加密</option>
|
<option {{if eq true .t.Config.Crypt}}selected{{end}} value="1">加密</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" id="mux">
|
<div class="form-group" id="mux">
|
||||||
<label class="control-label">是否启用TCP复用(所有模式均支持)</label>
|
<label class="control-label">是否启用TCP复用(所有模式均支持)</label>
|
||||||
<select class="form-control" name="mux">
|
<select class="form-control" name="mux">
|
||||||
<option {{if eq false .t.Mux}}selected{{end}} value="0">不启用</option>
|
<option {{if eq false .t.Config.Mux}}selected{{end}} value="0">不启用</option>
|
||||||
<option {{if eq true .t.Mux}}selected{{end}} value="1">启用</option>
|
<option {{if eq true .t.Config.Mux}}selected{{end}} value="1">启用</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" id="u">
|
<div class="form-group" id="u">
|
||||||
<label class="control-label">验证用户名(仅socks5,web穿透支持)</label>
|
<label class="control-label">验证用户名(仅socks5,web穿透支持)</label>
|
||||||
<input class="form-control" value="{{.t.U}}" type="text" name="u"
|
<input class="form-control" value="{{.t.Config.U}}" type="text" name="u"
|
||||||
placeholder="不填则无需验证">
|
placeholder="不填则无需验证">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" id="p">
|
<div class="form-group" id="p">
|
||||||
<label class="control-label">验证密码(仅socks5,web穿透支持)</label>
|
<label class="control-label">验证密码(仅socks5,web穿透支持)</label>
|
||||||
<input class="form-control" value="{{.t.P}}" type="text" name="p"
|
<input class="form-control" value="{{.t.Config.P}}" type="text" name="p"
|
||||||
placeholder="不填则无需验证">
|
placeholder="不填则无需验证">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="control-label">客户端id</label>
|
<label class="control-label">客户端id</label>
|
||||||
<input class="form-control" value="{{.h.ClientId}}" type="text" name="client_id"
|
<input class="form-control" value="{{.h.Client.Id}}" type="text" name="client_id"
|
||||||
placeholder="客户端id">
|
placeholder="客户端id">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
<th>host</th>
|
<th>host</th>
|
||||||
<th>内网目标</th>
|
<th>内网目标</th>
|
||||||
<th>host改写</th>
|
<th>host改写</th>
|
||||||
|
<th>压缩方式</th>
|
||||||
|
<th>加密</th>
|
||||||
|
<th>多路复用</th>
|
||||||
|
<th>用户名</th>
|
||||||
|
<th>密码</th>
|
||||||
<th>出口流量</th>
|
<th>出口流量</th>
|
||||||
<th>入口流量</th>
|
<th>入口流量</th>
|
||||||
<th>操作</th>
|
<th>操作</th>
|
||||||
|
@ -68,13 +73,18 @@
|
||||||
},
|
},
|
||||||
dom: '<"top"fl><"toolbar">rt<"bottom"ip><"clear">',
|
dom: '<"top"fl><"toolbar">rt<"bottom"ip><"clear">',
|
||||||
columns: [ //这个是显示到界面上的个数据 格式为 {data:'显示的字段名'}
|
columns: [ //这个是显示到界面上的个数据 格式为 {data:'显示的字段名'}
|
||||||
{data: 'ClientId'},
|
{data: 'Remark'},
|
||||||
{data: 'Remark'},
|
{data: 'Remark'},
|
||||||
{data: 'Host'},
|
{data: 'Host'},
|
||||||
{data: 'Target'},
|
{data: 'Target'},
|
||||||
{data: 'HostChange'},
|
{data: 'HostChange'},
|
||||||
{data: 'HostChange'},
|
{data: 'HostChange'},
|
||||||
{data: 'HostChange'},
|
{data: 'HostChange'},
|
||||||
|
{data: 'HostChange'},
|
||||||
|
{data: 'HostChange'},
|
||||||
|
{data: 'HostChange'},
|
||||||
|
{data: 'HostChange'},
|
||||||
|
{data: 'HostChange'},
|
||||||
{data: 'Target'},
|
{data: 'Target'},
|
||||||
],
|
],
|
||||||
bFilter: false,
|
bFilter: false,
|
||||||
|
@ -88,6 +98,12 @@
|
||||||
+ ' </div>'
|
+ ' </div>'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
targets: 1,
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
return row.Client.Id
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
targets: -2,
|
targets: -2,
|
||||||
render: function (data, type, row, meta) {
|
render: function (data, type, row, meta) {
|
||||||
|
@ -99,6 +115,46 @@
|
||||||
render: function (data, type, row, meta) {
|
render: function (data, type, row, meta) {
|
||||||
return change(row.Flow.ExportFlow)
|
return change(row.Flow.ExportFlow)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
targets: -4,
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
return row.Client.Cnf.P
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
targets: -5,
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
return row.Client.Cnf.U
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
targets: -6,
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
if (row.Client.Cnf.Mux == "0") {
|
||||||
|
return "不启用"
|
||||||
|
} else {
|
||||||
|
return "启用"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
targets: -7,
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
if (row.Client.Cnf.Crypt == "0") {
|
||||||
|
return "不加密"
|
||||||
|
} else {
|
||||||
|
return "加密"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
targets: -8,
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
return row.Client.Cnf.Compress
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
buttons: []
|
buttons: []
|
||||||
|
|
|
@ -102,7 +102,7 @@
|
||||||
autoWidth: false,
|
autoWidth: false,
|
||||||
ordering: false,
|
ordering: false,
|
||||||
ajax: {
|
ajax: {
|
||||||
url: '/index/getserverconfig?type={{.type}}' + "&client_id=" +{{.client_id}},
|
url: '/index/gettunnel?type={{.type}}' + "&client_id=" +{{.client_id}},
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
},
|
},
|
||||||
dom: '<"top"fl><"toolbar">rt<"bottom"ip><"clear">',
|
dom: '<"top"fl><"toolbar">rt<"bottom"ip><"clear">',
|
||||||
|
@ -118,7 +118,7 @@
|
||||||
{data: 'U'},
|
{data: 'U'},
|
||||||
{data: 'P'},
|
{data: 'P'},
|
||||||
{data: 'ClientStatus'},
|
{data: 'ClientStatus'},
|
||||||
{data: 'IsRun'},
|
{data: 'Status'},
|
||||||
{data: 'ExportFlow'},
|
{data: 'ExportFlow'},
|
||||||
{data: 'InletFlow'},
|
{data: 'InletFlow'},
|
||||||
{data: "Id"}
|
{data: "Id"}
|
||||||
|
@ -127,7 +127,7 @@
|
||||||
columnDefs: [{
|
columnDefs: [{
|
||||||
targets: -1,
|
targets: -1,
|
||||||
render: function (data, type, row, meta) {
|
render: function (data, type, row, meta) {
|
||||||
if (row.IsRun == 1) {
|
if (row.Status == 1) {
|
||||||
btn = "<button onclick=\"stop('" + row.Id + "')\" class=\"btn btn-secondary btn-sm\" type=\"button\">关闭</button>"
|
btn = "<button onclick=\"stop('" + row.Id + "')\" class=\"btn btn-secondary btn-sm\" type=\"button\">关闭</button>"
|
||||||
} else {
|
} else {
|
||||||
btn = "<button onclick=\"start('" + row.Id + "')\" class=\"btn btn-success btn-sm\" type=\"button\">打开</button>"
|
btn = "<button onclick=\"start('" + row.Id + "')\" class=\"btn btn-success btn-sm\" type=\"button\">打开</button>"
|
||||||
|
@ -137,11 +137,43 @@
|
||||||
'<button onclick="del(\'' + row.Id + '\')" type="button" class="btn btn-danger btn-sm">删除</button>' +
|
'<button onclick="del(\'' + row.Id + '\')" type="button" class="btn btn-danger btn-sm">删除</button>' +
|
||||||
btn_edit + btn + ' </div>'
|
btn_edit + btn + ' </div>'
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
targets: 2,
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
return row.Client.Id
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
targets: 5,
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
if (row.UseClientCnf == true) {
|
||||||
|
return row.Client.Cnf.Compress
|
||||||
|
} else {
|
||||||
|
return row.Config.Compress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
targets: 8,
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
if (row.UseClientCnf == true) {
|
||||||
|
return row.Client.Cnf.U
|
||||||
|
} else {
|
||||||
|
return row.Config.U
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
targets: 9,
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
if (row.UseClientCnf == true) {
|
||||||
|
return row.Client.Cnf.P
|
||||||
|
} else {
|
||||||
|
return row.Config.P
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
targets: -4,
|
targets: -4,
|
||||||
render: function (data, type, row, meta) {
|
render: function (data, type, row, meta) {
|
||||||
if (data == 0) {
|
if (data == false) {
|
||||||
return "<span class=\"badge badge-pill badge-secondary\">暂停</span>"
|
return "<span class=\"badge badge-pill badge-secondary\">暂停</span>"
|
||||||
} else {
|
} else {
|
||||||
return "<span class=\"badge badge-pill badge-success\">正常</span>"
|
return "<span class=\"badge badge-pill badge-success\">正常</span>"
|
||||||
|
@ -151,7 +183,12 @@
|
||||||
{
|
{
|
||||||
targets: -9,
|
targets: -9,
|
||||||
render: function (data, type, row, meta) {
|
render: function (data, type, row, meta) {
|
||||||
if (data == "0") {
|
if (row.UseClientCnf == true) {
|
||||||
|
crypt = row.Client.Cnf.Crypt
|
||||||
|
} else {
|
||||||
|
crypt = row.Config.Crypt
|
||||||
|
}
|
||||||
|
if (crypt == "0") {
|
||||||
return "不加密"
|
return "不加密"
|
||||||
} else {
|
} else {
|
||||||
return "加密"
|
return "加密"
|
||||||
|
@ -161,7 +198,12 @@
|
||||||
{
|
{
|
||||||
targets: -8,
|
targets: -8,
|
||||||
render: function (data, type, row, meta) {
|
render: function (data, type, row, meta) {
|
||||||
if (data == "0") {
|
if (row.UseClientCnf == true) {
|
||||||
|
mux = row.Client.Cnf.Mux
|
||||||
|
} else {
|
||||||
|
mux = row.Config.Mux
|
||||||
|
}
|
||||||
|
if (mux == "0") {
|
||||||
return "不启用"
|
return "不启用"
|
||||||
} else {
|
} else {
|
||||||
return "启用"
|
return "启用"
|
||||||
|
@ -171,7 +213,7 @@
|
||||||
{
|
{
|
||||||
targets: -5,
|
targets: -5,
|
||||||
render: function (data, type, row, meta) {
|
render: function (data, type, row, meta) {
|
||||||
if (data == 0) {
|
if (row.Client.IsConnect == false) {
|
||||||
return "<span class=\"badge badge-pill badge-secondary\">离线</span>"
|
return "<span class=\"badge badge-pill badge-secondary\">离线</span>"
|
||||||
} else {
|
} else {
|
||||||
return "<span class=\"badge badge-pill badge-success\">在线</span>"
|
return "<span class=\"badge badge-pill badge-success\">在线</span>"
|
||||||
|
|
Loading…
Reference in New Issue