Skip to content

Commit ad0c449

Browse files
authored
Server manager support the NewUserConn operation (fatedier#1740)
support NewUserConn operation
1 parent 1c33018 commit ad0c449

File tree

9 files changed

+166
-4
lines changed

9 files changed

+166
-4
lines changed

doc/server_plugin.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ The response can look like any of the following:
7070

7171
### Operation
7272

73-
Currently `Login`, `NewProxy`, `Ping` and `NewWorkConn` operations are supported.
73+
Currently `Login`, `NewProxy`, `Ping`, `NewWorkConn` and `NewUserConn` operations are supported.
7474

7575
#### Login
7676

@@ -172,6 +172,25 @@ New work connection received from frpc (RPC sent after `run_id` is matched with
172172
}
173173
```
174174

175+
#### NewUserConn
176+
177+
New user connection received from proxy (support `tcp`, `stcp`, `https` and `tcpmux`) .
178+
179+
```
180+
{
181+
"content": {
182+
"user": {
183+
"user": <string>,
184+
"metas": map<string>string
185+
"run_id": <string>
186+
},
187+
"proxy_name": <string>,
188+
"proxy_type": <string>,
189+
"remote_addr": <string>
190+
}
191+
}
192+
```
193+
175194
### Server Plugin Configuration
176195

177196
```ini

doc/server_plugin_zh.md

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Response
6969

7070
### 操作类型
7171

72-
目前插件支持管理的操作类型有 `Login``NewProxy`
72+
目前插件支持管理的操作类型有 `Login``NewProxy``Ping``NewWorkConn``NewUserConn`
7373

7474
#### Login
7575

@@ -127,6 +127,63 @@ Response
127127
}
128128
```
129129

130+
#### Ping
131+
132+
心跳相关信息
133+
134+
```
135+
{
136+
"content": {
137+
"user": {
138+
"user": <string>,
139+
"metas": map<string>string
140+
"run_id": <string>
141+
},
142+
"timestamp": <int64>,
143+
"privilege_key": <string>
144+
}
145+
}
146+
```
147+
148+
#### NewWorkConn
149+
150+
新增 `frpc` 连接相关信息
151+
152+
```
153+
{
154+
"content": {
155+
"user": {
156+
"user": <string>,
157+
"metas": map<string>string
158+
"run_id": <string>
159+
},
160+
"run_id": <string>
161+
"timestamp": <int64>,
162+
"privilege_key": <string>
163+
}
164+
}
165+
```
166+
167+
#### NewUserConn
168+
169+
新增 `proxy` 连接相关信息 (支持 `tcp``stcp``https``tcpmux` 协议)。
170+
171+
```
172+
{
173+
"content": {
174+
"user": {
175+
"user": <string>,
176+
"metas": map<string>string
177+
"run_id": <string>
178+
},
179+
"proxy_name": <string>,
180+
"proxy_type": <string>,
181+
"remote_addr": <string>
182+
}
183+
}
184+
```
185+
186+
130187
### frps 中插件配置
131188

132189
```ini

models/plugin/server/manager.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type Manager struct {
2828
newProxyPlugins []Plugin
2929
pingPlugins []Plugin
3030
newWorkConnPlugins []Plugin
31+
newUserConnPlugins []Plugin
3132
}
3233

3334
func NewManager() *Manager {
@@ -36,6 +37,7 @@ func NewManager() *Manager {
3637
newProxyPlugins: make([]Plugin, 0),
3738
pingPlugins: make([]Plugin, 0),
3839
newWorkConnPlugins: make([]Plugin, 0),
40+
newUserConnPlugins: make([]Plugin, 0),
3941
}
4042
}
4143

@@ -52,6 +54,9 @@ func (m *Manager) Register(p Plugin) {
5254
if p.IsSupport(OpNewWorkConn) {
5355
m.pingPlugins = append(m.pingPlugins, p)
5456
}
57+
if p.IsSupport(OpNewUserConn) {
58+
m.newUserConnPlugins = append(m.newUserConnPlugins, p)
59+
}
5560
}
5661

