Skip to content

Commit

Permalink
Merge pull request #890 from fatedier/dev
Browse files Browse the repository at this point in the history
bump version to v0.21.0
  • Loading branch information
fatedier committed Aug 12, 2018
2 parents 629f285 + fb13774 commit 66a69f8
Show file tree
Hide file tree
Showing 19 changed files with 1,534 additions and 70 deletions.
7 changes: 4 additions & 3 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion client/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ func (sv *XtcpVisitor) worker() {
for {
conn, err := sv.l.Accept()
if err != nil {
sv.Warn("stcp local listener closed")
sv.Warn("xtcp local listener closed")
return
}

Expand Down
17 changes: 17 additions & 0 deletions cmd/frps/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/server"
"github.com/fatedier/frp/utils/log"
"github.com/fatedier/frp/utils/util"
"github.com/fatedier/frp/utils/version"
)

Expand All @@ -44,6 +45,7 @@ var (
proxyBindAddr string
vhostHttpPort int
vhostHttpsPort int
vhostHttpTimeout int64
dashboardAddr string
dashboardPort int
dashboardUser string
Expand Down Expand Up @@ -73,6 +75,7 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&proxyBindAddr, "proxy_bind_addr", "", "0.0.0.0", "proxy bind address")
rootCmd.PersistentFlags().IntVarP(&vhostHttpPort, "vhost_http_port", "", 0, "vhost http port")
rootCmd.PersistentFlags().IntVarP(&vhostHttpsPort, "vhost_https_port", "", 0, "vhost https port")
rootCmd.PersistentFlags().Int64VarP(&vhostHttpTimeout, "vhost_http_timeout", "", 60, "vhost http response header timeout")
rootCmd.PersistentFlags().StringVarP(&dashboardAddr, "dashboard_addr", "", "0.0.0.0", "dasboard address")
rootCmd.PersistentFlags().IntVarP(&dashboardPort, "dashboard_port", "", 0, "dashboard port")
rootCmd.PersistentFlags().StringVarP(&dashboardUser, "dashboard_user", "", "admin", "dashboard user")
Expand All @@ -84,6 +87,7 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token")
rootCmd.PersistentFlags().Int64VarP(&authTimeout, "auth_timeout", "", 900, "auth timeout")
rootCmd.PersistentFlags().StringVarP(&subDomainHost, "subdomain_host", "", "", "subdomain host")
rootCmd.PersistentFlags().StringVarP(&allowPorts, "allow_ports", "", "", "allow ports")
rootCmd.PersistentFlags().Int64VarP(&maxPortsPerClient, "max_ports_per_client", "", 0, "max ports per client")
}

