fix: 适配支持RFC 3489/5389/5780检测

This commit is contained in:
spiritlhl
2025-07-22 05:24:41 +00:00
parent f1b1b72943
commit c17f7bbd12
5 changed files with 244 additions and 48 deletions

View File

@@ -12,6 +12,67 @@ import (
"github.com/pion/logging"
)
// tryRFCMethod attempts NAT detection using specified RFC method
func tryRFCMethod(addrStr string, rfcMethod string) (bool, error) {
currentProtocol := "ipv4"
if model.IPVersion == "ipv6" || (model.IPVersion == "both" && strings.Contains(addrStr, "[") && strings.Contains(addrStr, "]")) {
currentProtocol = "ipv6"
}
var err1, err2 error
switch rfcMethod {
case "RFC5780":
if model.EnableLoger {
model.Log.Infof("[%s] Trying RFC 5780 method with server %s", currentProtocol, addrStr)
}
err1 = stuncheck.MappingTests(addrStr)
if err1 != nil {
model.NatMappingBehavior = "inconclusive"
if model.EnableLoger {
model.Log.Warnf("[%s] RFC5780 NAT mapping behavior: inconclusive", currentProtocol)
}
}
err2 = stuncheck.FilteringTests(addrStr)
if err2 != nil {
model.NatFilteringBehavior = "inconclusive"
if model.EnableLoger {
model.Log.Warnf("[%s] RFC5780 NAT filtering behavior: inconclusive", currentProtocol)
}
}
case "RFC5389":
if model.EnableLoger {
model.Log.Infof("[%s] Trying RFC 5389/8489 method with server %s", currentProtocol, addrStr)
}
err1 = stuncheck.MappingTestsRFC5389(addrStr)
if err1 != nil {
model.NatMappingBehavior = "inconclusive"
model.NatFilteringBehavior = "inconclusive"
if model.EnableLoger {
model.Log.Warnf("[%s] RFC5389 NAT detection: inconclusive", currentProtocol)
}
}
case "RFC3489":
if model.EnableLoger {
model.Log.Infof("[%s] Trying RFC 3489 method with server %s", currentProtocol, addrStr)
}
err1 = stuncheck.MappingTestsRFC3489(addrStr)
if err1 != nil {
model.NatMappingBehavior = "inconclusive"
model.NatFilteringBehavior = "inconclusive"
if model.EnableLoger {
model.Log.Warnf("[%s] RFC3489 NAT detection: inconclusive", currentProtocol)
}
}
}
if model.NatMappingBehavior != "inconclusive" && model.NatFilteringBehavior != "inconclusive" &&
model.NatMappingBehavior != "" && model.NatFilteringBehavior != "" {
if model.EnableLoger {
model.Log.Infof("[%s] Successfully determined NAT type using %s with server %s", currentProtocol, rfcMethod, addrStr)
}
return true, nil
}
return false, nil
}
func main() {
var showVersion, help bool
gostunFlag := flag.NewFlagSet("gostun", flag.ContinueOnError)
@@ -57,53 +118,49 @@ func main() {
} else {
addrStrList = model.GetDefaultServers(model.IPVersion)
}
// checkStatus := false
for _, addrStr := range addrStrList {
model.NatMappingBehavior = ""
model.NatFilteringBehavior = ""
currentProtocol := "ipv4"
if originalIPVersion == "both" {
if strings.Contains(addrStr, "[") && strings.Contains(addrStr, "]") &&
!strings.Contains(addrStr, ".") {
currentProtocol = "ipv6"
model.IPVersion = "ipv6"
} else {
currentProtocol = "ipv4"
model.IPVersion = "ipv4"
}
} else {
currentProtocol = originalIPVersion
}
if model.EnableLoger {
model.Log.Infof("Testing server %s with protocol %s", addrStr, currentProtocol)
}
err1 := stuncheck.MappingTests(addrStr)
if err1 != nil {
model.NatMappingBehavior = "inconclusive"
if model.EnableLoger {
model.Log.Warnf("[%s] NAT mapping behavior: inconclusive", currentProtocol)
}
}
err2 := stuncheck.FilteringTests(addrStr)
if err2 != nil {
model.NatFilteringBehavior = "inconclusive"
if model.EnableLoger {
model.Log.Warnf("[%s] NAT filtering behavior: inconclusive", currentProtocol)
}
}
if model.NatMappingBehavior != "inconclusive" && model.NatFilteringBehavior != "inconclusive" &&
model.NatMappingBehavior != "" && model.NatFilteringBehavior != "" {
// checkStatus = true
if model.EnableLoger {
model.Log.Infof("[%s] Successfully determined NAT type with server %s", currentProtocol, addrStr)
}
// RFC methods in order of preference: 5780 -> 5389 -> 3489
rfcMethods := []string{"RFC5780", "RFC5389", "RFC3489"}
successfulDetection := false
for _, rfcMethod := range rfcMethods {
if successfulDetection {
break
}
if model.EnableLoger {
model.Log.Warnf("[%s] Server %s failed to determine NAT type, trying next server", currentProtocol, addrStr)
for _, addrStr := range addrStrList {
model.NatMappingBehavior = ""
model.NatFilteringBehavior = ""
currentProtocol := "ipv4"
if originalIPVersion == "both" {
if strings.Contains(addrStr, "[") && strings.Contains(addrStr, "]") &&
!strings.Contains(addrStr, ".") {
currentProtocol = "ipv6"
model.IPVersion = "ipv6"
} else {
currentProtocol = "ipv4"
model.IPVersion = "ipv4"
}
} else {
currentProtocol = originalIPVersion
}
if model.EnableLoger {
model.Log.Infof("Testing server %s with protocol %s using %s", addrStr, currentProtocol, rfcMethod)
}
success, err := tryRFCMethod(addrStr, rfcMethod)
if err != nil && model.EnableLoger {
model.Log.Warnf("[%s] Error with %s method: %v", currentProtocol, rfcMethod, err)
}
if success {
successfulDetection = true
break
}
if model.EnableLoger {
model.Log.Warnf("[%s] Server %s failed to determine NAT type using %s, trying next server", currentProtocol, addrStr, rfcMethod)
}
}
if !successfulDetection && model.EnableLoger {
model.Log.Warnf("All servers failed with %s method, trying next RFC method", rfcMethod)
}
}
model.IPVersion = originalIPVersion
res := stuncheck.CheckType()
fmt.Printf("NAT Type: %s\n", res)
}
}