固定UDP模式的源端口,改善在一些负载均衡网络环境下的效果,在使用ENV "NEXTTRACE_RANDOMPORT" 支持继续随机分配源端口。

https://github.com/nxtrace/NTrace-core/issues/296
https://github.com/nxtrace/NTrace-core/pull/297

Co-authored-by: Yunlq <vinculo025@gmail.com>
Co-authored-by: tsosunchia <59512455+tsosunchia@users.noreply.github.com>
This commit is contained in:
tsosunchia
2025-04-14 22:04:22 +08:00
parent 8fb1220f1b
commit 4d8e7e322b

View File

@@ -4,6 +4,7 @@ import (
"log"
"math/rand"
"net"
"strconv"
"sync"
"time"
@@ -135,9 +136,11 @@ func (t *UDPTracer) handleICMPMessage(msg ReceivedMessage, data []byte) {
}
}
func (t *UDPTracer) getUDPConn(try int) (net.IP, int, net.PacketConn) {
srcIP, _ := util.LocalIPPort(t.DestIP)
var cachedLocalPort int
var localPortOnce sync.Once
func (t *UDPTracer) getUDPConn(try int) (net.IP, int, net.PacketConn, error) {
srcIP, _ := util.LocalIPPort(t.DestIP)
var ipString string
if srcIP == nil {
ipString = ""
@@ -145,14 +148,37 @@ func (t *UDPTracer) getUDPConn(try int) (net.IP, int, net.PacketConn) {
ipString = srcIP.String()
}
udpConn, err := net.ListenPacket("udp", ipString+":0")
if err != nil {
if try > 3 {
log.Fatal(err)
// Check environment variable to decide caching behavior
if util.GetenvDefault("NEXTTRACE_RANDOMPORT", "") == "" {
// Use cached random port logic
if cachedLocalPort == 0 {
// First time: listen on a random port
udpConn, err := net.ListenPacket("udp", ipString+":0")
if err != nil {
if try > 3 {
log.Fatal(err)
}
return srcIP, 0, nil, err
}
cachedLocalPort = udpConn.LocalAddr().(*net.UDPAddr).Port
// Close the initial connection after obtaining the port
udpConn.Close()
}
return t.getUDPConn(try + 1)
// Use the cached local port to establish a new connection
udpConn, err := net.ListenPacket("udp", ipString+":"+strconv.Itoa(cachedLocalPort))
if err != nil {
return srcIP, cachedLocalPort, nil, err
}
return srcIP, cachedLocalPort, udpConn, nil
} else {
// Without caching: create a new connection each time using a new random port
udpConn, err := net.ListenPacket("udp", ipString+":0")
if err != nil {
return srcIP, 0, nil, err
}
localPort := udpConn.LocalAddr().(*net.UDPAddr).Port
return srcIP, localPort, udpConn, nil
}
return srcIP, udpConn.LocalAddr().(*net.UDPAddr).Port, udpConn
}
func (t *UDPTracer) send(ttl int) error {
@@ -167,7 +193,10 @@ func (t *UDPTracer) send(ttl int) error {
return nil
}
srcIP, srcPort, udpConn := t.getUDPConn(0)
srcIP, srcPort, udpConn, err := t.getUDPConn(0)
if err != nil {
return err
}
defer udpConn.Close()
//var payload []byte