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:
程广 2026-07-10 08:11:55 +08:00
parent 5e09b26261
commit 5022da4885
5 changed files with 233 additions and 5 deletions

View File

@ -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 ./...` 编译验证。 所有修改已通过 `go build ./...` 编译验证。

View File

@ -8,6 +8,7 @@ import (
"strings" "strings"
"git.kingecg.top/kingecg/gohttpd/admin" "git.kingecg.top/kingecg/gohttpd/admin"
"git.kingecg.top/kingecg/gohttpd/handler"
"git.kingecg.top/kingecg/gohttpd/model" "git.kingecg.top/kingecg/gohttpd/model"
"git.kingecg.top/kingecg/gohttpd/server" "git.kingecg.top/kingecg/gohttpd/server"
"git.kingecg.top/kingecg/gohttpd/utils" "git.kingecg.top/kingecg/gohttpd/utils"
@ -61,6 +62,15 @@ func (g *GoHttp) Start() {
listener.Serve() 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 服务成功启动的信息 // 记录 GoHttp 服务成功启动的信息
g.logger.Info("gohttpd start success") g.logger.Info("gohttpd start success")
} }

121
handler/tcpproxy.go Normal file
View File

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

View File

@ -62,10 +62,19 @@ type JwtConfig struct {
} }
type GoHttpdConfig struct { type GoHttpdConfig struct {
Logging gologger.LoggersConfig `json:"logging"` Logging gologger.LoggersConfig `json:"logging"`
Admin *HttpServerConfig `json:"admin"` Admin *HttpServerConfig `json:"admin"`
IncludDir string `json:"includs"` IncludDir string `json:"includs"`
Servers []*HttpServerConfig `json:"servers"` 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{ var DefaultAdminConfig HttpServerConfig = HttpServerConfig{

View File

@ -10,6 +10,7 @@ import (
"io" "io"
"git.kingecg.top/kingecg/cmux" "git.kingecg.top/kingecg/cmux"
"git.kingecg.top/kingecg/gohttpd/handler"
"git.kingecg.top/kingecg/gohttpd/model" "git.kingecg.top/kingecg/gohttpd/model"
logger "git.kingecg.top/kingecg/gologger" logger "git.kingecg.top/kingecg/gologger"
) )
@ -246,3 +247,31 @@ func StartServer(name string, port int) {
} }
listener.StartServer(name) 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))
}
}
}