5762
func (m *Manager) Login(content *LoginContent) (*LoginContent, error) {
@@ -189,3 +194,37 @@ func (m *Manager) NewWorkConn(content *NewWorkConnContent) (*NewWorkConnContent,
189194
}
190195
return content, nil
191196
}
197+
198+
func (m *Manager) NewUserConn(content *NewUserConnContent) (*NewUserConnContent, error) {
199+
if len(m.newUserConnPlugins) == 0 {
200+
return content, nil
201+
}
202+
203+
var (
204+
res = &Response{
205+
Reject: false,
206+
Unchange: true,
207+
}
208+
retContent interface{}
209+
err error
210+
)
211+
reqid, _ := util.RandId()
212+
xl := xlog.New().AppendPrefix("reqid: " + reqid)
213+
ctx := xlog.NewContext(context.Background(), xl)
214+
ctx = NewReqidContext(ctx, reqid)
215+
216+
for _, p := range m.newUserConnPlugins {
217+
res, retContent, err = p.Handle(ctx, OpNewUserConn, *content)
218+
if err != nil {
219+
xl.Info("send NewUserConn request to plugin [%s] error: %v", p.Name(), err)
220+
return nil, errors.New("send NewUserConn request to plugin error")
221+
}
222+
if res.Reject {
223+
return nil, fmt.Errorf("%s", res.RejectReason)
224+
}
225+
if !res.Unchange {
226+
content = retContent.(*NewUserConnContent)
227+
}
228+
}
229+
return content, nil
230+
}

models/plugin/server/plugin.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const (
2525
OpNewProxy = "NewProxy"
2626
OpPing = "Ping"
2727
OpNewWorkConn = "NewWorkConn"
28+
OpNewUserConn = "NewUserConn"
2829
)
2930

3031
type Plugin interface {

models/plugin/server/types.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,10 @@ type NewWorkConnContent struct {
5555
User UserInfo `json:"user"`
5656
msg.NewWorkConn
5757
}
58+
59+
type NewUserConnContent struct {
60+
User UserInfo `json:"user"`
61+
ProxyName string `json:"proxy_name"`
62+
ProxyType string `json:"proxy_type"`
63+
RemoteAddr string `json:"remote_addr"`
64+
}

server/control.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,9 +486,16 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
486486
return
487487
}
488488

489+
// User info
490+
userInfo := plugin.UserInfo{
491+
User: ctl.loginMsg.User,
492+
Metas: ctl.loginMsg.Metas,
493+
RunId: ctl.runId,
494+
}
495+
489496
// NewProxy will return a interface Proxy.
490497
// In fact it create different proxies by different proxy type, we just call run() here.
491-
pxy, err := proxy.NewProxy(ctl.ctx, ctl.runId, ctl.rc, ctl.poolCount, ctl.GetWorkConn, pxyConf, ctl.serverCfg)
498+
pxy, err := proxy.NewProxy(ctl.ctx, userInfo, ctl.rc, ctl.poolCount, ctl.GetWorkConn, pxyConf, ctl.serverCfg)
492499
if err != nil {
493500
return remoteAddr, err
494501
}

server/controller/resource.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package controller
1616

