فهرست منبع

all: change passwd to auth_token and improve authentication

fatedier 9 سال پیش
والد
کامیت
bc176b90f1

+ 2 - 1
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

+ 2 - 2
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

+ 5 - 1
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")

+ 12 - 4
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

+ 9 - 3
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)
 	}

+ 10 - 5
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"]

+ 1 - 0
src/frp/models/consts/consts.go

@@ -18,6 +18,7 @@ package consts
 const (
 	Idle = iota
 	Working
+	Closed
 )
 
 // msg type

+ 2 - 1
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 {

+ 2 - 2
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"]

+ 10 - 8
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()
 }
 

+ 8 - 0
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)
+}