From bc176b90f1ab9f633971e8b051db01802c75e364 Mon Sep 17 00:00:00 2001 From: fatedier Date: Tue, 5 Apr 2016 17:18:21 +0800 Subject: [PATCH] all: change passwd to auth_token and improve authentication --- conf/frpc.ini | 3 ++- conf/frps.ini | 4 ++-- src/frp/cmd/frpc/control.go | 6 +++++- src/frp/cmd/frps/control.go | 16 ++++++++++++---- src/frp/models/client/client.go | 12 +++++++++--- src/frp/models/client/config.go | 15 ++++++++++----- src/frp/models/consts/consts.go | 1 + src/frp/models/msg/msg.go | 3 ++- src/frp/models/server/config.go | 4 ++-- src/frp/models/server/server.go | 18 ++++++++++-------- src/frp/utils/pcrypto/pcrypto.go | 8 ++++++++ 11 files changed, 63 insertions(+), 27 deletions(-) diff --git a/conf/frpc.ini b/conf/frpc.ini index 50a3760..2f48a80 100644 --- a/conf/frpc.ini +++ b/conf/frpc.ini @@ -6,10 +6,11 @@ server_port = 7000 log_file = console # debug, info, warn, error log_level = debug +# for authentication +auth_token = 123 # test1 is the proxy name same as server's configuration [test1] -passwd = 123 local_ip = 127.0.0.1 local_port = 22 # true or false, if true, messages between frps and frpc will be encrypted, default is false diff --git a/conf/frps.ini b/conf/frps.ini index 0358a7a..c410410 100644 --- a/conf/frps.ini +++ b/conf/frps.ini @@ -7,8 +7,8 @@ log_file = console # debug, info, warn, error log_level = debug -# test1 is the proxy name, client will use this name and passwd to connect to server +# test1 is the proxy name, client will use this name and auth_token to connect to server [test1] -passwd = 123 +auth_token = 123 bind_addr = 0.0.0.0 listen_port = 6000 diff --git a/src/frp/cmd/frpc/control.go b/src/frp/cmd/frpc/control.go index 3ca8bad..06a4fda 100644 --- a/src/frp/cmd/frpc/control.go +++ b/src/frp/cmd/frpc/control.go @@ -26,6 +26,7 @@ import ( "frp/models/msg" "frp/utils/conn" "frp/utils/log" + "frp/utils/pcrypto" ) func ControlProcess(cli *client.ProxyClient, wait *sync.WaitGroup) { @@ -130,11 +131,14 @@ func loginToServer(cli *client.ProxyClient) (c *conn.Conn, err error) { return } + nowTime := time.Now().Unix() + authKey := pcrypto.GetAuthKey(cli.Name + cli.AuthToken + fmt.Sprintf("%d", nowTime)) req := &msg.ControlReq{ Type: consts.NewCtlConn, ProxyName: cli.Name, - Passwd: cli.Passwd, + AuthKey: authKey, UseEncryption: cli.UseEncryption, + Timestamp: nowTime, } buf, _ := json.Marshal(req) err = c.Write(string(buf) + "\n") diff --git a/src/frp/cmd/frps/control.go b/src/frp/cmd/frps/control.go index dc2eb53..67cd642 100644 --- a/src/frp/cmd/frps/control.go +++ b/src/frp/cmd/frps/control.go @@ -25,6 +25,7 @@ import ( "frp/models/server" "frp/utils/conn" "frp/utils/log" + "frp/utils/pcrypto" ) func ProcessControlConn(l *conn.Listener) { @@ -197,16 +198,23 @@ func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) { return } - // check password - if req.Passwd != s.Passwd { - info = fmt.Sprintf("ProxyName [%s], password is not correct", req.ProxyName) + // check authKey + nowTime := time.Now().Unix() + authKey := pcrypto.GetAuthKey(req.ProxyName + s.AuthToken + fmt.Sprintf("%d", req.Timestamp)) + // authKey avaiable in 15 minutes + if nowTime-req.Timestamp > 15*60 { + info = fmt.Sprintf("ProxyName [%s], authorization timeout", req.ProxyName) + log.Warn(info) + return + } else if req.AuthKey != authKey { + info = fmt.Sprintf("ProxyName [%s], authorization failed", req.ProxyName) log.Warn(info) return } // control conn if req.Type == consts.NewCtlConn { - if s.Status != consts.Idle { + if s.Status == consts.Working { info = fmt.Sprintf("ProxyName [%s], already in use", req.ProxyName) log.Warn(info) return diff --git a/src/frp/models/client/client.go b/src/frp/models/client/client.go index 8310610..b0b947b 100644 --- a/src/frp/models/client/client.go +++ b/src/frp/models/client/client.go @@ -16,16 +16,19 @@ package client import ( "encoding/json" + "fmt" + "time" "frp/models/consts" "frp/models/msg" "frp/utils/conn" "frp/utils/log" + "frp/utils/pcrypto" ) type ProxyClient struct { Name string - Passwd string + AuthToken string LocalIp string LocalPort int64 UseEncryption bool @@ -52,10 +55,13 @@ func (p *ProxyClient) GetRemoteConn(addr string, port int64) (c *conn.Conn, err return } + nowTime := time.Now().Unix() + authKey := pcrypto.GetAuthKey(p.Name + p.AuthToken + fmt.Sprintf("%d", nowTime)) req := &msg.ControlReq{ Type: consts.NewWorkConn, ProxyName: p.Name, - Passwd: p.Passwd, + AuthKey: authKey, + Timestamp: nowTime, } buf, _ := json.Marshal(req) @@ -83,7 +89,7 @@ func (p *ProxyClient) StartTunnel(serverAddr string, serverPort int64) (err erro log.Debug("Join two connections, (l[%s] r[%s]) (l[%s] r[%s])", localConn.GetLocalAddr(), localConn.GetRemoteAddr(), remoteConn.GetLocalAddr(), remoteConn.GetRemoteAddr()) if p.UseEncryption { - go conn.JoinMore(localConn, remoteConn, p.Passwd) + go conn.JoinMore(localConn, remoteConn, p.AuthToken) } else { go conn.Join(localConn, remoteConn) } diff --git a/src/frp/models/client/config.go b/src/frp/models/client/config.go index 1e94743..3c09c75 100644 --- a/src/frp/models/client/config.go +++ b/src/frp/models/client/config.go @@ -69,6 +69,14 @@ func LoadConf(confFile string) (err error) { LogLevel = tmpStr } + var authToken string + tmpStr, ok = conf.Get("common", "auth_token") + if ok { + authToken = tmpStr + } else { + return fmt.Errorf("auth_token not found") + } + // proxies for name, section := range conf { if name != "common" { @@ -76,11 +84,8 @@ func LoadConf(confFile string) (err error) { // name proxyClient.Name = name - // passwd - proxyClient.Passwd, ok = section["passwd"] - if !ok { - return fmt.Errorf("Parse ini file error: proxy [%s] no passwd found", proxyClient.Name) - } + // auth_token + proxyClient.AuthToken = authToken // local_ip proxyClient.LocalIp, ok = section["local_ip"] diff --git a/src/frp/models/consts/consts.go b/src/frp/models/consts/consts.go index 342046e..7bb0944 100644 --- a/src/frp/models/consts/consts.go +++ b/src/frp/models/consts/consts.go @@ -18,6 +18,7 @@ package consts const ( Idle = iota Working + Closed ) // msg type diff --git a/src/frp/models/msg/msg.go b/src/frp/models/msg/msg.go index 5bc21ed..d1b57ad 100644 --- a/src/frp/models/msg/msg.go +++ b/src/frp/models/msg/msg.go @@ -23,8 +23,9 @@ type GeneralRes struct { type ControlReq struct { Type int64 `json:"type"` ProxyName string `json:"proxy_name,omitempty"` - Passwd string `json:"passwd, omitempty"` + AuthKey string `json:"auth_key, omitempty"` UseEncryption bool `json:"use_encryption, omitempty"` + Timestamp int64 `json:"timestamp, omitempty"` } type ControlRes struct { diff --git a/src/frp/models/server/config.go b/src/frp/models/server/config.go index b2eb63f..23fd969 100644 --- a/src/frp/models/server/config.go +++ b/src/frp/models/server/config.go @@ -75,9 +75,9 @@ func LoadConf(confFile string) (err error) { proxyServer := &ProxyServer{} proxyServer.Name = name - proxyServer.Passwd, ok = section["passwd"] + proxyServer.AuthToken, ok = section["auth_token"] if !ok { - return fmt.Errorf("Parse ini file error: proxy [%s] no passwd found", proxyServer.Name) + return fmt.Errorf("Parse ini file error: proxy [%s] no auth_token found", proxyServer.Name) } proxyServer.BindAddr, ok = section["bind_addr"] diff --git a/src/frp/models/server/server.go b/src/frp/models/server/server.go index 8f285d0..d6e06da 100644 --- a/src/frp/models/server/server.go +++ b/src/frp/models/server/server.go @@ -26,7 +26,7 @@ import ( type ProxyServer struct { Name string - Passwd string + AuthToken string UseEncryption bool BindAddr string ListenPort int64 @@ -135,7 +135,7 @@ func (p *ProxyServer) Start() (err error) { userConn.GetLocalAddr(), userConn.GetRemoteAddr()) if p.UseEncryption { - go conn.JoinMore(userConn, workConn, p.Passwd) + go conn.JoinMore(userConn, workConn, p.AuthToken) } else { go conn.Join(userConn, workConn) } @@ -147,13 +147,15 @@ func (p *ProxyServer) Start() (err error) { func (p *ProxyServer) Close() { p.Lock() - p.Status = consts.Idle - if p.listener != nil { - p.listener.Close() + if p.Status != consts.Closed { + p.Status = consts.Closed + if p.listener != nil { + p.listener.Close() + } + close(p.ctlMsgChan) + close(p.workConnChan) + p.userConnList = list.New() } - close(p.ctlMsgChan) - close(p.workConnChan) - p.userConnList = list.New() p.Unlock() } diff --git a/src/frp/utils/pcrypto/pcrypto.go b/src/frp/utils/pcrypto/pcrypto.go index 2e8ba92..a4772a8 100644 --- a/src/frp/utils/pcrypto/pcrypto.go +++ b/src/frp/utils/pcrypto/pcrypto.go @@ -19,6 +19,7 @@ import ( "compress/gzip" "crypto/aes" "crypto/cipher" + "crypto/md5" "encoding/base64" "encoding/hex" "errors" @@ -105,3 +106,10 @@ func pKCS7UnPadding(origData []byte) []byte { unpadding := int(origData[length-1]) return origData[:(length - unpadding)] } + +func GetAuthKey(str string) (authKey string) { + md5Ctx := md5.New() + md5Ctx.Write([]byte(str)) + md5Str := md5Ctx.Sum(nil) + return hex.EncodeToString(md5Str) +}