Expand Down Expand Up @@ -165,6 +169,7 @@ func parseServerCommonCfgFromCmd() (err error) {
g.GlbServerCfg.ProxyBindAddr = proxyBindAddr
g.GlbServerCfg.VhostHttpPort = vhostHttpPort
g.GlbServerCfg.VhostHttpsPort = vhostHttpsPort
g.GlbServerCfg.VhostHttpTimeout = vhostHttpTimeout
g.GlbServerCfg.DashboardAddr = dashboardAddr
g.GlbServerCfg.DashboardPort = dashboardPort
g.GlbServerCfg.DashboardUser = dashboardUser
Expand All @@ -176,6 +181,18 @@ func parseServerCommonCfgFromCmd() (err error) {
g.GlbServerCfg.Token = token
g.GlbServerCfg.AuthTimeout = authTimeout
g.GlbServerCfg.SubDomainHost = subDomainHost
if len(allowPorts) > 0 {
// e.g. 1000-2000,2001,2002,3000-4000
ports, errRet := util.ParseRangeNumbers(allowPorts)
if errRet != nil {
err = fmt.Errorf("Parse conf error: allow_ports: %v", errRet)
return
}

for _, port := range ports {
g.GlbServerCfg.AllowPorts[int(port)] = struct{}{}
}
}
g.GlbServerCfg.MaxPortsPerClient = maxPortsPerClient
return
}
Expand Down
2 changes: 1 addition & 1 deletion conf/frpc_full.ini
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ user = your_name
login_fail_exit = true

# communication protocol used to connect to server
# now it supports tcp and kcp, default is tcp
# now it supports tcp and kcp and websocket, default is tcp
protocol = tcp

# specify a dns server, so frpc will use this instead of default one
Expand Down
3 changes: 3 additions & 0 deletions conf/frps_full.ini
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ kcp_bind_port = 7000
vhost_http_port = 80
vhost_https_port = 443

# response header timeout(seconds) for vhost http server, default is 60s
# vhost_http_timeout = 60

# set dashboard_addr and dashboard_port to view dashboard of frps
# dashboard_addr's default value is same with bind_addr
# dashboard is available only if dashboard_port is set
Expand Down
7 changes: 4 additions & 3 deletions models/config/client_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,10 @@ func UnmarshalClientConfFromIni(defaultCfg *ClientCommonConf, content string) (c
}

if tmpStr, ok = conf.Get("common", "protocol"); ok {
// Now it only support tcp and kcp.
if tmpStr != "kcp" {
tmpStr = "tcp"
// Now it only support tcp and kcp and websocket.
if tmpStr != "tcp" && tmpStr != "kcp" && tmpStr != "websocket" {
err = fmt.Errorf("Parse conf error: invalid protocol")
return
}
cfg.Protocol = tmpStr
}
Expand Down
2 changes: 0 additions & 2 deletions models/config/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,6 @@ func (cfg *StcpProxyConf) UnmarshalFromIni(prefix string, name string, section i
cfg.Sk = section["sk"]

if tmpStr == "visitor" {
prefix := section["prefix"]
cfg.ServerName = prefix + section["server_name"]
if cfg.BindAddr = section["bind_addr"]; cfg.BindAddr == "" {
cfg.BindAddr = "127.0.0.1"
Expand Down Expand Up @@ -777,7 +776,6 @@ func (cfg *XtcpProxyConf) UnmarshalFromIni(prefix string, name string, section i
cfg.Sk = section["sk"]

if tmpStr == "visitor" {
prefix := section["prefix"]
cfg.ServerName = prefix + section["server_name"]
if cfg.BindAddr = section["bind_addr"]; cfg.BindAddr == "" {
cfg.BindAddr = "127.0.0.1"
Expand Down
18 changes: 16 additions & 2 deletions models/config/server_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,11 @@ type ServerCommonConf struct {
VhostHttpPort int `json:"vhost_http_port"`

// if VhostHttpsPort equals 0, don't listen a public port for https protocol
VhostHttpsPort int `json:"vhost_http_port"`
DashboardAddr string `json:"dashboard_addr"`
VhostHttpsPort int `json:"vhost_http_port"`

VhostHttpTimeout int64 `json:"vhost_http_timeout"`

DashboardAddr string `json:"dashboard_addr"`

// if DashboardPort equals 0, dashboard is not available
DashboardPort int `json:"dashboard_port"`
Expand Down Expand Up @@ -84,6 +87,7 @@ func GetDefaultServerConf() *ServerCommonConf {
ProxyBindAddr: "0.0.0.0",
VhostHttpPort: 0,
VhostHttpsPort: 0,
VhostHttpTimeout: 60,
DashboardAddr: "0.0.0.0",
DashboardPort: 0,
DashboardUser: "admin",
Expand Down Expand Up @@ -181,6 +185,16 @@ func UnmarshalServerConfFromIni(defaultCfg *ServerCommonConf, content string) (c
cfg.VhostHttpsPort = 0
}

if tmpStr, ok = conf.Get("common", "vhost_http_timeout"); ok {
v, errRet := strconv.ParseInt(tmpStr, 10, 64)
if errRet != nil || v < 0 {
err = fmt.Errorf("Parse conf error: invalid vhost_http_timeout")
return
} else {
cfg.VhostHttpTimeout = v
}
}

if tmpStr, ok = conf.Get("common", "dashboard_addr"); ok {
cfg.DashboardAddr = tmpStr
} else {
Expand Down
36 changes: 25 additions & 11 deletions server/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package server

import (
"bytes"
"fmt"
"io/ioutil"
"net"
Expand Down Expand Up @@ -53,6 +54,9 @@ type Service struct {
// Accept connections using kcp
kcpListener frpNet.Listener

// Accept connections using websocket
websocketListener frpNet.Listener

// For https proxies, route requests to different clients by hostname and other infomation
VhostHttpsMuxer *vhost.HttpsMuxer

Expand Down Expand Up @@ -109,9 +113,6 @@ func NewService() (svr *Service, err error) {
if cfg.BindPort == cfg.VhostHttpsPort {
httpsMuxOn = true
}
if httpMuxOn || httpsMuxOn {
svr.muxer = mux.NewMux()
}
}

// Listen for accepting connections from client.
Expand All @@ -120,10 +121,11 @@ func NewService() (svr *Service, err error) {
err = fmt.Errorf("Create server listener error, %v", err)
return
}
if svr.muxer != nil {
go svr.muxer.Serve(ln)
ln = svr.muxer.DefaultListener()
}

svr.muxer = mux.NewMux(ln)
go svr.muxer.Serve()
ln = svr.muxer.DefaultListener()

svr.listener = frpNet.WrapLogListener(ln)
log.Info("frps tcp listen on %s:%d", cfg.BindAddr, cfg.BindPort)

Expand All @@ -137,9 +139,18 @@ func NewService() (svr *Service, err error) {
log.Info("frps kcp listen on udp %s:%d", cfg.BindAddr, cfg.KcpBindPort)
}

// Listen for accepting connections from client using websocket protocol.
websocketPrefix := []byte("GET " + frpNet.FrpWebsocketPath)
websocketLn := svr.muxer.Listen(0, uint32(len(websocketPrefix)), func(data []byte) bool {
return bytes.Equal(data, websocketPrefix)
})
svr.websocketListener = frpNet.NewWebsocketListener(websocketLn)

// Create http vhost muxer.
if cfg.VhostHttpPort > 0 {
rp := vhost.NewHttpReverseProxy()
rp := vhost.NewHttpReverseProxy(vhost.HttpReverseProxyOptions{
ResponseHeaderTimeoutS: cfg.VhostHttpTimeout,
})
svr.httpReverseProxy = rp

address := fmt.Sprintf("%s:%d", cfg.ProxyBindAddr, cfg.VhostHttpPort)
Expand All @@ -149,7 +160,7 @@ func NewService() (svr *Service, err error) {
}
var l net.Listener
if httpMuxOn {
l = svr.muxer.ListenHttp(0)
l = svr.muxer.ListenHttp(1)
} else {
l, err = net.Listen("tcp", address)
if err != nil {
Expand All @@ -165,7 +176,7 @@ func NewService() (svr *Service, err error) {
if cfg.VhostHttpsPort > 0 {
var l net.Listener
if httpsMuxOn {
l = svr.muxer.ListenHttps(0)
l = svr.muxer.ListenHttps(1)
} else {
l, err = net.Listen("tcp", fmt.Sprintf("%s:%d", cfg.ProxyBindAddr, cfg.VhostHttpsPort))
if err != nil {
Expand Down Expand Up @@ -204,6 +215,7 @@ func NewService() (svr *Service, err error) {
}
log.Info("Dashboard listen on %s:%d", cfg.DashboardAddr, cfg.DashboardPort)
}

return
}

Expand All @@ -214,8 +226,10 @@ func (svr *Service) Run() {
if g.GlbServerCfg.KcpBindPort > 0 {
go svr.HandleListener(svr.kcpListener)
}
svr.HandleListener(svr.listener)

go svr.HandleListener(svr.websocketListener)

svr.HandleListener(svr.listener)
}

func (svr *Service) HandleListener(l frpNet.Listener) {
Expand Down
100 changes: 66 additions & 34 deletions utils/net/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,45 +96,34 @@ func (conn *WrapReadWriteCloserConn) SetWriteDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "wrap", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}

func ConnectServer(protocol string, addr string) (c Conn, err error) {
switch protocol {
case "tcp":
return ConnectTcpServer(addr)
case "kcp":
kcpConn, errRet := kcp.DialWithOptions(addr, nil, 10, 3)
if errRet != nil {
err = errRet
return
}
kcpConn.SetStreamMode(true)
kcpConn.SetWriteDelay(true)
kcpConn.SetNoDelay(1, 20, 2, 1)
kcpConn.SetWindowSize(128, 512)
kcpConn.SetMtu(1350)
kcpConn.SetACKNoDelay(false)
kcpConn.SetReadBuffer(4194304)
kcpConn.SetWriteBuffer(4194304)
c = WrapConn(kcpConn)
return
default:
return nil, fmt.Errorf("unsupport protocol: %s", protocol)
type CloseNotifyConn struct {
net.Conn
log.Logger

// 1 means closed
closeFlag int32

closeFn func()
}

// closeFn will be only called once
func WrapCloseNotifyConn(c net.Conn, closeFn func()) Conn {
return &CloseNotifyConn{
Conn: c,
Logger: log.NewPrefixLogger(""),
closeFn: closeFn,
}
}

func ConnectServerByProxy(proxyUrl string, protocol string, addr string) (c Conn, err error) {
switch protocol {
case "tcp":
var conn net.Conn
if conn, err = gnet.DialTcpByProxy(proxyUrl, addr); err != nil {
return
func (cc *CloseNotifyConn) Close() (err error) {
pflag := atomic.SwapInt32(&cc.closeFlag, 1)
if pflag == 0 {
err = cc.Close()
if cc.closeFn != nil {
cc.closeFn()
}
return WrapConn(conn), nil
case "kcp":
// http proxy is not supported for kcp
return ConnectServer(protocol, addr)
default:
return nil, fmt.Errorf("unsupport protocol: %s", protocol)
}
return
}

type StatsConn struct {
Expand Down Expand Up @@ -175,3 +164,46 @@ func (statsConn *StatsConn) Close() (err error) {
}
return
}

func ConnectServer(protocol string, addr string) (c Conn, err error) {
switch protocol {
case "tcp":
return ConnectTcpServer(addr)
case "kcp":
kcpConn, errRet := kcp.DialWithOptions(addr, nil, 10, 3)
if errRet != nil {
err = errRet
return
}
kcpConn.SetStreamMode(true)
kcpConn.SetWriteDelay(true)
kcpConn.SetNoDelay(1, 20, 2, 1)
kcpConn.SetWindowSize(128, 512)
kcpConn.SetMtu(1350)
kcpConn.SetACKNoDelay(false)
kcpConn.SetReadBuffer(4194304)
kcpConn.SetWriteBuffer(4194304)
c = WrapConn(kcpConn)
return
default:
return nil, fmt.Errorf("unsupport protocol: %s", protocol)
}
}

func ConnectServerByProxy(proxyUrl string, protocol string, addr string) (c Conn, err error) {
switch protocol {
case "tcp":
var conn net.Conn
if conn, err = gnet.DialTcpByProxy(proxyUrl, addr); err != nil {
return
}
return WrapConn(conn), nil
case "kcp":
// http proxy is not supported for kcp
return ConnectServer(protocol, addr)
case "websocket":
return ConnectWebsocketServer(addr)
default:
return nil, fmt.Errorf("unsupport protocol: %s", protocol)
}
}
Loading

0 comments on commit 66a69f8

Please sign in to comment.