v0.0.2 - 替换gostun的实现版本

This commit is contained in:
spiritlhl
2024-06-25 03:06:25 +00:00
parent 0242086adb
commit 83b9503eee
5 changed files with 59 additions and 369 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
run: |
git config --global user.name 'github-actions'
git config --global user.email 'github-actions@github.com'
TAG="v0.0.1-$(date +'%Y%m%d%H%M%S')"
TAG="v0.0.2-$(date +'%Y%m%d%H%M%S')"
git tag $TAG
git push origin $TAG
env:
+7 -5
View File
@@ -4,8 +4,8 @@ go 1.22.4
require (
github.com/libp2p/go-nat v0.2.0
github.com/pion/logging v0.2.2
github.com/pion/stun v0.6.1
github.com/oneclickvirt/defaultset v0.0.2-20240624082446
github.com/oneclickvirt/gostun v0.0.2-20240625025941
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/yusufpapurcu/wmi v1.2.4
golang.org/x/sys v0.21.0
@@ -18,14 +18,16 @@ require (
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
github.com/oneclickvirt/defaultset v0.0.2-20240624082446 // indirect
github.com/pion/dtls/v2 v2.2.7 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/stun/v2 v2.0.0 // indirect
github.com/pion/transport/v2 v2.2.1 // indirect
github.com/pion/transport/v3 v3.0.1 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sync v0.2.0 // indirect
)
+17 -4
View File
@@ -17,14 +17,18 @@ github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9t
github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
github.com/oneclickvirt/defaultset v0.0.2-20240624082446 h1:5Pg3mK/u/vQvSz7anu0nxzrNdELi/AcDAU1mMsmPzyc=
github.com/oneclickvirt/defaultset v0.0.2-20240624082446/go.mod h1:e9Jt4tf2sbemCtc84/XgKcHy9EZ2jkc5x2sW1NiJS+E=
github.com/oneclickvirt/gostun v0.0.2-20240625025941 h1:h+ZL8jkjXR6QE0qEX34FjWTv89+lNj2fEkWx5Agpgzc=
github.com/oneclickvirt/gostun v0.0.2-20240625025941/go.mod h1:f7DPEXAxbmwXSW33dbxtb0/KzqvOBWhTs2Or5xBerQA=
github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0=
github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ=
github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM=
github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
@@ -44,6 +48,8 @@ github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8t
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
@@ -51,8 +57,9 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -63,8 +70,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -80,17 +88,22 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+1 -1
View File
@@ -1,6 +1,6 @@
package model
const BasicsVersion = "v0.0.1"
const BasicsVersion = "v0.0.2"
var EnableLoger bool
+33 -358
View File
@@ -1,368 +1,43 @@
package system
import (
"errors"
"flag"
"fmt"
"net"
"os"
"time"
"github.com/pion/logging"
"github.com/pion/stun"
)
// From https://github.com/pion/stun/blob/master/cmd/stun-nat-behaviour/main.go
// I only make changes to summarize the NAT type
// my changes start
var (
NatMappingBehavior string
NatFilteringBehavior string
)
// my changes end
type stunServerConn struct {
conn net.PacketConn
LocalAddr net.Addr
RemoteAddr *net.UDPAddr
OtherAddr *net.UDPAddr
messageChan chan *stun.Message
}
func (c *stunServerConn) Close() error {
return c.conn.Close()
}
var (
addrStrPtr = flag.String("server", "stun.voipgate.com:3478", "STUN server address") //nolint:gochecknoglobals
timeoutPtr = flag.Int("timeout", 3, "the number of seconds to wait for STUN server's response") //nolint:gochecknoglobals
verbose = flag.Int("verbose", 0, "the verbosity level") //nolint:gochecknoglobals // my changes
log logging.LeveledLogger //nolint:gochecknoglobals
)
const (
messageHeaderSize = 20
)
var (
errResponseMessage = errors.New("error reading from response message channel")
errTimedOut = errors.New("timed out waiting for response")
errNoOtherAddress = errors.New("no OTHER-ADDRESS in message")
"github.com/oneclickvirt/gostun/model"
"github.com/oneclickvirt/gostun/stuncheck"
)
func getNatType() string {
flag.Parse()
var logLevel logging.LogLevel
switch *verbose {
case 0:
logLevel = logging.LogLevelWarn // default // my changes
case 1:
logLevel = logging.LogLevelInfo
case 2:
logLevel = logging.LogLevelDebug
case 3:
logLevel = logging.LogLevelTrace
model.EnableLoger = false
addrStrPtrList := []string{
"stun.voipgate.com:3478",
"stun.miwifi.com:3478",
"stunserver.stunprotocol.org:3478",
}
log = logging.NewDefaultLeveledLoggerForScope("", logLevel, os.Stdout)
if err := mappingTests(*addrStrPtr); err != nil {
NatMappingBehavior = "inconclusive" // my changes
// log.Warn("NAT mapping behavior: inconclusive")
}
if err := filteringTests(*addrStrPtr); err != nil {
NatFilteringBehavior = "inconclusive" // my changes
// log.Warn("NAT filtering behavior: inconclusive")
}
// my changes start
if NatMappingBehavior != "" && NatFilteringBehavior != "" {
if NatMappingBehavior == "inconclusive" || NatFilteringBehavior == "inconclusive" {
return "Inconclusive"
} else if NatMappingBehavior == "endpoint independent" && NatFilteringBehavior == "endpoint independent" {
return "Full Cone"
} else if NatMappingBehavior == "endpoint independent" && NatFilteringBehavior == "address dependent" {
return "Restricted Cone"
} else if NatMappingBehavior == "endpoint independent" && NatFilteringBehavior == "address and port dependent" {
return "Port Restricted Cone"
} else if NatMappingBehavior == "address and port dependent" && NatFilteringBehavior == "address and port dependent" {
return "Symmetric"
} else {
return fmt.Sprintf("%v[NatMappingBehavior] %v[NatFilteringBehavior]", NatMappingBehavior, NatFilteringBehavior)
}
} else {
return "Inconclusive"
}
// my changes end
}
// RFC5780: 4.3. Determining NAT Mapping Behavior
func mappingTests(addrStr string) error {
mapTestConn, err := connect(addrStr)
if err != nil {
// log.Warnf("Error creating STUN connection: %s", err)
return err
}
// Test I: Regular binding request
log.Info("Mapping Test I: Regular binding request")
request := stun.MustBuild(stun.TransactionID, stun.BindingRequest)
resp, err := mapTestConn.roundTrip(request, mapTestConn.RemoteAddr)
if err != nil {
return err
}
// Parse response message for XOR-MAPPED-ADDRESS and make sure OTHER-ADDRESS valid
resps1 := parse(resp)
if resps1.xorAddr == nil || resps1.otherAddr == nil {
log.Info("Error: NAT discovery feature not supported by this server")
return errNoOtherAddress
}
addr, err := net.ResolveUDPAddr("udp4", resps1.otherAddr.String())
if err != nil {
log.Infof("Failed resolving OTHER-ADDRESS: %v", resps1.otherAddr)
return err
}
mapTestConn.OtherAddr = addr
log.Infof("Received XOR-MAPPED-ADDRESS: %v", resps1.xorAddr)
// Assert mapping behavior
if resps1.xorAddr.String() == mapTestConn.LocalAddr.String() {
NatMappingBehavior = "endpoint independent (no NAT)" // my changes
// log.Warn("=> NAT mapping behavior: endpoint independent (no NAT)")
return nil
}
// Test II: Send binding request to the other address but primary port
log.Info("Mapping Test II: Send binding request to the other address but primary port")
oaddr := *mapTestConn.OtherAddr
oaddr.Port = mapTestConn.RemoteAddr.Port
resp, err = mapTestConn.roundTrip(request, &oaddr)
if err != nil {
return err
}
// Assert mapping behavior
resps2 := parse(resp)
log.Infof("Received XOR-MAPPED-ADDRESS: %v", resps2.xorAddr)
if resps2.xorAddr.String() == resps1.xorAddr.String() {
NatMappingBehavior = "endpoint independent" // my changes
// log.Warn("=> NAT mapping behavior: endpoint independent")
return nil
}
// Test III: Send binding request to the other address and port
log.Info("Mapping Test III: Send binding request to the other address and port")
resp, err = mapTestConn.roundTrip(request, mapTestConn.OtherAddr)
if err != nil {
return err
}
// Assert mapping behavior
resps3 := parse(resp)
log.Infof("Received XOR-MAPPED-ADDRESS: %v", resps3.xorAddr)
if resps3.xorAddr.String() == resps2.xorAddr.String() {
NatMappingBehavior = "address dependent" // my changes
// log.Warn("=> NAT mapping behavior: address dependent")
} else {
NatMappingBehavior = "address and port dependent" // my changes
// log.Warn("=> NAT mapping behavior: address and port dependent")
}
return mapTestConn.Close()
}
// RFC5780: 4.4. Determining NAT Filtering Behavior
func filteringTests(addrStr string) error {
mapTestConn, err := connect(addrStr)
if err != nil {
// log.Warnf("Error creating STUN connection: %s", err)
return err
}
// Test I: Regular binding request
log.Info("Filtering Test I: Regular binding request")
request := stun.MustBuild(stun.TransactionID, stun.BindingRequest)
resp, err := mapTestConn.roundTrip(request, mapTestConn.RemoteAddr)
if err != nil || errors.Is(err, errTimedOut) {
return err
}
resps := parse(resp)
if resps.xorAddr == nil || resps.otherAddr == nil {
// log.Warn("Error: NAT discovery feature not supported by this server")
return errNoOtherAddress
}
addr, err := net.ResolveUDPAddr("udp4", resps.otherAddr.String())
if err != nil {
log.Infof("Failed resolving OTHER-ADDRESS: %v", resps.otherAddr)
return err
}
mapTestConn.OtherAddr = addr
// Test II: Request to change both IP and port
log.Info("Filtering Test II: Request to change both IP and port")
request = stun.MustBuild(stun.TransactionID, stun.BindingRequest)
request.Add(stun.AttrChangeRequest, []byte{0x00, 0x00, 0x00, 0x06})
resp, err = mapTestConn.roundTrip(request, mapTestConn.RemoteAddr)
if err == nil {
parse(resp) // just to print out the resp
NatFilteringBehavior = "endpoint independent" // my changes
// log.Warn("=> NAT filtering behavior: endpoint independent")
return nil
} else if !errors.Is(err, errTimedOut) {
return err // something else went wrong
}
// Test III: Request to change port only
log.Info("Filtering Test III: Request to change port only")
request = stun.MustBuild(stun.TransactionID, stun.BindingRequest)
request.Add(stun.AttrChangeRequest, []byte{0x00, 0x00, 0x00, 0x02})
resp, err = mapTestConn.roundTrip(request, mapTestConn.RemoteAddr)
if err == nil {
parse(resp) // just to print out the resp
NatFilteringBehavior = "address dependent" // my changes
// log.Warn("=> NAT filtering behavior: address dependent")
} else if errors.Is(err, errTimedOut) {
NatFilteringBehavior = "address and port dependent" // my changes
// log.Warn("=> NAT filtering behavior: address and port dependent")
}
return mapTestConn.Close()
}
// Parse a STUN message
func parse(msg *stun.Message) (ret struct {
xorAddr *stun.XORMappedAddress
otherAddr *stun.OtherAddress
respOrigin *stun.ResponseOrigin
mappedAddr *stun.MappedAddress
software *stun.Software
},
) {
ret.mappedAddr = &stun.MappedAddress{}
ret.xorAddr = &stun.XORMappedAddress{}
ret.respOrigin = &stun.ResponseOrigin{}
ret.otherAddr = &stun.OtherAddress{}
ret.software = &stun.Software{}
if ret.xorAddr.GetFrom(msg) != nil {
ret.xorAddr = nil
}
if ret.otherAddr.GetFrom(msg) != nil {
ret.otherAddr = nil
}
if ret.respOrigin.GetFrom(msg) != nil {
ret.respOrigin = nil
}
if ret.mappedAddr.GetFrom(msg) != nil {
ret.mappedAddr = nil
}
if ret.software.GetFrom(msg) != nil {
ret.software = nil
}
log.Debugf("%v", msg)
log.Debugf("\tMAPPED-ADDRESS: %v", ret.mappedAddr)
log.Debugf("\tXOR-MAPPED-ADDRESS: %v", ret.xorAddr)
log.Debugf("\tRESPONSE-ORIGIN: %v", ret.respOrigin)
log.Debugf("\tOTHER-ADDRESS: %v", ret.otherAddr)
log.Debugf("\tSOFTWARE: %v", ret.software)
for _, attr := range msg.Attributes {
switch attr.Type {
case
stun.AttrXORMappedAddress,
stun.AttrOtherAddress,
stun.AttrResponseOrigin,
stun.AttrMappedAddress,
stun.AttrSoftware:
break //nolint:staticcheck
default:
log.Debugf("\t%v (l=%v)", attr, attr.Length)
}
}
return ret
}
// Given an address string, returns a StunServerConn
func connect(addrStr string) (*stunServerConn, error) {
log.Infof("Connecting to STUN server: %s", addrStr)
addr, err := net.ResolveUDPAddr("udp4", addrStr)
if err != nil {
// log.Warnf("Error resolving address: %s", err)
return nil, err
}
c, err := net.ListenUDP("udp4", nil)
if err != nil {
return nil, err
}
log.Infof("Local address: %s", c.LocalAddr())
log.Infof("Remote address: %s", addr.String())
mChan := listen(c)
return &stunServerConn{
conn: c,
LocalAddr: c.LocalAddr(),
RemoteAddr: addr,
messageChan: mChan,
}, nil
}
// Send request and wait for response or timeout
func (c *stunServerConn) roundTrip(msg *stun.Message, addr net.Addr) (*stun.Message, error) {
_ = msg.NewTransactionID()
log.Infof("Sending to %v: (%v bytes)", addr, msg.Length+messageHeaderSize)
log.Debugf("%v", msg)
for _, attr := range msg.Attributes {
log.Debugf("\t%v (l=%v)", attr, attr.Length)
}
_, err := c.conn.WriteTo(msg.Raw, addr)
if err != nil {
// log.Warnf("Error sending request to %v", addr)
return nil, err
}
// Wait for response or timeout
select {
case m, ok := <-c.messageChan:
if !ok {
return nil, errResponseMessage
}
return m, nil
case <-time.After(time.Duration(*timeoutPtr) * time.Second):
log.Infof("Timed out waiting for response from server %v", addr)
return nil, errTimedOut
}
}
// taken from https://github.com/pion/stun/blob/master/cmd/stun-traversal/main.go
func listen(conn *net.UDPConn) (messages chan *stun.Message) {
messages = make(chan *stun.Message)
go func() {
for {
buf := make([]byte, 1024)
n, addr, err := conn.ReadFromUDP(buf)
if err != nil {
close(messages)
return
checkStatus := true
for _, addrStr := range addrStrPtrList {
err1 := stuncheck.MappingTests(addrStr)
if err1 != nil {
model.NatMappingBehavior = "inconclusive"
if model.EnableLoger {
model.Log.Warn("NAT mapping behavior: inconclusive")
}
log.Infof("Response from %v: (%v bytes)", addr, n)
buf = buf[:n]
m := new(stun.Message)
m.Raw = buf
err = m.Decode()
if err != nil {
log.Infof("Error decoding message: %v", err)
close(messages)
return
}
messages <- m
checkStatus = false
}
}()
return
err2 := stuncheck.FilteringTests(addrStr)
if err2 != nil {
model.NatFilteringBehavior = "inconclusive"
if model.EnableLoger {
model.Log.Warn("NAT filtering behavior: inconclusive")
}
checkStatus = false
}
if model.NatMappingBehavior == "inconclusive" || model.NatFilteringBehavior == "inconclusive" {
checkStatus = false
} else if model.NatMappingBehavior != "inconclusive" && model.NatFilteringBehavior != "inconclusive" {
checkStatus = true
}
if checkStatus {
break
}
}
return stuncheck.CheckType()
}