Merge pull request #217 from fatedier/dev

bump version to 0.9.2
This commit is contained in:
fatedier 2017-01-08 09:22:28 -06:00 committed by GitHub
commit edb97abf50
12 changed files with 139 additions and 29 deletions

View File

@ -3,15 +3,23 @@ export GO15VENDOREXPERIMENT := 1
all: build
build: gox app more
gox:
go get github.com/mitchellh/gox
build: app
app:
gox -osarch "darwin/386 darwin/amd64 linux/386 linux/amd64 linux/arm windows/386 windows/amd64" ./src/...
more:
env GOOS=darwin GOARCH=386 go build -o ./frpc_darwin_386 ./src/cmd/frpc
env GOOS=darwin GOARCH=386 go build -o ./frps_darwin_386 ./src/cmd/frps
env GOOS=darwin GOARCH=amd64 go build -o ./frpc_darwin_amd64 ./src/cmd/frpc
env GOOS=darwin GOARCH=amd64 go build -o ./frps_darwin_amd64 ./src/cmd/frps
env GOOS=linux GOARCH=386 go build -o ./frpc_linux_386 ./src/cmd/frpc
env GOOS=linux GOARCH=386 go build -o ./frps_linux_386 ./src/cmd/frps
env GOOS=linux GOARCH=amd64 go build -o ./frpc_linux_amd64 ./src/cmd/frpc
env GOOS=linux GOARCH=amd64 go build -o ./frps_linux_amd64 ./src/cmd/frps
env GOOS=linux GOARCH=arm go build -o ./frpc_linux_arm ./src/cmd/frpc
env GOOS=linux GOARCH=arm go build -o ./frps_linux_arm ./src/cmd/frps
env GOOS=windows GOARCH=386 go build -o ./frpc_windows_386.exe ./src/cmd/frpc
env GOOS=windows GOARCH=386 go build -o ./frps_windows_386.exe ./src/cmd/frps
env GOOS=windows GOARCH=amd64 go build -o ./frpc_windows_amd64.exe ./src/cmd/frpc
env GOOS=windows GOARCH=amd64 go build -o ./frps_windows_amd64.exe ./src/cmd/frps
env GOOS=linux GOARCH=mips64 go build -o ./frpc_linux_mips64 ./src/cmd/frpc
env GOOS=linux GOARCH=mips64 go build -o ./frps_linux_mips64 ./src/cmd/frps
env GOOS=linux GOARCH=mips64le go build -o ./frpc_linux_mips64le ./src/cmd/frpc

View File

