mirror of
https://github.com/qtgolang/SunnyNet.git
synced 2026-08-30 22:11:29 -07:00
2025-11-06
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
@echo off
|
||||
set CGO_ENABLED=1
|
||||
set GOOS=windows
|
||||
set GOARCH=386
|
||||
set tmpPath=%~dp0
|
||||
cd %tmpPath:~0,1%:
|
||||
for %%I in ("%tmpPath%..\") do set "parentPath=%%~fI"
|
||||
cd %parentPath%
|
||||
go build -trimpath -buildmode=c-shared -tags mini -ldflags "-s -w" -o "G:\Sunny\SunnyNet\BuildLibrary\SunnyNet.dll"
|
||||
@echo on
|
||||
20
BuildLibrary/MacOs_amd64.sh
Normal file
20
BuildLibrary/MacOs_amd64.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
echo "" > /dev/null
|
||||
echo "正在编译..."
|
||||
set CGO_ENABLED=1
|
||||
set GOOS=darwin
|
||||
set GOARCH=amd64
|
||||
tmpPath=$(dirname "$(readlink -f "$0")")
|
||||
parentPath=$(dirname "$tmpPath")
|
||||
cd "$parentPath"
|
||||
|
||||
go build -trimpath -buildmode=c-shared -ldflags "-s -w" -o "$tmpPath/Library/darwin/amd64/SunnyNet.dylib"
|
||||
# 检查命令的退出状态码
|
||||
if [ $? -ne 0 ]; then
|
||||
echo ""
|
||||
echo ""
|
||||
echo "编译失败!"
|
||||
else
|
||||
echo ""
|
||||
echo ""
|
||||
echo "编译完成!"
|
||||
fi
|
||||
20
BuildLibrary/MacOs_arm64.sh
Normal file
20
BuildLibrary/MacOs_arm64.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
echo "" > /dev/null
|
||||
echo "正在编译..."
|
||||
set CGO_ENABLED=1
|
||||
set GOOS=darwin
|
||||
set GOARCH=arm64
|
||||
tmpPath=$(dirname "$(readlink -f "$0")")
|
||||
parentPath=$(dirname "$tmpPath")
|
||||
cd "$parentPath"
|
||||
|
||||
go build -trimpath -buildmode=c-shared -ldflags "-s -w" -o "$tmpPath/Library/darwin/arm64/SunnyNet.dylib"
|
||||
# 检查命令的退出状态码
|
||||
if [ $? -ne 0 ]; then
|
||||
echo ""
|
||||
echo ""
|
||||
echo "编译失败!"
|
||||
else
|
||||
echo ""
|
||||
echo ""
|
||||
echo "编译完成!"
|
||||
fi
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
295
README.md
295
README.md
@@ -1,205 +1,120 @@
|
||||
# Sunny网络中间件 SDK 文档
|
||||
|
||||
<div style="text-align: center;"><h3><a style="color: red;">请注意:由于本仓库历史记录太大</a></div></h3></center>
|
||||
<div style="text-align: center;"><h3><a style="color: red;">本仓库于 2025-04-24 删除重建</a></div></h3></center>
|
||||
<div align="center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="210" height="20" role="img" aria-label="Platform: Windows | Linux | macOS"><title>Platform: Windows | Linux | macOS</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="210" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="57" height="20" fill="#555"/><rect x="57" width="153" height="20" fill="#007ec6"/><rect width="210" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="295" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470">Platform</text><text x="295" y="140" transform="scale(.1)" fill="#fff" textLength="470">Platform</text><text aria-hidden="true" x="1325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1430">Windows | Linux | macOS</text><text x="1325" y="140" transform="scale(.1)" fill="#fff" textLength="1430">Windows | Linux | macOS</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="20" role="img" aria-label="Go: >=1.16"><title>Go: >=1.16</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="78" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="25" height="20" fill="#555"/><rect x="25" width="53" height="20" fill="#97ca00"/><rect width="78" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="135" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="150">Go</text><text x="135" y="140" transform="scale(.1)" fill="#fff" textLength="150">Go</text><text aria-hidden="true" x="505" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">>=1.16</text><text x="505" y="140" transform="scale(.1)" fill="#fff" textLength="430">>=1.16</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="82" height="20" role="img" aria-label="License: MIT"><title>License: MIT</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="82" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="51" height="20" fill="#555"/><rect x="51" width="31" height="20" fill="#dfb317"/><rect width="82" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="265" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="410">License</text><text x="265" y="140" transform="scale(.1)" fill="#fff" textLength="410">License</text><text aria-hidden="true" x="655" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="210">MIT</text><text x="655" y="140" transform="scale(.1)" fill="#fff" textLength="210">MIT</text></g></svg>
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
<h3>跨平台网络分析组件 SDK</h3>
|
||||
<p>类似 Fiddler 的网络中间件,支持 HTTP/HTTPS/WS/WSS/TCP/UDP 网络分析</p>
|
||||
</div>
|
||||
|
||||
## 📌 重要通知
|
||||
|
||||
<div align="center">
|
||||
<h3><span style="color: red;">请注意: 由于本仓库历史记录太大</span></h3>
|
||||
<h3><span style="color: red;">本仓库于 2025-04-24 删除重建</span></h3>
|
||||
</div>
|
||||
|
||||
## 🌟 项目简介
|
||||
|
||||
Sunny网络中间件是一个功能强大的跨平台网络分析组件,专为二次开发而设计。它提供了完整的网络流量捕获和修改功能,支持多种协议类型。
|
||||
|
||||
## 🚀 主要特性
|
||||
|
||||
- ✅ **多协议支持**: HTTP/HTTPS/WS/WSS/TCP/UDP 网络分析
|
||||
- ✅ **数据获取与修改**: 可获取和修改所有协议的发送及返回数据
|
||||
- ✅ **代理设置**: 可为指定连接设置独立代理
|
||||
- ✅ **连接重定向**: 支持 HTTP/HTTPS/WS/WSS/TCP/TLS-TCP 链接重定向
|
||||
- ✅ **数据解码**: 支持 gzip, deflate, br, zstd 解码
|
||||
- ✅ **主动发送**: 支持 WS/WSS/TCP/TLS-TCP/UDP 主动发送数据
|
||||
- ✅ **跨平台**: 支持 Windows、Linux 和 macOS
|
||||
- ✅ **脚本支持**: 支持通过Go脚本自定义处理逻辑
|
||||
|
||||
## 🚦 多驱动支持
|
||||
|
||||
| 驱动名称 | 平台 | 127.0.0.1捕获 | 内网捕获 | 兼容性 |
|
||||
|---------|------|-------------|------|-------|
|
||||
| Netfilter | Windows | ✅ | ✅ | 一般 |
|
||||
| Proxifier | Windows | ✅ | ✅ | 一般 |
|
||||
| Tun(WinDivert) | Windows | ❌ | ✅ | 较好 |
|
||||
| Tun(VPN) | Android | ✅ | ✅ | 较好 |
|
||||
| Tun(utun) | MacOs | ❌ | ❌ | 较好 |
|
||||
| Tun(tun) | Linux | ❌ | ❌ | 较好 |
|
||||
|
||||
## 📚 SDK API 参考
|
||||
|
||||
|
||||
|
||||
有关Go语言环境下使用SunnyNet的详细示例,请参考 [Go语言使用示例](README_go.md) 文档。
|
||||
|
||||
|
||||
|
||||
完整的API参考文档请查看 [API参考文档](README_api.md)。
|
||||
|
||||
|
||||
## ⚙️ 使用说明
|
||||
|
||||
### 系统要求
|
||||
|
||||
- Windows 7 及以上版本(使用 Go 1.21 以下版本编译)
|
||||
- Windows 10/11 推荐(支持最新 Go 版本)
|
||||
- Linux / macOS 最新稳定版本
|
||||
|
||||
# <center><h3>Sunny网络中间件</center></h3></center>
|
||||
|
||||
---
|
||||
|
||||
> Sunny网络中间件 和 Fiddler 类似。 是可跨平台的网络分析组件
|
||||
```log
|
||||
可用于HTTP/HTTPS/WS/WSS/TCP/UDP网络分析 为二次开发量身制作
|
||||
|
||||
支持 获取/修改 HTTP/HTTPS/WS/WSS/TCP/TLS-TCP/UDP 发送及返回数据
|
||||
## 🛠 编译说明
|
||||
|
||||
### Windows 编译步骤
|
||||
|
||||
1. 安装 [TDM-GCC](https://github.com/jmeubank/tdm-gcc/releases/download/v10.3.0-tdm64-2/tdm64-gcc-10.3.0-2.exe)
|
||||
2. 进入到 SunnyNet 目录
|
||||
3. 执行命令 `.\BuildLibrary\BuildALL.bat`
|
||||
|
||||
### Linux 编译步骤
|
||||
|
||||
1. 确保已安装 GCC 工具链
|
||||
2. 进入到 SunnyNet 目录
|
||||
3. 执行命令 `.\BuildLibrary\Linux64.sh`
|
||||
4. 或 执行命令 `.\BuildLibrary\Linux32.sh`
|
||||
|
||||
### macOS 编译步骤
|
||||
|
||||
1. 确保已安装 GCC 工具链
|
||||
2. 进入到 SunnyNet 目录
|
||||
3. 执行命令 `.\BuildLibrary\MacOs_amd64.sh`
|
||||
4. 或 执行命令 `.\BuildLibrary\MacOs_arm64.sh`
|
||||
|
||||
支持 对 HTTP/HTTPS/WS/WSS 指定连接使用指定代理
|
||||
|
||||
## 📨 BUG 反馈与技术支持
|
||||
<p>项目网站: <a href="https://esunny.vip/">https://esunny.vip/</a></p>
|
||||
|
||||
支持 对 HTTP/HTTPS/WS/WSS/TCP/TLS-TCP 链接重定向
|
||||
|
||||
支持 gzip, deflate, br, zstd 解码
|
||||
|
||||
支持 WS/WSS/TCP/TLS-TCP/UDP 主动发送数据
|
||||
|
||||
```
|
||||
<p><strong>QQ群:</strong></p>
|
||||
|
||||
---
|
||||
* # 由于代码主要是做DLL使用,部分功能未封装给Go使用,请自行探索!
|
||||
* # 如需支持Win7系统
|
||||
* # 请使用Go1.21以下版本编译,例如 go 1.20.4版本
|
||||
* # <a href="https://github.com/jmeubank/tdm-gcc/releases/download/v10.3.0-tdm64-2/tdm64-gcc-10.3.0-2.exe">编译请使用 TDM-GCC</a>
|
||||
<div style="text-align: center;"><h2><a style="color: red;">BUG 反馈</a></h2></div>
|
||||
<div style="text-align: center;"><h3>QQ群:</h3></div>
|
||||
<div style="text-align: center;"><h3>一群:751406884</h3></div>
|
||||
<div style="text-align: center;"><h3>二群:545120699</h3></div>
|
||||
<div style="text-align: center;"><h3>三群:170902713</h3></div>
|
||||
<div style="text-align: center;"><h3>四群:1070797457</h3></div>
|
||||
<div style="text-align: center;"><h3>网址:<a href="https://esunny.vip/">https://esunny.vip/</a></h3></div>
|
||||
<ul>
|
||||
|
||||
---
|
||||
<li>一群:751406884</li>
|
||||
|
||||
### <center><h3>各语言,示例文件以及抓包工具 下载地址 </center>
|
||||
<div style="text-align: center;"><h3>https://wwxa.lanzouu.com/b02p4aet8j</h3></div>
|
||||
<div style="text-align: center;"><h3>密码:4h7r</h3></div>
|
||||
<div style="text-align: center;"><h3></h3></div>
|
||||
<li>二群:545120699</li>
|
||||
|
||||
<li>三群:170902713</li>
|
||||
|
||||
<li>四群:1070797457</li>
|
||||
|
||||
</ul>
|
||||
|
||||
## 📦 下载资源
|
||||
|
||||
|
||||
---
|
||||
- > GoLang使用示例代码
|
||||
|
||||
```golang
|
||||
package main
|
||||
<p>各语言示例文件以及抓包工具下载地址:</p>
|
||||
|
||||
import (
|
||||
"github.com/qtgolang/SunnyNet/SunnyNet"
|
||||
"github.com/qtgolang/SunnyNet/src/public"
|
||||
"time"
|
||||
"log"
|
||||
"fmt"
|
||||
)
|
||||
func main() {
|
||||
var Sunny = SunnyNet.NewSunny()
|
||||
/*
|
||||
//载入自定义证书
|
||||
cert := SunnyNet.NewCertManager()
|
||||
ok := cert.LoadP12Certificate("C:\\Users\\Qin\\Desktop\\Cert\\ca6afc5aa40fcbd3.p12", "GXjc75IRAO0T")
|
||||
fmt.Println("载入P12:", ok)
|
||||
fmt.Println("证书名称:", cert.GetCommonName())
|
||||
<p>🔗 <a href="https://wwxa.lanzouu.com/b02p4aet8j">https://wwxa.lanzouu.com/b02p4aet8j</a></p>
|
||||
|
||||
//给指定域名使用这个证书
|
||||
Sunny.AddHttpCertificate("api.vlightv.com", cert, SunnyNet.HTTPCertRules_Request)
|
||||
<p><strong>密码:</strong> 4h7r</p>
|
||||
|
||||
*/
|
||||
## ⚠️ 注意事项
|
||||
|
||||
/*
|
||||
log := func(Context int, info ...any) {
|
||||
fmt.Println("x脚本日志", fmt.Sprintf("%v", info))
|
||||
}
|
||||
save := func(Context int, code []byte) {
|
||||
//在这里将code代码 储存到文件,下次启动时,载入恢复
|
||||
}
|
||||
Sunny.SetScriptCall(log, save)
|
||||
//载入上次保存的脚本代码
|
||||
Sunny.SetScriptCode(string(GoScriptCode.DefaultCode))
|
||||
*/
|
||||
|
||||
/*
|
||||
//设置全局上游代理
|
||||
Sunny.SetGlobalProxy("socket://192.168.31.1:4321", 60000)
|
||||
|
||||
//指定IP或域名不使用全局的上游代理
|
||||
Sunny.CompileProxyRegexp("127.0.0.1;[::1];192.168.*;*.baidu.com")
|
||||
*/
|
||||
|
||||
/*
|
||||
//开启强制走TCP,开启后 https 将不会解密 直接转发数据流量
|
||||
Sunny.MustTcp(true)
|
||||
*/
|
||||
/*
|
||||
//禁止TCP,所有TCP流量将直接断开连接
|
||||
Sunny.DisableTCP(true)
|
||||
*/
|
||||
|
||||
/*
|
||||
//设置强制走TCP规则,使用这个函数后 就不要使用 Sunny.MustTcp(true) 否则这个函数无效
|
||||
Sunny.SetMustTcpRegexp("tpstelemetry.tencent.com", true)
|
||||
*/
|
||||
/*
|
||||
//使用驱动抓包 (两个驱动各有特点自行尝试,哪个能用/好用 用哪个)
|
||||
Sunny.OpenDrive(true) // 使用 NFAPI 驱动
|
||||
Sunny.OpenDrive(false) // 使用 Proxifier 驱动 不支持32位操作系统,不支持UDP数据捕获
|
||||
|
||||
Sunny.ProcessAddName("gamemon.des") //添加指定进程名称
|
||||
Sunny.ProcessDelName("gamemon.des") //删除已添加的指定进程名称
|
||||
Sunny.ProcessAddPid(1122) //添加指定进程PID
|
||||
Sunny.ProcessDelPid(1122) //删除已添加的指定进程PID
|
||||
Sunny.ProcessCancelAll() //删除已添加的所有进程名称/PID
|
||||
Sunny.ProcessALLName(true, false) //捕获全部进程开始后,添加进程名称-PID无效
|
||||
*/
|
||||
//设置回调地址
|
||||
Sunny.SetGoCallback(HttpCallback, TcpCallback, WSCallback, UdpCallback)
|
||||
Port := 2025
|
||||
Sunny.SetPort(Port).Start()
|
||||
err := Sunny.Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("Run Port=", Port)
|
||||
//阻止程序退出
|
||||
select {}
|
||||
}
|
||||
|
||||
func HttpCallback(Conn SunnyNet.ConnHTTP) {
|
||||
|
||||
if Conn.Type() == public.HttpSendRequest {
|
||||
//fmt.Println(Conn.URL())
|
||||
//发起请求
|
||||
|
||||
//直接响应,不让其发送请求
|
||||
//Conn.StopRequest(200, "Hello Word")
|
||||
|
||||
} else if Conn.Type() == public.HttpResponseOK {
|
||||
//请求完成
|
||||
//log.Println("Call", Conn.URL())
|
||||
} else if Conn.Type() == public.HttpRequestFail {
|
||||
//请求错误
|
||||
/* fmt.Println(Conn.Request.URL.String(), Conn.GetError())
|
||||
*/
|
||||
}
|
||||
}
|
||||
func WSCallback(Conn SunnyNet.ConnWebSocket) {
|
||||
log.Println("WebSocket", Conn.URL())
|
||||
}
|
||||
func TcpCallback(Conn SunnyNet.ConnTCP) {
|
||||
|
||||
if Conn.Type() == public.SunnyNetMsgTypeTCPAboutToConnect {
|
||||
//即将连接
|
||||
mode := string(Conn.Body())
|
||||
log.Println("PID", Conn.PID(), "TCP 即将连接到:", mode, Conn.LocalAddress(), "->", Conn.RemoteAddress())
|
||||
//修改目标连接地址
|
||||
//Conn.SetNewAddress("8.8.8.8:8080")
|
||||
return
|
||||
}
|
||||
|
||||
if Conn.Type() == public.SunnyNetMsgTypeTCPConnectOK {
|
||||
log.Println("PID", Conn.PID(), "TCP 连接到:", Conn.LocalAddress(), "->", Conn.RemoteAddress(), "成功")
|
||||
return
|
||||
}
|
||||
|
||||
if Conn.Type() == public.SunnyNetMsgTypeTCPClose {
|
||||
log.Println("PID", Conn.PID(), "TCP 断开连接:", Conn.LocalAddress(), "->", Conn.RemoteAddress())
|
||||
return
|
||||
}
|
||||
if Conn.Type() == public.SunnyNetMsgTypeTCPClientSend {
|
||||
log.Println("PID", Conn.PID(), "发送数据", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.Type(), Conn.BodyLen(), Conn.Body())
|
||||
return
|
||||
}
|
||||
if Conn.Type() == public.SunnyNetMsgTypeTCPClientReceive {
|
||||
log.Println("PID", Conn.PID(), "收到数据", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.Type(), Conn.BodyLen(), Conn.Body())
|
||||
return
|
||||
}
|
||||
}
|
||||
func UdpCallback(Conn SunnyNet.ConnUDP) {
|
||||
|
||||
if Conn.Type() == public.SunnyNetUDPTypeSend {
|
||||
//客户端向服务器端发送数据
|
||||
log.Println("PID", Conn.PID(), "发送UDP", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.BodyLen())
|
||||
//修改发送的数据
|
||||
//Conn.SetBody([]byte("Hello Word"))
|
||||
|
||||
return
|
||||
}
|
||||
if Conn.Type() == public.SunnyNetUDPTypeReceive {
|
||||
//服务器端向客户端发送数据
|
||||
log.Println("PID", Conn.PID(), "接收UDP", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.BodyLen())
|
||||
//修改响应的数据
|
||||
//Conn.SetBody([]byte("Hello Word"))
|
||||
return
|
||||
}
|
||||
if Conn.Type() == public.SunnyNetUDPTypeClosed {
|
||||
|
||||
log.Println("PID", Conn.PID(), "关闭UDP", Conn.LocalAddress(), Conn.RemoteAddress())
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
1. 如需支持 Win7 系统,请使用 Go 1.21 以下版本编译,例如 go 1.20.4 版本
|
||||
2. <a href="https://github.com/jmeubank/tdm-gcc/releases/download/v10.3.0-tdm64-2/tdm64-gcc-10.3.0-2.exe">编译请使用 TDM-GCC</a>
|
||||
281
README_api.md
Normal file
281
README_api.md
Normal file
@@ -0,0 +1,281 @@
|
||||
# Sunny网络中间件 SDK API 参考
|
||||
|
||||
## 目录
|
||||
|
||||
- [SunnyNet核心类](#sunnynet核心类)
|
||||
- [创建和管理SunnyNet实例](#创建和管理sunnynet实例)
|
||||
- [证书管理](#证书管理)
|
||||
- [回调设置](#回调设置)
|
||||
- [代理设置](#代理设置)
|
||||
- [TCP/UDP控制](#tcpudp控制)
|
||||
- [Socks5代理验证](#socks5代理验证)
|
||||
- [进程代理](#进程代理)
|
||||
- [网络设置](#网络设置)
|
||||
- [脚本支持](#脚本支持)
|
||||
- [HTTP/HTTPS处理](#httphttps处理)
|
||||
- [请求信息获取与修改](#请求信息获取与修改)
|
||||
- [响应信息获取与修改](#响应信息获取与修改)
|
||||
- [HTTP客户端](#http客户端)
|
||||
- [WebSocket处理](#websocket处理)
|
||||
- [TCP处理](#tcp处理)
|
||||
- [UDP处理](#udp处理)
|
||||
- [证书管理器](#证书管理器)
|
||||
- [其他工具函数](#其他工具函数)
|
||||
- [数据压缩/解压缩](#数据压缩解压缩)
|
||||
- [图片处理](#图片处理)
|
||||
- [Protobuf处理](#protobuf处理)
|
||||
- [队列操作](#队列操作)
|
||||
- [TCP客户端](#tcp客户端)
|
||||
- [WebSocket客户端](#websocket客户端)
|
||||
- [Redis客户端](#redis客户端)
|
||||
- [Go Map操作](#go-map操作)
|
||||
|
||||
## SunnyNet核心类
|
||||
|
||||
### 创建和管理SunnyNet实例
|
||||
- `CreateSunnyNet() int` - 创建Sunny中间件对象
|
||||
- `ReleaseSunnyNet(SunnyContext int) bool` - 释放SunnyNet
|
||||
- `SunnyNetStart(SunnyContext int) bool` - 启动Sunny中间件
|
||||
- `SunnyNetClose(SunnyContext int) bool` - 关闭停止指定Sunny中间件
|
||||
- `SunnyNetSetPort(SunnyContext, Port int) bool` - 设置指定端口
|
||||
- `SunnyNetError(SunnyContext int) uintptr` - 获取中间件启动时的错误信息
|
||||
|
||||
### 证书管理
|
||||
- `SunnyNetSetCert(SunnyContext, CertificateManagerId int) bool` - 设置自定义证书
|
||||
- `SunnyNetInstallCert(SunnyContext int) uintptr` - 安装证书到Windows系统内
|
||||
- `ExportCert(SunnyContext int) uintptr` - 导出已设置的证书
|
||||
|
||||
### 回调设置
|
||||
- `SunnyNetSetCallback(SunnyContext, httpCallback, tcpCallback, wsCallback, udpCallback int) bool` - 设置中间件回调地址
|
||||
|
||||
### 代理设置
|
||||
- `SetGlobalProxy(SunnyContext int, ProxyAddress *C.char, outTime int) bool` - 设置全局上游代理
|
||||
- `CompileProxyRegexp(SunnyContext int, Regexp *C.char) bool` - 设置中间件上游代理使用规则
|
||||
|
||||
### TCP/UDP控制
|
||||
- `SunnyNetMustTcp(SunnyContext int, open bool)` - 设置中间件是否开启强制走TCP
|
||||
- `SetMustTcpRegexp(SunnyContext int, Regexp *C.char, RulesAllow bool) bool` - 设置强制走TCP规则
|
||||
- `DisableTCP(SunnyContext int, Disable bool) bool` - 禁用TCP
|
||||
- `DisableUDP(SunnyContext int, Disable bool) bool` - 禁用UDP
|
||||
|
||||
### Socks5代理验证
|
||||
- `SunnyNetSocket5AddUser(SunnyContext int, User, Pass *C.char) bool` - 添加S5代理需要验证的用户名
|
||||
- `SunnyNetVerifyUser(SunnyContext int, open bool) bool` - 开启身份验证模式
|
||||
- `SunnyNetSocket5DelUser(SunnyContext int, User *C.char) bool` - 删除S5需要验证的用户名
|
||||
- `SunnyNetGetSocket5User(Theology int) uintptr` - 获取授权的S5账号
|
||||
|
||||
### 进程代理
|
||||
- `OpenDrive(SunnyContext int, devMode int) bool` - 开始进程代理/打开驱动
|
||||
- `UnDrive(SunnyContext int)` - 卸载驱动
|
||||
- `ProcessAddName(SunnyContext int, Name *C.char)` - 进程代理添加进程名
|
||||
- `ProcessDelName(SunnyContext int, Name *C.char)` - 进程代理删除进程名
|
||||
- `ProcessAddPid(SunnyContext, pid int)` - 进程代理添加PID
|
||||
- `ProcessDelPid(SunnyContext, pid int)` - 进程代理删除PID
|
||||
- `ProcessCancelAll(SunnyContext int)` - 进程代理取消全部已设置的进程名
|
||||
- `ProcessALLName(SunnyContext int, open, StopNetwork bool)` - 进程代理设置是否全部进程通过
|
||||
|
||||
### 网络设置
|
||||
- `SetOutRouterIP(SunnyContext int, value *C.char) bool` - 设置数据出口IP
|
||||
- `SetIeProxy(SunnyContext int) bool` - 设置IE代理
|
||||
- `CancelIEProxy(SunnyContext int) bool` - 取消设置的IE代理
|
||||
- `SetDnsServer(ServerName *C.char)` - 设置Dns解析服务器
|
||||
|
||||
### 脚本支持
|
||||
- `SetScriptCode(SunnyContext int, code uintptr, length int) uintptr` - 加载用户的脚本代码
|
||||
- `SetScriptCall(SunnyContext int, LOG, SAVE uintptr)` - 设置脚本代码的回调函数
|
||||
- `SetScriptPage(SunnyContext int, Page *C.char) uintptr` - 设置脚本编辑器页面
|
||||
|
||||
## HTTP/HTTPS处理
|
||||
|
||||
### 请求信息获取与修改
|
||||
- `GetRequestProto(MessageId int) uintptr` - 获取HTTPS请求的协议版本
|
||||
- `SetRequestUrl(MessageId int, URI *C.char) bool` - 修改HTTP/S当前请求的URL
|
||||
- `GetRequestHeader(MessageId int, name *C.char) uintptr` - 获取HTTP/S当前请求数据中的指定协议头
|
||||
- `SetRequestHeader(MessageId int, name, val *C.char)` - 设置HTTP/S请求体中的协议头
|
||||
- `DelRequestHeader(MessageId int, name *C.char)` - 删除HTTP/S请求数据中指定的协议头
|
||||
- `GetRequestAllHeader(MessageId int) uintptr` - 获取HTTP/S当前请求数据全部协议头
|
||||
- `SetRequestALLHeader(MessageId int, val *C.char)` - 设置HTTP/S请求体中的全部协议头
|
||||
- `GetRequestCookie(MessageId int, name *C.char) uintptr` - 获取HTTP/S当前请求数据中指定的Cookie
|
||||
- `GetRequestALLCookie(MessageId int) uintptr` - 获取HTTP/S当前请求全部Cookie
|
||||
- `SetRequestCookie(MessageId int, name, val *C.char)` - 修改、设置HTTP/S当前请求数据中指定Cookie
|
||||
- `SetRequestAllCookie(MessageId int, val *C.char)` - 修改、设置HTTP/S当前请求数据中的全部Cookie
|
||||
- `GetRequestBodyLen(MessageId int) int` - 获取HTTP/S当前请求POST提交数据长度
|
||||
- `GetRequestBody(MessageId int) uintptr` - 获取HTTP/S当前POST提交数据
|
||||
- `SetRequestData(MessageId int, data uintptr, dataLen int) bool` - 设置、修改HTTP/S当前请求POST提交数据
|
||||
- `IsRequestRawBody(MessageId int) bool` - 此请求是否为原始body
|
||||
- `RawRequestDataToFile(MessageId int, saveFileName uintptr, len int) bool` - 获取HTTP/S当前POST提交数据原始Data
|
||||
|
||||
### 响应信息获取与修改
|
||||
- `GetResponseProto(MessageId int) uintptr` - 获取HTTPS响应的协议版本
|
||||
- `GetResponseHeader(MessageId int, name *C.char) uintptr` - 获取HTTP/S当前返回数据中指定的协议头
|
||||
- `SetResponseHeader(MessageId int, name *C.char, val *C.char)` - 修改、设置HTTP/S当前返回数据中的指定协议头
|
||||
- `DelResponseHeader(MessageId int, name *C.char)` - 删除HTTP/S返回数据中指定的协议头
|
||||
- `GetResponseAllHeader(MessageId int) uintptr` - 获取HTTP/S当前返回全部协议头
|
||||
- `SetResponseAllHeader(MessageId int, value *C.char)` - 修改、设置HTTP/S当前返回数据中的全部协议头
|
||||
- `GetResponseBodyLen(MessageId int) int` - 获取HTTP/S当前返回数据长度
|
||||
- `GetResponseBody(MessageId int) uintptr` - 获取HTTP/S当前返回数据
|
||||
- `SetResponseData(MessageId int, data uintptr, dataLen int) bool` - 设置、修改HTTP/S当前请求返回数据
|
||||
- `GetResponseStatusCode(MessageId int) int` - 获取HTTP/S返回的状态码
|
||||
- `GetResponseStatus(MessageId int) uintptr` - 获取HTTP/S返回的状态文本
|
||||
- `SetResponseStatus(MessageId, code int)` - 修改HTTP/S返回的状态码
|
||||
|
||||
### HTTP客户端
|
||||
- `CreateHTTPClient() int` - 创建HTTP客户端
|
||||
- `RemoveHTTPClient(Context int)` - 释放HTTP客户端
|
||||
- `HTTPOpen(Context int, Method, URL *C.char)` - HTTP客户端Open
|
||||
- `HTTPSetHeader(Context int, name, value *C.char)` - HTTP客户端设置协议头
|
||||
- `HTTPSetProxyIP(Context int, ProxyUrl *C.char) bool` - HTTP客户端设置代理IP
|
||||
- `HTTPSetServerIP(Context int, ServerIP *C.char)` - HTTP客户端设置真实连接IP地址
|
||||
- `HTTPSetTimeouts(Context int, t1 int)` - HTTP客户端设置超时
|
||||
- `HTTPSendBin(Context int, body uintptr, bodyLength int)` - HTTP客户端发送Body
|
||||
- `HTTPGetHeads(Context int) uintptr` - HTTP客户端返回响应全部Heads
|
||||
- `HTTPGetHeader(Context int, name *C.char) uintptr` - HTTP客户端返回响应HTTPGetHeader
|
||||
- `HTTPGetRequestHeader(Context int) uintptr` - HTTP客户端添加的全部协议头
|
||||
- `HTTPGetBodyLen(Context int) int` - HTTP客户端返回响应长度
|
||||
- `HTTPGetBody(Context int) uintptr` - HTTP客户端返回响应内容
|
||||
- `HTTPGetCode(Context int) int` - HTTP客户端返回响应状态码
|
||||
- `HTTPSetCertManager(Context, CertManagerContext int) bool` - HTTP客户端设置证书管理器
|
||||
- `HTTPSetRedirect(Context int, Redirect bool) bool` - HTTP客户端设置重定向
|
||||
- `HTTPSetRandomTLS(Context int, RandomTLS bool) bool` - HTTP客户端设置随机使用TLS指纹
|
||||
- `HTTPSetH2Config(Context int, config *C.char) bool` - HTTP客户端设置HTTP2指纹
|
||||
|
||||
## WebSocket处理
|
||||
- `GetWebsocketBodyLen(MessageId int) int` - 获取WebSocket消息长度
|
||||
- `GetWebsocketBody(MessageId int) uintptr` - 获取WebSocket消息
|
||||
- `SetWebsocketBody(MessageId int, data uintptr, dataLen int) bool` - 修改WebSocket消息
|
||||
- `SendWebsocketBody(Theology, MessageType int, data uintptr, dataLen int) bool` - 主动向Websocket服务器发送消息
|
||||
- `SendWebsocketClientBody(Theology, MessageType int, data uintptr, dataLen int) bool` - 主动向Websocket客户端发送消息
|
||||
- `CloseWebsocket(Theology int) bool` - 主动关闭Websocket
|
||||
|
||||
## TCP处理
|
||||
- `SetTcpBody(MessageId, MsgType int, data uintptr, dataLen int) bool` - 修改TCP消息数据
|
||||
- `SetTcpAgent(MessageId int, ProxyUrl *C.char, outTime int) bool` - 给当前TCP连接设置代理
|
||||
- `TcpCloseClient(theology int) bool` - 根据唯一ID关闭指定的TCP连接
|
||||
- `SetTcpConnectionIP(MessageId int, address *C.char) bool` - 给指定的TCP连接修改目标连接地址
|
||||
- `TcpSendMsg(theology int, data uintptr, dataLen int) int` - 指定的TCP连接模拟客户端向服务器端主动发送数据
|
||||
- `TcpSendMsgClient(theology int, data uintptr, dataLen int) int` - 指定的TCP连接模拟服务器端向客户端主动发送数据
|
||||
|
||||
## UDP处理
|
||||
- `GetUdpData(MessageId int) uintptr` - 获取UDP数据
|
||||
- `SetUdpData(MessageId int, val uintptr, valLen int) bool` - 设置修改UDP数据
|
||||
- `UdpSendToClient(theology int, data uintptr, dataLen int) bool` - 指定的UDP连接模拟服务器端向客户端主动发送数据
|
||||
- `UdpSendToServer(theology int, data uintptr, dataLen int) bool` - 指定的UDP连接模拟客户端向服务器端主动发送数据
|
||||
|
||||
## 证书管理器
|
||||
- `CreateCertificate() int` - 创建证书管理器对象
|
||||
- `RemoveCertificate(Context int)` - 释放证书管理器对象
|
||||
- `LoadX509Certificate(Context int, Host, CA, KEY *C.char) bool` - 载入X509证书
|
||||
- `LoadX509KeyPair(Context int, CaPath, KeyPath *C.char) bool` - 载入X509证书2
|
||||
- `LoadP12Certificate(Context int, Name, Password *C.char) bool` - 载入p12证书
|
||||
- `SetInsecureSkipVerify(Context int, b bool) bool` - 设置跳过主机验证
|
||||
- `SetServerName(Context int, name *C.char) bool` - 设置ServerName
|
||||
- `GetServerName(Context int) uintptr` - 取ServerName
|
||||
- `AddCertPoolPath(Context int, cer *C.char) bool` - 设置信任的证书从文件
|
||||
- `AddCertPoolText(Context int, cer *C.char) bool` - 设置信任的证书从文本
|
||||
- `SetCipherSuites(Context int, val *C.char) bool` - 设置CipherSuites
|
||||
- `AddClientAuth(Context, val int) bool` - 设置ClientAuth
|
||||
- `CreateCA(Context int, Country, Organization, OrganizationalUnit, Province, CommonName, Locality *C.char, bits, NotAfter int) bool` - 创建证书
|
||||
- `ExportCA(Context int) uintptr` - 导出证书
|
||||
- `ExportKEY(Context int) uintptr` - 导出私钥
|
||||
- `ExportPub(Context int) uintptr` - 导出公钥
|
||||
- `ExportP12(Context int, path, pass *C.char) bool` - 导出为P12
|
||||
- `GetCommonName(Context int) uintptr` - 获取证书CommonName字段
|
||||
|
||||
## 其他工具函数
|
||||
- `GetSunnyVersion() uintptr` - 获取SunnyNet版本
|
||||
- `Free(ptr uintptr)` - 释放指针
|
||||
- `SetHTTPRequestMaxUpdateLength(SunnyContext int, i int64) bool` - 设置HTTP请求提交数据的最大长度
|
||||
- `RandomRequestCipherSuites(MessageId int) bool` - 随机设置请求CipherSuites
|
||||
- `SetRequestHTTP2Config(MessageId int, h2Config *C.char) bool` - 设置HTTP 2.0请求指纹配置
|
||||
- `GetRequestClientIp(MessageId int) uintptr` - 获取当前HTTP/S请求由哪个IP发起
|
||||
- `GetResponseServerAddress(MessageId int) uintptr` - 获取HTTP/S相应的服务器地址
|
||||
- `SetRequestOutTime(MessageId int, times int)` - 请求设置超时-毫秒
|
||||
- `GetMessageNote(MessageId int) uintptr` - 获取请求中的注释
|
||||
- `BytesToInt(data uintptr, dataLen int) int` - 将Go int的Bytes转为int
|
||||
|
||||
### 数据压缩/解压缩
|
||||
- `GzipUnCompress(data uintptr, dataLen int) uintptr` - Gzip解压缩
|
||||
- `GzipCompress(data uintptr, dataLen int) uintptr` - Gzip压缩
|
||||
- `BrUnCompress(data uintptr, dataLen int) uintptr` - br解压缩
|
||||
- `BrCompress(data uintptr, dataLen int) uintptr` - br压缩
|
||||
- `BrotliCompress(data uintptr, dataLen int) uintptr` - br压缩(别名)
|
||||
- `ZSTDDecompress(data uintptr, dataLen int) uintptr` - ZSTD解压缩
|
||||
- `ZSTDCompress(data uintptr, dataLen int) uintptr` - ZSTD压缩
|
||||
- `ZlibUnCompress(data uintptr, dataLen int) uintptr` - Zlib解压缩
|
||||
- `ZlibCompress(data uintptr, dataLen int) uintptr` - Zlib压缩
|
||||
- `DeflateUnCompress(data uintptr, dataLen int) uintptr` - Deflate解压缩
|
||||
- `DeflateCompress(data uintptr, dataLen int) uintptr` - Deflate压缩
|
||||
|
||||
### 图片处理
|
||||
- `WebpToJpegBytes(data uintptr, dataLen int, SaveQuality int) uintptr` - Webp图片转JEG图片字节数组
|
||||
- `WebpToPngBytes(data uintptr, dataLen int) uintptr` - Webp图片转Png图片字节数组
|
||||
- `WebpToJpeg(webpPath, savePath *C.char, SaveQuality int) bool` - Webp图片转JEG图片根据文件名
|
||||
- `WebpToPng(webpPath, savePath *C.char) bool` - Webp图片转Png图片根据文件名
|
||||
|
||||
### Protobuf处理
|
||||
- `JsonToPB(bin uintptr, binLen int) uintptr` - JSON格式的protobuf数据转为protobuf二进制数据
|
||||
- `PbToJson(bin uintptr, binLen int) uintptr` - protobuf数据转为JSON格式
|
||||
|
||||
### 队列操作
|
||||
- `CreateQueue(name *C.char)` - 创建队列
|
||||
- `QueueIsEmpty(name *C.char) bool` - 队列是否为空
|
||||
- `QueueRelease(name *C.char)` - 清空销毁队列
|
||||
- `QueueLength(name *C.char) int` - 取队列长度
|
||||
- `QueuePush(name *C.char, val uintptr, valLen int)` - 加入队列
|
||||
- `QueuePull(name *C.char) uintptr` - 队列弹出
|
||||
|
||||
### TCP客户端
|
||||
- `CreateSocketClient() int` - 创建TCP客户端
|
||||
- `RemoveSocketClient(Context int)` - 释放TCP客户端
|
||||
- `SocketClientDial(Context int, addr *C.char, call int, isTls, synchronous bool, ProxyUrl *C.char, CertificateConText int, OutTime int, OutRouterIP *C.char) bool` - TCP客户端连接
|
||||
- `SocketClientReceive(Context, OutTimes int) uintptr` - TCP客户端同步模式下接收数据
|
||||
- `SocketClientWrite(Context, OutTimes int, val uintptr, valLen int) int` - TCP客户端发送数据
|
||||
- `SocketClientClose(Context int)` - TCP客户端断开连接
|
||||
- `SocketClientSetBufferSize(Context, BufferSize int) bool` - TCP客户端置缓冲区大小
|
||||
- `SocketClientGetErr(Context int) uintptr` - TCP客户端取错误
|
||||
|
||||
### WebSocket客户端
|
||||
- `CreateWebsocket() int` - 创建WebSocket客户端对象
|
||||
- `RemoveWebsocket(Context int)` - 释放WebSocket客户端对象
|
||||
- `WebsocketDial(Context int, URL, Heads *C.char, call int, synchronous bool, ProxyUrl *C.char, CertificateConText, outTime int, OutRouterIP *C.char) bool` - Websocket客户端连接
|
||||
- `WebsocketReceive(Context, OutTimes int) uintptr` - Websocket客户端同步模式下接收数据
|
||||
- `WebsocketReadWrite(Context int, val uintptr, valLen int, messageType int) bool` - Websocket客户端发送数据
|
||||
- `WebsocketClose(Context int)` - Websocket客户端断开
|
||||
- `WebsocketHeartbeat(Context, HeartbeatTime, call int)` - Websocket客户端心跳设置
|
||||
- `WebsocketGetErr(Context int) uintptr` - Websocket客户端获取错误
|
||||
|
||||
### Redis客户端
|
||||
- `CreateRedis() int` - 创建Redis对象
|
||||
- `RemoveRedis(Context int)` - 释放Redis对象
|
||||
- `RedisDial(Context int, host, pass *C.char, db, PoolSize, MinIdleCons, DialTimeout, ReadTimeout, WriteTimeout, PoolTimeout, IdleCheckFrequency, IdleTimeout int, error uintptr) bool` - Redis连接
|
||||
- `RedisSetBytes(Context int, key *C.char, val uintptr, valLen int, expr int) bool` - Redis设置Bytes值
|
||||
- `RedisSet(Context int, key, val *C.char, expr int) bool` - Redis设置值
|
||||
- `RedisSetNx(Context int, key, val *C.char, expr int) bool` - Redis设置NX
|
||||
- `RedisExists(Context int, key *C.char) bool` - Redis检查指定key是否存在
|
||||
- `RedisGetBytes(Context int, key *C.char) uintptr` - Redis取Bytes值
|
||||
- `RedisGetStr(Context int, key *C.char) uintptr` - Redis取文本值
|
||||
- `RedisDo(Context int, args *C.char, error uintptr) uintptr` - Redis自定义执行和查询命令
|
||||
- `RedisGetInt(Context int, key *C.char) int64` - Redis取整数值
|
||||
- `RedisGetKeys(Context int, key *C.char) uintptr` - Redis取指定条件键名
|
||||
- `RedisDelete(Context int, key *C.char) bool` - Redis删除
|
||||
- `RedisFlushDB(Context int)` - Redis清空当前数据库
|
||||
- `RedisFlushAll(Context int)` - Redis清空redis服务器
|
||||
- `RedisClose(Context int)` - Redis关闭
|
||||
- `RedisSubscribe(Context int, scribe *C.char, call int, nc bool) bool` - Redis订阅消息
|
||||
|
||||
### Go Map操作
|
||||
- `CreateKeys() int` - GoMap创建
|
||||
- `RemoveKeys(KeysHandle int)` - GoMap删除GoMap
|
||||
- `KeysDelete(KeysHandle int, name *C.char)` - GoMap删除
|
||||
- `KeysRead(KeysHandle int, name *C.char) uintptr` - GoMap读取字符串/字节数组
|
||||
- `KeysWrite(KeysHandle int, name *C.char, val uintptr, length int)` - GoMap写字节数组
|
||||
- `KeysWriteFloat(KeysHandle int, name *C.char, val float64)` - GoMap写浮点数
|
||||
- `KeysReadFloat(KeysHandle int, name *C.char) float64` - GoMap读浮点数
|
||||
- `KeysWriteLong(KeysHandle int, name *C.char, val int64)` - GoMap写长整数
|
||||
- `KeysReadLong(KeysHandle int, name *C.char) int64` - GoMap读长整数
|
||||
- `KeysWriteInt(KeysHandle int, name *C.char, val int)` - GoMap写整数
|
||||
- `KeysReadInt(KeysHandle int, name *C.char) int` - GoMap读整数
|
||||
- `KeysEmpty(KeysHandle int)` - GoMap清空
|
||||
- `KeysGetCount(KeysHandle int) int` - GoMap取数量
|
||||
- `KeysGetJson(KeysHandle int) uintptr` - GoMap转为JSON字符串
|
||||
- `KeysWriteStr(KeysHandle int, name *C.char, val uintptr, len int)` - GoMap写字符串
|
||||
514
README_go.md
Normal file
514
README_go.md
Normal file
@@ -0,0 +1,514 @@
|
||||
# SunnyNet Go语言使用示例
|
||||
|
||||
本文档提供了SunnyNet网络中间件在Go语言环境下的各种使用场景示例,基于test.go文件中的实际代码示例。
|
||||
|
||||
## 目录
|
||||
|
||||
1. [基础HTTP代理](#基础http代理)
|
||||
2. [双向认证处理](#双向认证处理)
|
||||
3. [WebSocket处理](#websocket处理)
|
||||
4. [TCP连接处理](#tcp连接处理)
|
||||
5. [UDP数据处理](#udp数据处理)
|
||||
6. [证书管理](#证书管理)
|
||||
7. [代理设置](#代理设置)
|
||||
8. [驱动模式](#驱动模式)
|
||||
9. [DNS解析模式](#dns解析模式)
|
||||
10. [其他功能](#其他功能)
|
||||
|
||||
## 基础HTTP代理
|
||||
|
||||
### 简单HTTP代理服务器
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"github.com/qtgolang/SunnyNet/SunnyNet"
|
||||
"github.com/qtgolang/SunnyNet/src/public"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var Sunny = SunnyNet.NewSunny()
|
||||
|
||||
// 设置回调地址
|
||||
Sunny.SetGoCallback(HttpCallback, TcpCallback, WSCallback, UdpCallback)
|
||||
|
||||
Port := 2021
|
||||
Sunny.SetPort(Port).Start()
|
||||
|
||||
err := Sunny.Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Run Port=", Port)
|
||||
|
||||
// 阻止程序退出
|
||||
select {}
|
||||
}
|
||||
|
||||
func HttpCallback(Conn SunnyNet.ConnHTTP) {
|
||||
switch Conn.Type() {
|
||||
case public.HttpSendRequest: // 发起请求
|
||||
fmt.Println("发起请求", Conn.URL(), Conn.Proto(), Conn.GetProcessName())
|
||||
// 直接响应,不让其发送请求
|
||||
// Conn.StopRequest(200, "Hello Word")
|
||||
return
|
||||
case public.HttpResponseOK: // 请求完成
|
||||
bs := Conn.GetResponseBody()
|
||||
log.Println("请求完成", Conn.GetResponseProto(), Conn.URL(), len(bs), Conn.GetResponseHeader())
|
||||
return
|
||||
case public.HttpRequestFail: // 请求错误
|
||||
// fmt.Println(time.Now(), Conn.URL(), Conn.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func WSCallback(Conn SunnyNet.ConnWebSocket) {
|
||||
switch Conn.Type() {
|
||||
case public.WebsocketConnectionOK: // 连接成功
|
||||
log.Println("PID", Conn.PID(), "Websocket 连接成功:", Conn.URL())
|
||||
return
|
||||
case public.WebsocketUserSend: // 发送数据
|
||||
log.Println("PID", Conn.PID(), "Websocket 发送数据:", Conn.MessageType(), "->", hex.EncodeToString(Conn.Body()))
|
||||
return
|
||||
case public.WebsocketServerSend: // 收到数据
|
||||
log.Println("PID", Conn.PID(), "Websocket 收到数据:", Conn.MessageType(), "->", hex.EncodeToString(Conn.Body()))
|
||||
return
|
||||
case public.WebsocketDisconnect: // 连接关闭
|
||||
log.Println("PID", Conn.PID(), "Websocket 连接关闭", Conn.URL())
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TcpCallback(Conn SunnyNet.ConnTCP) {
|
||||
switch Conn.Type() {
|
||||
case public.SunnyNetMsgTypeTCPAboutToConnect: // 即将连接
|
||||
mode := string(Conn.Body())
|
||||
log.Println("PID", Conn.PID(), "TCP 即将连接到:", mode, Conn.LocalAddress(), "->", Conn.RemoteAddress())
|
||||
// 修改目标连接地址
|
||||
// Conn.SetNewAddress("8.8.8.8:8080")
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPConnectOK: // 连接成功
|
||||
// log.Println("PID", Conn.PID(), "TCP 连接到:", Conn.LocalAddress(), "->", Conn.RemoteAddress(), "成功")
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPClose: // 连接关闭
|
||||
// log.Println("PID", Conn.PID(), "TCP 断开连接:", Conn.LocalAddress(), "->", Conn.RemoteAddress())
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPClientSend: // 客户端发送数据
|
||||
// log.Println("PID", Conn.PID(), "TCP 发送数据", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.Type(), Conn.BodyLen(), len(Conn.Body()))
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPClientReceive: // 客户端收到数据
|
||||
// log.Println("PID", Conn.PID(), "收到数据", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.Type(), Conn.BodyLen(), len(Conn.Body()))
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func UdpCallback(Conn SunnyNet.ConnUDP) {
|
||||
switch Conn.Type() {
|
||||
case public.SunnyNetUDPTypeSend: // 客户端向服务器端发送数据
|
||||
log.Println("PID", Conn.PID(), Conn.GetProcessName(), "发送UDP", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.BodyLen())
|
||||
// 修改发送的数据
|
||||
// Conn.SetBody([]byte("Hello Word"))
|
||||
return
|
||||
case public.SunnyNetUDPTypeReceive: // 服务器端向客户端发送数据
|
||||
log.Println("PID", Conn.PID(), Conn.GetProcessName(), "接收UDP", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.BodyLen())
|
||||
// 修改响应的数据
|
||||
// Conn.SetBody([]byte("Hello Word"))
|
||||
return
|
||||
case public.SunnyNetUDPTypeClosed: // 关闭会话
|
||||
log.Println("PID", Conn.PID(), Conn.GetProcessName(), "关闭UDP", Conn.LocalAddress(), Conn.RemoteAddress())
|
||||
return
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 双向认证处理
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"github.com/qtgolang/SunnyNet/SunnyNet"
|
||||
"github.com/qtgolang/SunnyNet/src/public"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var Sunny = SunnyNet.NewSunny()
|
||||
// 载入自定义证书
|
||||
cert := SunnyNet.NewCertManager()
|
||||
ok := cert.LoadP12Certificate("./test.p12", "password")
|
||||
if ok {
|
||||
fmt.Println("证书名称:", cert.GetCommonName())
|
||||
// 给指定域名使用这个证书
|
||||
// SunnyNet.HTTPCertRules_ResponseAndRequest 按需调整 SunnyNet.HTTPCertRules_Request、SunnyNet.HTTPCertRules_Response
|
||||
Sunny.AddHttpCertificate("api.test.com", cert, SunnyNet.HTTPCertRules_ResponseAndRequest)
|
||||
}else{
|
||||
panic("载入P12证书失败")
|
||||
}
|
||||
// 设置回调地址
|
||||
Sunny.SetGoCallback(HttpCallback, nil, nil, nil)
|
||||
|
||||
Port := 2021
|
||||
Sunny.SetPort(Port).Start()
|
||||
|
||||
err := Sunny.Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Run Port=", Port)
|
||||
|
||||
// 阻止程序退出
|
||||
select {}
|
||||
}
|
||||
|
||||
func HttpCallback(Conn SunnyNet.ConnHTTP) {
|
||||
switch Conn.Type() {
|
||||
case public.HttpSendRequest: // 发起请求
|
||||
fmt.Println("发起请求", Conn.URL(), Conn.Proto(), Conn.GetProcessName())
|
||||
// 直接响应,不让其发送请求
|
||||
// Conn.StopRequest(200, "Hello Word")
|
||||
return
|
||||
case public.HttpResponseOK: // 请求完成
|
||||
bs := Conn.GetResponseBody()
|
||||
log.Println("请求完成", Conn.GetResponseProto(), Conn.URL(), len(bs), Conn.GetResponseHeader())
|
||||
return
|
||||
case public.HttpRequestFail: // 请求错误
|
||||
// fmt.Println(time.Now(), Conn.URL(), Conn.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## WebSocket处理
|
||||
|
||||
### WebSocket连接监控
|
||||
|
||||
```go
|
||||
func WSCallback(Conn SunnyNet.ConnWebSocket) {
|
||||
switch Conn.Type() {
|
||||
case public.WebsocketConnectionOK: // 连接成功
|
||||
log.Println("PID", Conn.PID(), "Websocket 连接成功:", Conn.URL())
|
||||
// 连接建立时可以主动发送消息
|
||||
// Conn.SendToClient(1, []byte("Hello from proxy!"))
|
||||
return
|
||||
case public.WebsocketUserSend: // 发送数据
|
||||
log.Println("PID", Conn.PID(), "Websocket 发送数据:", Conn.MessageType(), "->", hex.EncodeToString(Conn.Body()))
|
||||
// 可以修改发送的消息
|
||||
// if Conn.MessageType() == 1 { // 文本消息
|
||||
// modifiedMsg := []byte("modified: " + string(Conn.Body()))
|
||||
// Conn.SetBody(modifiedMsg)
|
||||
// }
|
||||
// 拦截此消息,不让此消息发出
|
||||
// Conn.SetBody(nil)
|
||||
// 主动向客户端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToClient([]byte("模拟服务端发送到客户端的消息"))
|
||||
// 主动向服务端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToServer([]byte("模拟客户端发送到服务端的消息"))
|
||||
return
|
||||
case public.WebsocketServerSend: // 收到数据
|
||||
log.Println("PID", Conn.PID(), "Websocket 收到数据:", Conn.MessageType(), "->", hex.EncodeToString(Conn.Body()))
|
||||
// 可以修改接收的消息
|
||||
// if Conn.MessageType() == 1 { // 文本消息
|
||||
// modifiedMsg := []byte("modified: " + string(Conn.Body()))
|
||||
// Conn.SetBody(modifiedMsg)
|
||||
// }
|
||||
// 拦截此消息,不让此消息发出
|
||||
// Conn.SetBody(nil)
|
||||
// 主动向客户端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToClient([]byte("模拟服务端发送到客户端的消息"))
|
||||
// 主动向服务端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToServer([]byte("模拟客户端发送到服务端的消息"))
|
||||
return
|
||||
case public.WebsocketDisconnect: // 连接关闭
|
||||
log.Println("PID", Conn.PID(), "Websocket 连接关闭", Conn.URL())
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## TCP连接处理
|
||||
|
||||
### TCP连接监控
|
||||
|
||||
```go
|
||||
func TcpCallback(Conn SunnyNet.ConnTCP) {
|
||||
switch Conn.Type() {
|
||||
case public.SunnyNetMsgTypeTCPAboutToConnect: // 即将连接
|
||||
mode := string(Conn.Body())
|
||||
log.Println("PID", Conn.PID(), "TCP 即将连接到:", mode, Conn.LocalAddress(), "->", Conn.RemoteAddress())
|
||||
// 修改目标连接地址
|
||||
// Conn.SetNewAddress("8.8.8.8:8080")
|
||||
// 设置TCP代理
|
||||
// Conn.SetAgent("socks5://user:pass@127.0.0.1:1080", 30)
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPConnectOK: // 连接成功
|
||||
// log.Println("PID", Conn.PID(), "TCP 连接到:", Conn.LocalAddress(), "->", Conn.RemoteAddress(), "成功")
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPClose: // 连接关闭
|
||||
// log.Println("PID", Conn.PID(), "TCP 断开连接:", Conn.LocalAddress(), "->", Conn.RemoteAddress())
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPClientSend: // 客户端发送数据
|
||||
// log.Println("PID", Conn.PID(), "TCP 发送数据", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.Type(), Conn.BodyLen(), len(Conn.Body()))
|
||||
// 修改发送的数据
|
||||
// Conn.SetBody([]byte("modified data"))
|
||||
// 拦截此消息,不让此消息发出
|
||||
// Conn.SetBody(nil)
|
||||
// 主动向客户端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToClient([]byte("模拟服务端发送到客户端的消息"))
|
||||
// 主动向服务端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToServer([]byte("模拟客户端发送到服务端的消息"))
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPClientReceive: // 客户端收到数据
|
||||
// log.Println("PID", Conn.PID(), "收到数据", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.Type(), Conn.BodyLen(), len(Conn.Body()))
|
||||
// 修改接收的数据
|
||||
// Conn.SetBody([]byte("modified response"))
|
||||
// 拦截此消息,不让此消息发出
|
||||
// Conn.SetBody(nil)
|
||||
// 主动向客户端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToClient([]byte("模拟服务端发送到客户端的消息"))
|
||||
// 主动向服务端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToServer([]byte("模拟客户端发送到服务端的消息"))
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## UDP数据处理
|
||||
|
||||
### UDP监控
|
||||
|
||||
```go
|
||||
func UdpCallback(Conn SunnyNet.ConnUDP) {
|
||||
switch Conn.Type() {
|
||||
case public.SunnyNetUDPTypeSend: // 客户端向服务器端发送数据
|
||||
log.Println("PID", Conn.PID(), Conn.GetProcessName(), "发送UDP", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.BodyLen())
|
||||
// 修改发送的数据
|
||||
// Conn.SetBody([]byte("Hello Word"))
|
||||
// 拦截此消息,不让此消息发出
|
||||
// Conn.SetBody(nil)
|
||||
// 主动向客户端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToClient([]byte("模拟服务端发送到客户端的消息"))
|
||||
// 主动向服务端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToServer([]byte("模拟客户端发送到服务端的消息"))
|
||||
return
|
||||
case public.SunnyNetUDPTypeReceive: // 服务器端向客户端发送数据
|
||||
log.Println("PID", Conn.PID(), Conn.GetProcessName(), "接收UDP", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.BodyLen())
|
||||
// 修改响应的数据
|
||||
// Conn.SetBody([]byte("Hello Word"))
|
||||
// 拦截此消息,不让此消息发出
|
||||
// Conn.SetBody(nil)
|
||||
// 主动向客户端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToClient([]byte("模拟服务端发送到客户端的消息"))
|
||||
// 主动向服务端发送数据(可将Conn储存到全局随时调用)
|
||||
// Conn.SendToServer([]byte("模拟客户端发送到服务端的消息"))
|
||||
return
|
||||
case public.SunnyNetUDPTypeClosed: // 关闭会话
|
||||
log.Println("PID", Conn.PID(), Conn.GetProcessName(), "关闭UDP", Conn.LocalAddress(), Conn.RemoteAddress())
|
||||
return
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 证书管理
|
||||
|
||||
### 创建自定义证书
|
||||
|
||||
```go
|
||||
|
||||
var Sunny = SunnyNet.NewSunny()
|
||||
|
||||
Cert := SunnyNet.NewCertManager()
|
||||
|
||||
//从文件载入证书并且设置为SunnyNet根证书
|
||||
if Cert.LoadP12Certificate("./SunnyNet.p12", "1234567890") {
|
||||
Sunny.SetCert(Cert.Context())
|
||||
}
|
||||
|
||||
success := Cert.CreateCA(
|
||||
"CN", // Country
|
||||
"My Organization", // Organization
|
||||
"IT", // Organizational Unit
|
||||
"Beijing", // Province
|
||||
"My Custom CA", // Common Name
|
||||
"Beijing", // Locality
|
||||
2048, // bits
|
||||
365, // NotAfter (days)
|
||||
)
|
||||
|
||||
if success {
|
||||
fmt.Println("CA证书创建成功")
|
||||
// 导出证书
|
||||
caPem := Cert.ExportCA()
|
||||
keyPem := Cert.ExportKEY()
|
||||
|
||||
fmt.Println("CA证书:", caPem)
|
||||
fmt.Println("私钥:", keyPem)
|
||||
//导出到文件
|
||||
Cert.ExportP12("./SunnyNet.p12", "1234567890")
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 代理设置
|
||||
|
||||
### 全局上游代理
|
||||
|
||||
```go
|
||||
// 设置全局上游代理
|
||||
Sunny.SetGlobalProxy("socket://192.168.31.1:4321", 60000)
|
||||
|
||||
// 指定IP或域名不使用全局的上游代理
|
||||
Sunny.CompileProxyRegexp("127.0.0.1;[::1];192.168.*;*.baidu.com")
|
||||
|
||||
```
|
||||
|
||||
### 强制TCP模式
|
||||
|
||||
```go
|
||||
// 开启强制走TCP,开启后 https 将不会解密 直接转发数据流量
|
||||
Sunny.MustTcp(true)
|
||||
|
||||
// 或者设置强制走TCP规则,使用这个函数后 就不要使用 Sunny.MustTcp(true) 否则这个函数无效
|
||||
Sunny.SetMustTcpRegexp("tpstelemetry.tencent.com", true)
|
||||
|
||||
// 设置TCP规则模式 (true: 规则内走TCP, false: 规则外走TCP)
|
||||
Sunny.SetMustTcpRegexp("*.google.com;*.github.com", true)
|
||||
```
|
||||
|
||||
### 禁用TCP/UDP
|
||||
|
||||
```go
|
||||
// 禁止TCP,所有TCP流量将直接断开连接
|
||||
Sunny.DisableTCP(true)
|
||||
|
||||
// 禁止UDP,所有UDP流量将直接断开连接
|
||||
Sunny.DisableUDP(true)
|
||||
```
|
||||
|
||||
## 驱动模式
|
||||
|
||||
### 使用驱动抓包
|
||||
|
||||
```go
|
||||
// 使用驱动抓包 (两个驱动各有特点自行尝试,哪个能用/好用 用哪个)
|
||||
// 0=Proxifier,1=NFAPI,2=Tun
|
||||
success := Sunny.OpenDrive(2)
|
||||
if success {
|
||||
fmt.Println("驱动启动成功")
|
||||
} else {
|
||||
fmt.Println("驱动启动失败")
|
||||
}
|
||||
|
||||
// 添加指定进程名称进行抓包
|
||||
Sunny.ProcessAddName("chrome.exe")
|
||||
Sunny.ProcessAddName("firefox.exe")
|
||||
|
||||
// 删除已添加的指定进程名称
|
||||
Sunny.ProcessDelName("firefox.exe")
|
||||
|
||||
// 添加指定进程PID进行抓包
|
||||
Sunny.ProcessAddPid(1234)
|
||||
|
||||
// 删除已添加的指定进程PID
|
||||
Sunny.ProcessDelPid(1234)
|
||||
|
||||
// 删除已添加的所有进程名称/PID
|
||||
Sunny.ProcessCancelAll()
|
||||
|
||||
// 捕获全部进程开始后,添加进程名称-PID无效
|
||||
Sunny.ProcessALLName(true, false)
|
||||
|
||||
// 设置数据出口IP
|
||||
Sunny.SetOutRouterIP("192.168.1.100")
|
||||
```
|
||||
|
||||
## DNS解析模式
|
||||
|
||||
### DNS使用的3种模式
|
||||
|
||||
```go
|
||||
/*
|
||||
DNS使用的3种模式
|
||||
当你设置了全局上游代理,或对请求单独设置了代理的情况下,使用DNS模式,视情况而定,来选择设置
|
||||
情况1.你没有使用全局上游代理,也没有对请求单独设置代理,这种情况下,没什么好说的,无论你设置的是那种模式,都只会使用本机的DNS进行解析!
|
||||
情况2.你使用了全局上游代理或请求单独设置代理,这种情况下,你设置以下3种模式会有区别
|
||||
1.使用 本地解析 模式,你要访问的目标地址,通过你本地DNS解析出的IP,可能会被服务器拒绝连接。这时候你需要尝试 远程解析/远程服务器解析
|
||||
2.使用 远程解析 模式,你所使用的代理服务器可能存在无法解析的情况。这时你应该尝试 远程服务器解析
|
||||
3.使用 远程服务器解析 模式,远程服务器解析 会使用你设置的代理,连接到远程DNS服务器进行查询并且解析,可能会导致首次访问变慢
|
||||
|
||||
Sunny.SetDnsServer("local") //本地解析
|
||||
Sunny.SetDnsServer("remote") //远程解析
|
||||
Sunny.SetDnsServer("223.5.5.5:853") //远程服务器解析
|
||||
*/
|
||||
|
||||
// 设置DNS解析模式示例
|
||||
Sunny.SetDnsServer("223.5.5.5:853") // 使用远程DNS服务器解析
|
||||
```
|
||||
|
||||
## 其他功能
|
||||
|
||||
### 设置出口IP
|
||||
|
||||
```go
|
||||
// 设置数据出口IP
|
||||
Sunny.SetOutRouterIP("192.168.31.154")
|
||||
|
||||
// 为请求单独设置出口IP(在回调中设置)
|
||||
// Conn.SetOutRouterIP("192.168.31.154")
|
||||
|
||||
```
|
||||
|
||||
### 脚本功能
|
||||
|
||||
```go
|
||||
log := func(Context int, info ...any) {
|
||||
fmt.Println("x脚本日志", fmt.Sprintf("%v", info))
|
||||
}
|
||||
save := func(Context int, code []byte) {
|
||||
// 在这里将code代码 储存到文件,下次启动时,载入恢复
|
||||
}
|
||||
Sunny.SetScriptCall(log, save)
|
||||
// 载入上次保存的脚本代码
|
||||
Sunny.SetScriptCode(string(GoScriptCode.DefaultCode))
|
||||
|
||||
// 设置脚本页面
|
||||
Sunny.SetScriptPage("MyScriptEditor")
|
||||
//设置后 使用浏览器访问 http://127.0.0.1:{prot}/MyScriptEditor 来使用脚本
|
||||
```
|
||||
|
||||
### 数据压缩/解压缩
|
||||
|
||||
```go
|
||||
// Gzip压缩
|
||||
originalData := []byte("Hello, World!")
|
||||
//压缩 仅支持 gzip、br、deflate、zstd、zlib 算法
|
||||
compressedData := Compress.CompressAuto("gzip", originalData)
|
||||
if compressedData != nil {
|
||||
fmt.Printf("压缩后长度: %d\n", len(compressedData))
|
||||
// 解压缩 仅支持 gzip、br、deflate、zstd、zlib 算法
|
||||
decompressedData := Compress.UnCompressAuto("gzip", compressedData)
|
||||
if decompressedData != nil {
|
||||
fmt.Printf("解压后数据: %s\n", string(decompressedData))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
以上示例展示了SunnyNet在各种场景下的使用方法,开发者可以根据具体需求选择合适的示例进行参考和修改。[有任何Bug和示例错误可以随时反馈](README.md)
|
||||
BIN
SunnyNet.7z
BIN
SunnyNet.7z
Binary file not shown.
@@ -2450,13 +2450,12 @@ func (s *Sunny) InstallCert() string {
|
||||
}
|
||||
|
||||
// SetCert 设置证书
|
||||
func (s *Sunny) SetCert(ManagerId int) *Sunny {
|
||||
Manager := Certificate.LoadCertificateContext(ManagerId)
|
||||
func (s *Sunny) SetCert(ManagerContext int) *Sunny {
|
||||
Manager := Certificate.LoadCertificateContext(ManagerContext)
|
||||
if Manager == nil {
|
||||
s.Error = errors.New("CertificateManager invalid ")
|
||||
return s
|
||||
}
|
||||
|
||||
var err error
|
||||
s.initCertOK = false
|
||||
p, _ := pem.Decode([]byte(Manager.ExportCA()))
|
||||
|
||||
@@ -26,6 +26,7 @@ type CertManager struct {
|
||||
PrivateKey string
|
||||
Certificates string
|
||||
Cert string
|
||||
context int
|
||||
}
|
||||
|
||||
var Lock sync.Mutex
|
||||
@@ -37,6 +38,7 @@ func CreateCertificate() int {
|
||||
w := &CertManager{Tls: &tls.Config{}}
|
||||
Context := NewMessageId()
|
||||
Map[Context] = w
|
||||
w.context = Context
|
||||
return Context
|
||||
}
|
||||
|
||||
@@ -51,7 +53,14 @@ func RemoveCertificate(Context int) {
|
||||
c = nil
|
||||
delete(Map, Context)
|
||||
}
|
||||
|
||||
func (c *CertManager) Context() int {
|
||||
Lock.Lock()
|
||||
defer Lock.Unlock()
|
||||
if c.context == 0 {
|
||||
c.context = NewMessageId()
|
||||
}
|
||||
return c.context
|
||||
}
|
||||
func LoadCertificateContext(Context int) *CertManager {
|
||||
s := Map[Context]
|
||||
if s == nil {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/klauspost/compress/zstd"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _null_bytes = make([]byte, 0)
|
||||
@@ -111,3 +112,38 @@ func ZSTDDecompress(input []byte) []byte {
|
||||
a, _ := decoder.DecodeAll(input, nil)
|
||||
return a
|
||||
}
|
||||
|
||||
var decompressors = map[string]func([]byte) []byte{
|
||||
"gzip": GzipUnCompress,
|
||||
"br": BrUnCompress,
|
||||
"deflate": DeflateUnCompress,
|
||||
"zstd": ZSTDDecompress,
|
||||
"zlib": ZlibUnCompress,
|
||||
}
|
||||
var encompressors = map[string]func([]byte) []byte{
|
||||
"gzip": GzipCompress,
|
||||
"br": BrCompress,
|
||||
"deflate": DeflateCompress,
|
||||
"zstd": ZSTDCompress,
|
||||
"zlib": ZlibCompress,
|
||||
}
|
||||
|
||||
// CompressAuto 自动压缩 仅支持 gzip、br、deflate、zstd、zlib 算法
|
||||
func CompressAuto(encoding string, data []byte) []byte {
|
||||
if Compress, ok := encompressors[strings.ToLower(encoding)]; ok {
|
||||
if compressed := Compress(data); len(compressed) > 0 {
|
||||
return compressed
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnCompressAuto 自动解压缩 仅支持 gzip、br、deflate、zstd、zlib 算法
|
||||
func UnCompressAuto(encoding string, data []byte) []byte {
|
||||
if decompressor, ok := decompressors[strings.ToLower(encoding)]; ok {
|
||||
if uncompressed := decompressor(data); len(uncompressed) > 0 {
|
||||
return uncompressed
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ done
|
||||
}
|
||||
|
||||
// startWatchdog 启动路由恢复监控脚本(防止主进程异常退出导致网络不恢复)
|
||||
func startWatchdog() { // 定义 startWatchdog 函数
|
||||
func startWatchdog() { // 定义 startWatchdog 函数
|
||||
if watchdogStarted { // 如果已启动
|
||||
return // 直接返回
|
||||
}
|
||||
|
||||
@@ -222,6 +222,9 @@ func (d *DevConn) SetWriteDeadline(t time.Time) error {
|
||||
}
|
||||
|
||||
func (d *DevConn) PushClientPayload(payload []byte, seq uint32) {
|
||||
if seq != d.clientNext {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
d.mu.Lock()
|
||||
clientNext := d.clientNext
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
package WinDivert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/qtgolang/SunnyNet/src/ProcessDrv/ProcessCheck"
|
||||
@@ -19,11 +18,7 @@ var (
|
||||
sessionsMu sync.Mutex
|
||||
sessions = make(map[uint16]*DevConn)
|
||||
)
|
||||
|
||||
func sessKey(ip net.IP, port uint16) string {
|
||||
return ip.String() + ":" + fmt.Sprint(port)
|
||||
}
|
||||
|
||||
|
||||
type expiry struct {
|
||||
pid int32
|
||||
name string
|
||||
@@ -68,8 +63,11 @@ func getPidByPort(kind string, port uint16) (int32, string) {
|
||||
|
||||
var loopbackV4 = net.IPv4(127, 0, 0, 1)
|
||||
var loopbackV6 = net.IPv6loopback
|
||||
var mm sync.Mutex
|
||||
|
||||
func (d *Divert) handleCommand(h *Handle, data []byte, addr *Address, tcp *layers.TCP, clientIP, serverIP net.IP, clientPort, serverPort uint16, v4 bool) {
|
||||
mm.Lock()
|
||||
defer mm.Unlock()
|
||||
if !addr.Outbound() || (clientIP.Equal(serverIP) && (serverIP.Equal(loopbackV4) || serverIP.Equal(loopbackV6))) {
|
||||
_, _ = h.Send(data, addr)
|
||||
return
|
||||
@@ -130,19 +128,17 @@ func (d *Divert) handleCommand(h *Handle, data []byte, addr *Address, tcp *layer
|
||||
return
|
||||
}
|
||||
|
||||
if tcp.ACK && !tcp.SYN && len(tcp.Payload) == 0 {
|
||||
return
|
||||
}
|
||||
// 处理 payload:写入 devConn 并向内核注入 ACK(告知 we've consumed bytes)
|
||||
if len(tcp.Payload) > 0 {
|
||||
fmt.Println(string(tcp.Payload))
|
||||
// 写入 session buffer 并更新 clientNext
|
||||
sess.PushClientPayload(tcp.Payload, tcp.Seq)
|
||||
return
|
||||
}
|
||||
|
||||
sess.mu.Lock()
|
||||
sess.clientNext = tcp.Seq
|
||||
sess.mu.Unlock()
|
||||
// 其他情况原样放行
|
||||
_, _ = h.Send(data, addr)
|
||||
//_, _ = h.Send(data, addr)
|
||||
return
|
||||
}
|
||||
func (d *Divert) handleIPv4(h *Handle, data []byte, addr *Address, ip4 *layers.IPv4, pkt gopacket.Packet) bool {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const SunnyVersion = "2025-10-24"
|
||||
const SunnyVersion = "2025-11-06"
|
||||
const Information = `
|
||||
------------------------------------------------------
|
||||
欢迎使用 SunnyNet 网络中间件 - V` + SunnyVersion + `
|
||||
|
||||
@@ -801,7 +801,9 @@ func (c *Conn) WriteMessage(messageType int, data []byte) error {
|
||||
return w.Close()
|
||||
}
|
||||
func (c *Conn) WriteFullMessage(messageType int, data []byte) error {
|
||||
if len(data) < cap(c.writeBuf) || (c.newCompressionWriter == nil || !c.enableWriteCompression) {
|
||||
a1 := len(data) < cap(c.writeBuf)
|
||||
a2 := !c.enableWriteCompression
|
||||
if a1 || a2 {
|
||||
return c.WriteMessage(messageType, data)
|
||||
}
|
||||
var mw messageWriter
|
||||
|
||||
37
test.go
37
test.go
@@ -3,27 +3,12 @@ package main
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/qtgolang/SunnyNet/Api"
|
||||
"github.com/qtgolang/SunnyNet/SunnyNet"
|
||||
"github.com/qtgolang/SunnyNet/src/dns"
|
||||
"github.com/qtgolang/SunnyNet/src/encoding/hex"
|
||||
"github.com/qtgolang/SunnyNet/src/public"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func wss() {
|
||||
defer os.Exit(0)
|
||||
dns.SetDnsServer("remote")
|
||||
id := Api.CreateHTTPClient()
|
||||
Api.HTTPSetProxyIP(id, "http://:@183.146.240.245:13477")
|
||||
Api.HTTPOpen(id, "GET", "https://www.baidu.com/s")
|
||||
Api.HTTPSetHeader(id, "host", "www.baidu.com")
|
||||
Api.HTTPSendBin(id, []byte(""))
|
||||
|
||||
fmt.Println(Api.HTTPGetCode(id))
|
||||
|
||||
}
|
||||
func Test() {
|
||||
//wss()
|
||||
var Sunny = SunnyNet.NewSunny()
|
||||
@@ -38,7 +23,6 @@ func Test() {
|
||||
Sunny.AddHttpCertificate("api.vlightv.com", cert, SunnyNet.HTTPCertRules_Request)
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
log := func(Context int, info ...any) {
|
||||
fmt.Println("x脚本日志", fmt.Sprintf("%v", info))
|
||||
@@ -122,8 +106,8 @@ func Test() {
|
||||
//Sunny.SetGlobalProxy("http://abc9068377_mdse-zone-abc:11223344@b062e1016fa4e9c4.abcproxy.vip:4950", 60000)
|
||||
//if Sunny.OpenDrive(2) {
|
||||
Sunny.ProcessAddName("as5.exe")
|
||||
//Sunny.ProcessAddName("com.apple.WebKit.Networking")
|
||||
Sunny.ProcessAddName("go_build_VxOCR.exe")
|
||||
Sunny.ProcessAddName("chrome.exe")
|
||||
//Sunny.ProcessAddName("WeChatAppEx.exe")
|
||||
//Sunny.ProcessALLName(true, false)
|
||||
//}
|
||||
//fmt.Println(Sunny.SetIEProxy())
|
||||
@@ -137,13 +121,8 @@ func Test() {
|
||||
//阻止程序退出
|
||||
select {}
|
||||
}
|
||||
func updateLog() {
|
||||
//2025-07-16 修复 GET 请求,可能导致服务器出现响应501:https://c1-nuwa.lefile.cn/t_/cn_zh/version/css/aaa13d3c3f1d2708624c179cbba4e8bb.css
|
||||
//2025-07-19 修复 WSS 可能异常断开
|
||||
//2025-07-26 修复 开启强制TCP 无法访问脚本编辑
|
||||
//2025-07-26 优化 脚本编辑
|
||||
}
|
||||
func HttpCallback(Conn SunnyNet.ConnHTTP) {
|
||||
return
|
||||
switch Conn.Type() {
|
||||
case public.HttpSendRequest: //发起请求
|
||||
fmt.Println("发起请求", Conn.URL(), Conn.Proto(), Conn.GetProcessName())
|
||||
@@ -184,7 +163,6 @@ func WSCallback(Conn SunnyNet.ConnWebSocket) {
|
||||
}
|
||||
}
|
||||
func TcpCallback(Conn SunnyNet.ConnTCP) {
|
||||
return
|
||||
switch Conn.Type() {
|
||||
case public.SunnyNetMsgTypeTCPAboutToConnect: //即将连接
|
||||
mode := string(Conn.Body())
|
||||
@@ -193,23 +171,24 @@ func TcpCallback(Conn SunnyNet.ConnTCP) {
|
||||
//Conn.SetNewAddress("8.8.8.8:8080")
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPConnectOK: //连接成功
|
||||
log.Println("PID", Conn.PID(), "TCP 连接到:", Conn.LocalAddress(), "->", Conn.RemoteAddress(), "成功")
|
||||
//log.Println("PID", Conn.PID(), "TCP 连接到:", Conn.LocalAddress(), "->", Conn.RemoteAddress(), "成功")
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPClose: //连接关闭
|
||||
log.Println("PID", Conn.PID(), "TCP 断开连接:", Conn.LocalAddress(), "->", Conn.RemoteAddress())
|
||||
//log.Println("PID", Conn.PID(), "TCP 断开连接:", Conn.LocalAddress(), "->", Conn.RemoteAddress())
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPClientSend: //客户端发送数据
|
||||
log.Println("PID", Conn.PID(), "TCP 发送数据", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.Type(), Conn.BodyLen(), len(Conn.Body()))
|
||||
//log.Println("PID", Conn.PID(), "TCP 发送数据", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.Type(), Conn.BodyLen(), len(Conn.Body()))
|
||||
return
|
||||
case public.SunnyNetMsgTypeTCPClientReceive: //客户端收到数据
|
||||
|
||||
log.Println("PID", Conn.PID(), "收到数据", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.Type(), Conn.BodyLen(), len(Conn.Body()))
|
||||
//log.Println("PID", Conn.PID(), "收到数据", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.Type(), Conn.BodyLen(), len(Conn.Body()))
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
func UdpCallback(Conn SunnyNet.ConnUDP) {
|
||||
return
|
||||
switch Conn.Type() {
|
||||
case public.SunnyNetUDPTypeSend: //客户端向服务器端发送数据
|
||||
log.Println("PID", Conn.PID(), Conn.GetProcessName(), "发送UDP", Conn.LocalAddress(), Conn.RemoteAddress(), Conn.BodyLen())
|
||||
|
||||
Reference in New Issue
Block a user