Browse Source

all: now messages between frps and frpc can be encryped when use_encryption set true

pull/12/head
fatedier 9 years ago
parent
commit
80fc76da52
  1. 2
      README.md
  2. 2
      conf/frpc.ini
  3. 7
      src/frp/cmd/frpc/control.go
  4. 3
      src/frp/cmd/frps/control.go
  5. 16
      src/frp/models/client/client.go
  6. 11
      src/frp/models/client/config.go
  7. 7
      src/frp/models/msg/msg.go
  8. 19
      src/frp/models/server/server.go
  9. 36
      src/frp/utils/conn/conn.go
  10. 4
      src/frp/utils/pcrypto/pcrypto.go
  11. 10
      src/frp/utils/pcrypto/pcrypto_test.go

2
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

2
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

7
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")

3
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 {

16
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
}

11
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
}
}

7
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 {

19
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)
}
}
}()

36
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')

4
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 {

10
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)
}

Loading…
Cancel
Save