mirror of
https://github.com/bolucat/Archive.git
synced 2025-12-24 13:28:37 +08:00
Update On Wed Jul 16 20:42:02 CEST 2025
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<div align="center">
|
||||
<img src="https://cdn.yobc.de/assets/np-gopher.png" alt="nodepass" width="300">
|
||||
|
||||
[](https://github.com/avelino/awesome-go)
|
||||
[](https://github.com/avelino/awesome-go#networking)
|
||||
[](https://github.com/yosebyte/nodepass/releases)
|
||||
[](https://github.com/yosebyte/nodepass/releases)
|
||||
[](https://goreportcard.com/report/github.com/yosebyte/nodepass)
|
||||
@@ -18,7 +18,7 @@ English | [简体中文](README_zh.md)
|
||||
## 💎 Key Features
|
||||
|
||||
- **🌐 Universal Functionality**
|
||||
- Supports TCP/UDP tunneling and protocol conversion across diverse networks.
|
||||
- Basic TCP/UDP tunneling and protocol conversion across diverse networks.
|
||||
- Compatible with port mapping, NAT traversal, and traffic relay.
|
||||
- Cross-platform, multi-architecture, single binary or container.
|
||||
|
||||
@@ -27,20 +27,20 @@ English | [简体中文](README_zh.md)
|
||||
- Eliminates handshake delays, boosts performance.
|
||||
- Auto-scaling with real-time capacity adjustment.
|
||||
|
||||
- **⚙️ Zero-Config**
|
||||
- No config files required, ready to use via CLI.
|
||||
- Optimized for CI/CD and containers.
|
||||
- Flexible tuning via environment variables.
|
||||
- **🧬 Innovative Architecture**
|
||||
- Integrated S/C/M architecture, flexible mode switching.
|
||||
- Full decoupling of control/data channels.
|
||||
- API-instance management, multi-instance collaboration.
|
||||
|
||||
- **🔐 Multi-level Security**
|
||||
- Three TLS modes: plaintext, self-signed, strict validation.
|
||||
- Covers development to enterprise security needs.
|
||||
- Hot-reload certificates with zero downtime.
|
||||
|
||||
- **🧠 Innovative Architecture**
|
||||
- Integrated S/C/M architecture, flexible mode switching.
|
||||
- Full decoupling of control/data channels.
|
||||
- API-instance management, multi-instance collaboration.
|
||||
- **⚙️ Minimal Configuration**
|
||||
- No config files required, ready to use via CLI.
|
||||
- Optimized for CI/CD and containers.
|
||||
- Flexible tuning via environment variables.
|
||||
|
||||
- **📈 Performance**
|
||||
- Intelligent scheduling, auto-tuning, ultra-low resource usage.
|
||||
@@ -88,7 +88,7 @@ Explore the complete documentation to learn more about NodePass:
|
||||
- [How It Works](/docs/en/how-it-works.md)
|
||||
- [Troubleshooting](/docs/en/troubleshooting.md)
|
||||
|
||||
## 🌐 Ecosystem
|
||||
## 🌱 Ecosystem
|
||||
|
||||
The [NodePassProject](https://github.com/NodePassProject) organization develops various frontend applications and auxiliary tools to enhance the NodePass experience:
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div align="center">
|
||||
<img src="https://cdn.yobc.de/assets/np-gopher.png" alt="nodepass" width="300">
|
||||
|
||||
[](https://github.com/avelino/awesome-go)
|
||||
[](https://github.com/avelino/awesome-go#networking)
|
||||
[](https://github.com/yosebyte/nodepass/releases)
|
||||
[](https://github.com/yosebyte/nodepass/releases)
|
||||
[](https://goreportcard.com/report/github.com/yosebyte/nodepass)
|
||||
@@ -18,7 +18,7 @@
|
||||
## 💎 核心功能
|
||||
|
||||
- **🌐 通用网络隧道**
|
||||
- 支持 TCP/UDP 隧道,具备协议转换能力,适配多种网络结构。
|
||||
- 基础 TCP/UDP 隧道,具备协议转换能力,适配多种网络结构。
|
||||
- 完整适配端口映射、内网穿透、流量中转等多场景应用需求。
|
||||
- 多平台、多架构支持,支持独立二进制文件、容器灵活部署。
|
||||
|
||||
@@ -27,27 +27,27 @@
|
||||
- 消除连接的握手等待,显著提升了性能体验。
|
||||
- 支持实时容量自适应,动态调整连接池规模。
|
||||
|
||||
- **⚙️ 零配置启动**
|
||||
- 无需配置文件,仅命令行参数即可运行,适合自动化和快速迭代。
|
||||
- 适配 CI/CD 流程与容器环境,极大提升部署和运维效率。
|
||||
- 支持环境变量性能调优,灵活适应不同运行环境。
|
||||
- **🧬 创新架构设计**
|
||||
- Server-Client-Master 多模式整合架构设计,灵活切换。
|
||||
- 将 S/C 控制通道与数据通道完全解耦,相互独立、各司其职。
|
||||
- 主控-实例的管理方式,支持动态扩容、多实例协作和集中控制。
|
||||
|
||||
- **🔐 多级安全策略**
|
||||
- 三种 TLS 模式:明文、自签名、严格验证,适配不同安全等级。
|
||||
- 满足从开发测试到企业级高安全部署的全场景需求。
|
||||
- 支持证书文件的热重载,免停运、无缝处理证书更新问题。
|
||||
|
||||
- **🧠 创新架构设计**
|
||||
- Server-Client-Master 多模式整合架构设计,灵活切换。
|
||||
- 将 S/C 控制通道与数据通道完全解耦,相互独立、各司其职。
|
||||
- 主控-实例的管理方式,支持动态扩容、多实例协作和集中控制。
|
||||
- **⚙️ 极简配置方式**
|
||||
- 无需配置文件,仅命令行参数即可运行,适合自动化和快速迭代。
|
||||
- 适配 CI/CD 流程与容器环境,极大提升部署和运维效率。
|
||||
- 支持环境变量性能调优,灵活适应不同运行环境。
|
||||
|
||||
- **📈 高性能优化**
|
||||
- 智能流量调度与自动连接调优,极低资源占用。
|
||||
- 高并发、高负载状态下卓越的系统稳定性能。
|
||||
- 健康检查、断线重连、故障自愈,确保持续高可用。
|
||||
|
||||
- **💡 可视化生态**
|
||||
- **💡 可视化管理**
|
||||
- 配套跨平台、多样化的管理前端应用,具备可视化配置能力。
|
||||
- 主流平台支持一键部署脚本,支撑灵活配置和辅助管理。
|
||||
- 具备实时隧道监控、实例管理、主控管理、流量统计等丰富功能。
|
||||
@@ -88,7 +88,7 @@ nodepass "master://:10101/api?log=debug&tls=1"
|
||||
- [工作原理](/docs/zh/how-it-works.md)
|
||||
- [故障排除](/docs/zh/troubleshooting.md)
|
||||
|
||||
## 🌐 生态系统
|
||||
## 🌱 生态系统
|
||||
|
||||
[NodePassProject](https://github.com/NodePassProject) 组织开发了各种前端应用和辅助工具来增强 NodePass 体验:
|
||||
|
||||
|
||||
@@ -6,5 +6,5 @@ require (
|
||||
github.com/NodePassProject/cert v1.0.0
|
||||
github.com/NodePassProject/conn v1.0.1
|
||||
github.com/NodePassProject/logs v1.0.1
|
||||
github.com/NodePassProject/pool v1.0.8
|
||||
github.com/NodePassProject/pool v1.0.9
|
||||
)
|
||||
|
||||
@@ -4,5 +4,5 @@ github.com/NodePassProject/conn v1.0.1 h1:vuzcQQj+cqENagzEYPwse9Vvlj/8vfkyNZCp5R
|
||||
github.com/NodePassProject/conn v1.0.1/go.mod h1:mWe3Rylunp6Sx4v6pkSGgYZe2R+I/O+7nZ2od0yJ3aQ=
|
||||
github.com/NodePassProject/logs v1.0.1 h1:WDHY1DcTO+7NydBzuRpxhEw6pWYayBdDjjZzU1uDKac=
|
||||
github.com/NodePassProject/logs v1.0.1/go.mod h1:ocFTMNXBTnQFJFAhF+qobAzu7+y+wYPik7D+a1jPfis=
|
||||
github.com/NodePassProject/pool v1.0.8 h1:zuqVdQj0OBarIo/P/BdpTxXk8kbjU2GYJJaVA5T+LwQ=
|
||||
github.com/NodePassProject/pool v1.0.8/go.mod h1:kdRAEDK45j/+iHH4kRTpXt/wI28NIguJ13n/5NDXxkw=
|
||||
github.com/NodePassProject/pool v1.0.9 h1:8VKKv8kJqg1FX9Odx9Vu2eTUOpO2G84uSfiyDTuHvvA=
|
||||
github.com/NodePassProject/pool v1.0.9/go.mod h1:kdRAEDK45j/+iHH4kRTpXt/wI28NIguJ13n/5NDXxkw=
|
||||
|
||||
@@ -401,12 +401,6 @@ func (c *Common) commonTCPLoop() {
|
||||
continue
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if targetConn != nil {
|
||||
targetConn.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
c.targetTCPConn = targetConn.(*net.TCPConn)
|
||||
c.logger.Debug("Target connection: %v <-> %v", targetConn.LocalAddr(), targetConn.RemoteAddr())
|
||||
|
||||
@@ -414,7 +408,12 @@ func (c *Common) commonTCPLoop() {
|
||||
c.semaphore <- struct{}{}
|
||||
|
||||
go func(targetConn net.Conn) {
|
||||
defer func() { <-c.semaphore }()
|
||||
defer func() {
|
||||
if targetConn != nil {
|
||||
targetConn.Close()
|
||||
}
|
||||
<-c.semaphore
|
||||
}()
|
||||
|
||||
// 从连接池获取连接
|
||||
id, remoteConn := c.tunnelPool.ServerGet()
|
||||
@@ -448,7 +447,7 @@ func (c *Common) commonTCPLoop() {
|
||||
return
|
||||
}
|
||||
|
||||
c.logger.Debug("TCP launch signal: %v -> %v", id, c.tunnelTCPConn.RemoteAddr())
|
||||
c.logger.Debug("TCP launch signal: pid %v -> %v", id, c.tunnelTCPConn.RemoteAddr())
|
||||
c.logger.Debug("Starting exchange: %v <-> %v", remoteConn.LocalAddr(), targetConn.LocalAddr())
|
||||
|
||||
// 交换数据
|
||||
@@ -468,8 +467,9 @@ func (c *Common) commonUDPLoop() {
|
||||
case <-c.ctx.Done():
|
||||
return
|
||||
default:
|
||||
// 读取来自目标的UDP数据
|
||||
buffer := make([]byte, udpDataBufSize)
|
||||
|
||||
// 读取来自目标的UDP数据
|
||||
n, clientAddr, err := c.targetUDPConn.ReadFromUDP(buffer)
|
||||
if err != nil {
|
||||
continue
|
||||
@@ -477,7 +477,7 @@ func (c *Common) commonUDPLoop() {
|
||||
|
||||
c.logger.Debug("Target connection: %v <-> %v", c.targetUDPConn.LocalAddr(), clientAddr)
|
||||
|
||||
// 从连接池获取连接
|
||||
// 获取池连接
|
||||
id, remoteConn := c.tunnelPool.ServerGet()
|
||||
if remoteConn == nil {
|
||||
c.logger.Error("Get failed: %v not found", id)
|
||||
@@ -486,51 +486,84 @@ func (c *Common) commonUDPLoop() {
|
||||
}
|
||||
|
||||
c.logger.Debug("Tunnel connection: get %v <- pool active %v", id, c.tunnelPool.Active())
|
||||
|
||||
defer func() {
|
||||
c.tunnelPool.Put(id, remoteConn)
|
||||
c.logger.Debug("Tunnel connection: put %v -> pool active %v", id, c.tunnelPool.Active())
|
||||
}()
|
||||
|
||||
c.logger.Debug("Tunnel connection: %v <-> %v", remoteConn.LocalAddr(), remoteConn.RemoteAddr())
|
||||
|
||||
// 使用信号量限制并发数
|
||||
c.semaphore <- struct{}{}
|
||||
|
||||
go func(buffer []byte, n int, clientAddr *net.UDPAddr, remoteConn net.Conn) {
|
||||
defer func() { <-c.semaphore }()
|
||||
go func(remoteConn net.Conn, clientAddr *net.UDPAddr, id string) {
|
||||
defer func() {
|
||||
c.tunnelPool.Put(id, remoteConn)
|
||||
c.logger.Debug("Tunnel connection: put %v -> pool active %v", id, c.tunnelPool.Active())
|
||||
<-c.semaphore
|
||||
}()
|
||||
|
||||
// 构建并发送启动URL到客户端
|
||||
launchURL := &url.URL{
|
||||
Host: id,
|
||||
Fragment: "2", // UDP模式
|
||||
buffer := make([]byte, udpDataBufSize)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
return
|
||||
default:
|
||||
// 设置TCP读取超时
|
||||
if err := remoteConn.SetReadDeadline(time.Now().Add(tcpReadTimeout)); err != nil {
|
||||
c.logger.Error("SetReadDeadline failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 从池连接读取数据
|
||||
x, err := remoteConn.Read(buffer)
|
||||
if err != nil {
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||
c.logger.Debug("UDP session abort: %v", err)
|
||||
} else if strings.Contains(err.Error(), "use of closed network connection") {
|
||||
c.logger.Debug("Read closed: %v", err)
|
||||
} else {
|
||||
c.logger.Error("Read failed: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 将数据写入目标UDP连接
|
||||
tx, err := c.targetUDPConn.WriteToUDP(buffer[:x], clientAddr)
|
||||
if err != nil {
|
||||
c.logger.Error("WriteToUDP failed: %v", err)
|
||||
return
|
||||
}
|
||||
// 传输完成,广播统计信息
|
||||
c.logger.Event("Transfer complete: TRAFFIC_STATS|TCP_RX=0|TCP_TX=0|UDP_RX=0|UDP_TX=%v", tx)
|
||||
}
|
||||
}
|
||||
}(remoteConn, clientAddr, id)
|
||||
|
||||
c.mu.Lock()
|
||||
_, err = c.tunnelTCPConn.Write(append(c.xor([]byte(launchURL.String())), '\n'))
|
||||
c.mu.Unlock()
|
||||
// 构建并发送启动URL到客户端
|
||||
launchURL := &url.URL{
|
||||
Host: clientAddr.String(),
|
||||
Path: id,
|
||||
Fragment: "2", // UDP模式
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.logger.Error("Write failed: %v", err)
|
||||
return
|
||||
}
|
||||
c.mu.Lock()
|
||||
_, err = c.tunnelTCPConn.Write(append(c.xor([]byte(launchURL.String())), '\n'))
|
||||
c.mu.Unlock()
|
||||
if err != nil {
|
||||
c.logger.Error("Write failed: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
c.logger.Debug("UDP launch signal: %v -> %v", id, c.tunnelTCPConn.RemoteAddr())
|
||||
c.logger.Debug("Starting transfer: %v <-> %v", remoteConn.LocalAddr(), c.targetUDPConn.LocalAddr())
|
||||
c.logger.Debug("UDP launch signal: pid %v -> %v", id, c.tunnelTCPConn.RemoteAddr())
|
||||
c.logger.Debug("Starting transfer: %v <-> %v", remoteConn.LocalAddr(), c.targetUDPConn.LocalAddr())
|
||||
|
||||
// 处理UDP/TCP数据传输
|
||||
rx, tx, _ := conn.DataTransfer(
|
||||
c.targetUDPConn,
|
||||
remoteConn,
|
||||
clientAddr,
|
||||
buffer[:n],
|
||||
udpDataBufSize,
|
||||
tcpReadTimeout,
|
||||
)
|
||||
// 将原始数据写入池连接
|
||||
rx, err := remoteConn.Write(buffer[:n])
|
||||
if err != nil {
|
||||
c.logger.Error("Write failed: %v", err)
|
||||
remoteConn.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
// 传输完成,广播统计信息
|
||||
c.logger.Event("Transfer complete: TRAFFIC_STATS|TCP_RX=0|TCP_TX=0|UDP_RX=%v|UDP_TX=%v", rx, tx)
|
||||
}(buffer, n, clientAddr, remoteConn)
|
||||
// 传输完成,广播统计信息
|
||||
c.logger.Event("Transfer complete: TRAFFIC_STATS|TCP_RX=0|TCP_TX=0|UDP_RX=%v|UDP_TX=0", rx)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -566,7 +599,7 @@ func (c *Common) commonOnce() {
|
||||
case "1": // TCP
|
||||
go c.commonTCPOnce(signalURL.Host)
|
||||
case "2": // UDP
|
||||
go c.commonUDPOnce(signalURL.Host)
|
||||
go c.commonUDPOnce(signalURL)
|
||||
default:
|
||||
// 健康检查或无效信号
|
||||
}
|
||||
@@ -576,7 +609,7 @@ func (c *Common) commonOnce() {
|
||||
|
||||
// commonTCPOnce 共用处理单个TCP请求
|
||||
func (c *Common) commonTCPOnce(id string) {
|
||||
c.logger.Debug("TCP launch signal: %v <- %v", id, c.tunnelTCPConn.RemoteAddr())
|
||||
c.logger.Debug("TCP launch signal: pid %v <- %v", id, c.tunnelTCPConn.RemoteAddr())
|
||||
|
||||
// 从连接池获取连接
|
||||
remoteConn := c.tunnelPool.ClientGet(id)
|
||||
@@ -619,54 +652,125 @@ func (c *Common) commonTCPOnce(id string) {
|
||||
}
|
||||
|
||||
// commonUDPOnce 共用处理单个UDP请求
|
||||
func (c *Common) commonUDPOnce(id string) {
|
||||
c.logger.Debug("UDP launch signal: %v <- %v", id, c.tunnelTCPConn.RemoteAddr())
|
||||
func (c *Common) commonUDPOnce(signalURL *url.URL) {
|
||||
id := strings.TrimPrefix(signalURL.Path, "/")
|
||||
c.logger.Debug("UDP launch signal: pid %v <- %v", id, c.tunnelTCPConn.RemoteAddr())
|
||||
|
||||
// 从连接池获取连接
|
||||
// 获取池连接
|
||||
remoteConn := c.tunnelPool.ClientGet(id)
|
||||
if remoteConn == nil {
|
||||
c.logger.Error("Get failed: %v not found", id)
|
||||
return
|
||||
}
|
||||
|
||||
c.logger.Debug("Tunnel connection: get %v <- pool active %v", id, c.tunnelPool.Active())
|
||||
|
||||
defer func() {
|
||||
c.tunnelPool.Put(id, remoteConn)
|
||||
c.logger.Debug("Tunnel connection: put %v -> pool active %v", id, c.tunnelPool.Active())
|
||||
}()
|
||||
|
||||
c.logger.Debug("Tunnel connection: %v <-> %v", remoteConn.LocalAddr(), remoteConn.RemoteAddr())
|
||||
|
||||
// 连接到目标UDP地址
|
||||
targetConn, err := net.DialTimeout("udp", c.targetUDPAddr.String(), udpDialTimeout)
|
||||
if err != nil {
|
||||
c.logger.Error("Dial failed: %v", err)
|
||||
return
|
||||
var targetConn *net.UDPConn
|
||||
sessionKey := signalURL.Host
|
||||
|
||||
// 获取或创建目标UDP会话
|
||||
if session, ok := c.targetUDPSession.Load(sessionKey); ok {
|
||||
targetConn = session.(*net.UDPConn)
|
||||
c.logger.Debug("Using UDP session: %v <-> %v", targetConn.LocalAddr(), targetConn.RemoteAddr())
|
||||
} else {
|
||||
// 创建新的会话
|
||||
session, err := net.DialTimeout("udp", c.targetUDPAddr.String(), udpDialTimeout)
|
||||
if err != nil {
|
||||
c.logger.Error("Dial failed: %v", err)
|
||||
return
|
||||
}
|
||||
c.targetUDPSession.Store(sessionKey, session)
|
||||
|
||||
targetConn = session.(*net.UDPConn)
|
||||
c.logger.Debug("Target connection: %v <-> %v", targetConn.LocalAddr(), targetConn.RemoteAddr())
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if targetConn != nil {
|
||||
targetConn.Close()
|
||||
done := make(chan struct{}, 2)
|
||||
|
||||
go func() {
|
||||
defer func() { done <- struct{}{} }()
|
||||
buffer := make([]byte, udpDataBufSize)
|
||||
for {
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
return
|
||||
default:
|
||||
// 设置TCP读取超时
|
||||
if err := remoteConn.SetReadDeadline(time.Now().Add(tcpReadTimeout)); err != nil {
|
||||
c.logger.Error("SetReadDeadline failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 从隧道连接读取数据
|
||||
x, err := remoteConn.Read(buffer)
|
||||
if err != nil {
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||
c.logger.Debug("Read timeout: %v", err)
|
||||
} else if strings.Contains(err.Error(), "use of closed network connection") {
|
||||
c.logger.Debug("Read closed: %v", err)
|
||||
} else {
|
||||
c.logger.Error("Read failed: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 将数据写入目标UDP连接
|
||||
rx, err := targetConn.Write(buffer[:x])
|
||||
if err != nil {
|
||||
c.logger.Error("Write failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 传输完成,广播统计信息
|
||||
c.logger.Event("Transfer complete: TRAFFIC_STATS|TCP_RX=0|TCP_TX=0|UDP_RX=%v|UDP_TX=0", rx)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
c.targetUDPConn = targetConn.(*net.UDPConn)
|
||||
c.logger.Debug("Target connection: %v <-> %v", targetConn.LocalAddr(), targetConn.RemoteAddr())
|
||||
c.logger.Debug("Starting transfer: %v <-> %v", remoteConn.LocalAddr(), targetConn.LocalAddr())
|
||||
go func() {
|
||||
defer func() { done <- struct{}{} }()
|
||||
buffer := make([]byte, udpDataBufSize)
|
||||
for {
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
return
|
||||
default:
|
||||
// 设置UDP读取超时
|
||||
if err := targetConn.SetReadDeadline(time.Now().Add(udpReadTimeout)); err != nil {
|
||||
c.logger.Error("SetReadDeadline failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 处理UDP/TCP数据传输
|
||||
rx, tx, _ := conn.DataTransfer(
|
||||
c.targetUDPConn,
|
||||
remoteConn,
|
||||
nil,
|
||||
nil,
|
||||
udpDataBufSize,
|
||||
udpReadTimeout,
|
||||
)
|
||||
// 从目标UDP连接读取数据
|
||||
x, err := targetConn.Read(buffer)
|
||||
if err != nil {
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||
c.logger.Debug("Read timeout: %v", err)
|
||||
} else if strings.Contains(err.Error(), "use of closed network connection") {
|
||||
c.logger.Debug("Read closed: %v", err)
|
||||
} else {
|
||||
c.logger.Error("Read failed: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 传输完成,广播统计信息
|
||||
c.logger.Event("Transfer complete: TRAFFIC_STATS|TCP_RX=0|TCP_TX=0|UDP_RX=%v|UDP_TX=%v", rx, tx)
|
||||
// 将数据写回隧道连接
|
||||
tx, err := remoteConn.Write(buffer[:x])
|
||||
if err != nil {
|
||||
c.logger.Error("Write failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 传输完成,广播统计信息
|
||||
c.logger.Event("Transfer complete: TRAFFIC_STATS|TCP_RX=0|TCP_TX=0|UDP_RX=0|UDP_TX=%v", tx)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// 等待任一协程完成
|
||||
<-done
|
||||
c.tunnelPool.Put(id, remoteConn)
|
||||
c.logger.Debug("Tunnel connection: put %v -> pool active %v", id, c.tunnelPool.Active())
|
||||
}
|
||||
|
||||
// singleLoop 单端转发处理循环
|
||||
@@ -700,12 +804,6 @@ func (c *Common) singleTCPLoop() error {
|
||||
continue
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if tunnelConn != nil {
|
||||
tunnelConn.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
c.tunnelTCPConn = tunnelConn.(*net.TCPConn)
|
||||
c.logger.Debug("Tunnel connection: %v <-> %v", tunnelConn.LocalAddr(), tunnelConn.RemoteAddr())
|
||||
|
||||
@@ -713,21 +811,26 @@ func (c *Common) singleTCPLoop() error {
|
||||
c.semaphore <- struct{}{}
|
||||
|
||||
go func(tunnelConn net.Conn) {
|
||||
defer func() { <-c.semaphore }()
|
||||
defer func() {
|
||||
if tunnelConn != nil {
|
||||
tunnelConn.Close()
|
||||
}
|
||||
<-c.semaphore
|
||||
}()
|
||||
|
||||
// 从连接池中获取连接
|
||||
targetConn := c.tunnelPool.ClientGet("")
|
||||
if targetConn == nil {
|
||||
c.logger.Error("Get failed: no target connection available")
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
return
|
||||
}
|
||||
|
||||
c.logger.Debug("Target connection: pool active %v / %v per %v", c.tunnelPool.Active(), c.tunnelPool.Capacity(), c.tunnelPool.Interval())
|
||||
c.logger.Debug("Target connection: get relay-id <- pool active %v", c.tunnelPool.Active())
|
||||
|
||||
defer func() {
|
||||
if targetConn != nil {
|
||||
targetConn.Close()
|
||||
}
|
||||
c.tunnelPool.Put("", targetConn)
|
||||
c.logger.Debug("Tunnel connection: put relay-id -> pool active %v", c.tunnelPool.Active())
|
||||
}()
|
||||
|
||||
c.targetTCPConn = targetConn.(*net.TCPConn)
|
||||
@@ -785,7 +888,12 @@ func (c *Common) singleUDPLoop() error {
|
||||
c.semaphore <- struct{}{}
|
||||
|
||||
go func(targetConn *net.UDPConn, clientAddr *net.UDPAddr, sessionKey string) {
|
||||
defer func() { <-c.semaphore }()
|
||||
defer func() {
|
||||
if targetConn != nil {
|
||||
targetConn.Close()
|
||||
}
|
||||
<-c.semaphore
|
||||
}()
|
||||
|
||||
buffer := make([]byte, udpDataBufSize)
|
||||
|
||||
@@ -805,9 +913,10 @@ func (c *Common) singleUDPLoop() error {
|
||||
// 从UDP读取响应
|
||||
n, err := targetConn.Read(buffer)
|
||||
if err != nil {
|
||||
// 检查是否为超时错误
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||
c.logger.Debug("UDP session abort: %v", err)
|
||||
} else if strings.Contains(err.Error(), "use of closed network connection") {
|
||||
c.logger.Debug("Read closed: %v", err)
|
||||
} else {
|
||||
c.logger.Error("Read failed: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user