```
feat: 新增TCP代理服务器功能 新增完整的TCP代理服务器功能,支持在指定端口监听TCP请求并转发到目标服务器。 包含以下主要变更: - 新增 handler/tcpproxy.go 文件,实现 TcpProxyHandler 结构体和相关方法 - 在 model/model.go 中添加 TcpProxyConfig 配置结构 - 在 server/manager.go 中添加TCP代理服务器管理功能 - 修改 gohttp.go 在启动时初始化并启动TCP代理服务器 - 支持多TCP代理配置,每个代理可独立设置监听地址和目标服务器 - 提供完整的启动、停止和数据转发功能 - 包含详细的配置示例和文档说明 ```
This commit is contained in:
parent
5e09b26261
commit
5022da4885
61
changes.md
61
changes.md
|
|
@ -130,6 +130,65 @@ if slices.Contains(deniedIPs, clientIP) { ... }
|
|||
|
||||
---
|
||||
|
||||
## 6. 构建验证
|
||||
## 6. 新增功能:TCP代理服务器
|
||||
|
||||
### 6.1 功能概述
|
||||
|
||||
新增TCP代理服务器功能,支持在指定端口监听TCP请求并转发到指定服务器的指定端口。可以配置多个TCP代理。
|
||||
|
||||
### 6.2 新增文件
|
||||
|
||||
**handler/tcpproxy.go** - TCP代理处理器实现:
|
||||
- `TcpProxyHandler` 结构体:管理TCP代理连接
|
||||
- `NewTcpProxyHandler` 函数:创建新的TCP代理处理器
|
||||
- `Start` 方法:启动TCP代理监听
|
||||
- `Stop` 方法:停止TCP代理服务器
|
||||
- `pipe` 方法:连接间数据转发
|
||||
|
||||
### 6.3 配置模型 (model/model.go)
|
||||
|
||||
新增 `TcpProxyConfig` 配置结构:
|
||||
```go
|
||||
type TcpProxyConfig struct {
|
||||
Name string `json:"name"` // 代理名称
|
||||
Listen string `json:"listen"` // 监听地址,格式如 "0.0.0.0:8080"
|
||||
Target string `json:"target"` // 目标服务器地址,格式如 "192.168.1.1:3306"
|
||||
Enabled bool `json:"enabled"` // 是否启用
|
||||
}
|
||||
```
|
||||
|
||||
### 6.4 配置示例
|
||||
|
||||
在 `config.json` 中添加TCP代理配置:
|
||||
```json
|
||||
{
|
||||
"tcp_proxys": [
|
||||
{
|
||||
"name": "mysql-proxy",
|
||||
"listen": "0.0.0.0:3307",
|
||||
"target": "192.168.1.100:3306",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "redis-proxy",
|
||||
"listen": "0.0.0.0:6380",
|
||||
"target": "192.168.1.101:6379",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 6.5 服务器管理 (server/manager.go)
|
||||
|
||||
新增TCP代理服务器管理功能:
|
||||
- `TcpProxyManager`:TCP代理处理器映射
|
||||
- `AddTcpProxy`:注册TCP代理服务器
|
||||
- `StartTcpProxies`:启动所有TCP代理服务器
|
||||
- `StopTcpProxies`:停止所有TCP代理服务器
|
||||
|
||||
---
|
||||
|
||||
## 7. 构建验证
|
||||
|
||||
所有修改已通过 `go build ./...` 编译验证。
|
||||
|
|
|
|||
10
gohttp.go
10
gohttp.go
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"git.kingecg.top/kingecg/gohttpd/admin"
|
||||
"git.kingecg.top/kingecg/gohttpd/handler"
|
||||
"git.kingecg.top/kingecg/gohttpd/model"
|
||||
"git.kingecg.top/kingecg/gohttpd/server"
|
||||
"git.kingecg.top/kingecg/gohttpd/utils"
|
||||
|
|
@ -61,6 +62,15 @@ func (g *GoHttp) Start() {
|
|||
listener.Serve()
|
||||
}
|
||||
|
||||
// 启动TCP代理服务器
|
||||
for _, tcpConf := range conf.TcpProxys {
|
||||
if tcpConf.Enabled {
|
||||
tcpProxy := handler.NewTcpProxyHandler(tcpConf.Name, tcpConf.Listen, tcpConf.Target)
|
||||
server.AddTcpProxy(tcpConf.Name, tcpProxy)
|
||||
tcpProxy.Start()
|
||||
}
|
||||
}
|
||||
|
||||
// 记录 GoHttp 服务成功启动的信息
|
||||
g.logger.Info("gohttpd start success")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"git.kingecg.top/kingecg/gologger"
|
||||
)
|
||||
|
||||
// TcpProxyHandler TCP代理处理器
|
||||
type TcpProxyHandler struct {
|
||||
Name string
|
||||
Listen string
|
||||
Target string
|
||||
listener net.Listener
|
||||
wg sync.WaitGroup
|
||||
stopCh chan struct{}
|
||||
}
|
||||
|
||||
func NewTcpProxyHandler(name, listen, target string) *TcpProxyHandler {
|
||||
return &TcpProxyHandler{
|
||||
Name: name,
|
||||
Listen: listen,
|
||||
Target: target,
|
||||
stopCh: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Start 开始监听并处理TCP连接
|
||||
func (t *TcpProxyHandler) Start() error {
|
||||
l := gologger.GetLogger("TcpProxy")
|
||||
l.Info(fmt.Sprintf("TCP proxy [%s] starting, listen: %s, target: %s", t.Name, t.Listen, t.Target))
|
||||
|
||||
var err error
|
||||
t.listener, err = net.Listen("tcp", t.Listen)
|
||||
if err != nil {
|
||||
l.Error(fmt.Sprintf("TCP proxy [%s] failed to listen on %s: %v", t.Name, t.Listen, err))
|
||||
return err
|
||||
}
|
||||
|
||||
go t.acceptLoop()
|
||||
return nil
|
||||
}
|
||||
|
||||
// acceptLoop 接受连接并处理
|
||||
func (t *TcpProxyHandler) acceptLoop() {
|
||||
l := gologger.GetLogger("TcpProxy")
|
||||
for {
|
||||
conn, err := t.listener.Accept()
|
||||
if err != nil {
|
||||
select {
|
||||
case <-t.stopCh:
|
||||
l.Info(fmt.Sprintf("TCP proxy [%s] stopped", t.Name))
|
||||
return
|
||||
default:
|
||||
l.Error(fmt.Sprintf("TCP proxy [%s] accept error: %v", t.Name, err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
t.wg.Add(1)
|
||||
go t.handleConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// handleConn 处理单个TCP连接
|
||||
func (t *TcpProxyHandler) handleConn(clientConn net.Conn) {
|
||||
defer t.wg.Done()
|
||||
l := gologger.GetLogger("TcpProxy")
|
||||
|
||||
l.Debug(fmt.Sprintf("TCP proxy [%s] new connection from %s", t.Name, clientConn.RemoteAddr()))
|
||||
|
||||
// 连接到目标服务器
|
||||
targetConn, err := net.DialTimeout("tcp", t.Target, 10*1000000000) // 10秒超时
|
||||
if err != nil {
|
||||
l.Error(fmt.Sprintf("TCP proxy [%s] failed to connect to target %s: %v", t.Name, t.Target, err))
|
||||
clientConn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// 使用管道模式转发数据
|
||||
go t.pipe(clientConn, targetConn, "client->target")
|
||||
go t.pipe(targetConn, clientConn, "target->client")
|
||||
|
||||
l.Debug(fmt.Sprintf("TCP proxy [%s] connection established", t.Name))
|
||||
}
|
||||
|
||||
// pipe 在两个连接之间转发数据
|
||||
func (t *TcpProxyHandler) pipe(dst, src net.Conn, direction string) {
|
||||
defer dst.Close()
|
||||
l := gologger.GetLogger("TcpProxy")
|
||||
buf := make([]byte, 8192)
|
||||
for {
|
||||
n, err := src.Read(buf)
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
l.Debug(fmt.Sprintf("TCP proxy [%s] %s read error: %v", t.Name, direction, err))
|
||||
}
|
||||
return
|
||||
}
|
||||
_, err = dst.Write(buf[:n])
|
||||
if err != nil {
|
||||
l.Debug(fmt.Sprintf("TCP proxy [%s] %s write error: %v", t.Name, direction, err))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop 停止TCP代理服务器
|
||||
func (t *TcpProxyHandler) Stop() error {
|
||||
l := gologger.GetLogger("TcpProxy")
|
||||
l.Info(fmt.Sprintf("TCP proxy [%s] stopping...", t.Name))
|
||||
close(t.stopCh)
|
||||
if t.listener != nil {
|
||||
t.listener.Close()
|
||||
}
|
||||
t.wg.Wait()
|
||||
l.Info(fmt.Sprintf("TCP proxy [%s] stopped", t.Name))
|
||||
return nil
|
||||
}
|
||||
|
|
@ -62,10 +62,19 @@ type JwtConfig struct {
|
|||
}
|
||||
|
||||
type GoHttpdConfig struct {
|
||||
Logging gologger.LoggersConfig `json:"logging"`
|
||||
Admin *HttpServerConfig `json:"admin"`
|
||||
IncludDir string `json:"includs"`
|
||||
Servers []*HttpServerConfig `json:"servers"`
|
||||
Logging gologger.LoggersConfig `json:"logging"`
|
||||
Admin *HttpServerConfig `json:"admin"`
|
||||
IncludDir string `json:"includs"`
|
||||
Servers []*HttpServerConfig `json:"servers"`
|
||||
TcpProxys []*TcpProxyConfig `json:"tcp_proxys"`
|
||||
}
|
||||
|
||||
// TcpProxyConfig TCP代理服务器配置
|
||||
type TcpProxyConfig struct {
|
||||
Name string `json:"name"` // 代理名称
|
||||
Listen string `json:"listen"` // 监听地址,格式如 "0.0.0.0:8080"
|
||||
Target string `json:"target"` // 目标服务器地址,格式如 "192.168.1.1:3306"
|
||||
Enabled bool `json:"enabled"` // 是否启用
|
||||
}
|
||||
|
||||
var DefaultAdminConfig HttpServerConfig = HttpServerConfig{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"io"
|
||||
|
||||
"git.kingecg.top/kingecg/cmux"
|
||||
"git.kingecg.top/kingecg/gohttpd/handler"
|
||||
"git.kingecg.top/kingecg/gohttpd/model"
|
||||
logger "git.kingecg.top/kingecg/gologger"
|
||||
)
|
||||
|
|
@ -246,3 +247,31 @@ func StartServer(name string, port int) {
|
|||
}
|
||||
listener.StartServer(name)
|
||||
}
|
||||
|
||||
// TcpProxyManager TCP代理服务器管理器
|
||||
var TcpProxyManager = make(map[string]*handler.TcpProxyHandler)
|
||||
|
||||
// AddTcpProxy 添加TCP代理服务器
|
||||
func AddTcpProxy(name string, proxy *handler.TcpProxyHandler) {
|
||||
TcpProxyManager[name] = proxy
|
||||
}
|
||||
|
||||
// StartTcpProxies 启动所有TCP代理服务器
|
||||
func StartTcpProxies() {
|
||||
l := logger.GetLogger("TcpProxy")
|
||||
for _, proxy := range TcpProxyManager {
|
||||
if err := proxy.Start(); err != nil {
|
||||
l.Error(fmt.Sprintf("Failed to start TCP proxy [%s]: %v", proxy.Name, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StopTcpProxies 停止所有TCP代理服务器
|
||||
func StopTcpProxies() {
|
||||
l := logger.GetLogger("TcpProxy")
|
||||
for _, proxy := range TcpProxyManager {
|
||||
if err := proxy.Stop(); err != nil {
|
||||
l.Error(fmt.Sprintf("Failed to stop TCP proxy [%s]: %v", proxy.Name, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue