mirror of
https://gitee.com/IrisVega/frp.git
synced 2024-11-01 22:31:29 +08:00
commit
edb97abf50
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
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)
|
||||
}
|
||||
|
@ -85,7 +85,9 @@ func controlWorker(c *conn.Conn) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if ret == 0 {
|
||||
closeFlag = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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" {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var version string = "0.9.1"
|
||||
var version string = "0.9.2"
|
||||
|
||||
func Full() string {
|
||||
return version
|
||||
|
Loading…
Reference in New Issue
Block a user