提交 0f6f674a 编写于 作者: F fatedier

cmd: support more cli command

上级 82dc1e92
...@@ -39,7 +39,7 @@ ci: ...@@ -39,7 +39,7 @@ ci:
go test -v ./tests/... go test -v ./tests/...
cd ./tests && ./clean_test.sh && cd - cd ./tests && ./clean_test.sh && cd -
ciclean: cic:
cd ./tests && ./clean_test.sh && cd - cd ./tests && ./clean_test.sh && cd -
alltest: gotest ci alltest: gotest ci
......
...@@ -383,7 +383,7 @@ Then visit `http://[server_addr]:7500` to see dashboard, default username and pa ...@@ -383,7 +383,7 @@ Then visit `http://[server_addr]:7500` to see dashboard, default username and pa
### Authentication ### Authentication
Since v0.10.0, you only need to set `privilege_token` in frps.ini and frpc.ini. Since v0.10.0, you only need to set `token` in frps.ini and frpc.ini.
Note that time duration between server of frpc and frps mustn't exceed 15 minutes because timestamp is used for authentication. Note that time duration between server of frpc and frps mustn't exceed 15 minutes because timestamp is used for authentication.
...@@ -539,7 +539,7 @@ type = http ...@@ -539,7 +539,7 @@ type = http
local_port = 80 local_port = 80
custom_domains = test.yourdomain.com custom_domains = test.yourdomain.com
http_user = abc http_user = abc
http_pwd = abc http_passwd = abc
``` ```
Visit `http://test.yourdomain.com` and now you need to input username and password. Visit `http://test.yourdomain.com` and now you need to input username and password.
......
...@@ -401,7 +401,7 @@ dashboard_pwd = admin ...@@ -401,7 +401,7 @@ dashboard_pwd = admin
### 身份验证 ### 身份验证
从 v0.10.0 版本开始,所有 proxy 配置全部放在客户端(也就是之前版本的特权模式),服务端和客户端的 common 配置中的 `privilege_token` 参数一致则身份验证通过。 从 v0.10.0 版本开始,所有 proxy 配置全部放在客户端(也就是之前版本的特权模式),服务端和客户端的 common 配置中的 `token` 参数一致则身份验证通过。
需要注意的是 frpc 所在机器和 frps 所在机器的时间相差不能超过 15 分钟,因为时间戳会被用于加密验证中,防止报文被劫持后被其他人利用。 需要注意的是 frpc 所在机器和 frps 所在机器的时间相差不能超过 15 分钟,因为时间戳会被用于加密验证中,防止报文被劫持后被其他人利用。
...@@ -565,7 +565,7 @@ type = http ...@@ -565,7 +565,7 @@ type = http
local_port = 80 local_port = 80
custom_domains = test.yourdomain.com custom_domains = test.yourdomain.com
http_user = abc http_user = abc
http_pwd = abc http_passwd = abc
``` ```
通过浏览器访问 `http://test.yourdomain.com`,需要输入配置的用户名和密码才能访问。 通过浏览器访问 `http://test.yourdomain.com`,需要输入配置的用户名和密码才能访问。
......
...@@ -20,7 +20,7 @@ import ( ...@@ -20,7 +20,7 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/g"
frpNet "github.com/fatedier/frp/utils/net" frpNet "github.com/fatedier/frp/utils/net"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
...@@ -35,7 +35,7 @@ func (svr *Service) RunAdminServer(addr string, port int) (err error) { ...@@ -35,7 +35,7 @@ func (svr *Service) RunAdminServer(addr string, port int) (err error) {
// url router // url router
router := httprouter.New() router := httprouter.New()
user, passwd := config.ClientCommonCfg.AdminUser, config.ClientCommonCfg.AdminPwd user, passwd := g.GlbClientCfg.AdminUser, g.GlbClientCfg.AdminPwd
// api, see dashboard_api.go // api, see dashboard_api.go
router.GET("/api/reload", frpNet.HttprouterBasicAuth(svr.apiReload, user, passwd)) router.GET("/api/reload", frpNet.HttprouterBasicAuth(svr.apiReload, user, passwd))
......
...@@ -17,6 +17,7 @@ package client ...@@ -17,6 +17,7 @@ package client
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil"
"net/http" "net/http"
"sort" "sort"
"strings" "strings"
...@@ -24,6 +25,7 @@ import ( ...@@ -24,6 +25,7 @@ import (
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
ini "github.com/vaughan0/go-ini" ini "github.com/vaughan0/go-ini"
"github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/utils/log" "github.com/fatedier/frp/utils/log"
) )
...@@ -51,15 +53,16 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprout ...@@ -51,15 +53,16 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprout
log.Info("Http request: [/api/reload]") log.Info("Http request: [/api/reload]")
conf, err := ini.LoadFile(config.ClientCommonCfg.ConfigFile) b, err := ioutil.ReadFile(g.GlbClientCfg.CfgFile)
if err != nil { if err != nil {
res.Code = 1 res.Code = 1
res.Msg = err.Error() res.Msg = err.Error()
log.Error("reload frpc config file error: %v", err) log.Error("reload frpc config file error: %v", err)
return return
} }
content := string(b)
newCommonCfg, err := config.LoadClientCommonConf(conf) newCommonCfg, err := config.UnmarshalClientConfFromIni(nil, content)
if err != nil { if err != nil {
res.Code = 2 res.Code = 2
res.Msg = err.Error() res.Msg = err.Error()
...@@ -67,7 +70,15 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprout ...@@ -67,7 +70,15 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprout
return return
} }
pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromFile(config.ClientCommonCfg.User, conf, newCommonCfg.Start) conf, err := ini.LoadFile(g.GlbClientCfg.CfgFile)
if err != nil {
res.Code = 1
res.Msg = err.Error()
log.Error("reload frpc config file error: %v", err)
return
}
pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromIni(g.GlbClientCfg.User, conf, newCommonCfg.Start)
if err != nil { if err != nil {
res.Code = 3 res.Code = 3
res.Msg = err.Error() res.Msg = err.Error()
...@@ -125,18 +136,18 @@ func NewProxyStatusResp(status *ProxyStatus) ProxyStatusResp { ...@@ -125,18 +136,18 @@ func NewProxyStatusResp(status *ProxyStatus) ProxyStatusResp {
} }
psr.Plugin = cfg.Plugin psr.Plugin = cfg.Plugin
if status.Err != "" { if status.Err != "" {
psr.RemoteAddr = fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, cfg.RemotePort) psr.RemoteAddr = fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, cfg.RemotePort)
} else { } else {
psr.RemoteAddr = config.ClientCommonCfg.ServerAddr + status.RemoteAddr psr.RemoteAddr = g.GlbClientCfg.ServerAddr + status.RemoteAddr
} }
case *config.UdpProxyConf: case *config.UdpProxyConf:
if cfg.LocalPort != 0 { if cfg.LocalPort != 0 {
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort) psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort)
} }
if status.Err != "" { if status.Err != "" {
psr.RemoteAddr = fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, cfg.RemotePort) psr.RemoteAddr = fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, cfg.RemotePort)
} else { } else {
psr.RemoteAddr = config.ClientCommonCfg.ServerAddr + status.RemoteAddr psr.RemoteAddr = g.GlbClientCfg.ServerAddr + status.RemoteAddr
} }
case *config.HttpProxyConf: case *config.HttpProxyConf:
if cfg.LocalPort != 0 { if cfg.LocalPort != 0 {
......
...@@ -21,6 +21,9 @@ import ( ...@@ -21,6 +21,9 @@ import (
"sync" "sync"
"time" "time"
"github.com/xtaci/smux"
"github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/models/msg"
"github.com/fatedier/frp/utils/crypto" "github.com/fatedier/frp/utils/crypto"
...@@ -29,7 +32,6 @@ import ( ...@@ -29,7 +32,6 @@ import (
"github.com/fatedier/frp/utils/shutdown" "github.com/fatedier/frp/utils/shutdown"
"github.com/fatedier/frp/utils/util" "github.com/fatedier/frp/utils/util"
"github.com/fatedier/frp/utils/version" "github.com/fatedier/frp/utils/version"
"github.com/xtaci/smux"
) )
const ( const (
...@@ -82,8 +84,8 @@ func NewControl(svr *Service, pxyCfgs map[string]config.ProxyConf, visitorCfgs m ...@@ -82,8 +84,8 @@ func NewControl(svr *Service, pxyCfgs map[string]config.ProxyConf, visitorCfgs m
loginMsg := &msg.Login{ loginMsg := &msg.Login{
Arch: runtime.GOARCH, Arch: runtime.GOARCH,
Os: runtime.GOOS, Os: runtime.GOOS,
PoolCount: config.ClientCommonCfg.PoolCount, PoolCount: g.GlbClientCfg.PoolCount,
User: config.ClientCommonCfg.User, User: g.GlbClientCfg.User,
Version: version.Full(), Version: version.Full(),
} }
ctl := &Control{ ctl := &Control{
...@@ -110,7 +112,7 @@ func (ctl *Control) Run() (err error) { ...@@ -110,7 +112,7 @@ func (ctl *Control) Run() (err error) {
// if login_fail_exit is true, just exit this program // if login_fail_exit is true, just exit this program
// otherwise sleep a while and continues relogin to server // otherwise sleep a while and continues relogin to server
if config.ClientCommonCfg.LoginFailExit { if g.GlbClientCfg.LoginFailExit {
return return
} else { } else {
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)
...@@ -183,8 +185,8 @@ func (ctl *Control) login() (err error) { ...@@ -183,8 +185,8 @@ func (ctl *Control) login() (err error) {
ctl.session.Close() ctl.session.Close()
} }
conn, err := frpNet.ConnectServerByHttpProxy(config.ClientCommonCfg.HttpProxy, config.ClientCommonCfg.Protocol, conn, err := frpNet.ConnectServerByHttpProxy(g.GlbClientCfg.HttpProxy, g.GlbClientCfg.Protocol,
fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerPort)) fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerPort))
if err != nil { if err != nil {
return err return err
} }
...@@ -195,7 +197,7 @@ func (ctl *Control) login() (err error) { ...@@ -195,7 +197,7 @@ func (ctl *Control) login() (err error) {
} }
}() }()
if config.ClientCommonCfg.TcpMux { if g.GlbClientCfg.TcpMux {
session, errRet := smux.Client(conn, nil) session, errRet := smux.Client(conn, nil)
if errRet != nil { if errRet != nil {
return errRet return errRet
...@@ -210,7 +212,7 @@ func (ctl *Control) login() (err error) { ...@@ -210,7 +212,7 @@ func (ctl *Control) login() (err error) {
} }
now := time.Now().Unix() now := time.Now().Unix()
ctl.loginMsg.PrivilegeKey = util.GetAuthKey(config.ClientCommonCfg.PrivilegeToken, now) ctl.loginMsg.PrivilegeKey = util.GetAuthKey(g.GlbClientCfg.Token, now)
ctl.loginMsg.Timestamp = now ctl.loginMsg.Timestamp = now
ctl.loginMsg.RunId = ctl.runId ctl.loginMsg.RunId = ctl.runId
...@@ -234,7 +236,7 @@ func (ctl *Control) login() (err error) { ...@@ -234,7 +236,7 @@ func (ctl *Control) login() (err error) {
ctl.conn = conn ctl.conn = conn
// update runId got from server // update runId got from server
ctl.runId = loginRespMsg.RunId ctl.runId = loginRespMsg.RunId
config.ClientCommonCfg.ServerUdpPort = loginRespMsg.ServerUdpPort g.GlbClientCfg.ServerUdpPort = loginRespMsg.ServerUdpPort
ctl.ClearLogPrefix() ctl.ClearLogPrefix()
ctl.AddLogPrefix(loginRespMsg.RunId) ctl.AddLogPrefix(loginRespMsg.RunId)
ctl.Info("login to server success, get run id [%s], server udp port [%d]", loginRespMsg.RunId, loginRespMsg.ServerUdpPort) ctl.Info("login to server success, get run id [%s], server udp port [%d]", loginRespMsg.RunId, loginRespMsg.ServerUdpPort)
...@@ -242,7 +244,7 @@ func (ctl *Control) login() (err error) { ...@@ -242,7 +244,7 @@ func (ctl *Control) login() (err error) {
} }
func (ctl *Control) connectServer() (conn frpNet.Conn, err error) { func (ctl *Control) connectServer() (conn frpNet.Conn, err error) {
if config.ClientCommonCfg.TcpMux { if g.GlbClientCfg.TcpMux {
stream, errRet := ctl.session.OpenStream() stream, errRet := ctl.session.OpenStream()
if errRet != nil { if errRet != nil {
err = errRet err = errRet
...@@ -251,8 +253,8 @@ func (ctl *Control) connectServer() (conn frpNet.Conn, err error) { ...@@ -251,8 +253,8 @@ func (ctl *Control) connectServer() (conn frpNet.Conn, err error) {
} }
conn = frpNet.WrapConn(stream) conn = frpNet.WrapConn(stream)
} else { } else {
conn, err = frpNet.ConnectServerByHttpProxy(config.ClientCommonCfg.HttpProxy, config.ClientCommonCfg.Protocol, conn, err = frpNet.ConnectServerByHttpProxy(g.GlbClientCfg.HttpProxy, g.GlbClientCfg.Protocol,
fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerPort)) fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerPort))
if err != nil { if err != nil {
ctl.Warn("start new connection to server error: %v", err) ctl.Warn("start new connection to server error: %v", err)
return return
...@@ -271,7 +273,7 @@ func (ctl *Control) reader() { ...@@ -271,7 +273,7 @@ func (ctl *Control) reader() {
defer ctl.readerShutdown.Done() defer ctl.readerShutdown.Done()
defer close(ctl.closedCh) defer close(ctl.closedCh)
encReader := crypto.NewReader(ctl.conn, []byte(config.ClientCommonCfg.PrivilegeToken)) encReader := crypto.NewReader(ctl.conn, []byte(g.GlbClientCfg.Token))
for { for {
if m, err := msg.ReadMsg(encReader); err != nil { if m, err := msg.ReadMsg(encReader); err != nil {
if err == io.EOF { if err == io.EOF {
...@@ -290,7 +292,7 @@ func (ctl *Control) reader() { ...@@ -290,7 +292,7 @@ func (ctl *Control) reader() {
// writer writes messages got from sendCh to frps // writer writes messages got from sendCh to frps
func (ctl *Control) writer() { func (ctl *Control) writer() {
defer ctl.writerShutdown.Done() defer ctl.writerShutdown.Done()
encWriter, err := crypto.NewWriter(ctl.conn, []byte(config.ClientCommonCfg.PrivilegeToken)) encWriter, err := crypto.NewWriter(ctl.conn, []byte(g.GlbClientCfg.Token))
if err != nil { if err != nil {
ctl.conn.Error("crypto new writer error: %v", err) ctl.conn.Error("crypto new writer error: %v", err)
ctl.conn.Close() ctl.conn.Close()
...@@ -318,7 +320,7 @@ func (ctl *Control) msgHandler() { ...@@ -318,7 +320,7 @@ func (ctl *Control) msgHandler() {
}() }()
defer ctl.msgHandlerShutdown.Done() defer ctl.msgHandlerShutdown.Done()
hbSend := time.NewTicker(time.Duration(config.ClientCommonCfg.HeartBeatInterval) * time.Second) hbSend := time.NewTicker(time.Duration(g.GlbClientCfg.HeartBeatInterval) * time.Second)
defer hbSend.Stop() defer hbSend.Stop()
hbCheck := time.NewTicker(time.Second) hbCheck := time.NewTicker(time.Second)
defer hbCheck.Stop() defer hbCheck.Stop()
...@@ -332,7 +334,7 @@ func (ctl *Control) msgHandler() { ...@@ -332,7 +334,7 @@ func (ctl *Control) msgHandler() {
ctl.Debug("send heartbeat to server") ctl.Debug("send heartbeat to server")
ctl.sendCh <- &msg.Ping{} ctl.sendCh <- &msg.Ping{}
case <-hbCheck.C: case <-hbCheck.C:
if time.Since(ctl.lastPong) > time.Duration(config.ClientCommonCfg.HeartBeatTimeout)*time.Second { if time.Since(ctl.lastPong) > time.Duration(g.GlbClientCfg.HeartBeatTimeout)*time.Second {
ctl.Warn("heartbeat timeout") ctl.Warn("heartbeat timeout")
// let reader() stop // let reader() stop
ctl.conn.Close() ctl.conn.Close()
......
...@@ -22,6 +22,7 @@ import ( ...@@ -22,6 +22,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/models/msg"
"github.com/fatedier/frp/models/plugin" "github.com/fatedier/frp/models/plugin"
...@@ -46,7 +47,7 @@ type Proxy interface { ...@@ -46,7 +47,7 @@ type Proxy interface {
func NewProxy(pxyConf config.ProxyConf) (pxy Proxy) { func NewProxy(pxyConf config.ProxyConf) (pxy Proxy) {
baseProxy := BaseProxy{ baseProxy := BaseProxy{
Logger: log.NewPrefixLogger(pxyConf.GetName()), Logger: log.NewPrefixLogger(pxyConf.GetBaseInfo().ProxyName),
} }
switch cfg := pxyConf.(type) { switch cfg := pxyConf.(type) {
case *config.TcpProxyConf: case *config.TcpProxyConf:
...@@ -115,7 +116,7 @@ func (pxy *TcpProxy) Close() { ...@@ -115,7 +116,7 @@ func (pxy *TcpProxy) Close() {
func (pxy *TcpProxy) InWorkConn(conn frpNet.Conn) { func (pxy *TcpProxy) InWorkConn(conn frpNet.Conn) {
HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
[]byte(config.ClientCommonCfg.PrivilegeToken)) []byte(g.GlbClientCfg.Token))
} }
// HTTP // HTTP
...@@ -144,7 +145,7 @@ func (pxy *HttpProxy) Close() { ...@@ -144,7 +145,7 @@ func (pxy *HttpProxy) Close() {
func (pxy *HttpProxy) InWorkConn(conn frpNet.Conn) { func (pxy *HttpProxy) InWorkConn(conn frpNet.Conn) {
HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
[]byte(config.ClientCommonCfg.PrivilegeToken)) []byte(g.GlbClientCfg.Token))
} }
// HTTPS // HTTPS
...@@ -173,7 +174,7 @@ func (pxy *HttpsProxy) Close() { ...@@ -173,7 +174,7 @@ func (pxy *HttpsProxy) Close() {
func (pxy *HttpsProxy) InWorkConn(conn frpNet.Conn) { func (pxy *HttpsProxy) InWorkConn(conn frpNet.Conn) {
HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
[]byte(config.ClientCommonCfg.PrivilegeToken)) []byte(g.GlbClientCfg.Token))
} }
// STCP // STCP
...@@ -202,7 +203,7 @@ func (pxy *StcpProxy) Close() { ...@@ -202,7 +203,7 @@ func (pxy *StcpProxy) Close() {
func (pxy *StcpProxy) InWorkConn(conn frpNet.Conn) { func (pxy *StcpProxy) InWorkConn(conn frpNet.Conn) {
HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn,
[]byte(config.ClientCommonCfg.PrivilegeToken)) []byte(g.GlbClientCfg.Token))
} }
// XTCP // XTCP
...@@ -243,7 +244,7 @@ func (pxy *XtcpProxy) InWorkConn(conn frpNet.Conn) { ...@@ -243,7 +244,7 @@ func (pxy *XtcpProxy) InWorkConn(conn frpNet.Conn) {
Sid: natHoleSidMsg.Sid, Sid: natHoleSidMsg.Sid,
} }
raddr, _ := net.ResolveUDPAddr("udp", raddr, _ := net.ResolveUDPAddr("udp",
fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerUdpPort)) fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerUdpPort))
clientConn, err := net.DialUDP("udp", nil, raddr) clientConn, err := net.DialUDP("udp", nil, raddr)
defer clientConn.Close() defer clientConn.Close()
......
...@@ -62,8 +62,8 @@ type ProxyStatus struct { ...@@ -62,8 +62,8 @@ type ProxyStatus struct {
func NewProxyWrapper(cfg config.ProxyConf) *ProxyWrapper { func NewProxyWrapper(cfg config.ProxyConf) *ProxyWrapper {
return &ProxyWrapper{ return &ProxyWrapper{
Name: cfg.GetName(), Name: cfg.GetBaseInfo().ProxyName,
Type: cfg.GetType(), Type: cfg.GetBaseInfo().ProxyType,
Status: ProxyStatusNew, Status: ProxyStatusNew,
Cfg: cfg, Cfg: cfg,
pxy: nil, pxy: nil,
...@@ -227,7 +227,7 @@ func (pm *ProxyManager) CheckAndStartProxy(pxyStatus []string) { ...@@ -227,7 +227,7 @@ func (pm *ProxyManager) CheckAndStartProxy(pxyStatus []string) {
for _, s := range pxyStatus { for _, s := range pxyStatus {
if status == s { if status == s {
var newProxyMsg msg.NewProxy var newProxyMsg msg.NewProxy
pxy.Cfg.UnMarshalToMsg(&newProxyMsg) pxy.Cfg.MarshalToMsg(&newProxyMsg)
err := pm.sendMsg(&newProxyMsg) err := pm.sendMsg(&newProxyMsg)
if err != nil { if err != nil {
pm.Warn("[%s] proxy send NewProxy message error") pm.Warn("[%s] proxy send NewProxy message error")
...@@ -240,15 +240,16 @@ func (pm *ProxyManager) CheckAndStartProxy(pxyStatus []string) { ...@@ -240,15 +240,16 @@ func (pm *ProxyManager) CheckAndStartProxy(pxyStatus []string) {
} }
for _, cfg := range pm.visitorCfgs { for _, cfg := range pm.visitorCfgs {
if _, exist := pm.visitors[cfg.GetName()]; !exist { name := cfg.GetBaseInfo().ProxyName
pm.Info("try to start visitor [%s]", cfg.GetName()) if _, exist := pm.visitors[name]; !exist {
pm.Info("try to start visitor [%s]", name)
visitor := NewVisitor(pm.ctl, cfg) visitor := NewVisitor(pm.ctl, cfg)
err := visitor.Run() err := visitor.Run()
if err != nil { if err != nil {
visitor.Warn("start error: %v", err) visitor.Warn("start error: %v", err)
continue continue
} }
pm.visitors[cfg.GetName()] = visitor pm.visitors[name] = visitor
visitor.Info("start visitor success") visitor.Info("start visitor success")
} }
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
package client package client
import ( import (
"github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/utils/log" "github.com/fatedier/frp/utils/log"
) )
...@@ -41,12 +42,12 @@ func (svr *Service) Run() error { ...@@ -41,12 +42,12 @@ func (svr *Service) Run() error {
return err return err
} }
if config.ClientCommonCfg.AdminPort != 0 { if g.GlbClientCfg.AdminPort != 0 {
err = svr.RunAdminServer(config.ClientCommonCfg.AdminAddr, config.ClientCommonCfg.AdminPort) err = svr.RunAdminServer(g.GlbClientCfg.AdminAddr, g.GlbClientCfg.AdminPort)
if err != nil { if err != nil {
log.Warn("run admin server error: %v", err) log.Warn("run admin server error: %v", err)
} }
log.Info("admin server listen on %s:%d", config.ClientCommonCfg.AdminAddr, config.ClientCommonCfg.AdminPort) log.Info("admin server listen on %s:%d", g.GlbClientCfg.AdminAddr, g.GlbClientCfg.AdminPort)
} }
<-svr.closedCh <-svr.closedCh
......
...@@ -26,6 +26,7 @@ import ( ...@@ -26,6 +26,7 @@ import (
"golang.org/x/net/ipv4" "golang.org/x/net/ipv4"
"github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/models/msg"
frpIo "github.com/fatedier/frp/utils/io" frpIo "github.com/fatedier/frp/utils/io"
...@@ -45,7 +46,7 @@ type Visitor interface { ...@@ -45,7 +46,7 @@ type Visitor interface {
func NewVisitor(ctl *Control, pxyConf config.ProxyConf) (visitor Visitor) { func NewVisitor(ctl *Control, pxyConf config.ProxyConf) (visitor Visitor) {
baseVisitor := BaseVisitor{ baseVisitor := BaseVisitor{
ctl: ctl, ctl: ctl,
Logger: log.NewPrefixLogger(pxyConf.GetName()), Logger: log.NewPrefixLogger(pxyConf.GetBaseInfo().ProxyName),
} }
switch cfg := pxyConf.(type) { switch cfg := pxyConf.(type) {
case *config.StcpProxyConf: case *config.StcpProxyConf:
...@@ -193,13 +194,13 @@ func (sv *XtcpVisitor) handleConn(userConn frpNet.Conn) { ...@@ -193,13 +194,13 @@ func (sv *XtcpVisitor) handleConn(userConn frpNet.Conn) {
defer userConn.Close() defer userConn.Close()
sv.Debug("get a new xtcp user connection") sv.Debug("get a new xtcp user connection")
if config.ClientCommonCfg.ServerUdpPort == 0 { if g.GlbClientCfg.ServerUdpPort == 0 {
sv.Error("xtcp is not supported by server") sv.Error("xtcp is not supported by server")
return return
} }
raddr, err := net.ResolveUDPAddr("udp", raddr, err := net.ResolveUDPAddr("udp",
fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerUdpPort)) fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerUdpPort))
visitorConn, err := net.DialUDP("udp", nil, raddr) visitorConn, err := net.DialUDP("udp", nil, raddr)
defer visitorConn.Close() defer visitorConn.Close()
......
...@@ -15,291 +15,9 @@ ...@@ -15,291 +15,9 @@
package main package main
import ( import (
"encoding/base64" "github.com/fatedier/frp/cmd/frpc/sub"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
docopt "github.com/docopt/docopt-go"
"github.com/rodaine/table"
ini "github.com/vaughan0/go-ini"
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/utils/log"
"github.com/fatedier/frp/utils/version"
) )
var (
configFile string = "./frpc.ini"
)
var usage string = `frpc is the client of frp
Usage:
frpc [-c config_file] [-L log_file] [--log-level=<log_level>] [--server-addr=<server_addr>]
frpc reload [-c config_file]
frpc status [-c config_file]
frpc -h | --help
frpc -v | --version
Options:
-c config_file set config file
-L log_file set output log file, including console
--log-level=<log_level> set log level: debug, info, warn, error
--server-addr=<server_addr> addr which frps is listening for, example: 0.0.0.0:7000
-h --help show this screen
-v --version show version
`
func main() { func main() {
var err error sub.Execute()
confFile := "./frpc.ini"
// the configures parsed from file will be replaced by those from command line if exist
args, err := docopt.Parse(usage, nil, true, version.Full(), false)
if args["-c"] != nil {
confFile = args["-c"].(string)
}
conf, err := ini.LoadFile(confFile)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
config.ClientCommonCfg, err = config.LoadClientCommonConf(conf)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
config.ClientCommonCfg.ConfigFile = confFile
// check if reload command
if args["reload"] != nil {
if args["reload"].(bool) {
if err = CmdReload(); err != nil {
fmt.Printf("frpc reload error: %v\n", err)
os.Exit(1)
} else {
fmt.Printf("reload success\n")
os.Exit(0)
}
}
}
// check if status command
if args["status"] != nil {
if args["status"].(bool) {
if err = CmdStatus(); err != nil {
fmt.Printf("frpc get status error: %v\n", err)
os.Exit(1)
} else {
os.Exit(0)
}
}
}
if args["-L"] != nil {
if args["-L"].(string) == "console" {
config.ClientCommonCfg.LogWay = "console"
} else {
config.ClientCommonCfg.LogWay = "file"
config.ClientCommonCfg.LogFile = args["-L"].(string)
}
}
if args["--log-level"] != nil {
config.ClientCommonCfg.LogLevel = args["--log-level"].(string)
}
if args["--server-addr"] != nil {
addr := strings.Split(args["--server-addr"].(string), ":")
if len(addr) != 2 {
fmt.Println("--server-addr format error: example 0.0.0.0:7000")
os.Exit(1)
}
serverPort, err := strconv.ParseInt(addr[1], 10, 64)
if err != nil {
fmt.Println("--server-addr format error, example 0.0.0.0:7000")
os.Exit(1)
}
config.ClientCommonCfg.ServerAddr = addr[0]
config.ClientCommonCfg.ServerPort = int(serverPort)
}
if args["-v"] != nil {
if args["-v"].(bool) {
fmt.Println(version.Full())
os.Exit(0)
}
}
pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromFile(config.ClientCommonCfg.User, conf, config.ClientCommonCfg.Start)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
log.InitLog(config.ClientCommonCfg.LogWay, config.ClientCommonCfg.LogFile,
config.ClientCommonCfg.LogLevel, config.ClientCommonCfg.LogMaxDays)
svr := client.NewService(pxyCfgs, visitorCfgs)
// Capture the exit signal if we use kcp.
if config.ClientCommonCfg.Protocol == "kcp" {
go HandleSignal(svr)
}
err = svr.Run()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func HandleSignal(svr *client.Service) {
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
<-ch
svr.Close()
time.Sleep(250 * time.Millisecond)
os.Exit(0)
}
func CmdReload() error {
if config.ClientCommonCfg.AdminPort == 0 {
return fmt.Errorf("admin_port shoud be set if you want to use reload feature")
}
req, err := http.NewRequest("GET", "http://"+
config.ClientCommonCfg.AdminAddr+":"+fmt.Sprintf("%d", config.ClientCommonCfg.AdminPort)+"/api/reload", nil)
if err != nil {
return err
}
authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(config.ClientCommonCfg.AdminUser+":"+
config.ClientCommonCfg.AdminPwd))
req.Header.Add("Authorization", authStr)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
} else {
if resp.StatusCode != 200 {
return fmt.Errorf("admin api status code [%d]", resp.StatusCode)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
res := &client.GeneralResponse{}
err = json.Unmarshal(body, &res)
if err != nil {
return fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(string(body)))
} else if res.Code != 0 {
return fmt.Errorf(res.Msg)
}
}
return nil
}
func CmdStatus() error {
if config.ClientCommonCfg.AdminPort == 0 {
return fmt.Errorf("admin_port shoud be set if you want to get proxy status")
}
req, err := http.NewRequest("GET", "http://"+
config.ClientCommonCfg.AdminAddr+":"+fmt.Sprintf("%d", config.ClientCommonCfg.AdminPort)+"/api/status", nil)
if err != nil {
return err
}
authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(config.ClientCommonCfg.AdminUser+":"+
config.ClientCommonCfg.AdminPwd))
req.Header.Add("Authorization", authStr)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
} else {
if resp.StatusCode != 200 {
return fmt.Errorf("admin api status code [%d]", resp.StatusCode)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
res := &client.StatusResp{}
err = json.Unmarshal(body, &res)
if err != nil {
return fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(string(body)))
}
fmt.Println("Proxy Status...")
if len(res.Tcp) > 0 {
fmt.Printf("TCP")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Tcp {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
if len(res.Udp) > 0 {
fmt.Printf("UDP")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Udp {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
if len(res.Http) > 0 {
fmt.Printf("HTTP")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Http {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
if len(res.Https) > 0 {
fmt.Printf("HTTPS")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Https {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
if len(res.Stcp) > 0 {
fmt.Printf("STCP")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Stcp {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
if len(res.Xtcp) > 0 {
fmt.Printf("XTCP")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Xtcp {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
}
return nil
} }
// Copyright 2018 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sub
import (
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/consts"
)
func init() {
httpCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address")
httpCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user")
httpCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp")
httpCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token")
httpCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
httpCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path")
httpCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days")
httpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name")
httpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip")
httpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port")
httpCmd.PersistentFlags().StringVarP(&customDomains, "custom_domain", "d", "", "custom domain")
httpCmd.PersistentFlags().StringVarP(&subDomain, "sd", "", "", "sub domain")
httpCmd.PersistentFlags().StringVarP(&locations, "locations", "", "", "locations")
httpCmd.PersistentFlags().StringVarP(&httpUser, "http_user", "", "admin", "http auth user")
httpCmd.PersistentFlags().StringVarP(&httpPwd, "http_pwd", "", "admin", "http auth password")
httpCmd.PersistentFlags().StringVarP(&hostHeaderRewrite, "host_header_rewrite", "", "", "host header rewrite")
httpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
httpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
rootCmd.AddCommand(httpCmd)
}
var httpCmd = &cobra.Command{
Use: "http",
Short: "Run frpc with a single http proxy",
RunE: func(cmd *cobra.Command, args []string) error {
err := parseClientCommonCfg(CfgFileTypeCmd, "")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
cfg := &config.HttpProxyConf{}
var prefix string
if user != "" {
prefix = user + "."
}
cfg.ProxyName = prefix + proxyName
cfg.ProxyType = consts.HttpProxy
cfg.LocalIp = localIp
cfg.LocalPort = localPort
cfg.CustomDomains = strings.Split(customDomains, ",")
cfg.SubDomain = subDomain
cfg.Locations = strings.Split(locations, ",")
cfg.HttpUser = httpUser
cfg.HttpPwd = httpPwd
cfg.HostHeaderRewrite = hostHeaderRewrite
cfg.UseEncryption = useEncryption
cfg.UseCompression = useCompression
err = cfg.CheckForCli()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
proxyConfs := map[string]config.ProxyConf{
cfg.ProxyName: cfg,
}
err = startService(proxyConfs, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
return nil
},
}
// Copyright 2018 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sub
import (
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/consts"
)
func init() {
httpsCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address")
httpsCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user")
httpsCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp")
httpsCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token")
httpsCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
httpsCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path")
httpsCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days")
httpsCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name")
httpsCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip")
httpsCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port")
httpsCmd.PersistentFlags().StringVarP(&customDomains, "custom_domain", "d", "", "custom domain")
httpsCmd.PersistentFlags().StringVarP(&subDomain, "sd", "", "", "sub domain")
httpsCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
httpsCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
rootCmd.AddCommand(httpsCmd)
}
var httpsCmd = &cobra.Command{
Use: "https",
Short: "Run frpc with a single https proxy",
RunE: func(cmd *cobra.Command, args []string) error {
err := parseClientCommonCfg(CfgFileTypeCmd, "")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
cfg := &config.HttpsProxyConf{}
var prefix string
if user != "" {
prefix = user + "."
}
cfg.ProxyName = prefix + proxyName
cfg.ProxyType = consts.HttpsProxy
cfg.LocalIp = localIp
cfg.LocalPort = localPort
cfg.CustomDomains = strings.Split(customDomains, ",")
cfg.SubDomain = subDomain
cfg.UseEncryption = useEncryption
cfg.UseCompression = useCompression
err = cfg.CheckForCli()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
proxyConfs := map[string]config.ProxyConf{
cfg.ProxyName: cfg,
}
err = startService(proxyConfs, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
return nil
},
}
// Copyright 2018 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sub
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
"github.com/spf13/cobra"
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/g"
)
func init() {
rootCmd.AddCommand(reloadCmd)
}
var reloadCmd = &cobra.Command{
Use: "reload",
Short: "Hot-Reload frpc configuration",
RunE: func(cmd *cobra.Command, args []string) error {
err := parseClientCommonCfg(CfgFileTypeIni, cfgFile)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = reload()
if err != nil {
fmt.Printf("frpc reload error: %v\n", err)
os.Exit(1)
}
fmt.Printf("reload success\n")
return nil
},
}
func reload() error {
if g.GlbClientCfg.AdminPort == 0 {
return fmt.Errorf("admin_port shoud be set if you want to use reload feature")
}
req, err := http.NewRequest("GET", "http://"+
g.GlbClientCfg.AdminAddr+":"+fmt.Sprintf("%d", g.GlbClientCfg.AdminPort)+"/api/reload", nil)
if err != nil {
return err
}
authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(g.GlbClientCfg.AdminUser+":"+
g.GlbClientCfg.AdminPwd))
req.Header.Add("Authorization", authStr)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
} else {
if resp.StatusCode != 200 {
return fmt.Errorf("admin api status code [%d]", resp.StatusCode)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
res := &client.GeneralResponse{}
err = json.Unmarshal(body, &res)
if err != nil {
return fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(string(body)))
} else if res.Code != 0 {
return fmt.Errorf(res.Msg)
}
}
return nil
}
// Copyright 2018 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sub
import (
"fmt"
"io/ioutil"
"os"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
"github.com/spf13/cobra"
ini "github.com/vaughan0/go-ini"
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/utils/log"
"github.com/fatedier/frp/utils/version"
)
const (
CfgFileTypeIni = iota
CfgFileTypeCmd
)
var (
cfgFile string
showVersion bool
serverAddr string
user string
protocol string
token string
logLevel string
logFile string
logMaxDays int
proxyName string
localIp string
localPort int
remotePort int
useEncryption bool
useCompression bool
customDomains string
subDomain string
httpUser string
httpPwd string
locations string
hostHeaderRewrite string
role string
sk string
serverName string
bindAddr string
)
func init() {
rootCmd.PersistentFlags().StringVarP(&cfgFile, "", "c", "./frpc.ini", "config file of frpc")
rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc")
}
var rootCmd = &cobra.Command{
Use: "frpc",
Short: "frpc is the client of frp (https://github.com/fatedier/frp)",
RunE: func(cmd *cobra.Command, args []string) error {
if showVersion {
fmt.Println(version.Full())
return nil
}
// Do not show command usage here.
err := runClient(cfgFile)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
return nil
},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}
func handleSignal(svr *client.Service) {
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
<-ch
svr.Close()
time.Sleep(250 * time.Millisecond)
os.Exit(0)
}
func parseClientCommonCfg(fileType int, filePath string) (err error) {
if fileType == CfgFileTypeIni {
err = parseClientCommonCfgFromIni(filePath)
} else if fileType == CfgFileTypeCmd {
err = parseClientCommonCfgFromCmd()
}
if err != nil {
return
}
g.GlbClientCfg.CfgFile = cfgFile
err = g.GlbClientCfg.ClientCommonConf.Check()
if err != nil {
return
}
return
}
func parseClientCommonCfgFromIni(filePath string) (err error) {
b, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
content := string(b)
cfg, err := config.UnmarshalClientConfFromIni(&g.GlbClientCfg.ClientCommonConf, content)
if err != nil {
return err
}
g.GlbClientCfg.ClientCommonConf = *cfg
return
}
func parseClientCommonCfgFromCmd() (err error) {
strs := strings.Split(serverAddr, ":")
if len(strs) < 2 {
err = fmt.Errorf("invalid server_addr")
return
}
if strs[0] != "" {
g.GlbClientCfg.ServerAddr = strs[0]
}
g.GlbClientCfg.ServerPort, err = strconv.Atoi(strs[1])
if err != nil {
err = fmt.Errorf("invalid server_addr")
return
}
g.GlbClientCfg.User = user
g.GlbClientCfg.Protocol = protocol
g.GlbClientCfg.Token = token
g.GlbClientCfg.LogLevel = logLevel
g.GlbClientCfg.LogFile = logFile
g.GlbClientCfg.LogMaxDays = int64(logMaxDays)
return nil
}
func runClient(cfgFilePath string) (err error) {
err = parseClientCommonCfg(CfgFileTypeIni, cfgFilePath)
if err != nil {
return
}
conf, err := ini.LoadFile(cfgFilePath)
if err != nil {
return err
}
pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromIni(g.GlbClientCfg.User, conf, g.GlbClientCfg.Start)
if err != nil {
return err
}
err = startService(pxyCfgs, visitorCfgs)
return
}
func startService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.ProxyConf) (err error) {
log.InitLog(g.GlbClientCfg.LogWay, g.GlbClientCfg.LogFile, g.GlbClientCfg.LogLevel, g.GlbClientCfg.LogMaxDays)
svr := client.NewService(pxyCfgs, visitorCfgs)
// Capture the exit signal if we use kcp.
if g.GlbClientCfg.Protocol == "kcp" {
go handleSignal(svr)
}
err = svr.Run()
return
}
// Copyright 2018 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sub
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
"github.com/rodaine/table"
"github.com/spf13/cobra"
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/g"
)
func init() {
rootCmd.AddCommand(statusCmd)
}
var statusCmd = &cobra.Command{
Use: "status",
Short: "Overview of all proxies status",
RunE: func(cmd *cobra.Command, args []string) error {
err := parseClientCommonCfg(CfgFileTypeIni, cfgFile)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = status()
if err != nil {
fmt.Printf("frpc get status error: %v\n", err)
os.Exit(1)
}
return nil
},
}
func status() error {
if g.GlbClientCfg.AdminPort == 0 {
return fmt.Errorf("admin_port shoud be set if you want to get proxy status")
}
req, err := http.NewRequest("GET", "http://"+
g.GlbClientCfg.AdminAddr+":"+fmt.Sprintf("%d", g.GlbClientCfg.AdminPort)+"/api/status", nil)
if err != nil {
return err
}
authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(g.GlbClientCfg.AdminUser+":"+
g.GlbClientCfg.AdminPwd))
req.Header.Add("Authorization", authStr)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
} else {
if resp.StatusCode != 200 {
return fmt.Errorf("admin api status code [%d]", resp.StatusCode)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
res := &client.StatusResp{}
err = json.Unmarshal(body, &res)
if err != nil {
return fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(string(body)))
}
fmt.Println("Proxy Status...")
if len(res.Tcp) > 0 {
fmt.Printf("TCP")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Tcp {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
if len(res.Udp) > 0 {
fmt.Printf("UDP")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Udp {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
if len(res.Http) > 0 {
fmt.Printf("HTTP")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Http {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
if len(res.Https) > 0 {
fmt.Printf("HTTPS")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Https {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
if len(res.Stcp) > 0 {
fmt.Printf("STCP")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Stcp {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
if len(res.Xtcp) > 0 {
fmt.Printf("XTCP")
tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error")
for _, ps := range res.Xtcp {
tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err)
}
tbl.Print()
fmt.Println("")
}
}
return nil
}
// Copyright 2018 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sub
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/consts"
)
func init() {
stcpCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address")
stcpCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user")
stcpCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp")
stcpCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token")
stcpCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
stcpCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path")
stcpCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days")
stcpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name")
stcpCmd.PersistentFlags().StringVarP(&role, "role", "", "server", "role")
stcpCmd.PersistentFlags().StringVarP(&sk, "sk", "", "", "secret key")
stcpCmd.PersistentFlags().StringVarP(&serverName, "server_name", "", "", "server name")
stcpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip")
stcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port")
stcpCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "", "", "bind addr")
stcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
stcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
rootCmd.AddCommand(stcpCmd)
}
var stcpCmd = &cobra.Command{
Use: "http",
Short: "Run frpc with a single http proxy",
RunE: func(cmd *cobra.Command, args []string) error {
err := parseClientCommonCfg(CfgFileTypeCmd, "")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
cfg := &config.StcpProxyConf{}
var prefix string
if user != "" {
prefix = user + "."
}
cfg.ProxyName = prefix + proxyName
cfg.ProxyType = consts.StcpProxy
cfg.Role = role
cfg.Sk = sk
cfg.ServerName = serverName
cfg.LocalIp = localIp
cfg.LocalPort = localPort
cfg.BindAddr = bindAddr
cfg.UseEncryption = useEncryption
cfg.UseCompression = useCompression
err = cfg.CheckForCli()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if cfg.Role == "server" {
proxyConfs := map[string]config.ProxyConf{
cfg.ProxyName: cfg,
}
err = startService(proxyConfs, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
} else {
visitorConfs := map[string]config.ProxyConf{
cfg.ProxyName: cfg,
}
err = startService(nil, visitorConfs)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
return nil
},
}
// Copyright 2018 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sub
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/consts"
)
func init() {
tcpCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address")
tcpCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user")
tcpCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp")
tcpCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token")
tcpCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
tcpCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path")
tcpCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days")
tcpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name")
tcpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip")
tcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port")
tcpCmd.PersistentFlags().IntVarP(&remotePort, "remote_port", "r", 0, "remote port")
tcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
tcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
rootCmd.AddCommand(tcpCmd)
}
var tcpCmd = &cobra.Command{
Use: "tcp",
Short: "Run frpc with a single tcp proxy",
RunE: func(cmd *cobra.Command, args []string) error {
err := parseClientCommonCfg(CfgFileTypeCmd, "")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
cfg := &config.TcpProxyConf{}
var prefix string
if user != "" {
prefix = user + "."
}
cfg.ProxyName = prefix + proxyName
cfg.ProxyType = consts.TcpProxy
cfg.LocalIp = localIp
cfg.LocalPort = localPort
cfg.RemotePort = remotePort
cfg.UseEncryption = useEncryption
cfg.UseCompression = useCompression
err = cfg.CheckForCli()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
proxyConfs := map[string]config.ProxyConf{
cfg.ProxyName: cfg,
}
err = startService(proxyConfs, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
return nil
},
}
// Copyright 2018 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sub
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/consts"
)
func init() {
udpCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address")
udpCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user")
udpCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp")
udpCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token")
udpCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
udpCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path")
udpCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days")
udpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name")
udpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip")
udpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port")
udpCmd.PersistentFlags().IntVarP(&remotePort, "remote_port", "r", 0, "remote port")
udpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
udpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
rootCmd.AddCommand(udpCmd)
}
var udpCmd = &cobra.Command{
Use: "udp",
Short: "Run frpc with a single udp proxy",
RunE: func(cmd *cobra.Command, args []string) error {
err := parseClientCommonCfg(CfgFileTypeCmd, "")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
cfg := &config.UdpProxyConf{}
var prefix string
if user != "" {
prefix = user + "."
}
cfg.ProxyName = prefix + proxyName
cfg.ProxyType = consts.UdpProxy
cfg.LocalIp = localIp
cfg.LocalPort = localPort
cfg.RemotePort = remotePort
cfg.UseEncryption = useEncryption
cfg.UseCompression = useCompression
err = cfg.CheckForCli()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
proxyConfs := map[string]config.ProxyConf{
cfg.ProxyName: cfg,
}
err = startService(proxyConfs, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
return nil
},
}
// Copyright 2018 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sub
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/consts"
)
func init() {
xtcpCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address")
xtcpCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user")
xtcpCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp")
xtcpCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token")
xtcpCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
xtcpCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path")
xtcpCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days")
xtcpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name")
xtcpCmd.PersistentFlags().StringVarP(&role, "role", "", "server", "role")
xtcpCmd.PersistentFlags().StringVarP(&sk, "sk", "", "", "secret key")
xtcpCmd.PersistentFlags().StringVarP(&serverName, "server_name", "", "", "server name")
xtcpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip")
xtcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port")
xtcpCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "", "", "bind addr")
xtcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
xtcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
rootCmd.AddCommand(xtcpCmd)
}
var xtcpCmd = &cobra.Command{
Use: "http",
Short: "Run frpc with a single http proxy",
RunE: func(cmd *cobra.Command, args []string) error {
err := parseClientCommonCfg(CfgFileTypeCmd, "")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
cfg := &config.XtcpProxyConf{}
var prefix string
if user != "" {
prefix = user + "."
}
cfg.ProxyName = prefix + proxyName
cfg.ProxyType = consts.XtcpProxy
cfg.Role = role
cfg.Sk = sk
cfg.ServerName = serverName
cfg.LocalIp = localIp
cfg.LocalPort = localPort
cfg.BindAddr = bindAddr
cfg.UseEncryption = useEncryption
cfg.UseCompression = useCompression
err = cfg.CheckForCli()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if cfg.Role == "server" {
proxyConfs := map[string]config.ProxyConf{
cfg.ProxyName: cfg,
}
err = startService(proxyConfs, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
} else {
visitorConfs := map[string]config.ProxyConf{
cfg.ProxyName: cfg,
}
err = startService(nil, visitorConfs)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
return nil
},
}
// Copyright 2016 fatedier, fatedier@gmail.com // Copyright 2018 fatedier, fatedier@gmail.com
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
...@@ -14,105 +14,6 @@ ...@@ -14,105 +14,6 @@
package main package main
import (
"fmt"
"os"
"strconv"
"strings"
docopt "github.com/docopt/docopt-go"
ini "github.com/vaughan0/go-ini"
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/server"
"github.com/fatedier/frp/utils/log"
"github.com/fatedier/frp/utils/version"
)
var usage string = `frps is the server of frp
Usage:
frps [-c config_file] [-L log_file] [--log-level=<log_level>] [--addr=<bind_addr>]
frps -h | --help
frps -v | --version
Options:
-c config_file set config file
-L log_file set output log file, including console
--log-level=<log_level> set log level: debug, info, warn, error
--addr=<bind_addr> listen addr for client, example: 0.0.0.0:7000
-h --help show this screen
-v --version show version
`
func main() { func main() {
var err error Execute()
confFile := "./frps.ini"
// the configures parsed from file will be replaced by those from command line if exist
args, err := docopt.Parse(usage, nil, true, version.Full(), false)
if args["-c"] != nil {
confFile = args["-c"].(string)
}
conf, err := ini.LoadFile(confFile)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
config.ServerCommonCfg, err = config.LoadServerCommonConf(conf)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if args["-L"] != nil {
if args["-L"].(string) == "console" {
config.ServerCommonCfg.LogWay = "console"
} else {
config.ServerCommonCfg.LogWay = "file"
config.ServerCommonCfg.LogFile = args["-L"].(string)
}
}
if args["--log-level"] != nil {
config.ServerCommonCfg.LogLevel = args["--log-level"].(string)
}
if args["--addr"] != nil {
addr := strings.Split(args["--addr"].(string), ":")
if len(addr) != 2 {
fmt.Println("--addr format error: example 0.0.0.0:7000")
os.Exit(1)
}
bindPort, err := strconv.ParseInt(addr[1], 10, 64)
if err != nil {
fmt.Println("--addr format error, example 0.0.0.0:7000")
os.Exit(1)
}
config.ServerCommonCfg.BindAddr = addr[0]
config.ServerCommonCfg.BindPort = int(bindPort)
}
if args["-v"] != nil {
if args["-v"].(bool) {
fmt.Println(version.Full())
os.Exit(0)
}
}
log.InitLog(config.ServerCommonCfg.LogWay, config.ServerCommonCfg.LogFile,
config.ServerCommonCfg.LogLevel, config.ServerCommonCfg.LogMaxDays)
svr, err := server.NewService()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
log.Info("Start frps success")
if config.ServerCommonCfg.PrivilegeMode == true {
log.Info("PrivilegeMode is enabled, you should pay more attention to security issues")
}
server.ServerService = svr
svr.Run()
} }
package main
import (
"fmt"
"io/ioutil"
"os"
"github.com/spf13/cobra"
"github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/server"
"github.com/fatedier/frp/utils/log"
"github.com/fatedier/frp/utils/version"
)
const (
CfgFileTypeIni = iota
CfgFileTypeCmd
)
var (
cfgFile string
showVersion bool
bindAddr string
bindPort int
bindUdpPort int
kcpBindPort int
proxyBindAddr string
vhostHttpPort int
vhostHttpsPort int
dashboardAddr string
dashboardPort int
dashboardUser string
dashboardPwd string
assetsDir string
logFile string
logWay string
logLevel string
logMaxDays int64
token string
authTimeout int64
subDomainHost string
tcpMux bool
allowPorts string
maxPoolCount int64
maxPortsPerClient int64
)
func init() {
rootCmd.PersistentFlags().StringVarP(&cfgFile, "", "c", "", "config file of frps")
rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc")
rootCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "h", "0.0.0.0", "bind address")
rootCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "p", 7000, "bind port")
rootCmd.PersistentFlags().IntVarP(&bindUdpPort, "bind_udp_port", "", 0, "bind udp port")
rootCmd.PersistentFlags().IntVarP(&kcpBindPort, "kcp_bind_port", "", 0, "kcp bind udp port")
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().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")
rootCmd.PersistentFlags().StringVarP(&dashboardPwd, "dashboard_pwd", "", "admin", "dashboard password")
rootCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "log file")
rootCmd.PersistentFlags().StringVarP(&logWay, "log_way", "", "console", "log way")
rootCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
rootCmd.PersistentFlags().Int64VarP(&logMaxDays, "log_max_days", "", 3, "log_max_days")
rootCmd.PersistentFlags().StringVarP(&token, "token", "", "", "auth token")
rootCmd.PersistentFlags().Int64VarP(&authTimeout, "auth_timeout", "", 900, "auth timeout")
rootCmd.PersistentFlags().StringVarP(&subDomainHost, "subdomain_host", "", "", "subdomain host")
rootCmd.PersistentFlags().Int64VarP(&maxPortsPerClient, "max_ports_per_client", "", 0, "max ports per client")
}
var rootCmd = &cobra.Command{
Use: "frps",
Short: "frps is the server of frp (https://github.com/fatedier/frp)",
RunE: func(cmd *cobra.Command, args []string) error {
if showVersion {
fmt.Println(version.Full())
return nil
}
if cfgFile != "" {
parseServerCommonCfg(CfgFileTypeIni, cfgFile)
} else {
parseServerCommonCfg(CfgFileTypeCmd, "")
}
err := runServer()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
return nil
},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}
func parseServerCommonCfg(fileType int, filePath string) (err error) {
if fileType == CfgFileTypeIni {
err = parseServerCommonCfgFromIni(filePath)
} else if fileType == CfgFileTypeCmd {
err = parseServerCommonCfgFromCmd()
}
if err != nil {
return
}
g.GlbServerCfg.CfgFile = cfgFile
err = g.GlbServerCfg.ServerCommonConf.Check()
if err != nil {
return
}
return
}
func parseServerCommonCfgFromIni(filePath string) (err error) {
b, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
content := string(b)
cfg, err := config.UnmarshalServerConfFromIni(&g.GlbServerCfg.ServerCommonConf, content)
if err != nil {
return err
}
g.GlbServerCfg.ServerCommonConf = *cfg
return
}
func parseServerCommonCfgFromCmd() (err error) {
g.GlbServerCfg.BindAddr = bindAddr
g.GlbServerCfg.BindPort = bindPort
g.GlbServerCfg.BindUdpPort = bindUdpPort
g.GlbServerCfg.KcpBindPort = kcpBindPort
g.GlbServerCfg.ProxyBindAddr = proxyBindAddr
g.GlbServerCfg.VhostHttpPort = vhostHttpPort
g.GlbServerCfg.VhostHttpsPort = vhostHttpsPort
g.GlbServerCfg.DashboardAddr = dashboardAddr
g.GlbServerCfg.DashboardPort = dashboardPort
g.GlbServerCfg.DashboardUser = dashboardUser
g.GlbServerCfg.DashboardPwd = dashboardPwd
g.GlbServerCfg.LogFile = logFile
g.GlbServerCfg.LogWay = logWay
g.GlbServerCfg.LogLevel = logLevel
g.GlbServerCfg.LogMaxDays = logMaxDays
g.GlbServerCfg.Token = token
g.GlbServerCfg.AuthTimeout = authTimeout
g.GlbServerCfg.SubDomainHost = subDomainHost
g.GlbServerCfg.MaxPortsPerClient = maxPortsPerClient
return
}
func runServer() (err error) {
log.InitLog(g.GlbServerCfg.LogWay, g.GlbServerCfg.LogFile, g.GlbServerCfg.LogLevel,
g.GlbServerCfg.LogMaxDays)
svr, err := server.NewService()
if err != nil {
return err
}
log.Info("Start frps success")
server.ServerService = svr
svr.Run()
return
}
...@@ -7,7 +7,7 @@ server_port = 7000 ...@@ -7,7 +7,7 @@ server_port = 7000
# if you want to connect frps by http proxy, you can set http_proxy here or in global environment variables # if you want to connect frps by http proxy, you can set http_proxy here or in global environment variables
# it only works when protocol is tcp # it only works when protocol is tcp
# http_proxy = http://user:pwd@192.168.1.128:8080 # http_proxy = http://user:passwd@192.168.1.128:8080
# console or real logFile path like ./frpc.log # console or real logFile path like ./frpc.log
log_file = ./frpc.log log_file = ./frpc.log
...@@ -18,13 +18,13 @@ log_level = info ...@@ -18,13 +18,13 @@ log_level = info
log_max_days = 3 log_max_days = 3
# for authentication # for authentication
privilege_token = 12345678 token = 12345678
# set admin address for control frpc's action by http api such as reload # set admin address for control frpc's action by http api such as reload
admin_addr = 127.0.0.1 admin_addr = 127.0.0.1
admin_port = 7400 admin_port = 7400
admin_user = admin admin_user = admin
admin_pwd = admin admin_passwd = admin
# connections will be established in advance, default value is zero # connections will be established in advance, default value is zero
pool_count = 5 pool_count = 5
...@@ -109,7 +109,7 @@ use_compression = true ...@@ -109,7 +109,7 @@ use_compression = true
# http username and password are safety certification for http protocol # http username and password are safety certification for http protocol
# if not set, you can access this custom_domains without certification # if not set, you can access this custom_domains without certification
http_user = admin http_user = admin
http_pwd = admin http_passwd = admin
# if domain for frps is frps.com, then you can access [web01] proxy by URL http://test.frps.com # if domain for frps is frps.com, then you can access [web01] proxy by URL http://test.frps.com
subdomain = web01 subdomain = web01
custom_domains = web02.yourdomain.com custom_domains = web02.yourdomain.com
......
...@@ -25,9 +25,9 @@ vhost_https_port = 443 ...@@ -25,9 +25,9 @@ vhost_https_port = 443
dashboard_addr = 0.0.0.0 dashboard_addr = 0.0.0.0
dashboard_port = 7500 dashboard_port = 7500
# dashboard user and pwd for basic auth protect, if not set, both default value is admin # dashboard user and passwd for basic auth protect, if not set, both default value is admin
dashboard_user = admin dashboard_user = admin
dashboard_pwd = admin dashboard_passwd = admin
# dashboard assets directory(only for debug mode) # dashboard assets directory(only for debug mode)
# assets_dir = ./static # assets_dir = ./static
...@@ -39,8 +39,8 @@ log_level = info ...@@ -39,8 +39,8 @@ log_level = info
log_max_days = 3 log_max_days = 3
# privilege mode is the only supported mode since v0.10.0 # auth token
privilege_token = 12345678 token = 12345678
# heartbeat configure, it's not recommended to modify the default value # heartbeat configure, it's not recommended to modify the default value
# the default value of heartbeat_timeout is 90 # the default value of heartbeat_timeout is 90
......
package g
import (
"github.com/fatedier/frp/models/config"
)
var (
GlbClientCfg *ClientCfg
GlbServerCfg *ServerCfg
)
func init() {
GlbClientCfg = &ClientCfg{
ClientCommonConf: *config.GetDefaultClientConf(),
}
GlbServerCfg = &ServerCfg{
ServerCommonConf: *config.GetDefaultServerConf(),
}
}
type ClientCfg struct {
config.ClientCommonConf
CfgFile string
ServerUdpPort int // this is configured by login response from frps
}
type ServerCfg struct {
config.ServerCommonConf
CfgFile string
}
...@@ -23,46 +23,40 @@ import ( ...@@ -23,46 +23,40 @@ import (
ini "github.com/vaughan0/go-ini" ini "github.com/vaughan0/go-ini"
) )
var ClientCommonCfg *ClientCommonConf
// client common config // client common config
type ClientCommonConf struct { type ClientCommonConf struct {
ConfigFile string ServerAddr string `json:"server_addr"`
ServerAddr string ServerPort int `json:"server_port"`
ServerPort int HttpProxy string `json:"http_proxy"`
ServerUdpPort int // this is specified by login response message from frps LogFile string `json:"log_file"`
HttpProxy string LogWay string `json:"log_way"`
LogFile string LogLevel string `json:"log_level"`
LogWay string LogMaxDays int64 `json:"log_max_days"`
LogLevel string Token string `json:"token"`
LogMaxDays int64 AdminAddr string `json:"admin_addr"`
PrivilegeToken string AdminPort int `json:"admin_port"`
AdminAddr string AdminUser string `json:"admin_user"`
AdminPort int AdminPwd string `json:"admin_pwd"`
AdminUser string PoolCount int `json:"pool_count"`
AdminPwd string TcpMux bool `json:"tcp_mux"`
PoolCount int User string `json:"user"`
TcpMux bool LoginFailExit bool `json:"login_fail_exit"`
User string Start map[string]struct{} `json:"start"`
LoginFailExit bool Protocol string `json:"protocol"`
Start map[string]struct{} HeartBeatInterval int64 `json:"heartbeat_interval"`
Protocol string HeartBeatTimeout int64 `json:"heartbeat_timeout"`
HeartBeatInterval int64
HeartBeatTimeout int64
} }
func GetDeaultClientCommonConf() *ClientCommonConf { func GetDefaultClientConf() *ClientCommonConf {
return &ClientCommonConf{ return &ClientCommonConf{
ConfigFile: "./frpc.ini",
ServerAddr: "0.0.0.0", ServerAddr: "0.0.0.0",
ServerPort: 7000, ServerPort: 7000,
ServerUdpPort: 0, HttpProxy: os.Getenv("http_proxy"),
HttpProxy: "",
LogFile: "console", LogFile: "console",
LogWay: "console", LogWay: "console",
LogLevel: "info", LogLevel: "info",
LogMaxDays: 3, LogMaxDays: 3,
PrivilegeToken: "", Token: "",
AdminAddr: "127.0.0.1", AdminAddr: "127.0.0.1",
AdminPort: 0, AdminPort: 0,
AdminUser: "", AdminUser: "",
...@@ -78,21 +72,28 @@ func GetDeaultClientCommonConf() *ClientCommonConf { ...@@ -78,21 +72,28 @@ func GetDeaultClientCommonConf() *ClientCommonConf {
} }
} }
func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { func UnmarshalClientConfFromIni(defaultCfg *ClientCommonConf, content string) (cfg *ClientCommonConf, err error) {
cfg = defaultCfg
if cfg == nil {
cfg = GetDefaultClientConf()
}
conf, err := ini.Load(strings.NewReader(content))
if err != nil {
err = fmt.Errorf("parse ini conf file error: %v", err)
return nil, err
}
var ( var (
tmpStr string tmpStr string
ok bool ok bool
v int64 v int64
) )
cfg = GetDeaultClientCommonConf() if tmpStr, ok = conf.Get("common", "server_addr"); ok {
tmpStr, ok = conf.Get("common", "server_addr")
if ok {
cfg.ServerAddr = tmpStr cfg.ServerAddr = tmpStr
} }
tmpStr, ok = conf.Get("common", "server_port") if tmpStr, ok = conf.Get("common", "server_port"); ok {
if ok {
v, err = strconv.ParseInt(tmpStr, 10, 64) v, err = strconv.ParseInt(tmpStr, 10, 64)
if err != nil { if err != nil {
err = fmt.Errorf("Parse conf error: invalid server_port") err = fmt.Errorf("Parse conf error: invalid server_port")
...@@ -101,16 +102,11 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { ...@@ -101,16 +102,11 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) {
cfg.ServerPort = int(v) cfg.ServerPort = int(v)
} }
tmpStr, ok = conf.Get("common", "http_proxy") if tmpStr, ok = conf.Get("common", "http_proxy"); ok {
if ok {
cfg.HttpProxy = tmpStr cfg.HttpProxy = tmpStr
} else {
// get http_proxy from env
cfg.HttpProxy = os.Getenv("http_proxy")
} }
tmpStr, ok = conf.Get("common", "log_file") if tmpStr, ok = conf.Get("common", "log_file"); ok {
if ok {
cfg.LogFile = tmpStr cfg.LogFile = tmpStr
if cfg.LogFile == "console" { if cfg.LogFile == "console" {
cfg.LogWay = "console" cfg.LogWay = "console"
...@@ -119,30 +115,25 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { ...@@ -119,30 +115,25 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) {
} }
} }
tmpStr, ok = conf.Get("common", "log_level") if tmpStr, ok = conf.Get("common", "log_level"); ok {
if ok {
cfg.LogLevel = tmpStr cfg.LogLevel = tmpStr
} }
tmpStr, ok = conf.Get("common", "log_max_days") if tmpStr, ok = conf.Get("common", "log_max_days"); ok {
if ok {
if v, err = strconv.ParseInt(tmpStr, 10, 64); err == nil { if v, err = strconv.ParseInt(tmpStr, 10, 64); err == nil {
cfg.LogMaxDays = v cfg.LogMaxDays = v
} }
} }
tmpStr, ok = conf.Get("common", "privilege_token") if tmpStr, ok = conf.Get("common", "token"); ok {
if ok { cfg.Token = tmpStr
cfg.PrivilegeToken = tmpStr
} }
tmpStr, ok = conf.Get("common", "admin_addr") if tmpStr, ok = conf.Get("common", "admin_addr"); ok {
if ok {
cfg.AdminAddr = tmpStr cfg.AdminAddr = tmpStr
} }
tmpStr, ok = conf.Get("common", "admin_port") if tmpStr, ok = conf.Get("common", "admin_port"); ok {
if ok {
if v, err = strconv.ParseInt(tmpStr, 10, 64); err == nil { if v, err = strconv.ParseInt(tmpStr, 10, 64); err == nil {
cfg.AdminPort = int(v) cfg.AdminPort = int(v)
} else { } else {
...@@ -151,55 +142,44 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { ...@@ -151,55 +142,44 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) {
} }
} }
tmpStr, ok = conf.Get("common", "admin_user") if tmpStr, ok = conf.Get("common", "admin_user"); ok {
if ok {
cfg.AdminUser = tmpStr cfg.AdminUser = tmpStr
} }
tmpStr, ok = conf.Get("common", "admin_pwd") if tmpStr, ok = conf.Get("common", "admin_pwd"); ok {
if ok {
cfg.AdminPwd = tmpStr cfg.AdminPwd = tmpStr
} }
tmpStr, ok = conf.Get("common", "pool_count") if tmpStr, ok = conf.Get("common", "pool_count"); ok {
if ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err == nil {
v, err = strconv.ParseInt(tmpStr, 10, 64)
if err != nil {
cfg.PoolCount = 1
} else {
cfg.PoolCount = int(v) cfg.PoolCount = int(v)
} }
} }
tmpStr, ok = conf.Get("common", "tcp_mux") if tmpStr, ok = conf.Get("common", "tcp_mux"); ok && tmpStr == "false" {
if ok && tmpStr == "false" {
cfg.TcpMux = false cfg.TcpMux = false
} else { } else {
cfg.TcpMux = true cfg.TcpMux = true
} }
tmpStr, ok = conf.Get("common", "user") if tmpStr, ok = conf.Get("common", "user"); ok {
if ok {
cfg.User = tmpStr cfg.User = tmpStr
} }
tmpStr, ok = conf.Get("common", "start") if tmpStr, ok = conf.Get("common", "start"); ok {
if ok {
proxyNames := strings.Split(tmpStr, ",") proxyNames := strings.Split(tmpStr, ",")
for _, name := range proxyNames { for _, name := range proxyNames {
cfg.Start[strings.TrimSpace(name)] = struct{}{} cfg.Start[strings.TrimSpace(name)] = struct{}{}
} }
} }
tmpStr, ok = conf.Get("common", "login_fail_exit") if tmpStr, ok = conf.Get("common", "login_fail_exit"); ok && tmpStr == "false" {
if ok && tmpStr == "false" {
cfg.LoginFailExit = false cfg.LoginFailExit = false
} else { } else {
cfg.LoginFailExit = true cfg.LoginFailExit = true
} }
tmpStr, ok = conf.Get("common", "protocol") if tmpStr, ok = conf.Get("common", "protocol"); ok {
if ok {
// Now it only support tcp and kcp. // Now it only support tcp and kcp.
if tmpStr != "kcp" { if tmpStr != "kcp" {
tmpStr = "tcp" tmpStr = "tcp"
...@@ -207,10 +187,8 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { ...@@ -207,10 +187,8 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) {
cfg.Protocol = tmpStr cfg.Protocol = tmpStr
} }
tmpStr, ok = conf.Get("common", "heartbeat_timeout") if tmpStr, ok = conf.Get("common", "heartbeat_timeout"); ok {
if ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
v, err = strconv.ParseInt(tmpStr, 10, 64)
if err != nil {
err = fmt.Errorf("Parse conf error: invalid heartbeat_timeout") err = fmt.Errorf("Parse conf error: invalid heartbeat_timeout")
return return
} else { } else {
...@@ -218,17 +196,18 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { ...@@ -218,17 +196,18 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) {
} }
} }
tmpStr, ok = conf.Get("common", "heartbeat_interval") if tmpStr, ok = conf.Get("common", "heartbeat_interval"); ok {
if ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
v, err = strconv.ParseInt(tmpStr, 10, 64)
if err != nil {
err = fmt.Errorf("Parse conf error: invalid heartbeat_interval") err = fmt.Errorf("Parse conf error: invalid heartbeat_interval")
return return
} else { } else {
cfg.HeartBeatInterval = v cfg.HeartBeatInterval = v
} }
} }
return
}
func (cfg *ClientCommonConf) Check() (err error) {
if cfg.HeartBeatInterval <= 0 { if cfg.HeartBeatInterval <= 0 {
err = fmt.Errorf("Parse conf error: invalid heartbeat_interval") err = fmt.Errorf("Parse conf error: invalid heartbeat_interval")
return return
......
此差异已折叠。
...@@ -24,49 +24,59 @@ import ( ...@@ -24,49 +24,59 @@ import (
"github.com/fatedier/frp/utils/util" "github.com/fatedier/frp/utils/util"
) )
var ServerCommonCfg *ServerCommonConf var (
// server global configure used for generate proxy conf used in frps
proxyBindAddr string
subDomainHost string
vhostHttpPort int
vhostHttpsPort int
)
func InitServerCfg(cfg *ServerCommonConf) {
proxyBindAddr = cfg.ProxyBindAddr
subDomainHost = cfg.SubDomainHost
vhostHttpPort = cfg.VhostHttpPort
vhostHttpsPort = cfg.VhostHttpsPort
}
// common config // common config
type ServerCommonConf struct { type ServerCommonConf struct {
ConfigFile string BindAddr string `json:"bind_addr"`
BindAddr string BindPort int `json:"bind_port"`
BindPort int BindUdpPort int `json:"bind_udp_port"`
BindUdpPort int KcpBindPort int `json:"kcp_bind_port"`
KcpBindPort int ProxyBindAddr string `json:"proxy_bind_addr"`
ProxyBindAddr string
// If VhostHttpPort equals 0, don't listen a public port for http protocol. // If VhostHttpPort equals 0, don't listen a public port for http protocol.
VhostHttpPort int VhostHttpPort int `json:"vhost_http_port"`
// if VhostHttpsPort equals 0, don't listen a public port for https protocol // if VhostHttpsPort equals 0, don't listen a public port for https protocol
VhostHttpsPort int VhostHttpsPort int `json:"vhost_http_port"`
DashboardAddr string DashboardAddr string `json:"dashboard_addr"`
// if DashboardPort equals 0, dashboard is not available // if DashboardPort equals 0, dashboard is not available
DashboardPort int DashboardPort int `json:"dashboard_port"`
DashboardUser string DashboardUser string `json:"dashboard_user"`
DashboardPwd string DashboardPwd string `json:"dashboard_pwd"`
AssetsDir string AssetsDir string `json:"asserts_dir"`
LogFile string LogFile string `json:"log_file"`
LogWay string // console or file LogWay string `json:"log_way"` // console or file
LogLevel string LogLevel string `json:"log_level"`
LogMaxDays int64 LogMaxDays int64 `json:"log_max_days"`
PrivilegeMode bool Token string `json:"token"`
PrivilegeToken string AuthTimeout int64 `json:"auth_timeout"`
AuthTimeout int64 SubDomainHost string `json:"subdomain_host"`
SubDomainHost string TcpMux bool `json:"tcp_mux"`
TcpMux bool
PrivilegeAllowPorts map[int]struct{} PrivilegeAllowPorts map[int]struct{}
MaxPoolCount int64 MaxPoolCount int64 `json:"max_pool_count"`
MaxPortsPerClient int64 MaxPortsPerClient int64 `json:"max_ports_per_client"`
HeartBeatTimeout int64 HeartBeatTimeout int64 `json:"heart_beat_timeout"`
UserConnTimeout int64 UserConnTimeout int64 `json:"user_conn_timeout"`
} }
func GetDefaultServerCommonConf() *ServerCommonConf { func GetDefaultServerConf() *ServerCommonConf {
return &ServerCommonConf{ return &ServerCommonConf{
ConfigFile: "./frps.ini",
BindAddr: "0.0.0.0", BindAddr: "0.0.0.0",
BindPort: 7000, BindPort: 7000,
BindUdpPort: 0, BindUdpPort: 0,
...@@ -83,8 +93,7 @@ func GetDefaultServerCommonConf() *ServerCommonConf { ...@@ -83,8 +93,7 @@ func GetDefaultServerCommonConf() *ServerCommonConf {
LogWay: "console", LogWay: "console",
LogLevel: "info", LogLevel: "info",
LogMaxDays: 3, LogMaxDays: 3,
PrivilegeMode: true, Token: "",
PrivilegeToken: "",
AuthTimeout: 900, AuthTimeout: 900,
SubDomainHost: "", SubDomainHost: "",
TcpMux: true, TcpMux: true,
...@@ -96,22 +105,28 @@ func GetDefaultServerCommonConf() *ServerCommonConf { ...@@ -96,22 +105,28 @@ func GetDefaultServerCommonConf() *ServerCommonConf {
} }
} }
// Load server common configure. func UnmarshalServerConfFromIni(defaultCfg *ServerCommonConf, content string) (cfg *ServerCommonConf, err error) {
func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { cfg = defaultCfg
if cfg == nil {
cfg = GetDefaultServerConf()
}
conf, err := ini.Load(strings.NewReader(content))
if err != nil {
err = fmt.Errorf("parse ini conf file error: %v", err)
return nil, err
}
var ( var (
tmpStr string tmpStr string
ok bool ok bool
v int64 v int64
) )
cfg = GetDefaultServerCommonConf() if tmpStr, ok = conf.Get("common", "bind_addr"); ok {
tmpStr, ok = conf.Get("common", "bind_addr")
if ok {
cfg.BindAddr = tmpStr cfg.BindAddr = tmpStr
} }
tmpStr, ok = conf.Get("common", "bind_port") if tmpStr, ok = conf.Get("common", "bind_port"); ok {
if ok {
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
err = fmt.Errorf("Parse conf error: invalid bind_port") err = fmt.Errorf("Parse conf error: invalid bind_port")
return return
...@@ -120,8 +135,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -120,8 +135,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
} }
} }
tmpStr, ok = conf.Get("common", "bind_udp_port") if tmpStr, ok = conf.Get("common", "bind_udp_port"); ok {
if ok {
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
err = fmt.Errorf("Parse conf error: invalid bind_udp_port") err = fmt.Errorf("Parse conf error: invalid bind_udp_port")
return return
...@@ -130,8 +144,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -130,8 +144,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
} }
} }
tmpStr, ok = conf.Get("common", "kcp_bind_port") if tmpStr, ok = conf.Get("common", "kcp_bind_port"); ok {
if ok {
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
err = fmt.Errorf("Parse conf error: invalid kcp_bind_port") err = fmt.Errorf("Parse conf error: invalid kcp_bind_port")
return return
...@@ -140,15 +153,13 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -140,15 +153,13 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
} }
} }
tmpStr, ok = conf.Get("common", "proxy_bind_addr") if tmpStr, ok = conf.Get("common", "proxy_bind_addr"); ok {
if ok {
cfg.ProxyBindAddr = tmpStr cfg.ProxyBindAddr = tmpStr
} else { } else {
cfg.ProxyBindAddr = cfg.BindAddr cfg.ProxyBindAddr = cfg.BindAddr
} }
tmpStr, ok = conf.Get("common", "vhost_http_port") if tmpStr, ok = conf.Get("common", "vhost_http_port"); ok {
if ok {
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
err = fmt.Errorf("Parse conf error: invalid vhost_http_port") err = fmt.Errorf("Parse conf error: invalid vhost_http_port")
return return
...@@ -159,8 +170,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -159,8 +170,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
cfg.VhostHttpPort = 0 cfg.VhostHttpPort = 0
} }
tmpStr, ok = conf.Get("common", "vhost_https_port") if tmpStr, ok = conf.Get("common", "vhost_https_port"); ok {
if ok {
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
err = fmt.Errorf("Parse conf error: invalid vhost_https_port") err = fmt.Errorf("Parse conf error: invalid vhost_https_port")
return return
...@@ -171,15 +181,13 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -171,15 +181,13 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
cfg.VhostHttpsPort = 0 cfg.VhostHttpsPort = 0
} }
tmpStr, ok = conf.Get("common", "dashboard_addr") if tmpStr, ok = conf.Get("common", "dashboard_addr"); ok {
if ok {
cfg.DashboardAddr = tmpStr cfg.DashboardAddr = tmpStr
} else { } else {
cfg.DashboardAddr = cfg.BindAddr cfg.DashboardAddr = cfg.BindAddr
} }
tmpStr, ok = conf.Get("common", "dashboard_port") if tmpStr, ok = conf.Get("common", "dashboard_port"); ok {
if ok {
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
err = fmt.Errorf("Parse conf error: invalid dashboard_port") err = fmt.Errorf("Parse conf error: invalid dashboard_port")
return return
...@@ -190,23 +198,19 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -190,23 +198,19 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
cfg.DashboardPort = 0 cfg.DashboardPort = 0
} }
tmpStr, ok = conf.Get("common", "dashboard_user") if tmpStr, ok = conf.Get("common", "dashboard_user"); ok {
if ok {
cfg.DashboardUser = tmpStr cfg.DashboardUser = tmpStr
} }
tmpStr, ok = conf.Get("common", "dashboard_pwd") if tmpStr, ok = conf.Get("common", "dashboard_pwd"); ok {
if ok {
cfg.DashboardPwd = tmpStr cfg.DashboardPwd = tmpStr
} }
tmpStr, ok = conf.Get("common", "assets_dir") if tmpStr, ok = conf.Get("common", "assets_dir"); ok {
if ok {
cfg.AssetsDir = tmpStr cfg.AssetsDir = tmpStr
} }
tmpStr, ok = conf.Get("common", "log_file") if tmpStr, ok = conf.Get("common", "log_file"); ok {
if ok {
cfg.LogFile = tmpStr cfg.LogFile = tmpStr
if cfg.LogFile == "console" { if cfg.LogFile == "console" {
cfg.LogWay = "console" cfg.LogWay = "console"
...@@ -215,47 +219,33 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -215,47 +219,33 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
} }
} }
tmpStr, ok = conf.Get("common", "log_level") if tmpStr, ok = conf.Get("common", "log_level"); ok {
if ok {
cfg.LogLevel = tmpStr cfg.LogLevel = tmpStr
} }
tmpStr, ok = conf.Get("common", "log_max_days") if tmpStr, ok = conf.Get("common", "log_max_days"); ok {
if ok {
v, err = strconv.ParseInt(tmpStr, 10, 64) v, err = strconv.ParseInt(tmpStr, 10, 64)
if err == nil { if err == nil {
cfg.LogMaxDays = v cfg.LogMaxDays = v
} }
} }
tmpStr, ok = conf.Get("common", "privilege_mode") cfg.Token, _ = conf.Get("common", "token")
if ok {
if tmpStr == "true" {
cfg.PrivilegeMode = true
}
}
// PrivilegeMode configure
if cfg.PrivilegeMode == true {
cfg.PrivilegeToken, _ = conf.Get("common", "privilege_token")
allowPortsStr, ok := conf.Get("common", "privilege_allow_ports") if allowPortsStr, ok := conf.Get("common", "privilege_allow_ports"); ok {
if ok { // e.g. 1000-2000,2001,2002,3000-4000
// e.g. 1000-2000,2001,2002,3000-4000 ports, errRet := util.ParseRangeNumbers(allowPortsStr)
ports, errRet := util.ParseRangeNumbers(allowPortsStr) if errRet != nil {
if errRet != nil { err = fmt.Errorf("Parse conf error: privilege_allow_ports: %v", errRet)
err = fmt.Errorf("Parse conf error: privilege_allow_ports: %v", errRet) return
return }
}
for _, port := range ports { for _, port := range ports {
cfg.PrivilegeAllowPorts[int(port)] = struct{}{} cfg.PrivilegeAllowPorts[int(port)] = struct{}{}
}
} }
} }
tmpStr, ok = conf.Get("common", "max_pool_count") if tmpStr, ok = conf.Get("common", "max_pool_count"); ok {
if ok {
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
err = fmt.Errorf("Parse conf error: invalid max_pool_count") err = fmt.Errorf("Parse conf error: invalid max_pool_count")
return return
...@@ -268,8 +258,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -268,8 +258,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
} }
} }
tmpStr, ok = conf.Get("common", "max_ports_per_client") if tmpStr, ok = conf.Get("common", "max_ports_per_client"); ok {
if ok {
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
err = fmt.Errorf("Parse conf error: invalid max_ports_per_client") err = fmt.Errorf("Parse conf error: invalid max_ports_per_client")
return return
...@@ -282,8 +271,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -282,8 +271,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
} }
} }
tmpStr, ok = conf.Get("common", "authentication_timeout") if tmpStr, ok = conf.Get("common", "authentication_timeout"); ok {
if ok {
v, errRet := strconv.ParseInt(tmpStr, 10, 64) v, errRet := strconv.ParseInt(tmpStr, 10, 64)
if errRet != nil { if errRet != nil {
err = fmt.Errorf("Parse conf error: authentication_timeout is incorrect") err = fmt.Errorf("Parse conf error: authentication_timeout is incorrect")
...@@ -293,20 +281,17 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -293,20 +281,17 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
} }
} }
tmpStr, ok = conf.Get("common", "subdomain_host") if tmpStr, ok = conf.Get("common", "subdomain_host"); ok {
if ok {
cfg.SubDomainHost = strings.ToLower(strings.TrimSpace(tmpStr)) cfg.SubDomainHost = strings.ToLower(strings.TrimSpace(tmpStr))
} }
tmpStr, ok = conf.Get("common", "tcp_mux") if tmpStr, ok = conf.Get("common", "tcp_mux"); ok && tmpStr == "false" {
if ok && tmpStr == "false" {
cfg.TcpMux = false cfg.TcpMux = false
} else { } else {
cfg.TcpMux = true cfg.TcpMux = true
} }
tmpStr, ok = conf.Get("common", "heartbeat_timeout") if tmpStr, ok = conf.Get("common", "heartbeat_timeout"); ok {
if ok {
v, errRet := strconv.ParseInt(tmpStr, 10, 64) v, errRet := strconv.ParseInt(tmpStr, 10, 64)
if errRet != nil { if errRet != nil {
err = fmt.Errorf("Parse conf error: heartbeat_timeout is incorrect") err = fmt.Errorf("Parse conf error: heartbeat_timeout is incorrect")
...@@ -317,3 +302,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { ...@@ -317,3 +302,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
} }
return return
} }
func (cfg *ServerCommonConf) Check() (err error) {
return
}
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/consts" "github.com/fatedier/frp/models/consts"
"github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/models/msg"
...@@ -103,7 +104,7 @@ func (ctl *Control) Start() { ...@@ -103,7 +104,7 @@ func (ctl *Control) Start() {
loginRespMsg := &msg.LoginResp{ loginRespMsg := &msg.LoginResp{
Version: version.Full(), Version: version.Full(),
RunId: ctl.runId, RunId: ctl.runId,
ServerUdpPort: config.ServerCommonCfg.BindUdpPort, ServerUdpPort: g.GlbServerCfg.BindUdpPort,
Error: "", Error: "",
} }
msg.WriteMsg(ctl.conn, loginRespMsg) msg.WriteMsg(ctl.conn, loginRespMsg)
...@@ -172,7 +173,7 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) { ...@@ -172,7 +173,7 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) {
return return
} }
case <-time.After(time.Duration(config.ServerCommonCfg.UserConnTimeout) * time.Second): case <-time.After(time.Duration(g.GlbServerCfg.UserConnTimeout) * time.Second):
err = fmt.Errorf("timeout trying to get work connection") err = fmt.Errorf("timeout trying to get work connection")
ctl.conn.Warn("%v", err) ctl.conn.Warn("%v", err)
return return
...@@ -202,7 +203,7 @@ func (ctl *Control) writer() { ...@@ -202,7 +203,7 @@ func (ctl *Control) writer() {
defer ctl.allShutdown.Start() defer ctl.allShutdown.Start()
defer ctl.writerShutdown.Done() defer ctl.writerShutdown.Done()
encWriter, err := crypto.NewWriter(ctl.conn, []byte(config.ServerCommonCfg.PrivilegeToken)) encWriter, err := crypto.NewWriter(ctl.conn, []byte(g.GlbServerCfg.Token))
if err != nil { if err != nil {
ctl.conn.Error("crypto new writer error: %v", err) ctl.conn.Error("crypto new writer error: %v", err)
ctl.allShutdown.Start() ctl.allShutdown.Start()
...@@ -231,7 +232,7 @@ func (ctl *Control) reader() { ...@@ -231,7 +232,7 @@ func (ctl *Control) reader() {
defer ctl.allShutdown.Start() defer ctl.allShutdown.Start()
defer ctl.readerShutdown.Done() defer ctl.readerShutdown.Done()
encReader := crypto.NewReader(ctl.conn, []byte(config.ServerCommonCfg.PrivilegeToken)) encReader := crypto.NewReader(ctl.conn, []byte(g.GlbServerCfg.Token))
for { for {
if m, err := msg.ReadMsg(encReader); err != nil { if m, err := msg.ReadMsg(encReader); err != nil {
if err == io.EOF { if err == io.EOF {
...@@ -301,7 +302,7 @@ func (ctl *Control) manager() { ...@@ -301,7 +302,7 @@ func (ctl *Control) manager() {
for { for {
select { select {
case <-heartbeat.C: case <-heartbeat.C:
if time.Since(ctl.lastPing) > time.Duration(config.ServerCommonCfg.HeartBeatTimeout)*time.Second { if time.Since(ctl.lastPing) > time.Duration(g.GlbServerCfg.HeartBeatTimeout)*time.Second {
ctl.conn.Warn("heartbeat timeout") ctl.conn.Warn("heartbeat timeout")
ctl.allShutdown.Start() ctl.allShutdown.Start()
return return
...@@ -342,7 +343,7 @@ func (ctl *Control) manager() { ...@@ -342,7 +343,7 @@ func (ctl *Control) manager() {
func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err error) { func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err error) {
var pxyConf config.ProxyConf var pxyConf config.ProxyConf
// Load configures from NewProxy message and check. // Load configures from NewProxy message and check.
pxyConf, err = config.NewProxyConf(pxyMsg) pxyConf, err = config.NewProxyConfFromMsg(pxyMsg)
if err != nil { if err != nil {
return return
} }
...@@ -355,9 +356,9 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err ...@@ -355,9 +356,9 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
} }
// Check ports used number in each client // Check ports used number in each client
if config.ServerCommonCfg.MaxPortsPerClient > 0 { if g.GlbServerCfg.MaxPortsPerClient > 0 {
ctl.mu.Lock() ctl.mu.Lock()
if ctl.portsUsedNum+pxy.GetUsedPortsNum() > int(config.ServerCommonCfg.MaxPortsPerClient) { if ctl.portsUsedNum+pxy.GetUsedPortsNum() > int(g.GlbServerCfg.MaxPortsPerClient) {
ctl.mu.Unlock() ctl.mu.Unlock()
err = fmt.Errorf("exceed the max_ports_per_client") err = fmt.Errorf("exceed the max_ports_per_client")
return return
...@@ -404,7 +405,7 @@ func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) { ...@@ -404,7 +405,7 @@ func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) {
return return
} }
if config.ServerCommonCfg.MaxPortsPerClient > 0 { if g.GlbServerCfg.MaxPortsPerClient > 0 {
ctl.portsUsedNum = ctl.portsUsedNum - pxy.GetUsedPortsNum() ctl.portsUsedNum = ctl.portsUsedNum - pxy.GetUsedPortsNum()
} }
pxy.Close() pxy.Close()
......
...@@ -21,7 +21,7 @@ import ( ...@@ -21,7 +21,7 @@ import (
"time" "time"
"github.com/fatedier/frp/assets" "github.com/fatedier/frp/assets"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/g"
frpNet "github.com/fatedier/frp/utils/net" frpNet "github.com/fatedier/frp/utils/net"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
...@@ -36,7 +36,7 @@ func RunDashboardServer(addr string, port int) (err error) { ...@@ -36,7 +36,7 @@ func RunDashboardServer(addr string, port int) (err error) {
// url router // url router
router := httprouter.New() router := httprouter.New()
user, passwd := config.ServerCommonCfg.DashboardUser, config.ServerCommonCfg.DashboardPwd user, passwd := g.GlbServerCfg.DashboardUser, g.GlbServerCfg.DashboardPwd
// api, see dashboard_api.go // api, see dashboard_api.go
router.GET("/api/serverinfo", frpNet.HttprouterBasicAuth(apiServerInfo, user, passwd)) router.GET("/api/serverinfo", frpNet.HttprouterBasicAuth(apiServerInfo, user, passwd))
......
...@@ -18,6 +18,7 @@ import ( ...@@ -18,6 +18,7 @@ import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/consts" "github.com/fatedier/frp/models/consts"
"github.com/fatedier/frp/utils/log" "github.com/fatedier/frp/utils/log"
...@@ -60,7 +61,7 @@ func apiServerInfo(w http.ResponseWriter, r *http.Request, _ httprouter.Params) ...@@ -60,7 +61,7 @@ func apiServerInfo(w http.ResponseWriter, r *http.Request, _ httprouter.Params)
}() }()
log.Info("Http request: [/api/serverinfo]") log.Info("Http request: [/api/serverinfo]")
cfg := config.ServerCommonCfg cfg := &g.GlbServerCfg.ServerCommonConf
serverStats := StatsGetServer() serverStats := StatsGetServer()
res = ServerInfoResp{ res = ServerInfoResp{
Version: version.Full(), Version: version.Full(),
......
...@@ -18,7 +18,7 @@ import ( ...@@ -18,7 +18,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/g"
"github.com/fatedier/frp/utils/log" "github.com/fatedier/frp/utils/log"
"github.com/fatedier/frp/utils/metric" "github.com/fatedier/frp/utils/metric"
) )
...@@ -92,19 +92,19 @@ func StatsClearUselessInfo() { ...@@ -92,19 +92,19 @@ func StatsClearUselessInfo() {
} }
func StatsNewClient() { func StatsNewClient() {
if config.ServerCommonCfg.DashboardPort != 0 { if g.GlbServerCfg.DashboardPort != 0 {
globalStats.ClientCounts.Inc(1) globalStats.ClientCounts.Inc(1)
} }
} }
func StatsCloseClient() { func StatsCloseClient() {
if config.ServerCommonCfg.DashboardPort != 0 { if g.GlbServerCfg.DashboardPort != 0 {
globalStats.ClientCounts.Dec(1) globalStats.ClientCounts.Dec(1)
} }
} }
func StatsNewProxy(name string, proxyType string) { func StatsNewProxy(name string, proxyType string) {
if config.ServerCommonCfg.DashboardPort != 0 { if g.GlbServerCfg.DashboardPort != 0 {
globalStats.mu.Lock() globalStats.mu.Lock()
defer globalStats.mu.Unlock() defer globalStats.mu.Unlock()
counter, ok := globalStats.ProxyTypeCounts[proxyType] counter, ok := globalStats.ProxyTypeCounts[proxyType]
...@@ -130,7 +130,7 @@ func StatsNewProxy(name string, proxyType string) { ...@@ -130,7 +130,7 @@ func StatsNewProxy(name string, proxyType string) {
} }
func StatsCloseProxy(proxyName string, proxyType string) { func StatsCloseProxy(proxyName string, proxyType string) {
if config.ServerCommonCfg.DashboardPort != 0 { if g.GlbServerCfg.DashboardPort != 0 {
globalStats.mu.Lock() globalStats.mu.Lock()
defer globalStats.mu.Unlock() defer globalStats.mu.Unlock()
if counter, ok := globalStats.ProxyTypeCounts[proxyType]; ok { if counter, ok := globalStats.ProxyTypeCounts[proxyType]; ok {
...@@ -143,7 +143,7 @@ func StatsCloseProxy(proxyName string, proxyType string) { ...@@ -143,7 +143,7 @@ func StatsCloseProxy(proxyName string, proxyType string) {
} }
func StatsOpenConnection(name string) { func StatsOpenConnection(name string) {
if config.ServerCommonCfg.DashboardPort != 0 { if g.GlbServerCfg.DashboardPort != 0 {
globalStats.CurConns.Inc(1) globalStats.CurConns.Inc(1)
globalStats.mu.Lock() globalStats.mu.Lock()
...@@ -157,7 +157,7 @@ func StatsOpenConnection(name string) { ...@@ -157,7 +157,7 @@ func StatsOpenConnection(name string) {
} }
func StatsCloseConnection(name string) { func StatsCloseConnection(name string) {
if config.ServerCommonCfg.DashboardPort != 0 { if g.GlbServerCfg.DashboardPort != 0 {
globalStats.CurConns.Dec(1) globalStats.CurConns.Dec(1)
globalStats.mu.Lock() globalStats.mu.Lock()
...@@ -171,7 +171,7 @@ func StatsCloseConnection(name string) { ...@@ -171,7 +171,7 @@ func StatsCloseConnection(name string) {
} }
func StatsAddTrafficIn(name string, trafficIn int64) { func StatsAddTrafficIn(name string, trafficIn int64) {
if config.ServerCommonCfg.DashboardPort != 0 { if g.GlbServerCfg.DashboardPort != 0 {
globalStats.TotalTrafficIn.Inc(trafficIn) globalStats.TotalTrafficIn.Inc(trafficIn)
globalStats.mu.Lock() globalStats.mu.Lock()
...@@ -186,7 +186,7 @@ func StatsAddTrafficIn(name string, trafficIn int64) { ...@@ -186,7 +186,7 @@ func StatsAddTrafficIn(name string, trafficIn int64) {
} }
func StatsAddTrafficOut(name string, trafficOut int64) { func StatsAddTrafficOut(name string, trafficOut int64) {
if config.ServerCommonCfg.DashboardPort != 0 { if g.GlbServerCfg.DashboardPort != 0 {
globalStats.TotalTrafficOut.Inc(trafficOut) globalStats.TotalTrafficOut.Inc(trafficOut)
globalStats.mu.Lock() globalStats.mu.Lock()
......
...@@ -23,6 +23,7 @@ import ( ...@@ -23,6 +23,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/config"
"github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/models/msg"
"github.com/fatedier/frp/models/proto/udp" "github.com/fatedier/frp/models/proto/udp"
...@@ -126,7 +127,7 @@ func (pxy *BaseProxy) startListenHandler(p Proxy, handler func(Proxy, frpNet.Con ...@@ -126,7 +127,7 @@ func (pxy *BaseProxy) startListenHandler(p Proxy, handler func(Proxy, frpNet.Con
func NewProxy(ctl *Control, pxyConf config.ProxyConf) (pxy Proxy, err error) { func NewProxy(ctl *Control, pxyConf config.ProxyConf) (pxy Proxy, err error) {
basePxy := BaseProxy{ basePxy := BaseProxy{
name: pxyConf.GetName(), name: pxyConf.GetBaseInfo().ProxyName,
ctl: ctl, ctl: ctl,
listeners: make([]frpNet.Listener, 0), listeners: make([]frpNet.Listener, 0),
Logger: log.NewPrefixLogger(ctl.runId), Logger: log.NewPrefixLogger(ctl.runId),
...@@ -191,7 +192,7 @@ func (pxy *TcpProxy) Run() (remoteAddr string, err error) { ...@@ -191,7 +192,7 @@ func (pxy *TcpProxy) Run() (remoteAddr string, err error) {
remoteAddr = fmt.Sprintf(":%d", pxy.realPort) remoteAddr = fmt.Sprintf(":%d", pxy.realPort)
pxy.cfg.RemotePort = pxy.realPort pxy.cfg.RemotePort = pxy.realPort
listener, errRet := frpNet.ListenTcp(config.ServerCommonCfg.ProxyBindAddr, pxy.realPort) listener, errRet := frpNet.ListenTcp(g.GlbServerCfg.ProxyBindAddr, pxy.realPort)
if errRet != nil { if errRet != nil {
err = errRet err = errRet
return return
...@@ -244,7 +245,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) { ...@@ -244,7 +245,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) {
} }
tmpDomain := routeConfig.Domain tmpDomain := routeConfig.Domain
tmpLocation := routeConfig.Location tmpLocation := routeConfig.Location
addrs = append(addrs, util.CanonicalAddr(tmpDomain, int(config.ServerCommonCfg.VhostHttpPort))) addrs = append(addrs, util.CanonicalAddr(tmpDomain, int(g.GlbServerCfg.VhostHttpPort)))
pxy.closeFuncs = append(pxy.closeFuncs, func() { pxy.closeFuncs = append(pxy.closeFuncs, func() {
pxy.ctl.svr.httpReverseProxy.UnRegister(tmpDomain, tmpLocation) pxy.ctl.svr.httpReverseProxy.UnRegister(tmpDomain, tmpLocation)
}) })
...@@ -253,7 +254,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) { ...@@ -253,7 +254,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) {
} }
if pxy.cfg.SubDomain != "" { if pxy.cfg.SubDomain != "" {
routeConfig.Domain = pxy.cfg.SubDomain + "." + config.ServerCommonCfg.SubDomainHost routeConfig.Domain = pxy.cfg.SubDomain + "." + g.GlbServerCfg.SubDomainHost
for _, location := range locations { for _, location := range locations {
routeConfig.Location = location routeConfig.Location = location
err = pxy.ctl.svr.httpReverseProxy.Register(routeConfig) err = pxy.ctl.svr.httpReverseProxy.Register(routeConfig)
...@@ -262,7 +263,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) { ...@@ -262,7 +263,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) {
} }
tmpDomain := routeConfig.Domain tmpDomain := routeConfig.Domain
tmpLocation := routeConfig.Location tmpLocation := routeConfig.Location
addrs = append(addrs, util.CanonicalAddr(tmpDomain, int(config.ServerCommonCfg.VhostHttpPort))) addrs = append(addrs, util.CanonicalAddr(tmpDomain, g.GlbServerCfg.VhostHttpPort))
pxy.closeFuncs = append(pxy.closeFuncs, func() { pxy.closeFuncs = append(pxy.closeFuncs, func() {
pxy.ctl.svr.httpReverseProxy.UnRegister(tmpDomain, tmpLocation) pxy.ctl.svr.httpReverseProxy.UnRegister(tmpDomain, tmpLocation)
}) })
...@@ -286,7 +287,7 @@ func (pxy *HttpProxy) GetRealConn() (workConn frpNet.Conn, err error) { ...@@ -286,7 +287,7 @@ func (pxy *HttpProxy) GetRealConn() (workConn frpNet.Conn, err error) {
var rwc io.ReadWriteCloser = tmpConn var rwc io.ReadWriteCloser = tmpConn
if pxy.cfg.UseEncryption { if pxy.cfg.UseEncryption {
rwc, err = frpIo.WithEncryption(rwc, []byte(config.ServerCommonCfg.PrivilegeToken)) rwc, err = frpIo.WithEncryption(rwc, []byte(g.GlbServerCfg.Token))
if err != nil { if err != nil {
pxy.Error("create encryption stream error: %v", err) pxy.Error("create encryption stream error: %v", err)
return return
...@@ -334,11 +335,11 @@ func (pxy *HttpsProxy) Run() (remoteAddr string, err error) { ...@@ -334,11 +335,11 @@ func (pxy *HttpsProxy) Run() (remoteAddr string, err error) {
l.AddLogPrefix(pxy.name) l.AddLogPrefix(pxy.name)
pxy.Info("https proxy listen for host [%s]", routeConfig.Domain) pxy.Info("https proxy listen for host [%s]", routeConfig.Domain)
pxy.listeners = append(pxy.listeners, l) pxy.listeners = append(pxy.listeners, l)
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(config.ServerCommonCfg.VhostHttpsPort))) addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, g.GlbServerCfg.VhostHttpsPort))
} }
if pxy.cfg.SubDomain != "" { if pxy.cfg.SubDomain != "" {
routeConfig.Domain = pxy.cfg.SubDomain + "." + config.ServerCommonCfg.SubDomainHost routeConfig.Domain = pxy.cfg.SubDomain + "." + g.GlbServerCfg.SubDomainHost
l, errRet := pxy.ctl.svr.VhostHttpsMuxer.Listen(routeConfig) l, errRet := pxy.ctl.svr.VhostHttpsMuxer.Listen(routeConfig)
if errRet != nil { if errRet != nil {
err = errRet err = errRet
...@@ -347,7 +348,7 @@ func (pxy *HttpsProxy) Run() (remoteAddr string, err error) { ...@@ -347,7 +348,7 @@ func (pxy *HttpsProxy) Run() (remoteAddr string, err error) {
l.AddLogPrefix(pxy.name) l.AddLogPrefix(pxy.name)
pxy.Info("https proxy listen for host [%s]", routeConfig.Domain) pxy.Info("https proxy listen for host [%s]", routeConfig.Domain)
pxy.listeners = append(pxy.listeners, l) pxy.listeners = append(pxy.listeners, l)
addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(config.ServerCommonCfg.VhostHttpsPort))) addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(g.GlbServerCfg.VhostHttpsPort)))
} }
pxy.startListenHandler(pxy, HandleUserTcpConnection) pxy.startListenHandler(pxy, HandleUserTcpConnection)
...@@ -478,7 +479,7 @@ func (pxy *UdpProxy) Run() (remoteAddr string, err error) { ...@@ -478,7 +479,7 @@ func (pxy *UdpProxy) Run() (remoteAddr string, err error) {
remoteAddr = fmt.Sprintf(":%d", pxy.realPort) remoteAddr = fmt.Sprintf(":%d", pxy.realPort)
pxy.cfg.RemotePort = pxy.realPort pxy.cfg.RemotePort = pxy.realPort
addr, errRet := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", config.ServerCommonCfg.ProxyBindAddr, pxy.realPort)) addr, errRet := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", g.GlbServerCfg.ProxyBindAddr, pxy.realPort))
if errRet != nil { if errRet != nil {
err = errRet err = errRet
return return
...@@ -644,7 +645,7 @@ func HandleUserTcpConnection(pxy Proxy, userConn frpNet.Conn) { ...@@ -644,7 +645,7 @@ func HandleUserTcpConnection(pxy Proxy, userConn frpNet.Conn) {
var local io.ReadWriteCloser = workConn var local io.ReadWriteCloser = workConn
cfg := pxy.GetConf().GetBaseInfo() cfg := pxy.GetConf().GetBaseInfo()
if cfg.UseEncryption { if cfg.UseEncryption {
local, err = frpIo.WithEncryption(local, []byte(config.ServerCommonCfg.PrivilegeToken)) local, err = frpIo.WithEncryption(local, []byte(g.GlbServerCfg.Token))
if err != nil { if err != nil {
pxy.Error("create encryption stream error: %v", err) pxy.Error("create encryption stream error: %v", err)
return return
......
...@@ -21,7 +21,7 @@ import ( ...@@ -21,7 +21,7 @@ import (
"time" "time"
"github.com/fatedier/frp/assets" "github.com/fatedier/frp/assets"
"github.com/fatedier/frp/models/config" "github.com/fatedier/frp/g"
"github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/models/msg"
"github.com/fatedier/frp/utils/log" "github.com/fatedier/frp/utils/log"
frpNet "github.com/fatedier/frp/utils/net" frpNet "github.com/fatedier/frp/utils/net"
...@@ -71,7 +71,7 @@ type Service struct { ...@@ -71,7 +71,7 @@ type Service struct {
} }
func NewService() (svr *Service, err error) { func NewService() (svr *Service, err error) {
cfg := config.ServerCommonCfg cfg := &g.GlbServerCfg.ServerCommonConf
svr = &Service{ svr = &Service{
ctlManager: NewControlManager(), ctlManager: NewControlManager(),
pxyManager: NewProxyManager(), pxyManager: NewProxyManager(),
...@@ -170,7 +170,7 @@ func (svr *Service) Run() { ...@@ -170,7 +170,7 @@ func (svr *Service) Run() {
if svr.natHoleController != nil { if svr.natHoleController != nil {
go svr.natHoleController.Run() go svr.natHoleController.Run()
} }
if config.ServerCommonCfg.KcpBindPort > 0 { if g.GlbServerCfg.KcpBindPort > 0 {
go svr.HandleListener(svr.kcpListener) go svr.HandleListener(svr.kcpListener)
} }
svr.HandleListener(svr.listener) svr.HandleListener(svr.listener)
...@@ -233,7 +233,7 @@ func (svr *Service) HandleListener(l frpNet.Listener) { ...@@ -233,7 +233,7 @@ func (svr *Service) HandleListener(l frpNet.Listener) {
} }
} }
if config.ServerCommonCfg.TcpMux { if g.GlbServerCfg.TcpMux {
session, err := smux.Server(frpConn, nil) session, err := smux.Server(frpConn, nil)
if err != nil { if err != nil {
log.Warn("Failed to create mux connection: %v", err) log.Warn("Failed to create mux connection: %v", err)
...@@ -270,11 +270,11 @@ func (svr *Service) RegisterControl(ctlConn frpNet.Conn, loginMsg *msg.Login) (e ...@@ -270,11 +270,11 @@ func (svr *Service) RegisterControl(ctlConn frpNet.Conn, loginMsg *msg.Login) (e
// Check auth. // Check auth.
nowTime := time.Now().Unix() nowTime := time.Now().Unix()
if config.ServerCommonCfg.AuthTimeout != 0 && nowTime-loginMsg.Timestamp > config.ServerCommonCfg.AuthTimeout { if g.GlbServerCfg.AuthTimeout != 0 && nowTime-loginMsg.Timestamp > g.GlbServerCfg.AuthTimeout {
err = fmt.Errorf("authorization timeout") err = fmt.Errorf("authorization timeout")
return return
} }
if util.GetAuthKey(config.ServerCommonCfg.PrivilegeToken, loginMsg.Timestamp) != loginMsg.PrivilegeKey { if util.GetAuthKey(g.GlbServerCfg.Token, loginMsg.Timestamp) != loginMsg.PrivilegeKey {
err = fmt.Errorf("authorization failed") err = fmt.Errorf("authorization failed")
return return
} }
......
...@@ -4,7 +4,7 @@ server_port = 10700 ...@@ -4,7 +4,7 @@ server_port = 10700
log_file = ./frpc.log log_file = ./frpc.log
# debug, info, warn, error # debug, info, warn, error
log_level = debug log_level = debug
privilege_token = 123456 token = 123456
admin_port = 10600 admin_port = 10600
admin_user = abc admin_user = abc
admin_pwd = abc admin_pwd = abc
......
...@@ -4,7 +4,7 @@ server_port = 10700 ...@@ -4,7 +4,7 @@ server_port = 10700
log_file = ./frpc_visitor.log log_file = ./frpc_visitor.log
# debug, info, warn, error # debug, info, warn, error
log_level = debug log_level = debug
privilege_token = 123456 token = 123456
[stcp_visitor] [stcp_visitor]
type = stcp type = stcp
......
...@@ -4,6 +4,6 @@ bind_port = 10700 ...@@ -4,6 +4,6 @@ bind_port = 10700
vhost_http_port = 10804 vhost_http_port = 10804
log_file = ./frps.log log_file = ./frps.log
log_level = debug log_level = debug
privilege_token = 123456 token = 123456
privilege_allow_ports = 10000-20000,20002,30000-50000 privilege_allow_ports = 10000-20000,20002,30000-50000
subdomain_host = sub.com subdomain_host = sub.com
...@@ -19,7 +19,7 @@ import ( ...@@ -19,7 +19,7 @@ import (
"strings" "strings"
) )
var version string = "0.16.1" var version string = "0.17.0"
func Full() string { func Full() string {
return version return version
......
...@@ -223,7 +223,7 @@ func (c *Controller) RenderBytes() ([]byte, error) { ...@@ -223,7 +223,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
} }
buf.Reset() buf.Reset()
ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath() ,c.Data) ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath(), c.Data)
} }
return buf.Bytes(), err return buf.Bytes(), err
} }
...@@ -249,7 +249,7 @@ func (c *Controller) renderTemplate() (bytes.Buffer, error) { ...@@ -249,7 +249,7 @@ func (c *Controller) renderTemplate() (bytes.Buffer, error) {
} }
} }
} }
BuildTemplate(c.viewPath() , buildFiles...) BuildTemplate(c.viewPath(), buildFiles...)
} }
return buf, ExecuteViewPathTemplate(&buf, c.TplName, c.viewPath(), c.Data) return buf, ExecuteViewPathTemplate(&buf, c.TplName, c.viewPath(), c.Data)
} }
......
...@@ -172,10 +172,10 @@ func TestAdditionalViewPaths(t *testing.T) { ...@@ -172,10 +172,10 @@ func TestAdditionalViewPaths(t *testing.T) {
t.Fatal("TestAdditionalViewPaths expected error") t.Fatal("TestAdditionalViewPaths expected error")
} }
}() }()
ctrl.RenderString(); ctrl.RenderString()
}() }()
ctrl.TplName = "file2.tpl" ctrl.TplName = "file2.tpl"
ctrl.ViewPath = dir2 ctrl.ViewPath = dir2
ctrl.RenderString(); ctrl.RenderString()
} }
...@@ -109,4 +109,3 @@ func signature(project *LogProject, method, uri string, ...@@ -109,4 +109,3 @@ func signature(project *LogProject, method, uri string,
digest = base64.StdEncoding.EncodeToString(mac.Sum(nil)) digest = base64.StdEncoding.EncodeToString(mac.Sum(nil))
return return
} }
...@@ -48,7 +48,7 @@ var ( ...@@ -48,7 +48,7 @@ var (
"lte": true, "lte": true,
"eq": true, "eq": true,
"nq": true, "nq": true,
"ne": true, "ne": true,
"startswith": true, "startswith": true,
"endswith": true, "endswith": true,
"istartswith": true, "istartswith": true,
......
...@@ -31,11 +31,11 @@ import ( ...@@ -31,11 +31,11 @@ import (
) )
var ( var (
beegoTplFuncMap = make(template.FuncMap) beegoTplFuncMap = make(template.FuncMap)
beeViewPathTemplateLocked = false beeViewPathTemplateLocked = false
// beeViewPathTemplates caching map and supported template file extensions per view // beeViewPathTemplates caching map and supported template file extensions per view
beeViewPathTemplates = make(map[string]map[string]*template.Template) beeViewPathTemplates = make(map[string]map[string]*template.Template)
templatesLock sync.RWMutex templatesLock sync.RWMutex
// beeTemplateExt stores the template extension which will build // beeTemplateExt stores the template extension which will build
beeTemplateExt = []string{"tpl", "html"} beeTemplateExt = []string{"tpl", "html"}
// beeTemplatePreprocessors stores associations of extension -> preprocessor handler // beeTemplatePreprocessors stores associations of extension -> preprocessor handler
...@@ -46,7 +46,7 @@ var ( ...@@ -46,7 +46,7 @@ var (
// writing the output to wr. // writing the output to wr.
// A template will be executed safely in parallel. // A template will be executed safely in parallel.
func ExecuteTemplate(wr io.Writer, name string, data interface{}) error { func ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
return ExecuteViewPathTemplate(wr,name, BConfig.WebConfig.ViewsPath, data) return ExecuteViewPathTemplate(wr, name, BConfig.WebConfig.ViewsPath, data)
} }
// ExecuteViewPathTemplate applies the template with name and from specific viewPath to the specified data object, // ExecuteViewPathTemplate applies the template with name and from specific viewPath to the specified data object,
...@@ -57,7 +57,7 @@ func ExecuteViewPathTemplate(wr io.Writer, name string, viewPath string, data in ...@@ -57,7 +57,7 @@ func ExecuteViewPathTemplate(wr io.Writer, name string, viewPath string, data in
templatesLock.RLock() templatesLock.RLock()
defer templatesLock.RUnlock() defer templatesLock.RUnlock()
} }
if beeTemplates,ok := beeViewPathTemplates[viewPath]; ok { if beeTemplates, ok := beeViewPathTemplates[viewPath]; ok {
if t, ok := beeTemplates[name]; ok { if t, ok := beeTemplates[name]; ok {
var err error var err error
if t.Lookup(name) != nil { if t.Lookup(name) != nil {
...@@ -160,9 +160,9 @@ func AddTemplateExt(ext string) { ...@@ -160,9 +160,9 @@ func AddTemplateExt(ext string) {
beeTemplateExt = append(beeTemplateExt, ext) beeTemplateExt = append(beeTemplateExt, ext)
} }
// AddViewPath adds a new path to the supported view paths. // AddViewPath adds a new path to the supported view paths.
//Can later be used by setting a controller ViewPath to this folder //Can later be used by setting a controller ViewPath to this folder
//will panic if called after beego.Run() //will panic if called after beego.Run()
func AddViewPath(viewPath string) error { func AddViewPath(viewPath string) error {
if beeViewPathTemplateLocked { if beeViewPathTemplateLocked {
panic("Can not add new view paths after beego.Run()") panic("Can not add new view paths after beego.Run()")
...@@ -184,7 +184,7 @@ func BuildTemplate(dir string, files ...string) error { ...@@ -184,7 +184,7 @@ func BuildTemplate(dir string, files ...string) error {
} }
return errors.New("dir open err") return errors.New("dir open err")
} }
beeTemplates,ok := beeViewPathTemplates[dir]; beeTemplates, ok := beeViewPathTemplates[dir]
if !ok { if !ok {
panic("Unknown view path: " + dir) panic("Unknown view path: " + dir)
} }
......
...@@ -119,7 +119,7 @@ func (m *URLMap) GetMap() map[string]interface{} { ...@@ -119,7 +119,7 @@ func (m *URLMap) GetMap() map[string]interface{} {
func (m *URLMap) GetMapData() []map[string]interface{} { func (m *URLMap) GetMapData() []map[string]interface{} {
m.lock.Lock() m.lock.Lock()
defer m.lock.Unlock() defer m.lock.Unlock()
var resultLists []map[string]interface{} var resultLists []map[string]interface{}
for k, v := range m.urlmap { for k, v := range m.urlmap {
......
...@@ -12,146 +12,146 @@ import ( ...@@ -12,146 +12,146 @@ import (
type vendor int type vendor int
const ( const (
other vendor = iota other vendor = iota
intel intel
amd amd
via via
transmeta transmeta
nsc nsc
kvm // Kernel-based Virtual Machine kvm // Kernel-based Virtual Machine
msvm // Microsoft Hyper-V or Windows Virtual PC msvm // Microsoft Hyper-V or Windows Virtual PC
vmware vmware
xenhvm xenhvm
) )
const ( const (
cmov = 1 << iota // i686 CMOV cmov = 1 << iota // i686 CMOV
nx // NX (No-Execute) bit nx // NX (No-Execute) bit
amd3dnow // AMD 3DNOW amd3dnow // AMD 3DNOW
amd3dnowext // AMD 3DNowExt amd3dnowext // AMD 3DNowExt
mmx // standard MMX mmx // standard MMX
mmxext // SSE integer functions or AMD MMX ext mmxext // SSE integer functions or AMD MMX ext
sse // SSE functions sse // SSE functions
sse2 // P4 SSE functions sse2 // P4 SSE functions
sse3 // Prescott SSE3 functions sse3 // Prescott SSE3 functions
ssse3 // Conroe SSSE3 functions ssse3 // Conroe SSSE3 functions
sse4 // Penryn SSE4.1 functions sse4 // Penryn SSE4.1 functions
sse4a // AMD Barcelona microarchitecture SSE4a instructions sse4a // AMD Barcelona microarchitecture SSE4a instructions
sse42 // Nehalem SSE4.2 functions sse42 // Nehalem SSE4.2 functions
avx // AVX functions avx // AVX functions
avx2 // AVX2 functions avx2 // AVX2 functions
fma3 // Intel FMA 3 fma3 // Intel FMA 3
fma4 // Bulldozer FMA4 functions fma4 // Bulldozer FMA4 functions
xop // Bulldozer XOP functions xop // Bulldozer XOP functions
f16c // Half-precision floating-point conversion f16c // Half-precision floating-point conversion
bmi1 // Bit Manipulation Instruction Set 1 bmi1 // Bit Manipulation Instruction Set 1
bmi2 // Bit Manipulation Instruction Set 2 bmi2 // Bit Manipulation Instruction Set 2
tbm // AMD Trailing Bit Manipulation tbm // AMD Trailing Bit Manipulation
lzcnt // LZCNT instruction lzcnt // LZCNT instruction
popcnt // POPCNT instruction popcnt // POPCNT instruction
aesni // Advanced Encryption Standard New Instructions aesni // Advanced Encryption Standard New Instructions
clmul // Carry-less Multiplication clmul // Carry-less Multiplication
htt // Hyperthreading (enabled) htt // Hyperthreading (enabled)
hle // Hardware Lock Elision hle // Hardware Lock Elision
rtm // Restricted Transactional Memory rtm // Restricted Transactional Memory
rdrand // RDRAND instruction is available rdrand // RDRAND instruction is available
rdseed // RDSEED instruction is available rdseed // RDSEED instruction is available
adx // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) adx // Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
sha // Intel SHA Extensions sha // Intel SHA Extensions
avx512f // AVX-512 Foundation avx512f // AVX-512 Foundation
avx512dq // AVX-512 Doubleword and Quadword Instructions avx512dq // AVX-512 Doubleword and Quadword Instructions
avx512ifma // AVX-512 Integer Fused Multiply-Add Instructions avx512ifma // AVX-512 Integer Fused Multiply-Add Instructions
avx512pf // AVX-512 Prefetch Instructions avx512pf // AVX-512 Prefetch Instructions
avx512er // AVX-512 Exponential and Reciprocal Instructions avx512er // AVX-512 Exponential and Reciprocal Instructions
avx512cd // AVX-512 Conflict Detection Instructions avx512cd // AVX-512 Conflict Detection Instructions
avx512bw // AVX-512 Byte and Word Instructions avx512bw // AVX-512 Byte and Word Instructions
avx512vl // AVX-512 Vector Length Extensions avx512vl // AVX-512 Vector Length Extensions
avx512vbmi // AVX-512 Vector Bit Manipulation Instructions avx512vbmi // AVX-512 Vector Bit Manipulation Instructions
mpx // Intel MPX (Memory Protection Extensions) mpx // Intel MPX (Memory Protection Extensions)
erms // Enhanced REP MOVSB/STOSB erms // Enhanced REP MOVSB/STOSB
rdtscp // RDTSCP Instruction rdtscp // RDTSCP Instruction
cx16 // CMPXCHG16B Instruction cx16 // CMPXCHG16B Instruction
// Performance indicators // Performance indicators
sse2slow // SSE2 is supported, but usually not faster sse2slow // SSE2 is supported, but usually not faster
sse3slow // SSE3 is supported, but usually not faster sse3slow // SSE3 is supported, but usually not faster
atom // Atom processor, some SSSE3 instructions are slower atom // Atom processor, some SSSE3 instructions are slower
) )
var flagNames = map[flags]string{ var flagNames = map[flags]string{
cmov: "CMOV", // i686 CMOV cmov: "CMOV", // i686 CMOV
nx: "NX", // NX (No-Execute) bit nx: "NX", // NX (No-Execute) bit
amd3dnow: "AMD3DNOW", // AMD 3DNOW amd3dnow: "AMD3DNOW", // AMD 3DNOW
amd3dnowext: "AMD3DNOWEXT", // AMD 3DNowExt amd3dnowext: "AMD3DNOWEXT", // AMD 3DNowExt
mmx: "MMX", // Standard MMX mmx: "MMX", // Standard MMX
mmxext: "MMXEXT", // SSE integer functions or AMD MMX ext mmxext: "MMXEXT", // SSE integer functions or AMD MMX ext
sse: "SSE", // SSE functions sse: "SSE", // SSE functions
sse2: "SSE2", // P4 SSE2 functions sse2: "SSE2", // P4 SSE2 functions
sse3: "SSE3", // Prescott SSE3 functions sse3: "SSE3", // Prescott SSE3 functions
ssse3: "SSSE3", // Conroe SSSE3 functions ssse3: "SSSE3", // Conroe SSSE3 functions
sse4: "SSE4.1", // Penryn SSE4.1 functions sse4: "SSE4.1", // Penryn SSE4.1 functions
sse4a: "SSE4A", // AMD Barcelona microarchitecture SSE4a instructions sse4a: "SSE4A", // AMD Barcelona microarchitecture SSE4a instructions
sse42: "SSE4.2", // Nehalem SSE4.2 functions sse42: "SSE4.2", // Nehalem SSE4.2 functions
avx: "AVX", // AVX functions avx: "AVX", // AVX functions
avx2: "AVX2", // AVX functions avx2: "AVX2", // AVX functions
fma3: "FMA3", // Intel FMA 3 fma3: "FMA3", // Intel FMA 3
fma4: "FMA4", // Bulldozer FMA4 functions fma4: "FMA4", // Bulldozer FMA4 functions
xop: "XOP", // Bulldozer XOP functions xop: "XOP", // Bulldozer XOP functions
f16c: "F16C", // Half-precision floating-point conversion f16c: "F16C", // Half-precision floating-point conversion
bmi1: "BMI1", // Bit Manipulation Instruction Set 1 bmi1: "BMI1", // Bit Manipulation Instruction Set 1
bmi2: "BMI2", // Bit Manipulation Instruction Set 2 bmi2: "BMI2", // Bit Manipulation Instruction Set 2
tbm: "TBM", // AMD Trailing Bit Manipulation tbm: "TBM", // AMD Trailing Bit Manipulation
lzcnt: "LZCNT", // LZCNT instruction lzcnt: "LZCNT", // LZCNT instruction
popcnt: "POPCNT", // POPCNT instruction popcnt: "POPCNT", // POPCNT instruction
aesni: "AESNI", // Advanced Encryption Standard New Instructions aesni: "AESNI", // Advanced Encryption Standard New Instructions
clmul: "CLMUL", // Carry-less Multiplication clmul: "CLMUL", // Carry-less Multiplication
htt: "HTT", // Hyperthreading (enabled) htt: "HTT", // Hyperthreading (enabled)
hle: "HLE", // Hardware Lock Elision hle: "HLE", // Hardware Lock Elision
rtm: "RTM", // Restricted Transactional Memory rtm: "RTM", // Restricted Transactional Memory
rdrand: "RDRAND", // RDRAND instruction is available rdrand: "RDRAND", // RDRAND instruction is available
rdseed: "RDSEED", // RDSEED instruction is available rdseed: "RDSEED", // RDSEED instruction is available
adx: "ADX", // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) adx: "ADX", // Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
sha: "SHA", // Intel SHA Extensions sha: "SHA", // Intel SHA Extensions
avx512f: "AVX512F", // AVX-512 Foundation avx512f: "AVX512F", // AVX-512 Foundation
avx512dq: "AVX512DQ", // AVX-512 Doubleword and Quadword Instructions avx512dq: "AVX512DQ", // AVX-512 Doubleword and Quadword Instructions
avx512ifma: "AVX512IFMA", // AVX-512 Integer Fused Multiply-Add Instructions avx512ifma: "AVX512IFMA", // AVX-512 Integer Fused Multiply-Add Instructions
avx512pf: "AVX512PF", // AVX-512 Prefetch Instructions avx512pf: "AVX512PF", // AVX-512 Prefetch Instructions
avx512er: "AVX512ER", // AVX-512 Exponential and Reciprocal Instructions avx512er: "AVX512ER", // AVX-512 Exponential and Reciprocal Instructions
avx512cd: "AVX512CD", // AVX-512 Conflict Detection Instructions avx512cd: "AVX512CD", // AVX-512 Conflict Detection Instructions
avx512bw: "AVX512BW", // AVX-512 Byte and Word Instructions avx512bw: "AVX512BW", // AVX-512 Byte and Word Instructions
avx512vl: "AVX512VL", // AVX-512 Vector Length Extensions avx512vl: "AVX512VL", // AVX-512 Vector Length Extensions
avx512vbmi: "AVX512VBMI", // AVX-512 Vector Bit Manipulation Instructions avx512vbmi: "AVX512VBMI", // AVX-512 Vector Bit Manipulation Instructions
mpx: "MPX", // Intel MPX (Memory Protection Extensions) mpx: "MPX", // Intel MPX (Memory Protection Extensions)
erms: "ERMS", // Enhanced REP MOVSB/STOSB erms: "ERMS", // Enhanced REP MOVSB/STOSB
rdtscp: "RDTSCP", // RDTSCP Instruction rdtscp: "RDTSCP", // RDTSCP Instruction
cx16: "CX16", // CMPXCHG16B Instruction cx16: "CX16", // CMPXCHG16B Instruction
// Performance indicators // Performance indicators
sse2slow: "SSE2SLOW", // SSE2 supported, but usually not faster sse2slow: "SSE2SLOW", // SSE2 supported, but usually not faster
sse3slow: "SSE3SLOW", // SSE3 supported, but usually not faster sse3slow: "SSE3SLOW", // SSE3 supported, but usually not faster
atom: "ATOM", // Atom processor, some SSSE3 instructions are slower atom: "ATOM", // Atom processor, some SSSE3 instructions are slower
} }
// CPUInfo contains information about the detected system CPU. // CPUInfo contains information about the detected system CPU.
type cpuInfo struct { type cpuInfo struct {
brandname string // Brand name reported by the CPU brandname string // Brand name reported by the CPU
vendorid vendor // Comparable CPU vendor ID vendorid vendor // Comparable CPU vendor ID
features flags // Features of the CPU features flags // Features of the CPU
physicalcores int // Number of physical processor cores in your CPU. Will be 0 if undetectable. physicalcores int // Number of physical processor cores in your CPU. Will be 0 if undetectable.
threadspercore int // Number of threads per physical core. Will be 1 if undetectable. threadspercore int // Number of threads per physical core. Will be 1 if undetectable.
logicalcores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable. logicalcores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable.
family int // CPU family number family int // CPU family number
model int // CPU model number model int // CPU model number
cacheline int // Cache line size in bytes. Will be 0 if undetectable. cacheline int // Cache line size in bytes. Will be 0 if undetectable.
cache struct { cache struct {
l1i int // L1 Instruction Cache (per core or shared). Will be -1 if undetected l1i int // L1 Instruction Cache (per core or shared). Will be -1 if undetected
l1d int // L1 Data Cache (per core or shared). Will be -1 if undetected l1d int // L1 Data Cache (per core or shared). Will be -1 if undetected
l2 int // L2 Cache (per core or shared). Will be -1 if undetected l2 int // L2 Cache (per core or shared). Will be -1 if undetected
l3 int // L3 Instruction Cache (per core or shared). Will be -1 if undetected l3 int // L3 Instruction Cache (per core or shared). Will be -1 if undetected
} }
maxFunc uint32 maxFunc uint32
maxExFunc uint32 maxExFunc uint32
} }
var cpuid func(op uint32) (eax, ebx, ecx, edx uint32) var cpuid func(op uint32) (eax, ebx, ecx, edx uint32)
...@@ -638,18 +638,18 @@ func physicalCores() int { ...@@ -638,18 +638,18 @@ func physicalCores() int {
// Except from http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID // Except from http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID
var vendorMapping = map[string]vendor{ var vendorMapping = map[string]vendor{
"AMDisbetter!": amd, "AMDisbetter!": amd,
"AuthenticAMD": amd, "AuthenticAMD": amd,
"CentaurHauls": via, "CentaurHauls": via,
"GenuineIntel": intel, "GenuineIntel": intel,
"TransmetaCPU": transmeta, "TransmetaCPU": transmeta,
"GenuineTMx86": transmeta, "GenuineTMx86": transmeta,
"Geode by NSC": nsc, "Geode by NSC": nsc,
"VIA VIA VIA ": via, "VIA VIA VIA ": via,
"KVMKVMKVMKVM": kvm, "KVMKVMKVMKVM": kvm,
"Microsoft Hv": msvm, "Microsoft Hv": msvm,
"VMwareVMware": vmware, "VMwareVMware": vmware,
"XenVMMXenVMM": xenhvm, "XenVMMXenVMM": xenhvm,
} }
func vendorID() vendor { func vendorID() vendor {
...@@ -668,10 +668,10 @@ func cacheLine() int { ...@@ -668,10 +668,10 @@ func cacheLine() int {
} }
_, ebx, _, _ := cpuid(1) _, ebx, _, _ := cpuid(1)
cache := (ebx & 0xff00) >> 5 // cflush size cache := (ebx & 0xff00) >> 5 // cflush size
if cache == 0 && maxExtendedFunction() >= 0x80000006 { if cache == 0 && maxExtendedFunction() >= 0x80000006 {
_, _, ecx, _ := cpuid(0x80000006) _, _, ecx, _ := cpuid(0x80000006)
cache = ecx & 0xff // cacheline size cache = ecx & 0xff // cacheline size
} }
// TODO: Read from Cache and TLB Information // TODO: Read from Cache and TLB Information
return int(cache) return int(cache)
......
...@@ -181,7 +181,7 @@ func indentMessageLines(message string, longestLabelLen int) string { ...@@ -181,7 +181,7 @@ func indentMessageLines(message string, longestLabelLen int) string {
// no need to align first line because it starts at the correct location (after the label) // no need to align first line because it starts at the correct location (after the label)
if i != 0 { if i != 0 {
// append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen +1) + "\t") outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
} }
outBuf.WriteString(scanner.Text()) outBuf.WriteString(scanner.Text())
} }
...@@ -229,7 +229,7 @@ func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { ...@@ -229,7 +229,7 @@ func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
} }
type labeledContent struct { type labeledContent struct {
label string label string
content string content string
} }
......
...@@ -250,8 +250,8 @@ func TestEqualFormatting(t *testing.T) { ...@@ -250,8 +250,8 @@ func TestEqualFormatting(t *testing.T) {
msgAndArgs []interface{} msgAndArgs []interface{}
want string want string
}{ }{
{equalWant:"want", equalGot: "got", want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \treceived: \"got\"\n"}, {equalWant: "want", equalGot: "got", want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \treceived: \"got\"\n"},
{equalWant:"want", equalGot: "got", msgAndArgs: []interface{}{"hello, %v!", "world"}, want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \treceived: \"got\"\n\t\t\r\tMessages: \thello, world!\n"}, {equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{"hello, %v!", "world"}, want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \treceived: \"got\"\n\t\t\r\tMessages: \thello, world!\n"},
} { } {
mockT := &bufferT{} mockT := &bufferT{}
Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...) Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...)
......
...@@ -149,7 +149,7 @@ func cryptBlock(subkeys []uint32, b []uint32, r []byte, dst, src []byte, decrypt ...@@ -149,7 +149,7 @@ func cryptBlock(subkeys []uint32, b []uint32, r []byte, dst, src []byte, decrypt
permuteInitialBlock(b, src) permuteInitialBlock(b, src)
for i := 0; i < 32; i++ { for i := 0; i < 32; i++ {
if decrypt { if decrypt {
tm = b[0] ^ l1(p(b[1]^b[2]^b[3]^subkeys[31 - i])) tm = b[0] ^ l1(p(b[1]^b[2]^b[3]^subkeys[31-i]))
// tm = feistel1(b[0], b[1], b[2], b[3], subkeys[31-i]) // tm = feistel1(b[0], b[1], b[2], b[3], subkeys[31-i])
} else { } else {
tm = b[0] ^ l1(p(b[1]^b[2]^b[3]^subkeys[i])) tm = b[0] ^ l1(p(b[1]^b[2]^b[3]^subkeys[i]))
......
...@@ -383,8 +383,8 @@ func init() { ...@@ -383,8 +383,8 @@ func init() {
// 4253 and Oakley Group 2 in RFC 2409. // 4253 and Oakley Group 2 in RFC 2409.
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
g: new(big.Int).SetInt64(2), g: new(big.Int).SetInt64(2),
p: p, p: p,
pMinus1: new(big.Int).Sub(p, bigOne), pMinus1: new(big.Int).Sub(p, bigOne),
} }
...@@ -393,8 +393,8 @@ func init() { ...@@ -393,8 +393,8 @@ func init() {
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
g: new(big.Int).SetInt64(2), g: new(big.Int).SetInt64(2),
p: p, p: p,
pMinus1: new(big.Int).Sub(p, bigOne), pMinus1: new(big.Int).Sub(p, bigOne),
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册