1717
import (
1818
"github.com/fatedier/frp/models/nathole"
19+
plugin "github.com/fatedier/frp/models/plugin/server"
1920
"github.com/fatedier/frp/server/group"
2021
"github.com/fatedier/frp/server/ports"
2122
"github.com/fatedier/frp/utils/tcpmux"
@@ -50,4 +51,7 @@ type ResourceController struct {
5051

5152
// TcpMux HTTP CONNECT multiplexer
5253
TcpMuxHttpConnectMuxer *tcpmux.HttpConnectTcpMuxer
54+
55+
// All server manager plugin
56+
PluginManager *plugin.Manager
5357
}

server/proxy/proxy.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"github.com/fatedier/frp/models/config"
2626
"github.com/fatedier/frp/models/msg"
27+
plugin "github.com/fatedier/frp/models/plugin/server"
2728
"github.com/fatedier/frp/server/controller"
2829
"github.com/fatedier/frp/server/metrics"
2930
frpNet "github.com/fatedier/frp/utils/net"
@@ -41,6 +42,8 @@ type Proxy interface {
4142
GetConf() config.ProxyConf
4243
GetWorkConnFromPool(src, dst net.Addr) (workConn net.Conn, err error)
4344
GetUsedPortsNum() int
45+
GetResourceController() *controller.ResourceController
46+
GetUserInfo() plugin.UserInfo
4447
Close()
4548
}
4649

@@ -52,6 +55,7 @@ type BaseProxy struct {
5255
poolCount int
5356
getWorkConnFn GetWorkConnFn
5457
serverCfg config.ServerCommonConf
58+
userInfo plugin.UserInfo
5559

5660
mu sync.RWMutex
5761
xl *xlog.Logger
@@ -70,6 +74,14 @@ func (pxy *BaseProxy) GetUsedPortsNum() int {
7074
return pxy.usedPortsNum
7175
}
7276

77+
func (pxy *BaseProxy) GetResourceController() *controller.ResourceController {
78+
return pxy.rc
79+
}
80+
81+
func (pxy *BaseProxy) GetUserInfo() plugin.UserInfo {
82+
return pxy.userInfo
83+
}
84+
7385
func (pxy *BaseProxy) Close() {
7486
xl := xlog.FromContextSafe(pxy.ctx)
7587
xl.Info("proxy closing")
@@ -154,7 +166,7 @@ func (pxy *BaseProxy) startListenHandler(p Proxy, handler func(Proxy, net.Conn,
154166
}
155167
}
156168

157-
func NewProxy(ctx context.Context, runId string, rc *controller.ResourceController, poolCount int,
169+
func NewProxy(ctx context.Context, userInfo plugin.UserInfo, rc *controller.ResourceController, poolCount int,
158170
getWorkConnFn GetWorkConnFn, pxyConf config.ProxyConf, serverCfg config.ServerCommonConf) (pxy Proxy, err error) {
159171

160172
xl := xlog.FromContextSafe(ctx).Spawn().AppendPrefix(pxyConf.GetBaseInfo().ProxyName)
@@ -167,6 +179,7 @@ func NewProxy(ctx context.Context, runId string, rc *controller.ResourceControll
167179
serverCfg: serverCfg,
168180
xl: xl,
169181
ctx: xlog.NewContext(ctx, xl),
182+
userInfo: userInfo,
170183
}
171184
switch cfg := pxyConf.(type) {
172185
case *config.TcpProxyConf:
@@ -218,6 +231,20 @@ func HandleUserTcpConnection(pxy Proxy, userConn net.Conn, serverCfg config.Serv
218231
xl := xlog.FromContextSafe(pxy.Context())
219232
defer userConn.Close()
220233

234+
// server plugin hook
235+
rc := pxy.GetResourceController()
236+
content := &plugin.NewUserConnContent{
237+
User: pxy.GetUserInfo(),
238+
ProxyName: pxy.GetName(),
239+
ProxyType: pxy.GetConf().GetBaseInfo().ProxyType,
240+
RemoteAddr: userConn.RemoteAddr().String(),
241+
}
242+
_, err := rc.PluginManager.NewUserConn(content)
243+
if err != nil {
244+
xl.Warn("the user conn [%s] was rejected, err:%v", content.RemoteAddr, err)
245+
return
246+
}
247+
221248
// try all connections from the pool
222249
workConn, err := pxy.GetWorkConnFromPool(userConn.RemoteAddr(), userConn.LocalAddr())
223250
if err != nil {

server/service.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
119119
svr.pluginManager.Register(plugin.NewHTTPPluginOptions(options))
120120
log.Info("plugin [%s] has been registered", name)
121121
}
122+
svr.rc.PluginManager = svr.pluginManager
122123

123124
// Init group controller
124125
svr.rc.TcpGroupCtl = group.NewTcpGroupCtl(svr.rc.TcpPortManager)

0 commit comments

Comments
 (0)