@ -219,7 +219,7 @@ Then visit `http://[server_addr]:7500` to see dashboard, default username and pa
Client that want's to register must set a global `auth_token` equals to frps.ini.
Note that time duration bewtween frpc and frps mustn't exceed 15 minutes because timestamp is used for authentication.
Note that time duration between frpc and frps mustn't exceed 15 minutes because timestamp is used for authentication.
Howerver, this timeout duration can be modified by setting `authentication_timeout` in frps's configure file. It's defalut value is 900, means 15 minutes. If it is equals 0, then frps will not check authentication timeout.
@ -452,7 +452,6 @@ http_proxy = http://user:pwd@192.168.1.128:8080
## Development Plan
* Url router.
* Log http request information in frps.
* Direct reverse proxy, like haproxy.
* Load balance to different service in frpc.
@ -497,3 +496,4 @@ Donate money by [paypal](https://www.paypal.me/fatedier) to my account **fatedie
* [Damon Zhao](https://github.com/se77en)
* [Manfred Touron](https://github.com/moul)
* [xuebing1110](https://github.com/xuebing1110)
* [Anbitioner](https://github.com/bingtianbaihua)

View File

@ -469,7 +469,6 @@ http_proxy = http://user:pwd@192.168.1.128:8080
计划在后续版本中加入的功能与优化,排名不分先后,如果有其他功能建议欢迎在 [issues](https://github.com/fatedier/frp/issues) 中反馈。
* 支持 url 路由转发。
* frps 记录 http 请求日志。
* frps 支持直接反向代理,类似 haproxy。
* frpc 支持负载均衡到后端不同服务。
@ -516,3 +515,4 @@ frp 交流群606194980 (QQ 群号)
* [Damon Zhao](https://github.com/se77en)
* [Manfred Touron](https://github.com/moul)
* [xuebing1110](https://github.com/xuebing1110)
* [Anbitioner](https://github.com/bingtianbaihua)

View File

@ -22,6 +22,10 @@ auth_token = 123
# for privilege mode
privilege_token = 12345678
# heartbeat configure, it's not recommended to modify the default value
# the default value of heartbeat_interval is 10 and heartbeat_timeout is 30
# heartbeat_interval = 10
# heartbeat_timeout = 30
# ssh is the proxy name same as server's configuration
[ssh]

View File

@ -30,6 +30,10 @@ log_max_days = 3
privilege_mode = true
privilege_token = 12345678
# heartbeat configure, it's not recommended to modify the default value
# the default value of heartbeat_timeout is 30
# heartbeat_timeout = 30
# only allow frpc to bind ports you list, if you set nothing, there won't be any limit
privilege_allow_ports = 2000-3000,3001,3003,4000-50000

View File

@ -55,15 +55,24 @@ func msgReader(cli *client.ProxyClient, c *conn.Conn, msgSendChan chan interface
var heartbeatTimeout bool = false
timer := time.AfterFunc(time.Duration(client.HeartBeatTimeout)*time.Second, func() {
heartbeatTimeout = true
c.Close()
if c != nil {
c.Close()
}
if cli != nil {
// if it's not udp type, nothing will happen
cli.CloseUdpTunnel()
cli.SetCloseFlag(true)
}
log.Error("ProxyName [%s], heartbeatRes from frps timeout", cli.Name)
})
defer timer.Stop()
for {
buf, err := c.ReadLine()
if err == io.EOF || c == nil || c.IsClosed() {
if err == io.EOF || c.IsClosed() {
timer.Stop()
c.Close()
cli.SetCloseFlag(true)
log.Warn("ProxyName [%s], frps close this control conn!", cli.Name)
var delayTime time.Duration = 1
@ -76,11 +85,14 @@ func msgReader(cli *client.ProxyClient, c *conn.Conn, msgSendChan chan interface
msgSendChan = make(chan interface{}, 1024)
go heartbeatSender(c, msgSendChan)
go msgSender(cli, c, msgSendChan)
cli.SetCloseFlag(false)
break
}
if delayTime < 60 {
if delayTime < 30 {
delayTime = delayTime * 2
} else {
delayTime = 30
}
time.Sleep(delayTime * time.Second)
}

View File

@ -85,7 +85,9 @@ func controlWorker(c *conn.Conn) {
return
}
} else {
closeFlag = false
if ret == 0 {
closeFlag = false
}
return
}

View File

@ -39,6 +39,9 @@ type ProxyClient struct {
udpTunnel *conn.Conn
once sync.Once
closeFlag bool
mutex sync.RWMutex
}
// if proxy type is udp, keep a tcp connection for transferring udp packages
@ -48,7 +51,7 @@ func (pc *ProxyClient) StartUdpTunnelOnce(addr string, port int64) {
var c *conn.Conn
udpProcessor := NewUdpProcesser(nil, pc.LocalIp, pc.LocalPort)
for {
if pc.udpTunnel == nil || pc.udpTunnel.IsClosed() {
if !pc.IsClosed() && (pc.udpTunnel == nil || pc.udpTunnel.IsClosed()) {
if HttpProxy == "" {
c, err = conn.ConnectServer(fmt.Sprintf("%s:%d", addr, port))
} else {
@ -59,7 +62,7 @@ func (pc *ProxyClient) StartUdpTunnelOnce(addr string, port int64) {
time.Sleep(10 * time.Second)
continue
}
log.Info("ProxyName [%s], udp tunnel reconnect to server [%s:%d] success", pc.Name, addr, port)
log.Info("ProxyName [%s], udp tunnel connect to server [%s:%d] success", pc.Name, addr, port)
nowTime := time.Now().Unix()
req := &msg.ControlReq{
@ -82,8 +85,11 @@ func (pc *ProxyClient) StartUdpTunnelOnce(addr string, port int64) {
time.Sleep(1 * time.Second)
continue
}
pc.mutex.Lock()
pc.udpTunnel = c
udpProcessor.UpdateTcpConn(pc.udpTunnel)
pc.mutex.Unlock()
udpProcessor.Run()
}
time.Sleep(1 * time.Second)
@ -91,6 +97,14 @@ func (pc *ProxyClient) StartUdpTunnelOnce(addr string, port int64) {
})
}
func (pc *ProxyClient) CloseUdpTunnel() {
pc.mutex.RLock()
defer pc.mutex.RUnlock()
if pc.udpTunnel != nil {
pc.udpTunnel.Close()
}
}
func (pc *ProxyClient) GetLocalConn() (c *conn.Conn, err error) {
c, err = conn.ConnectServer(fmt.Sprintf("%s:%d", pc.LocalIp, pc.LocalPort))
if err != nil {
@ -158,3 +172,15 @@ func (pc *ProxyClient) StartTunnel(serverAddr string, serverPort int64) (err err
return nil
}
func (pc *ProxyClient) SetCloseFlag(closeFlag bool) {
pc.mutex.Lock()
defer pc.mutex.Unlock()
pc.closeFlag = closeFlag
}
func (pc *ProxyClient) IsClosed() bool {
pc.mutex.RLock()
defer pc.mutex.RUnlock()
return pc.closeFlag
}

View File

@ -33,8 +33,8 @@ var (
LogLevel string = "info"
LogMaxDays int64 = 3
PrivilegeToken string = ""
HeartBeatInterval int64 = 20
HeartBeatTimeout int64 = 90
HeartBeatInterval int64 = 10
HeartBeatTimeout int64 = 30
)
var ProxyClients map[string]*ProxyClient = make(map[string]*ProxyClient)
@ -98,6 +98,34 @@ func LoadConf(confFile string) (err error) {
authToken = tmpStr
}
tmpStr, ok = conf.Get("common", "heartbeat_timeout")
if ok {
v, err := strconv.ParseInt(tmpStr, 10, 64)
if err != nil {
return fmt.Errorf("Parse conf error: heartbeat_timeout is incorrect")
} else {
HeartBeatTimeout = v
}
}
tmpStr, ok = conf.Get("common", "heartbeat_interval")
if ok {
v, err := strconv.ParseInt(tmpStr, 10, 64)
if err != nil {
return fmt.Errorf("Parse conf error: heartbeat_interval is incorrect")
} else {
HeartBeatInterval = v
}
}
if HeartBeatInterval <= 0 {
return fmt.Errorf("Parse conf error: heartbeat_interval is incorrect")
}
if HeartBeatTimeout < HeartBeatInterval {
return fmt.Errorf("Parse conf error: heartbeat_timeout is incorrect, heartbeat_timeout is less than heartbeat_interval")
}
// proxies
for name, section := range conf {
if name != "common" {

View File

@ -51,7 +51,7 @@ var (
// if PrivilegeAllowPorts is not nil, tcp proxies which remote port exist in this map can be connected
PrivilegeAllowPorts map[int64]struct{}
MaxPoolCount int64 = 100
HeartBeatTimeout int64 = 90
HeartBeatTimeout int64 = 30
UserConnTimeout int64 = 10
VhostHttpMuxer *vhost.HttpMuxer
@ -237,6 +237,16 @@ func loadCommonConf(confFile string) error {
if ok {
SubDomainHost = strings.ToLower(strings.TrimSpace(SubDomainHost))
}
tmpStr, ok = conf.Get("common", "heartbeat_timeout")
if ok {
v, err := strconv.ParseInt(tmpStr, 10, 64)
if err != nil {
return fmt.Errorf("Parse conf error: heartbeat_timeout is incorrect")
} else {
HeartBeatTimeout = v
}
}
return nil
}
@ -395,7 +405,9 @@ func CreateProxy(s *ProxyServer) error {
if oldServer.Status == consts.Working {
return fmt.Errorf("this proxy is already working now")
}
oldServer.Lock()
oldServer.Release()
oldServer.Unlock()
if oldServer.PrivilegeMode {
delete(ProxyServers, s.Name)
}
@ -403,7 +415,6 @@ func CreateProxy(s *ProxyServer) error {
ProxyServers[s.Name] = s
metric.SetProxyInfo(s.Name, s.Type, s.BindAddr, s.UseEncryption, s.UseGzip,
s.PrivilegeMode, s.CustomDomains, s.Locations, s.ListenPort)
s.Init()
return nil
}

View File

@ -83,6 +83,8 @@ func NewProxyServerFromCtlMsg(req *msg.ControlReq) (p *ProxyServer) {
p.HostHeaderRewrite = req.HostHeaderRewrite
p.HttpUserName = req.HttpUserName
p.HttpPassWord = req.HttpPassWord
p.Init()
return
}
@ -276,10 +278,14 @@ func (p *ProxyServer) Start(c *conn.Conn) (err error) {
}
func (p *ProxyServer) Close() {
p.Lock()
defer p.Unlock()
oldStatus := p.Status
p.Release()
// if the proxy created by PrivilegeMode, delete it when closed
if p.PrivilegeMode {
if p.PrivilegeMode && oldStatus != consts.Closed {
// NOTE: this will take the global ProxyServerMap's lock
// if we only want to release resources, use Release() instead
DeleteProxy(p.Name)
@ -287,9 +293,6 @@ func (p *ProxyServer) Close() {
}
func (p *ProxyServer) Release() {
p.Lock()
defer p.Unlock()
if p.Status != consts.Closed {
p.Status = consts.Closed
for _, l := range p.listeners {
@ -297,10 +300,22 @@ func (p *ProxyServer) Release() {
l.Close()
}
}
close(p.ctlMsgChan)
close(p.workConnChan)
close(p.udpSenderChan)
close(p.closeChan)
if p.ctlMsgChan != nil {
close(p.ctlMsgChan)
p.ctlMsgChan = nil
}
if p.workConnChan != nil {
close(p.workConnChan)
p.workConnChan = nil
}
if p.udpSenderChan != nil {
close(p.udpSenderChan)
p.udpSenderChan = nil
}
if p.closeChan != nil {
close(p.closeChan)
p.closeChan = nil
}
if p.CtlConn != nil {
p.CtlConn.Close()
}

View File

@ -19,7 +19,7 @@ import (
"strings"
)
var version string = "0.9.1"
var version string = "0.9.2"
func Full() string {
return version