mirror of https://github.com/ehang-io/nps
健康检查
parent
f81fb7760e
commit
f78e81b452
|
@ -2,6 +2,7 @@ package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
|
"github.com/cnlh/nps/lib/config"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/mux"
|
"github.com/cnlh/nps/lib/mux"
|
||||||
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
|
@ -19,16 +20,18 @@ type TRPClient struct {
|
||||||
vKey string
|
vKey string
|
||||||
tunnel *mux.Mux
|
tunnel *mux.Mux
|
||||||
signal *conn.Conn
|
signal *conn.Conn
|
||||||
|
cnf *config.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
//new client
|
//new client
|
||||||
func NewRPClient(svraddr string, vKey string, bridgeConnType string, proxyUrl string) *TRPClient {
|
func NewRPClient(svraddr string, vKey string, bridgeConnType string, proxyUrl string, cnf *config.Config) *TRPClient {
|
||||||
return &TRPClient{
|
return &TRPClient{
|
||||||
svrAddr: svraddr,
|
svrAddr: svraddr,
|
||||||
vKey: vKey,
|
vKey: vKey,
|
||||||
bridgeConnType: bridgeConnType,
|
bridgeConnType: bridgeConnType,
|
||||||
stop: make(chan bool),
|
stop: make(chan bool),
|
||||||
proxyUrl: proxyUrl,
|
proxyUrl: proxyUrl,
|
||||||
|
cnf: cnf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +58,7 @@ func (s *TRPClient) Close() {
|
||||||
func (s *TRPClient) processor(c *conn.Conn) {
|
func (s *TRPClient) processor(c *conn.Conn) {
|
||||||
s.signal = c
|
s.signal = c
|
||||||
go s.dealChan()
|
go s.dealChan()
|
||||||
|
go heathCheck(s.cnf, c)
|
||||||
for {
|
for {
|
||||||
flags, err := c.ReadFlag()
|
flags, err := c.ReadFlag()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"container/heap"
|
||||||
|
"github.com/cnlh/nps/lib/config"
|
||||||
|
"github.com/cnlh/nps/lib/file"
|
||||||
|
"github.com/cnlh/nps/lib/sheap"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func heathCheck(cnf *config.Config, c net.Conn) {
|
||||||
|
var hosts []*file.Host
|
||||||
|
var tunnels []*file.Tunnel
|
||||||
|
h := &sheap.IntHeap{}
|
||||||
|
for _, v := range cnf.Hosts {
|
||||||
|
if v.HealthMaxFail > 0 && v.HealthCheckTimeout > 0 && v.HealthCheckInterval > 0 {
|
||||||
|
v.HealthNextTime = time.Now().Add(time.Duration(v.HealthCheckInterval))
|
||||||
|
heap.Push(h, v.HealthNextTime.Unix())
|
||||||
|
v.HealthMap = make(map[string]int)
|
||||||
|
hosts = append(hosts, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range cnf.Tasks {
|
||||||
|
if v.HealthMaxFail > 0 && v.HealthCheckTimeout > 0 && v.HealthCheckInterval > 0 {
|
||||||
|
v.HealthNextTime = time.Now().Add(time.Duration(v.HealthCheckInterval))
|
||||||
|
heap.Push(h, v.HealthNextTime.Unix())
|
||||||
|
v.HealthMap = make(map[string]int)
|
||||||
|
tunnels = append(tunnels, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(hosts) == 0 && len(tunnels) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
rs := heap.Pop(h).(int64) - time.Now().Unix()
|
||||||
|
if rs < 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
timer := time.NewTicker(time.Duration(rs))
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
for _, v := range hosts {
|
||||||
|
if v.HealthNextTime.Before(time.Now()) {
|
||||||
|
v.HealthNextTime = time.Now().Add(time.Duration(v.HealthCheckInterval))
|
||||||
|
//check
|
||||||
|
go checkHttp(v, c)
|
||||||
|
//reset time
|
||||||
|
heap.Push(h, v.HealthNextTime.Unix())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range tunnels {
|
||||||
|
if v.HealthNextTime.Before(time.Now()) {
|
||||||
|
v.HealthNextTime = time.Now().Add(time.Duration(v.HealthCheckInterval))
|
||||||
|
//check
|
||||||
|
go checkTcp(v, c)
|
||||||
|
//reset time
|
||||||
|
heap.Push(h, v.HealthNextTime.Unix())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkTcp(t *file.Tunnel, c net.Conn) {
|
||||||
|
arr := strings.Split(t.Target, "\n")
|
||||||
|
for _, v := range arr {
|
||||||
|
if _, err := net.DialTimeout("tcp", v, time.Duration(t.HealthCheckTimeout)); err != nil {
|
||||||
|
t.HealthMap[v] += 1
|
||||||
|
}
|
||||||
|
if t.HealthMap[v] > t.HealthMaxFail {
|
||||||
|
t.HealthMap[v] += 1
|
||||||
|
if t.HealthMap[v] == t.HealthMaxFail {
|
||||||
|
//send fail remove
|
||||||
|
ch <- file.NewHealthInfo("tcp", v, true)
|
||||||
|
}
|
||||||
|
} else if t.HealthMap[v] >= t.HealthMaxFail {
|
||||||
|
//send recovery add
|
||||||
|
ch <- file.NewHealthInfo("tcp", v, false)
|
||||||
|
t.HealthMap[v] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkHttp(h *file.Host, ch chan *file.HealthInfo) {
|
||||||
|
arr := strings.Split(h.Target, "\n")
|
||||||
|
client := &http.Client{}
|
||||||
|
client.Timeout = time.Duration(h.HealthCheckTimeout) * time.Second
|
||||||
|
for _, v := range arr {
|
||||||
|
if _, err := client.Get(v + h.HttpHealthUrl); err != nil {
|
||||||
|
h.HealthMap[v] += 1
|
||||||
|
if h.HealthMap[v] == h.HealthMaxFail {
|
||||||
|
//send fail remove
|
||||||
|
ch <- file.NewHealthInfo("http", v, true)
|
||||||
|
}
|
||||||
|
} else if h.HealthMap[v] >= h.HealthMaxFail {
|
||||||
|
//send recovery add
|
||||||
|
h.HealthMap[v] = 0
|
||||||
|
ch <- file.NewHealthInfo("http", v, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
serverAddr = flag.String("server", "", "Server addr (ip:port)")
|
serverAddr = flag.String("server", "", "Server addr (ip:port)")
|
||||||
configPath = flag.String("config", "npc.conf", "Configuration file path")
|
configPath = flag.String("config", "", "Configuration file path")
|
||||||
verifyKey = flag.String("vkey", "", "Authentication key")
|
verifyKey = flag.String("vkey", "", "Authentication key")
|
||||||
logType = flag.String("log", "stdout", "Log output mode(stdout|file)")
|
logType = flag.String("log", "stdout", "Log output mode(stdout|file)")
|
||||||
connType = flag.String("type", "tcp", "Connection type with the server(kcp|tcp)")
|
connType = flag.String("type", "tcp", "Connection type with the server(kcp|tcp)")
|
||||||
|
@ -21,6 +21,7 @@ var (
|
||||||
logLevel = flag.String("log_level", "7", "log level 0~7")
|
logLevel = flag.String("log_level", "7", "log level 0~7")
|
||||||
registerTime = flag.Int("time", 2, "register time long /h")
|
registerTime = flag.Int("time", 2, "register time long /h")
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if len(os.Args) > 2 {
|
if len(os.Args) > 2 {
|
||||||
|
@ -41,13 +42,23 @@ func main() {
|
||||||
} else {
|
} else {
|
||||||
logs.SetLogger(logs.AdapterFile, `{"level":`+*logLevel+`,"filename":"npc_log.log"}`)
|
logs.SetLogger(logs.AdapterFile, `{"level":`+*logLevel+`,"filename":"npc_log.log"}`)
|
||||||
}
|
}
|
||||||
if *verifyKey != "" && *serverAddr != "" {
|
env := common.GetEnvMap()
|
||||||
|
if *serverAddr == "" {
|
||||||
|
*serverAddr, _ = env["NPS_SERVER_ADDR"]
|
||||||
|
}
|
||||||
|
if *verifyKey == "" {
|
||||||
|
*verifyKey, _ = env["NPS_SERVER_VKEY"]
|
||||||
|
}
|
||||||
|
if *verifyKey != "" && *serverAddr != "" && *configPath == "" {
|
||||||
for {
|
for {
|
||||||
client.NewRPClient(*serverAddr, *verifyKey, *connType, *proxyUrl).Start()
|
client.NewRPClient(*serverAddr, *verifyKey, *connType, *proxyUrl).Start()
|
||||||
logs.Info("It will be reconnected in five seconds")
|
logs.Info("It will be reconnected in five seconds")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if *configPath == "" {
|
||||||
|
*configPath = "npc.conf"
|
||||||
|
}
|
||||||
client.StartFromFile(*configPath)
|
client.StartFromFile(*configPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
a.o.com,127.0.0.1:8082,2,,,111,/,3,5290945,30260,all
|
a.o.com,127.0.0.1:8082,2,,,111,/,3,5290945,32285,http
|
||||||
|
a.o.com,127.0.0.1:8080,2,,,,/,4,0,0,https
|
||||||
|
|
|
|
@ -1,16 +1,25 @@
|
||||||
[common]
|
[common]
|
||||||
server=127.0.0.1:8024
|
server={{.NPS_SERVER_ADDR}}
|
||||||
tp=tcp
|
tp=tcp
|
||||||
vkey=123
|
vkey={{.NPS_SERVER_VKEY}}
|
||||||
auto_reconnection=true
|
auto_reconnection=true
|
||||||
[web]
|
[web]
|
||||||
host=b.o.com
|
host=b.o.com
|
||||||
target=127.0.0.1:8082
|
target=127.0.0.1:8082
|
||||||
|
health_check_timeout = 3
|
||||||
|
health_check_max_failed = 3
|
||||||
|
health_check_interval = 10
|
||||||
|
health_http_url=/
|
||||||
|
|
||||||
[tcp]
|
[tcp]
|
||||||
mode=tcp
|
mode=tcp
|
||||||
target=8006-8010,8012
|
target=8006-8010,8012
|
||||||
port=9006-9010,9012
|
port=9006-9010,9012
|
||||||
targetAddr=123.206.77.88
|
targetAddr=123.206.77.88
|
||||||
|
health_check_timeout = 3
|
||||||
|
health_check_max_failed = 3
|
||||||
|
health_check_interval = 10
|
||||||
|
health_http_url=/
|
||||||
|
|
||||||
[socks5]
|
[socks5]
|
||||||
mode=socks5
|
mode=socks5
|
||||||
|
|
|
@ -2,13 +2,11 @@ appname = nps
|
||||||
#Boot mode(dev|pro)
|
#Boot mode(dev|pro)
|
||||||
runmode = dev
|
runmode = dev
|
||||||
|
|
||||||
#Web API unauthenticated IP address
|
|
||||||
#auth_key=test
|
|
||||||
#auth_crypt_key =1234567812345678
|
|
||||||
|
|
||||||
#HTTP(S) proxy port, no startup if empty
|
#HTTP(S) proxy port, no startup if empty
|
||||||
http_proxy_port=80
|
http_proxy_port=80
|
||||||
https_proxy_port=445
|
https_proxy_port=443
|
||||||
#certFile absolute path
|
#certFile absolute path
|
||||||
pem_path=conf/server.pem
|
pem_path=conf/server.pem
|
||||||
#KeyFile absolute path
|
#KeyFile absolute path
|
||||||
|
@ -43,5 +41,8 @@ web_username=admin
|
||||||
web_password=123
|
web_password=123
|
||||||
web_port = 8080
|
web_port = 8080
|
||||||
web_ip=0.0.0.0
|
web_ip=0.0.0.0
|
||||||
|
#Web API unauthenticated IP address
|
||||||
|
auth_key=test
|
||||||
|
auth_crypt_key =1234567812345678
|
||||||
|
|
||||||
#allow_ports=9001-9009,10001,11000-12000
|
#allow_ports=9001-9009,10001,11000-12000
|
|
@ -1,2 +1,4 @@
|
||||||
8025,socks5,,1,1,2,,0,0,
|
8025,socks5,,1,1,2,,0,0,
|
||||||
8026,httpProxy,,1,2,2,,0,0,
|
8026,httpProxy,,1,2,2,,0,0,
|
||||||
|
8001,tcp,"127.0.0.1:8080
|
||||||
|
127.0.0.1:8082",1,3,5,,0,0,
|
||||||
|
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"github.com/cnlh/nps/lib/crypt"
|
"github.com/cnlh/nps/lib/crypt"
|
||||||
"github.com/cnlh/nps/lib/pool"
|
"github.com/cnlh/nps/lib/pool"
|
||||||
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
@ -276,3 +277,29 @@ func GetLocalUdpAddr() (net.Conn, error) {
|
||||||
}
|
}
|
||||||
return tmpConn, tmpConn.Close()
|
return tmpConn, tmpConn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseStr(str string) (string, error) {
|
||||||
|
tmp := template.New("npc")
|
||||||
|
var err error
|
||||||
|
w := new(bytes.Buffer)
|
||||||
|
if tmp, err = tmp.Parse(str); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err = tmp.Execute(w, GetEnvMap()); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return w.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//get env
|
||||||
|
func GetEnvMap() map[string]string {
|
||||||
|
m := make(map[string]string)
|
||||||
|
environ := os.Environ()
|
||||||
|
for i := range environ {
|
||||||
|
tmp := strings.Split(environ[i], "=")
|
||||||
|
if len(tmp) == 2 {
|
||||||
|
m[tmp[0]] = tmp[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,9 @@ func NewConfig(path string) (c *Config, err error) {
|
||||||
if b, err = common.ReadAllFromFile(path); err != nil {
|
if b, err = common.ReadAllFromFile(path); err != nil {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
c.content = string(b)
|
if c.content, err = common.ParseStr(string(b)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if c.title, err = getAllTitle(c.content); err != nil {
|
if c.title, err = getAllTitle(c.content); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -153,6 +155,14 @@ func dealHost(s string) *file.Host {
|
||||||
h.HostChange = item[1]
|
h.HostChange = item[1]
|
||||||
case "location":
|
case "location":
|
||||||
h.Location = item[1]
|
h.Location = item[1]
|
||||||
|
case "health_check_timeout":
|
||||||
|
h.HealthCheckTimeout = common.GetIntNoErrByStr(item[1])
|
||||||
|
case "health_check_max_failed":
|
||||||
|
h.HealthMaxFail = common.GetIntNoErrByStr(item[1])
|
||||||
|
case "health_check_interval":
|
||||||
|
h.HealthCheckInterval = common.GetIntNoErrByStr(item[1])
|
||||||
|
case "health_http_url":
|
||||||
|
h.HttpHealthUrl = item[1]
|
||||||
default:
|
default:
|
||||||
if strings.Contains(item[0], "header") {
|
if strings.Contains(item[0], "header") {
|
||||||
headerChange += strings.Replace(item[0], "header_", "", -1) + ":" + item[1] + "\n"
|
headerChange += strings.Replace(item[0], "header_", "", -1) + ":" + item[1] + "\n"
|
||||||
|
@ -178,7 +188,7 @@ func dealTunnel(s string) *file.Tunnel {
|
||||||
case "mode":
|
case "mode":
|
||||||
t.Mode = item[1]
|
t.Mode = item[1]
|
||||||
case "target":
|
case "target":
|
||||||
t.Target = item[1]
|
t.Target = strings.Replace(item[1], ",", "\n", -1)
|
||||||
case "targetAddr":
|
case "targetAddr":
|
||||||
t.TargetAddr = item[1]
|
t.TargetAddr = item[1]
|
||||||
case "password":
|
case "password":
|
||||||
|
@ -187,6 +197,12 @@ func dealTunnel(s string) *file.Tunnel {
|
||||||
t.LocalPath = item[1]
|
t.LocalPath = item[1]
|
||||||
case "strip_pre":
|
case "strip_pre":
|
||||||
t.StripPre = item[1]
|
t.StripPre = item[1]
|
||||||
|
case "health_check_timeout":
|
||||||
|
t.HealthCheckTimeout = common.GetIntNoErrByStr(item[1])
|
||||||
|
case "health_check_max_failed":
|
||||||
|
t.HealthMaxFail = common.GetIntNoErrByStr(item[1])
|
||||||
|
case "health_check_interval":
|
||||||
|
t.HealthCheckInterval = common.GetIntNoErrByStr(item[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"github.com/cnlh/nps/lib/rate"
|
"github.com/cnlh/nps/lib/rate"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Flow struct {
|
type Flow struct {
|
||||||
|
@ -96,14 +97,15 @@ func (s *Client) HasHost(h *Host) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tunnel struct {
|
type Tunnel struct {
|
||||||
Id int //Id
|
Id int //Id
|
||||||
Port int //服务端监听端口
|
Port int //服务端监听端口
|
||||||
Mode string //启动方式
|
Mode string //启动方式
|
||||||
Target string //目标
|
Target string //目标
|
||||||
Status bool //设置是否开启
|
TargetArr []string //目标
|
||||||
RunStatus bool //当前运行状态
|
Status bool //设置是否开启
|
||||||
Client *Client //所属客户端id
|
RunStatus bool //当前运行状态
|
||||||
Ports string //客户端与服务端传递
|
Client *Client //所属客户端id
|
||||||
|
Ports string //客户端与服务端传递
|
||||||
Flow *Flow
|
Flow *Flow
|
||||||
Password string //私密模式密码,唯一
|
Password string //私密模式密码,唯一
|
||||||
Remark string //备注
|
Remark string //备注
|
||||||
|
@ -111,6 +113,35 @@ type Tunnel struct {
|
||||||
NoStore bool
|
NoStore bool
|
||||||
LocalPath string
|
LocalPath string
|
||||||
StripPre string
|
StripPre string
|
||||||
|
NowIndex int
|
||||||
|
Health
|
||||||
|
sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type Health struct {
|
||||||
|
HealthCheckTimeout int
|
||||||
|
HealthMaxFail int
|
||||||
|
HealthCheckInterval int
|
||||||
|
HealthNextTime time.Time
|
||||||
|
HealthMap map[string]int
|
||||||
|
HttpHealthUrl string
|
||||||
|
HealthRemoveArr []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Tunnel) GetRandomTarget() string {
|
||||||
|
if s.TargetArr == nil {
|
||||||
|
s.TargetArr = strings.Split(s.Target, "\n")
|
||||||
|
}
|
||||||
|
if len(s.TargetArr) == 1 {
|
||||||
|
return s.TargetArr[0]
|
||||||
|
}
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
if s.NowIndex >= len(s.TargetArr)-1 {
|
||||||
|
s.NowIndex = -1
|
||||||
|
}
|
||||||
|
s.NowIndex++
|
||||||
|
return s.TargetArr[s.NowIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
@ -133,7 +164,8 @@ type Host struct {
|
||||||
NowIndex int
|
NowIndex int
|
||||||
TargetArr []string
|
TargetArr []string
|
||||||
NoStore bool
|
NoStore bool
|
||||||
Scheme string //http https all
|
Scheme string //http https all
|
||||||
|
Health
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,10 +173,13 @@ func (s *Host) GetRandomTarget() string {
|
||||||
if s.TargetArr == nil {
|
if s.TargetArr == nil {
|
||||||
s.TargetArr = strings.Split(s.Target, "\n")
|
s.TargetArr = strings.Split(s.Target, "\n")
|
||||||
}
|
}
|
||||||
|
if len(s.TargetArr) == 1 {
|
||||||
|
return s.TargetArr[0]
|
||||||
|
}
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
if s.NowIndex >= len(s.TargetArr)-1 {
|
if s.NowIndex >= len(s.TargetArr)-1 {
|
||||||
s.NowIndex = 0
|
s.NowIndex = -1
|
||||||
} else {
|
} else {
|
||||||
s.NowIndex++
|
s.NowIndex++
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,18 +11,20 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
HTTP_GET = 716984
|
HTTP_GET = 716984
|
||||||
HTTP_POST = 807983
|
HTTP_POST = 807983
|
||||||
HTTP_HEAD = 726965
|
HTTP_HEAD = 726965
|
||||||
HTTP_PUT = 808585
|
HTTP_PUT = 808585
|
||||||
HTTP_DELETE = 686976
|
HTTP_DELETE = 686976
|
||||||
HTTP_CONNECT = 677978
|
HTTP_CONNECT = 677978
|
||||||
HTTP_OPTIONS = 798084
|
HTTP_OPTIONS = 798084
|
||||||
HTTP_TRACE = 848265
|
HTTP_TRACE = 848265
|
||||||
CLIENT = 848384
|
CLIENT = 848384
|
||||||
|
ACCEPT_TIME_OUT = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
type PortMux struct {
|
type PortMux struct {
|
||||||
|
@ -122,7 +124,11 @@ func (pMux *PortMux) process(conn net.Conn) {
|
||||||
if len(rs) == 0 {
|
if len(rs) == 0 {
|
||||||
rs = buf
|
rs = buf
|
||||||
}
|
}
|
||||||
ch <- newPortConn(conn, rs)
|
timer := time.NewTimer(ACCEPT_TIME_OUT)
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
case ch <- newPortConn(conn, rs):
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pMux *PortMux) Close() error {
|
func (pMux *PortMux) Close() error {
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package sheap
|
||||||
|
|
||||||
|
type IntHeap []int64
|
||||||
|
|
||||||
|
func (h IntHeap) Len() int { return len(h) }
|
||||||
|
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
|
||||||
|
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
||||||
|
|
||||||
|
func (h *IntHeap) Push(x interface{}) {
|
||||||
|
// Push and Pop use pointer receivers because they modify the slice's length,
|
||||||
|
// not just its contents.
|
||||||
|
*h = append(*h, x.(int64))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *IntHeap) Pop() interface{} {
|
||||||
|
old := *h
|
||||||
|
n := len(old)
|
||||||
|
x := old[n-1]
|
||||||
|
*h = old[0 : n-1]
|
||||||
|
return x
|
||||||
|
}
|
|
@ -159,7 +159,7 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
|
||||||
logs.Warn("auth error", err, r.RemoteAddr)
|
logs.Warn("auth error", err, r.RemoteAddr)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
lk := conn.NewLink(common.CONN_TCP, host.Target, host.Client.Cnf.Crypt, host.Client.Cnf.Compress, r.RemoteAddr)
|
lk := conn.NewLink(common.CONN_TCP, host.GetRandomTarget(), host.Client.Cnf.Crypt, host.Client.Cnf.Compress, r.RemoteAddr)
|
||||||
if target, err = s.bridge.SendLinkInfo(host.Client.Id, lk, c.Conn.RemoteAddr().String(), nil); err != nil {
|
if target, err = s.bridge.SendLinkInfo(host.Client.Id, lk, c.Conn.RemoteAddr().String(), nil); err != nil {
|
||||||
logs.Notice("connect to target %s error %s", lk.Host, err)
|
logs.Notice("connect to target %s error %s", lk.Host, err)
|
||||||
break
|
break
|
||||||
|
@ -174,10 +174,10 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
|
||||||
}()
|
}()
|
||||||
} else {
|
} else {
|
||||||
r, err = http.ReadRequest(bufio.NewReader(c))
|
r, err = http.ReadRequest(bufio.NewReader(c))
|
||||||
r.URL.Scheme = scheme
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
r.URL.Scheme = scheme
|
||||||
//What happened ,Why one character less???
|
//What happened ,Why one character less???
|
||||||
if r.Method == "ET" {
|
if r.Method == "ET" {
|
||||||
r.Method = "GET"
|
r.Method = "GET"
|
||||||
|
@ -190,10 +190,14 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
|
||||||
logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI)
|
logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI)
|
||||||
break
|
break
|
||||||
} else if host != lastHost {
|
} else if host != lastHost {
|
||||||
|
host.Client.AddConn()
|
||||||
|
if !hostTmp.Client.GetConn() {
|
||||||
|
break
|
||||||
|
}
|
||||||
host = hostTmp
|
host = hostTmp
|
||||||
lastHost = host
|
lastHost = host
|
||||||
isConn = true
|
isConn = true
|
||||||
host.Client.AddConn()
|
|
||||||
goto start
|
goto start
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +208,7 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
host.Flow.Add(int64(len(b)), 0)
|
host.Flow.Add(int64(len(b)), 0)
|
||||||
logs.Trace("http(s) request, method %s, host %s, url %s, remote address %s, target %s", r.Method, r.Host, r.RequestURI, r.RemoteAddr, host.Target)
|
logs.Trace("%s request, method %s, host %s, url %s, remote address %s, target %s", r.URL.Scheme, r.Method, r.Host, r.RequestURI, r.RemoteAddr, host.Target)
|
||||||
//write
|
//write
|
||||||
connClient.Write(b)
|
connClient.Write(b)
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ type process func(c *conn.Conn, s *TunnelModeServer) error
|
||||||
|
|
||||||
//tcp隧道模式
|
//tcp隧道模式
|
||||||
func ProcessTunnel(c *conn.Conn, s *TunnelModeServer) error {
|
func ProcessTunnel(c *conn.Conn, s *TunnelModeServer) error {
|
||||||
return s.DealClient(c, s.task.Target, nil, common.CONN_TCP)
|
return s.DealClient(c, s.task.GetRandomTarget(), nil, common.CONN_TCP)
|
||||||
}
|
}
|
||||||
|
|
||||||
//http代理模式
|
//http代理模式
|
||||||
|
|
|
@ -26,8 +26,8 @@ func (s *BaseController) Prepare() {
|
||||||
// param 2 is timestamp (It's limited to 20 seconds.)
|
// param 2 is timestamp (It's limited to 20 seconds.)
|
||||||
md5Key := s.GetString("auth_key")
|
md5Key := s.GetString("auth_key")
|
||||||
timestamp := s.GetIntNoErr("timestamp")
|
timestamp := s.GetIntNoErr("timestamp")
|
||||||
configKey := beego.AppConfig.String("authKey")
|
configKey := beego.AppConfig.String("auth_key")
|
||||||
if !(time.Now().Unix()-int64(timestamp) < 20 && time.Now().Unix()-int64(timestamp) > 0 && crypt.Md5(configKey+strconv.Itoa(timestamp)) == md5Key) {
|
if !(time.Now().Unix()-int64(timestamp) <= 20 && time.Now().Unix()-int64(timestamp) >= 0 && crypt.Md5(configKey+strconv.Itoa(timestamp)) == md5Key) {
|
||||||
if s.GetSession("auth") != true {
|
if s.GetSession("auth") != true {
|
||||||
s.Redirect("/login/index", 302)
|
s.Redirect("/login/index", 302)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,9 +38,11 @@
|
||||||
<div class="form-group" id="target">
|
<div class="form-group" id="target">
|
||||||
<label class="col-sm-2 control-label">target of Intranet(ip:port)</label>
|
<label class="col-sm-2 control-label">target of Intranet(ip:port)</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input class="form-control" type="text" name="target"
|
<textarea class="form-control" name="target" rows="4" placeholder="10.1.50.203:22
|
||||||
placeholder="such as 10.1.50.203:22 ">
|
10.1.50.202:22"></textarea>
|
||||||
<span class="help-block m-b-none">can only fill in ports if it is local machine proxy</span>
|
<span class="help-block m-b-none">can only fill in ports if it is local machine proxy, only tcp supports load balancing
|
||||||
|
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -39,10 +39,11 @@
|
||||||
<div class="form-group" id="target">
|
<div class="form-group" id="target">
|
||||||
<label class="col-sm-2 control-label">target of Intranet(ip:port)</label>
|
<label class="col-sm-2 control-label">target of Intranet(ip:port)</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input value="{{.t.Target}}" class="form-control" type="text" name="target"
|
<textarea class="form-control" name="target" rows="4" placeholder="10.1.50.203:22
|
||||||
placeholder="such as 10.1.50.203:22 ">
|
10.1.50.202:22">{{.t.Target}}</textarea>
|
||||||
<span class="help-block m-b-none">can only fill in ports if it is local machine proxy</span>
|
<span class="help-block m-b-none">can only fill in ports if it is local machine proxy, only tcp supports load balancing
|
||||||
</div>
|
|
||||||
|
</span> </div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" id="client_id">
|
<div class="form-group" id="client_id">
|
||||||
|
|
|
@ -120,4 +120,15 @@
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// googleTranslateElementInit()
|
||||||
|
//
|
||||||
|
// function googleTranslateElementInit() {
|
||||||
|
// new google.translate.TranslateElement({
|
||||||
|
// layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL
|
||||||
|
// }, 'wrapper');
|
||||||
|
// }
|
||||||
|
</script>
|
||||||
|
{{/*<script src="http://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>*/}}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue