Repository: fatedier/frp (language: go)

Issue:
请问插件开发时，如何获取到frpc客户端的真实IP？
### Bug Description

首先非常感谢能有这么好的工具！！非常感谢。

我使用frps的时候，一开始什么认证也没设，然后使用的过程中发现除了我的内网机器（frpc 客户端），还有美国ip的frpc 客户端在连接我的frps。

我就想在frpc 客户端连接我的frps的时候验证一下是否是我的内网机器ip，如果是就放行，否则就拒绝。

我稍微研究了一下，frps的log文件中有frpc 客户端的ip，但是插件开发时，Login,NewProxy,NewWorkConn,NewUserConn这些过程中的json信息中没有frpc 客户端的信息。
还请多多指教？！

### frpc Version

0.37.1

### frps Version

0.37.1

### System Architecture

windows/amd64

### Configurations

NONE

### Logs

_No response_

### Steps to reproduce

1. 
2. 
3. 
...


### Affected area

- [ ] Docs
- [ ] Installation
- [ ] Performance and Scalability
- [ ] Security
- [ ] User Experience
- [ ] Test and Release
- [ ] Developer Infrastructure
- [ ] Client Plugin
- [X] Server Plugin
- [ ] Extensions
- [ ] Others


Discussion / hints:
建议设置上 token，避免任何人都可以连接，也可以通过防火墙禁止某些 ip 段连接。
我也遇到这个问题了，能不能加上IP限制或类似功能。
> 建议设置上 token，避免任何人都可以连接，也可以通过防火墙禁止某些 ip 段连接。

我现在设置了，但是如果能设置IP限制什么的肯定更保险了。
可以考虑在 Login 的消息里附加上 frpc IP。

Fix patch:
diff --git a/pkg/plugin/server/types.go b/pkg/plugin/server/types.go
index 82d4032cb2a..4df79f46d62 100644
--- a/pkg/plugin/server/types.go
+++ b/pkg/plugin/server/types.go
@@ -33,6 +33,8 @@ type Response struct {
 
 type LoginContent struct {
 	msg.Login
+
+	ClientAddress string `json:"client_address,omitempty"`
 }
 
 type UserInfo struct {
diff --git a/server/service.go b/server/service.go
index 97a65f80e3b..f6e015a5563 100644
--- a/server/service.go
+++ b/server/service.go
@@ -334,7 +334,8 @@ func (svr *Service) handleConnection(ctx context.Context, conn net.Conn) {
 	case *msg.Login:
 		// server plugin hook
 		content := &plugin.LoginContent{
-			Login: *m,
+			Login:         *m,
+			ClientAddress: conn.RemoteAddr().String(),
 		}
 		retContent, err := svr.pluginManager.Login(content)
 		if err == nil {


Test patch:
diff --git a/test/e2e/plugin/server.go b/test/e2e/plugin/server.go
index 0cd618f93cd..79ecff44b04 100644
--- a/test/e2e/plugin/server.go
+++ b/test/e2e/plugin/server.go
@@ -24,9 +24,14 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
 
 		It("Auth for custom meta token", func() {
 			localPort := f.AllocPort()
+
+			clientAddressGot := false
 			handler := func(req *plugin.Request) *plugin.Response {
 				var ret plugin.Response
 				content := req.Content.(*plugin.LoginContent)
+				if content.ClientAddress != "" {
+					clientAddressGot = true
+				}
 				if content.Metas["token"] == "123" {
 					ret.Unchange = true
 				} else {
@@ -69,6 +74,8 @@ var _ = Describe("[Feature: Server-Plugins]", func() {
 
 			framework.NewRequestExpect(f).Port(remotePort).Ensure()
 			framework.NewRequestExpect(f).Port(remotePort2).ExpectError(true).Ensure()
+
+			framework.ExpectTrue(clientAddressGot)
 		})
 	})