Skip to content

Commit

Permalink
Merge pull request #41 from fatedier/dev
Browse files Browse the repository at this point in the history
release v0.7.0
  • Loading branch information
fatedier authored Jul 4, 2016
2 parents 6549810 + e99357d commit 28251a8
Show file tree
Hide file tree
Showing 23 changed files with 893 additions and 275 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ Interested in getting involved? We would like to help you!
* [fatedier](https://github.com/fatedier)
* [Hurricanezwf](https://github.com/Hurricanezwf)
* [vashstorm](https://github.com/vashstorm)
* [maodanp](https://github.com/maodanp)
1 change: 1 addition & 0 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ frp 目前正在前期开发阶段,master 分支用于发布稳定版本,dev
* [fatedier](https://github.com/fatedier)
* [Hurricanezwf](https://github.com/Hurricanezwf)
* [vashstorm](https://github.com/vashstorm)
* [maodanp](https://github.com/maodanp)
24 changes: 23 additions & 1 deletion conf/frpc.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ log_level = info
log_max_days = 3
# for authentication
auth_token = 123
# for privilege mode
privilege_token = 12345678

# ssh is the proxy name same as server's configuration
[ssh]
Expand All @@ -18,15 +20,35 @@ 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
# default is false
use_gzip = false

# Resolve your domain names to [server_addr] so you can use http://web01.yourdomain.com to browse web01 and http://web02.yourdomain.com to browse web02, the domains are set in frps.ini
[web01]
type = http
local_ip = 127.0.0.1
local_port = 80
use_encryption = true
use_gzip = true

[web02]
type = http
local_ip = 127.0.0.1
local_port = 8000

[privilege_ssh]
# if privilege_mode is enabled, this proxy will be created automatically
privilege_mode = true
type = tcp
local_ip = 127.0.0.1
local_port = 22
use_encryption = true
use_gzip = false
remote_port = 6001

[privilege_web]
privilege_mode = true
type = http
local_ip = 127.0.0.1
local_port = 80
use_gzip = true
custom_domains = web03.yourdomain.com
8 changes: 7 additions & 1 deletion conf/frps.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ bind_addr = 0.0.0.0
bind_port = 7000
# if you want to support virtual host, you must set the http port for listening (optional)
vhost_http_port = 80
vhost_https_port = 443
# if you want to configure or reload frps by dashboard, dashboard_port must be set
dashboard_port = 7500
# console or real logFile path like ./frps.log
log_file = ./frps.log
# debug, info, warn, error
log_level = info
log_max_days = 3
# if you enable privilege mode, frpc can create a proxy without pre-configure in frps when privilege_token is correct
privilege_mode = true
privilege_token = 12345678

# ssh is the proxy name, client will use this name and auth_token to connect to server
[ssh]
Expand All @@ -20,12 +24,14 @@ bind_addr = 0.0.0.0
listen_port = 6000

[web01]
# if type equals http, vhost_http_port must be set
type = http
auth_token = 123
# if proxy type equals http, custom_domains must be set separated by commas
custom_domains = web01.yourdomain.com,web01.yourdomain2.com

[web02]
type = http
# if type equals https, vhost_https_port must be set
type = https
auth_token = 123
custom_domains = web02.yourdomain.com
15 changes: 13 additions & 2 deletions src/frp/cmd/frpc/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,25 @@ func loginToServer(cli *client.ProxyClient) (c *conn.Conn, err error) {
}

nowTime := time.Now().Unix()
authKey := pcrypto.GetAuthKey(cli.Name + cli.AuthToken + fmt.Sprintf("%d", nowTime))
req := &msg.ControlReq{
Type: consts.NewCtlConn,
ProxyName: cli.Name,
AuthKey: authKey,
UseEncryption: cli.UseEncryption,
UseGzip: cli.UseGzip,
PrivilegeMode: cli.PrivilegeMode,
ProxyType: cli.Type,
Timestamp: nowTime,
}
if cli.PrivilegeMode {
privilegeKey := pcrypto.GetAuthKey(cli.Name + client.PrivilegeToken + fmt.Sprintf("%d", nowTime))
req.RemotePort = cli.RemotePort
req.CustomDomains = cli.CustomDomains
req.PrivilegeKey = privilegeKey
} else {
authKey := pcrypto.GetAuthKey(cli.Name + cli.AuthToken + fmt.Sprintf("%d", nowTime))
req.AuthKey = authKey
}

buf, _ := json.Marshal(req)
err = c.Write(string(buf) + "\n")
if err != nil {
Expand Down
85 changes: 69 additions & 16 deletions src/frp/cmd/frps/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,38 +194,88 @@ func msgSender(s *server.ProxyServer, c *conn.Conn, msgSendChan chan interface{}
// if success, ret equals 0, otherwise greater than 0
func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) {
ret = 1
// check if proxy name exist
s, ok := server.ProxyServers[req.ProxyName]
if !ok {
info = fmt.Sprintf("ProxyName [%s] is not exist", req.ProxyName)
log.Warn(info)
if req.PrivilegeMode && !server.PrivilegeMode {
info = fmt.Sprintf("ProxyName [%s], PrivilegeMode is disabled in frps", req.ProxyName)
log.Warn("info")
return
}

// check authKey
var (
s *server.ProxyServer
ok bool
)
s, ok = server.ProxyServers[req.ProxyName]
if req.PrivilegeMode && req.Type == consts.NewCtlConn {
log.Debug("ProxyName [%s], doLogin and privilege mode is enabled", req.ProxyName)
} else {
if !ok {
info = fmt.Sprintf("ProxyName [%s] is not exist", req.ProxyName)
log.Warn(info)
return
}
}

// check authKey or privilegeKey
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
if req.PrivilegeMode {
privilegeKey := pcrypto.GetAuthKey(req.ProxyName + server.PrivilegeToken + fmt.Sprintf("%d", req.Timestamp))
// privilegeKey avaiable in 15 minutes
if nowTime-req.Timestamp > 15*60 {
info = fmt.Sprintf("ProxyName [%s], privilege mode authorization timeout", req.ProxyName)
log.Warn(info)
return
} else if req.PrivilegeKey != privilegeKey {
info = fmt.Sprintf("ProxyName [%s], privilege mode authorization failed", req.ProxyName)
log.Warn(info)
return
}
} else {
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 req.PrivilegeMode {
s = server.NewProxyServerFromCtlMsg(req)
err := server.CreateProxy(s)
if err != nil {
info = fmt.Sprintf("ProxyName [%s], %v", req.ProxyName, err)
log.Warn(info)
return
}
}

if s.Status == consts.Working {
info = fmt.Sprintf("ProxyName [%s], already in use", req.ProxyName)
log.Warn(info)
return
}

// check if vhost_port is set
if s.Type == "http" && server.VhostHttpMuxer == nil {
info = fmt.Sprintf("ProxyName [%s], type [http] not support when vhost_http_port is not set", req.ProxyName)
log.Warn(info)
return
}
if s.Type == "https" && server.VhostHttpsMuxer == nil {
info = fmt.Sprintf("ProxyName [%s], type [https] not support when vhost_https_port is not set", req.ProxyName)
log.Warn(info)
return
}

// set infomations from frpc
s.UseEncryption = req.UseEncryption
s.UseGzip = req.UseGzip

// start proxy and listen for user connections, no block
err := s.Start(c)
Expand All @@ -235,6 +285,9 @@ func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) {
return
}
log.Info("ProxyName [%s], start proxy success", req.ProxyName)
if req.PrivilegeMode {
log.Info("ProxyName [%s], created by PrivilegeMode", req.ProxyName)
}
} else if req.Type == consts.NewWorkConn {
// work conn
if s.Status != consts.Working {
Expand Down
18 changes: 17 additions & 1 deletion src/frp/cmd/frps/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,25 @@ func main() {
log.Error("Create vhost http listener error, %v", err)
os.Exit(1)
}
server.VhostMuxer, err = vhost.NewHttpMuxer(vhostListener, 30*time.Second)
server.VhostHttpMuxer, err = vhost.NewHttpMuxer(vhostListener, 30*time.Second)
if err != nil {
log.Error("Create vhost httpMuxer error, %v", err)
}
}

// create vhost if VhostHttpPort != 0
if server.VhostHttpsPort != 0 {
vhostListener, err := conn.Listen(server.BindAddr, server.VhostHttpsPort)
if err != nil {
log.Error("Create vhost https listener error, %v", err)
os.Exit(1)
}
server.VhostHttpsMuxer, err = vhost.NewHttpsMuxer(vhostListener, 30*time.Second)
if err != nil {
log.Error("Create vhost httpsMuxer error, %v", err)
}
}

// create dashboard web server if DashboardPort is set, so it won't be 0
if server.DashboardPort != 0 {
err := server.RunDashboardServer(server.BindAddr, server.DashboardPort)
Expand All @@ -159,5 +172,8 @@ func main() {
}

log.Info("Start frps success")
if server.PrivilegeMode == true {
log.Info("PrivilegeMode is enabled, you should pay more attention to security issues")
}
ProcessControlConn(l)
}
35 changes: 19 additions & 16 deletions src/frp/models/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"time"

"frp/models/config"
"frp/models/consts"
"frp/models/msg"
"frp/utils/conn"
Expand All @@ -27,12 +28,12 @@ import (
)

type ProxyClient struct {
Name string
AuthToken string
LocalIp string
LocalPort int64
Type string
UseEncryption bool
config.BaseConf
LocalIp string
LocalPort int64

RemotePort int64
CustomDomains []string
}

func (p *ProxyClient) GetLocalConn() (c *conn.Conn, err error) {
Expand All @@ -57,12 +58,18 @@ func (p *ProxyClient) GetRemoteConn(addr string, port int64) (c *conn.Conn, err
}

nowTime := time.Now().Unix()
authKey := pcrypto.GetAuthKey(p.Name + p.AuthToken + fmt.Sprintf("%d", nowTime))
req := &msg.ControlReq{
Type: consts.NewWorkConn,
ProxyName: p.Name,
AuthKey: authKey,
Timestamp: nowTime,
Type: consts.NewWorkConn,
ProxyName: p.Name,
PrivilegeMode: p.PrivilegeMode,
Timestamp: nowTime,
}
if p.PrivilegeMode == true {
privilegeKey := pcrypto.GetAuthKey(p.Name + PrivilegeToken + fmt.Sprintf("%d", nowTime))
req.PrivilegeKey = privilegeKey
} else {
authKey := pcrypto.GetAuthKey(p.Name + p.AuthToken + fmt.Sprintf("%d", nowTime))
req.AuthKey = authKey
}

buf, _ := json.Marshal(req)
Expand All @@ -89,11 +96,7 @@ 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())
if p.UseEncryption {
go conn.JoinMore(localConn, remoteConn, p.AuthToken)
} else {
go conn.Join(localConn, remoteConn)
}
go msg.JoinMore(localConn, remoteConn, p.BaseConf)

return nil
}
Loading

0 comments on commit 28251a8

Please sign in to comment.