diff --git a/README.md b/README.md index 1c204d13..14e81ec0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ frp is a fast reverse proxy to help you expose a local server behind a NAT or fi ## Status -frp is under development and you can try it with available version 0.2.0. +frp is under development and you can try it with available version 0.3.0. ## Quick Start diff --git a/conf/frpc.ini b/conf/frpc.ini index 09dfeb75..50a37604 100644 --- a/conf/frpc.ini +++ b/conf/frpc.ini @@ -12,3 +12,5 @@ log_level = debug 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 +use_encryption = true diff --git a/src/frp/cmd/frpc/control.go b/src/frp/cmd/frpc/control.go index 3f3ae7f2..3ca8bada 100644 --- a/src/frp/cmd/frpc/control.go +++ b/src/frp/cmd/frpc/control.go @@ -131,9 +131,10 @@ func loginToServer(cli *client.ProxyClient) (c *conn.Conn, err error) { } req := &msg.ControlReq{ - Type: consts.NewCtlConn, - ProxyName: cli.Name, - Passwd: cli.Passwd, + Type: consts.NewCtlConn, + ProxyName: cli.Name, + Passwd: cli.Passwd, + UseEncryption: cli.UseEncryption, } 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 4402db50..dc2eb53c 100644 --- a/src/frp/cmd/frps/control.go +++ b/src/frp/cmd/frps/control.go @@ -212,6 +212,9 @@ func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) { return } + // set infomations from frpc + s.UseEncryption = req.UseEncryption + // start proxy and listen for user connections, no block err := s.Start() if err != nil { diff --git a/src/frp/models/client/client.go b/src/frp/models/client/client.go index 00164279..8310610e 100644 --- a/src/frp/models/client/client.go +++ b/src/frp/models/client/client.go @@ -24,10 +24,11 @@ import ( ) type ProxyClient struct { - Name string - Passwd string - LocalIp string - LocalPort int64 + Name string + Passwd string + LocalIp string + LocalPort int64 + UseEncryption bool } func (p *ProxyClient) GetLocalConn() (c *conn.Conn, err error) { @@ -81,8 +82,11 @@ func (p *ProxyClient) StartTunnel(serverAddr string, serverPort int64) (err erro // l means local, r means remote log.Debug("Join two connections, (l[%s] r[%s]) (l[%s] r[%s])", localConn.GetLocalAddr(), localConn.GetRemoteAddr(), remoteConn.GetLocalAddr(), remoteConn.GetRemoteAddr()) - // go conn.Join(localConn, remoteConn) - go conn.JoinMore(localConn, remoteConn, p.Passwd) + if p.UseEncryption { + go conn.JoinMore(localConn, remoteConn, p.Passwd) + } else { + go conn.Join(localConn, remoteConn) + } return nil } diff --git a/src/frp/models/client/config.go b/src/frp/models/client/config.go index e41fec82..1e947430 100644 --- a/src/frp/models/client/config.go +++ b/src/frp/models/client/config.go @@ -73,19 +73,23 @@ func LoadConf(confFile string) (err error) { for name, section := range conf { if name != "common" { proxyClient := &ProxyClient{} + // 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) } + // local_ip proxyClient.LocalIp, ok = section["local_ip"] if !ok { // use 127.0.0.1 as default proxyClient.LocalIp = "127.0.0.1" } + // local_port portStr, ok := section["local_port"] if ok { proxyClient.LocalPort, err = strconv.ParseInt(portStr, 10, 64) @@ -96,6 +100,13 @@ func LoadConf(confFile string) (err error) { return fmt.Errorf("Parse ini file error: proxy [%s] local_port not found", proxyClient.Name) } + // use_encryption + proxyClient.UseEncryption = false + useEncryptionStr, ok := section["use_encryption"] + if ok && useEncryptionStr == "true" { + proxyClient.UseEncryption = true + } + ProxyClients[proxyClient.Name] = proxyClient } } diff --git a/src/frp/models/msg/msg.go b/src/frp/models/msg/msg.go index 83b77f6b..5bc21ed2 100644 --- a/src/frp/models/msg/msg.go +++ b/src/frp/models/msg/msg.go @@ -21,9 +21,10 @@ type GeneralRes struct { // messages between control connection of frpc and frps type ControlReq struct { - Type int64 `json:"type"` - ProxyName string `json:"proxy_name,omitempty"` - Passwd string `json:"passwd, omitempty"` + Type int64 `json:"type"` + ProxyName string `json:"proxy_name,omitempty"` + Passwd string `json:"passwd, omitempty"` + UseEncryption bool `json:"use_encryption, omitempty"` } type ControlRes struct { diff --git a/src/frp/models/server/server.go b/src/frp/models/server/server.go index bb6373c3..8f285d05 100644 --- a/src/frp/models/server/server.go +++ b/src/frp/models/server/server.go @@ -25,11 +25,12 @@ import ( ) type ProxyServer struct { - Name string - Passwd string - BindAddr string - ListenPort int64 - Status int64 + Name string + Passwd string + UseEncryption bool + BindAddr string + ListenPort int64 + Status int64 listener *conn.Listener // accept new connection from remote users ctlMsgChan chan int64 // every time accept a new user conn, put "1" to the channel @@ -132,8 +133,12 @@ func (p *ProxyServer) Start() (err error) { // l means local, r means remote log.Debug("Join two connections, (l[%s] r[%s]) (l[%s] r[%s])", workConn.GetLocalAddr(), workConn.GetRemoteAddr(), userConn.GetLocalAddr(), userConn.GetRemoteAddr()) - // go conn.Join(workConn, userConn) - go conn.JoinMore(userConn, workConn, p.Passwd) + + if p.UseEncryption { + go conn.JoinMore(userConn, workConn, p.Passwd) + } else { + go conn.Join(userConn, workConn) + } } }() diff --git a/src/frp/utils/conn/conn.go b/src/frp/utils/conn/conn.go index 0f199cfc..eb064c4a 100644 --- a/src/frp/utils/conn/conn.go +++ b/src/frp/utils/conn/conn.go @@ -164,36 +164,38 @@ func Join(c1 *Conn, c2 *Conn) { return } -func JoinMore(local *Conn, remote *Conn, cryptoKey string) { +// messages from c1 to c2 will be encrypted +// and from c2 to c1 will be decrypted +func JoinMore(c1 *Conn, c2 *Conn, cryptKey string) { var wait sync.WaitGroup - encrypPipe := func(from *Conn, to *Conn, key string) { + encryptPipe := func(from *Conn, to *Conn, key string) { defer from.Close() defer to.Close() defer wait.Done() // we don't care about errors here - PipeEncryptoWriter(from.TcpConn, to.TcpConn, key) + PipeEncrypt(from.TcpConn, to.TcpConn, key) } - decryptoPipe := func(to *Conn, from *Conn, key string) { + decryptPipe := func(to *Conn, from *Conn, key string) { defer from.Close() defer to.Close() defer wait.Done() // we don't care about errors here - PipeDecryptoReader(to.TcpConn, from.TcpConn, key) + PipeDecrypt(to.TcpConn, from.TcpConn, key) } wait.Add(2) - go encrypPipe(local, remote, cryptoKey) - go decryptoPipe(remote, local, cryptoKey) + go encryptPipe(c1, c2, cryptKey) + go decryptPipe(c2, c1, cryptKey) wait.Wait() log.Debug("One tunnel stopped") return } -// decrypto msg from reader, then write into writer -func PipeDecryptoReader(r net.Conn, w net.Conn, key string) error { +// decrypt msg from reader, then write into writer +func PipeDecrypt(r net.Conn, w net.Conn, key string) error { laes := new(pcrypto.Pcrypto) if err := laes.Init([]byte(key)); err != nil { log.Error("Pcrypto Init error: %v", err) @@ -207,10 +209,10 @@ func PipeDecryptoReader(r net.Conn, w net.Conn, key string) error { return err } - res, err := laes.Decrypto(buf) + res, err := laes.Decrypt(buf) if err != nil { - log.Error("Decrypto [%s] error, %v", string(buf), err) - return fmt.Errorf("Decrypto [%s] error: %v", string(buf), err) + log.Error("Decrypt [%s] error, %v", string(buf), err) + return fmt.Errorf("Decrypt [%s] error: %v", string(buf), err) } _, err = w.Write(res) @@ -221,8 +223,8 @@ func PipeDecryptoReader(r net.Conn, w net.Conn, key string) error { return nil } -// recvive msg from reader, then encrypto msg into write -func PipeEncryptoWriter(r net.Conn, w net.Conn, key string) error { +// recvive msg from reader, then encrypt msg into write +func PipeEncrypt(r net.Conn, w net.Conn, key string) error { laes := new(pcrypto.Pcrypto) if err := laes.Init([]byte(key)); err != nil { log.Error("Pcrypto Init error: %v", err) @@ -237,10 +239,10 @@ func PipeEncryptoWriter(r net.Conn, w net.Conn, key string) error { if err != nil { return err } - res, err := laes.Encrypto(buf[:n]) + res, err := laes.Encrypt(buf[:n]) if err != nil { - log.Error("Encrypto error: %v", err) - return fmt.Errorf("Encrypto error: %v", err) + log.Error("Encrypt error: %v", err) + return fmt.Errorf("Encrypt error: %v", err) } res = append(res, '\n') diff --git a/src/frp/utils/pcrypto/pcrypto.go b/src/frp/utils/pcrypto/pcrypto.go index 8a4435e2..c2a25178 100644 --- a/src/frp/utils/pcrypto/pcrypto.go +++ b/src/frp/utils/pcrypto/pcrypto.go @@ -39,7 +39,7 @@ func (pc *Pcrypto) Init(key []byte) error { return err } -func (pc *Pcrypto) Encrypto(src []byte) ([]byte, error) { +func (pc *Pcrypto) Encrypt(src []byte) ([]byte, error) { // aes src = pKCS7Padding(src, aes.BlockSize) blockMode := cipher.NewCBCEncrypter(pc.paes, pc.pkey) @@ -57,7 +57,7 @@ func (pc *Pcrypto) Encrypto(src []byte) ([]byte, error) { return []byte(base64.StdEncoding.EncodeToString(zbuf.Bytes())), nil } -func (pc *Pcrypto) Decrypto(str []byte) ([]byte, error) { +func (pc *Pcrypto) Decrypt(str []byte) ([]byte, error) { // base64 data, err := base64.StdEncoding.DecodeString(string(str)) if err != nil { diff --git a/src/frp/utils/pcrypto/pcrypto_test.go b/src/frp/utils/pcrypto/pcrypto_test.go index 016dd529..e86762fe 100644 --- a/src/frp/utils/pcrypto/pcrypto_test.go +++ b/src/frp/utils/pcrypto/pcrypto_test.go @@ -19,10 +19,10 @@ import ( "testing" ) -func TestEncrypto(t *testing.T) { +func TestEncrypt(t *testing.T) { pp := new(Pcrypto) pp.Init([]byte("Hana")) - res, err := pp.Encrypto([]byte("Just One Test!")) + res, err := pp.Encrypt([]byte("Just One Test!")) if err != nil { t.Fatal(err) } @@ -30,15 +30,15 @@ func TestEncrypto(t *testing.T) { fmt.Printf("[%x]\n", res) } -func TestDecrypto(t *testing.T) { +func TestDecrypt(t *testing.T) { pp := new(Pcrypto) pp.Init([]byte("Hana")) - res, err := pp.Encrypto([]byte("Just One Test!")) + res, err := pp.Encrypt([]byte("Just One Test!")) if err != nil { t.Fatal(err) } - res, err = pp.Decrypto(res) + res, err = pp.Decrypt(res) if err != nil { t.Fatal(err) }