手把手教你用Go和Sunny网络中间件搭建一个简易HTTP/HTTPS代理服务器(支持WS/WSS/TCP/UDP)
用Go和Sunny网络中间件构建全能代理服务器的实战指南
在当今互联网开发中,网络中间件技术已成为开发者工具箱中不可或缺的一部分。无论是API调试、流量分析还是安全测试,一个灵活可定制的代理服务器都能大幅提升工作效率。本文将带您从零开始,使用Go语言和Sunny网络中间件库,构建一个支持HTTP/HTTPS/WS/WSS/TCP/UDP协议的全功能代理服务器。
1. 环境准备与Sunny中间件初探
在开始编码之前,我们需要先了解Sunny网络中间件的核心能力。与Fiddler类似,Sunny提供了跨平台的网络分析功能,但更侧重于开发者二次开发的需求。它支持多种协议的数据捕获和修改,是构建自定义代理服务的理想选择。
基础环境要求:
- Go 1.16或更高版本
- 支持的操作系统:Windows/Linux/macOS
- 网络访问权限(用于下载依赖)
安装Sunny库非常简单,只需执行以下命令:
go get github.com/qtgolang/SunnyNet/SunnyNetSunny的核心功能包括:
- 多协议支持(HTTP/HTTPS/WS/WSS/TCP/UDP)
- 请求/响应数据修改
- 连接重定向
- 数据压缩解码
- 主动发送网络数据
提示:在Windows系统上使用UDP功能时,可能需要加载特定驱动,这是Sunny在Windows平台的特别要求。
2. 构建基础代理服务器框架
让我们从创建一个最基本的代理服务器开始。这个框架将作为后续功能扩展的基础。
package main import ( "fmt" "github.com/qtgolang/SunnyNet/SunnyNet" "github.com/qtgolang/SunnyNet/public" "time" ) var Sunny = SunnyNet.NewSunny() func main() { // 设置各类协议的回调函数 Sunny.SetGoCallback(HttpCallback, TcpCallback, WSCallback, UdpCallback) // 设置监听端口并启动服务 Sunny.SetPort(2023).Start() fmt.Println("代理服务器已启动,监听端口 2023") // 防止主程序退出 time.Sleep(24 * time.Hour) }这个基础框架已经实现了:
- 创建Sunny中间件实例
- 设置各类协议的回调函数
- 绑定指定端口并启动服务
- 保持程序持续运行
关键组件解析:
NewSunny(): 创建新的Sunny中间件实例SetGoCallback(): 设置各协议的回调处理函数SetPort(): 指定监听端口Start(): 启动代理服务
3. 实现HTTP/HTTPS请求处理
HTTP/HTTPS是Web开发中最常用的协议,让我们深入实现这些协议的处理逻辑。
func HttpCallback(Conn *SunnyNet.HttpConn) { switch Conn.Type { case public.HttpSendRequest: // 请求发送前处理 fmt.Printf("请求URL: %s\n", Conn.Request.URL.String()) // 修改请求体示例 if Conn.Request.Body != nil { body, _ := io.ReadAll(Conn.Request.Body) _ = Conn.Request.Body.Close() // 在这里可以修改请求体内容 modifiedBody := []byte("Modified: " + string(body)) Conn.Request.Body = io.NopCloser(bytes.NewBuffer(modifiedBody)) } case public.HttpResponseOK: // 响应返回时处理 if Conn.Response.Body != nil { body, _ := io.ReadAll(Conn.Response.Body) _ = Conn.Response.Body.Close() // 在这里可以修改响应体内容 modifiedBody := []byte("Processed: " + string(body)) Conn.Response.Body = io.NopCloser(bytes.NewBuffer(modifiedBody)) } case public.HttpRequestFail: // 请求失败处理 fmt.Println("请求失败:", Conn.Request.URL.String()) } }HTTP处理关键点:
| 处理阶段 | 描述 | 典型应用场景 |
|---|---|---|
| HttpSendRequest | 请求发送前 | 修改请求头/体、阻断请求、记录日志 |
| HttpResponseOK | 收到响应后 | 修改响应内容、性能统计、数据脱敏 |
| HttpRequestFail | 请求失败时 | 错误监控、失败重试逻辑 |
注意:修改HTTPS请求需要正确配置证书,Sunny会自动处理证书相关逻辑,开发者无需额外操作。
4. WebSocket和TCP/UDP协议实现
除了HTTP协议,现代应用经常使用WebSocket和原始TCP/UDP协议进行通信。让我们看看如何实现这些协议的处理。
WebSocket回调实现:
func WSCallback(Conn *SunnyNet.WsConn) { // 打印WebSocket连接信息 fmt.Printf("WebSocket连接: %s\n", Conn.Url) // 可以在这里修改WebSocket数据 if len(Conn.Data) > 0 { // 示例:在每条消息前添加前缀 Conn.Data = append([]byte("WSProxy: "), Conn.Data...) } }TCP回调实现:
func TcpCallback(Conn *SunnyNet.TcpConn) { fmt.Printf("TCP连接 - 本地: %s, 远程: %s, 数据长度: %d\n", Conn.LocalAddr, Conn.RemoteAddr, Conn.GetBodyLen()) // TCP数据修改示例 if Conn.GetBodyLen() > 0 { original := Conn.GetBody() modified := []byte("TCPProxy: " + string(original)) Conn.SetBody(modified) } }UDP回调实现:
func UdpCallback(Conn *SunnyNet.UDPConn) { switch Conn.Type { case public.SunnyNetUDPTypeReceive: fmt.Printf("接收UDP数据 - 来自: %s, 长度: %d\n", Conn.RemoteAddress, len(Conn.Data)) case public.SunnyNetUDPTypeSend: fmt.Printf("发送UDP数据 - 到: %s, 长度: %d\n", Conn.RemoteAddress, len(Conn.Data)) // 修改发送的UDP数据 if len(Conn.Data) > 0 { Conn.Data = append([]byte("UDPProxy: "), Conn.Data...) } case public.SunnyNetUDPTypeClosed: fmt.Printf("UDP连接关闭 - 本地: %s\n", Conn.LocalAddress) } }协议支持对比表:
| 协议类型 | 数据修改 | 连接控制 | 适用场景 |
|---|---|---|---|
| HTTP/HTTPS | 支持 | 支持 | Web API、网页浏览 |
| WebSocket | 支持 | 支持 | 实时通信、聊天应用 |
| TCP | 支持 | 支持 | 传统客户端/服务器应用 |
| UDP | 支持 | 有限支持 | 视频流、游戏、DNS查询 |
5. 高级功能与性能优化
基础功能实现后,我们可以进一步扩展代理服务器的能力,并考虑性能优化。
连接重定向示例:
// 在HttpCallback函数中添加 if strings.Contains(Conn.Request.URL.Host, "example.com") { // 将example.com的请求重定向到其他地址 Conn.Request.URL.Host = "alternate.example.com" }使用特定代理:
// 为特定域名设置使用上级代理 if strings.HasSuffix(Conn.Request.URL.Host, ".google.com") { Sunny.SetProxy("http://parent-proxy:8080") }性能优化技巧:
- 连接池管理:重用TCP连接减少握手开销
- 并行处理:对独立请求使用goroutine并行处理
- 内存优化:及时释放不再使用的缓冲区
- 日志分级:生产环境关闭调试日志
错误处理最佳实践:
func HttpCallback(Conn *SunnyNet.HttpConn) { defer func() { if r := recover(); r != nil { fmt.Println("回调函数发生panic:", r) // 可以选择返回错误响应 Conn.StopRequest(500, "Internal Server Error") } }() // 正常的处理逻辑... }6. 实际应用场景与扩展思路
这个代理服务器框架可以应用于多种实际场景:
调试与开发:
- 修改API请求/响应进行前端开发
- 模拟慢速网络测试应用表现
- 注入测试数据验证边界条件
安全分析:
- 记录和分析网络流量
- 检测敏感数据传输
- 模拟中间人攻击测试应用安全性
性能监控:
- 统计API响应时间
- 分析网络延迟分布
- 识别性能瓶颈
扩展思路:
- 添加用户认证功能
- 实现规则引擎支持复杂流量路由
- 开发Web管理界面
- 集成Prometheus监控指标
- 支持插件机制扩展功能
// 示例:添加简单的认证中间件 func HttpCallback(Conn *SunnyNet.HttpConn) { if Conn.Type == public.HttpSendRequest { auth := Conn.Request.Header.Get("Authorization") if auth != "Bearer valid-token" { Conn.StopRequest(403, "Forbidden") return } } // 其他处理逻辑... }构建这样一个功能全面的代理服务器,不仅可以帮助我们深入理解网络协议的工作原理,还能根据具体需求灵活定制各种网络处理逻辑。Sunny中间件提供的丰富接口让这一切变得简单高效。
