Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NET-1341:fix ipv6 stun dns resolve issue #812

Merged
merged 1 commit into from
Jun 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 41 additions & 18 deletions stun/stun.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,38 +61,61 @@ func DoesIPExistLocally(ip net.IP) bool {
func HolePunch(portToStun int) (publicIP net.IP, publicPort int, natType string) {
for _, stunServer := range StunServers {
stunServer := stunServer
s, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", stunServer.Domain, stunServer.Port))
var err error
publicIP, publicPort, natType, err = callHolePunch(stunServer, portToStun, "udp4")
if err != nil {
logger.Log(1, "failed to resolve udp addr: ", err.Error())
continue
}
l := &net.UDPAddr{
IP: net.ParseIP(""),
Port: portToStun,
}
slog.Debug(fmt.Sprintf("hole punching port %d via stun server %s:%d", portToStun, stunServer.Domain, stunServer.Port))
publicIP, publicPort, natType, err = doStunTransaction(l, s)
if err != nil {
logger.Log(3, "stun transaction failed: ", stunServer.Domain, err.Error())
continue
slog.Warn("callHolePunch udp4 error", err.Error())
}
if publicPort == 0 || publicIP == nil || publicIP.IsUnspecified() {
continue
publicIP, publicPort, natType, err = callHolePunch(stunServer, portToStun, "udp6")
if err != nil {
slog.Warn("callHolePunch udp6 error", err.Error())
continue
}
}
break
}
slog.Debug("hole punching complete", "public ip", publicIP.String(), "public port", strconv.Itoa(publicPort))
slog.Debug("hole punching complete", "public ip", publicIP.String(), "public port", strconv.Itoa(publicPort), "nat type", natType)
return
}

func callHolePunch(stunServer StunServer, portToStun int, network string) (publicIP net.IP, publicPort int, natType string, err error) {
s, err := net.ResolveUDPAddr(network, fmt.Sprintf("%s:%d", stunServer.Domain, stunServer.Port))
if err != nil {
logger.Log(1, "failed to resolve udp addr: ", network, err.Error())
return nil, 0, "", err
}
l := &net.UDPAddr{
IP: net.ParseIP(""),
Port: portToStun,
}
slog.Debug(fmt.Sprintf("hole punching port %d via stun server %s:%d", portToStun, stunServer.Domain, stunServer.Port))
publicIP, publicPort, natType, err = doStunTransaction(l, s)
if err != nil {
logger.Log(3, "stun transaction failed: ", stunServer.Domain, err.Error())
return nil, 0, "", err
}

return
}

func doStunTransaction(lAddr, rAddr *net.UDPAddr) (publicIP net.IP, publicPort int, natType string, err error) {
conn, err := net.DialUDP("udp", lAddr, rAddr)
if err != nil {
logger.Log(0, "failed to dial: ", err.Error())
logger.Log(1, "failed to dial: ", err.Error())
return
}
re := strings.Split(conn.LocalAddr().String(), ":")
privIp := net.ParseIP(re[0])

re := conn.LocalAddr().String()
lIP := re[0:strings.LastIndex(re, ":")]
if strings.ContainsAny(lIP, "[") {
lIP = strings.ReplaceAll(lIP, "[", "")
}
if strings.ContainsAny(lIP, "]") {
lIP = strings.ReplaceAll(lIP, "]", "")
}

privIp := net.ParseIP(lIP)
defer func() {
if !privIp.Equal(publicIP) {
natType = nmmodels.NAT_Types.BehindNAT
Expand Down
Loading