gather_vnet_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. //go:build !js
  4. // +build !js
  5. package ice
  6. import (
  7. "context"
  8. "errors"
  9. "fmt"
  10. "net"
  11. "testing"
  12. "github.com/pion/logging"
  13. "github.com/pion/stun"
  14. "github.com/pion/transport/v2/test"
  15. "github.com/pion/transport/v2/vnet"
  16. "github.com/stretchr/testify/assert"
  17. )
  18. func TestVNetGather(t *testing.T) {
  19. report := test.CheckRoutines(t)
  20. defer report()
  21. loggerFactory := logging.NewDefaultLoggerFactory()
  22. t.Run("No local IP address", func(t *testing.T) {
  23. n, err := vnet.NewNet(&vnet.NetConfig{})
  24. assert.NoError(t, err)
  25. a, err := NewAgent(&AgentConfig{
  26. Net: n,
  27. })
  28. assert.NoError(t, err)
  29. localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4}, false)
  30. if len(localIPs) > 0 {
  31. t.Fatal("should return no local IP")
  32. } else if err != nil {
  33. t.Fatal(err)
  34. }
  35. assert.NoError(t, a.Close())
  36. })
  37. t.Run("Gather a dynamic IP address", func(t *testing.T) {
  38. cider := "1.2.3.0/24"
  39. _, ipNet, err := net.ParseCIDR(cider)
  40. if err != nil {
  41. t.Fatalf("Failed to parse CIDR: %s", err)
  42. }
  43. r, err := vnet.NewRouter(&vnet.RouterConfig{
  44. CIDR: cider,
  45. LoggerFactory: loggerFactory,
  46. })
  47. if err != nil {
  48. t.Fatalf("Failed to create a router: %s", err)
  49. }
  50. nw, err := vnet.NewNet(&vnet.NetConfig{})
  51. if err != nil {
  52. t.Fatalf("Failed to create a Net: %s", err)
  53. }
  54. err = r.AddNet(nw)
  55. if err != nil {
  56. t.Fatalf("Failed to add a Net to the router: %s", err)
  57. }
  58. a, err := NewAgent(&AgentConfig{
  59. Net: nw,
  60. })
  61. assert.NoError(t, err)
  62. localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4}, false)
  63. if len(localIPs) == 0 {
  64. t.Fatal("should have one local IP")
  65. } else if err != nil {
  66. t.Fatal(err)
  67. }
  68. for _, ip := range localIPs {
  69. if ip.IsLoopback() {
  70. t.Fatal("should not return loopback IP")
  71. }
  72. if !ipNet.Contains(ip) {
  73. t.Fatal("should be contained in the CIDR")
  74. }
  75. }
  76. assert.NoError(t, a.Close())
  77. })
  78. t.Run("listenUDP", func(t *testing.T) {
  79. r, err := vnet.NewRouter(&vnet.RouterConfig{
  80. CIDR: "1.2.3.0/24",
  81. LoggerFactory: loggerFactory,
  82. })
  83. if err != nil {
  84. t.Fatalf("Failed to create a router: %s", err)
  85. }
  86. nw, err := vnet.NewNet(&vnet.NetConfig{})
  87. if err != nil {
  88. t.Fatalf("Failed to create a Net: %s", err)
  89. }
  90. err = r.AddNet(nw)
  91. if err != nil {
  92. t.Fatalf("Failed to add a Net to the router: %s", err)
  93. }
  94. a, err := NewAgent(&AgentConfig{Net: nw})
  95. if err != nil {
  96. t.Fatalf("Failed to create agent: %s", err)
  97. }
  98. localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4}, false)
  99. if len(localIPs) == 0 {
  100. t.Fatal("localInterfaces found no interfaces, unable to test")
  101. } else if err != nil {
  102. t.Fatal(err)
  103. }
  104. ip := localIPs[0]
  105. conn, err := listenUDPInPortRange(a.net, a.log, 0, 0, udp, &net.UDPAddr{IP: ip, Port: 0})
  106. if err != nil {
  107. t.Fatalf("listenUDP error with no port restriction %v", err)
  108. } else if conn == nil {
  109. t.Fatalf("listenUDP error with no port restriction return a nil conn")
  110. }
  111. err = conn.Close()
  112. if err != nil {
  113. t.Fatalf("failed to close conn")
  114. }
  115. _, err = listenUDPInPortRange(a.net, a.log, 4999, 5000, udp, &net.UDPAddr{IP: ip, Port: 0})
  116. if !errors.Is(err, ErrPort) {
  117. t.Fatal("listenUDP with invalid port range did not return ErrPort")
  118. }
  119. conn, err = listenUDPInPortRange(a.net, a.log, 5000, 5000, udp, &net.UDPAddr{IP: ip, Port: 0})
  120. if err != nil {
  121. t.Fatalf("listenUDP error with no port restriction %v", err)
  122. } else if conn == nil {
  123. t.Fatalf("listenUDP error with no port restriction return a nil conn")
  124. }
  125. _, port, err := net.SplitHostPort(conn.LocalAddr().String())
  126. if err != nil {
  127. t.Fatal(err)
  128. } else if port != "5000" {
  129. t.Fatalf("listenUDP with port restriction of 5000 listened on incorrect port (%s)", port)
  130. }
  131. assert.NoError(t, conn.Close())
  132. assert.NoError(t, a.Close())
  133. })
  134. }
  135. func TestVNetGatherWithNAT1To1(t *testing.T) {
  136. report := test.CheckRoutines(t)
  137. defer report()
  138. loggerFactory := logging.NewDefaultLoggerFactory()
  139. log := loggerFactory.NewLogger("test")
  140. t.Run("gather 1:1 NAT external IPs as host candidates", func(t *testing.T) {
  141. externalIP0 := "1.2.3.4"
  142. externalIP1 := "1.2.3.5"
  143. localIP0 := "10.0.0.1"
  144. localIP1 := "10.0.0.2"
  145. map0 := fmt.Sprintf("%s/%s", externalIP0, localIP0)
  146. map1 := fmt.Sprintf("%s/%s", externalIP1, localIP1)
  147. wan, err := vnet.NewRouter(&vnet.RouterConfig{
  148. CIDR: "1.2.3.0/24",
  149. LoggerFactory: loggerFactory,
  150. })
  151. assert.NoError(t, err, "should succeed")
  152. lan, err := vnet.NewRouter(&vnet.RouterConfig{
  153. CIDR: "10.0.0.0/24",
  154. StaticIPs: []string{map0, map1},
  155. NATType: &vnet.NATType{
  156. Mode: vnet.NATModeNAT1To1,
  157. },
  158. LoggerFactory: loggerFactory,
  159. })
  160. assert.NoError(t, err, "should succeed")
  161. err = wan.AddRouter(lan)
  162. assert.NoError(t, err, "should succeed")
  163. nw, err := vnet.NewNet(&vnet.NetConfig{
  164. StaticIPs: []string{localIP0, localIP1},
  165. })
  166. if err != nil {
  167. t.Fatalf("Failed to create a Net: %s", err)
  168. }
  169. err = lan.AddNet(nw)
  170. assert.NoError(t, err, "should succeed")
  171. a, err := NewAgent(&AgentConfig{
  172. NetworkTypes: []NetworkType{
  173. NetworkTypeUDP4,
  174. },
  175. NAT1To1IPs: []string{map0, map1},
  176. Net: nw,
  177. })
  178. assert.NoError(t, err, "should succeed")
  179. defer a.Close() //nolint:errcheck
  180. done := make(chan struct{})
  181. err = a.OnCandidate(func(c Candidate) {
  182. if c == nil {
  183. close(done)
  184. }
  185. })
  186. assert.NoError(t, err, "should succeed")
  187. err = a.GatherCandidates()
  188. assert.NoError(t, err, "should succeed")
  189. log.Debug("Wait until gathering is complete...")
  190. <-done
  191. log.Debug("Gathering is done")
  192. candidates, err := a.GetLocalCandidates()
  193. assert.NoError(t, err, "should succeed")
  194. if len(candidates) != 2 {
  195. t.Fatal("There must be two candidates")
  196. }
  197. lAddr := [2]*net.UDPAddr{nil, nil}
  198. for i, candi := range candidates {
  199. lAddr[i] = candi.(*CandidateHost).conn.LocalAddr().(*net.UDPAddr) //nolint:forcetypeassert
  200. if candi.Port() != lAddr[i].Port {
  201. t.Fatalf("Unexpected candidate port: %d", candi.Port())
  202. }
  203. }
  204. if candidates[0].Address() == externalIP0 {
  205. if candidates[1].Address() != externalIP1 {
  206. t.Fatalf("Unexpected candidate IP: %s", candidates[1].Address())
  207. }
  208. if lAddr[0].IP.String() != localIP0 {
  209. t.Fatalf("Unexpected listen IP: %s", lAddr[0].IP.String())
  210. }
  211. if lAddr[1].IP.String() != localIP1 {
  212. t.Fatalf("Unexpected listen IP: %s", lAddr[1].IP.String())
  213. }
  214. } else if candidates[0].Address() == externalIP1 {
  215. if candidates[1].Address() != externalIP0 {
  216. t.Fatalf("Unexpected candidate IP: %s", candidates[1].Address())
  217. }
  218. if lAddr[0].IP.String() != localIP1 {
  219. t.Fatalf("Unexpected listen IP: %s", lAddr[0].IP.String())
  220. }
  221. if lAddr[1].IP.String() != localIP0 {
  222. t.Fatalf("Unexpected listen IP: %s", lAddr[1].IP.String())
  223. }
  224. }
  225. })
  226. t.Run("gather 1:1 NAT external IPs as srflx candidates", func(t *testing.T) {
  227. wan, err := vnet.NewRouter(&vnet.RouterConfig{
  228. CIDR: "1.2.3.0/24",
  229. LoggerFactory: loggerFactory,
  230. })
  231. assert.NoError(t, err, "should succeed")
  232. lan, err := vnet.NewRouter(&vnet.RouterConfig{
  233. CIDR: "10.0.0.0/24",
  234. StaticIPs: []string{
  235. "1.2.3.4/10.0.0.1",
  236. },
  237. NATType: &vnet.NATType{
  238. Mode: vnet.NATModeNAT1To1,
  239. },
  240. LoggerFactory: loggerFactory,
  241. })
  242. assert.NoError(t, err, "should succeed")
  243. err = wan.AddRouter(lan)
  244. assert.NoError(t, err, "should succeed")
  245. nw, err := vnet.NewNet(&vnet.NetConfig{
  246. StaticIPs: []string{
  247. "10.0.0.1",
  248. },
  249. })
  250. if err != nil {
  251. t.Fatalf("Failed to create a Net: %s", err)
  252. }
  253. err = lan.AddNet(nw)
  254. assert.NoError(t, err, "should succeed")
  255. a, err := NewAgent(&AgentConfig{
  256. NetworkTypes: []NetworkType{
  257. NetworkTypeUDP4,
  258. },
  259. NAT1To1IPs: []string{
  260. "1.2.3.4",
  261. },
  262. NAT1To1IPCandidateType: CandidateTypeServerReflexive,
  263. Net: nw,
  264. })
  265. assert.NoError(t, err, "should succeed")
  266. defer a.Close() //nolint:errcheck
  267. done := make(chan struct{})
  268. err = a.OnCandidate(func(c Candidate) {
  269. if c == nil {
  270. close(done)
  271. }
  272. })
  273. assert.NoError(t, err, "should succeed")
  274. err = a.GatherCandidates()
  275. assert.NoError(t, err, "should succeed")
  276. log.Debug("Wait until gathering is complete...")
  277. <-done
  278. log.Debug("Gathering is done")
  279. candidates, err := a.GetLocalCandidates()
  280. assert.NoError(t, err, "should succeed")
  281. if len(candidates) != 2 {
  282. t.Fatalf("Expected two candidates. actually %d", len(candidates))
  283. }
  284. var candiHost *CandidateHost
  285. var candiSrflx *CandidateServerReflexive
  286. for _, candidate := range candidates {
  287. switch candi := candidate.(type) {
  288. case *CandidateHost:
  289. candiHost = candi
  290. case *CandidateServerReflexive:
  291. candiSrflx = candi
  292. default:
  293. t.Fatal("Unexpected candidate type")
  294. }
  295. }
  296. assert.NotNil(t, candiHost, "should not be nil")
  297. assert.Equal(t, "10.0.0.1", candiHost.Address(), "should match")
  298. assert.NotNil(t, candiSrflx, "should not be nil")
  299. assert.Equal(t, "1.2.3.4", candiSrflx.Address(), "should match")
  300. })
  301. }
  302. func TestVNetGatherWithInterfaceFilter(t *testing.T) {
  303. report := test.CheckRoutines(t)
  304. defer report()
  305. loggerFactory := logging.NewDefaultLoggerFactory()
  306. r, err := vnet.NewRouter(&vnet.RouterConfig{
  307. CIDR: "1.2.3.0/24",
  308. LoggerFactory: loggerFactory,
  309. })
  310. if err != nil {
  311. t.Fatalf("Failed to create a router: %s", err)
  312. }
  313. nw, err := vnet.NewNet(&vnet.NetConfig{})
  314. if err != nil {
  315. t.Fatalf("Failed to create a Net: %s", err)
  316. }
  317. if err = r.AddNet(nw); err != nil {
  318. t.Fatalf("Failed to add a Net to the router: %s", err)
  319. }
  320. t.Run("InterfaceFilter should exclude the interface", func(t *testing.T) {
  321. a, err := NewAgent(&AgentConfig{
  322. Net: nw,
  323. InterfaceFilter: func(interfaceName string) bool {
  324. assert.Equal(t, "eth0", interfaceName)
  325. return false
  326. },
  327. })
  328. assert.NoError(t, err)
  329. localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4}, false)
  330. if err != nil {
  331. t.Fatal(err)
  332. } else if len(localIPs) != 0 {
  333. t.Fatal("InterfaceFilter should have excluded everything")
  334. }
  335. assert.NoError(t, a.Close())
  336. })
  337. t.Run("IPFilter should exclude the IP", func(t *testing.T) {
  338. a, err := NewAgent(&AgentConfig{
  339. Net: nw,
  340. IPFilter: func(ip net.IP) bool {
  341. assert.Equal(t, net.IP{1, 2, 3, 1}, ip)
  342. return false
  343. },
  344. })
  345. assert.NoError(t, err)
  346. localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4}, false)
  347. if err != nil {
  348. t.Fatal(err)
  349. } else if len(localIPs) != 0 {
  350. t.Fatal("IPFilter should have excluded everything")
  351. }
  352. assert.NoError(t, a.Close())
  353. })
  354. t.Run("InterfaceFilter should not exclude the interface", func(t *testing.T) {
  355. a, err := NewAgent(&AgentConfig{
  356. Net: nw,
  357. InterfaceFilter: func(interfaceName string) bool {
  358. assert.Equal(t, "eth0", interfaceName)
  359. return true
  360. },
  361. })
  362. assert.NoError(t, err)
  363. localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4}, false)
  364. if err != nil {
  365. t.Fatal(err)
  366. } else if len(localIPs) == 0 {
  367. t.Fatal("InterfaceFilter should not have excluded anything")
  368. }
  369. assert.NoError(t, a.Close())
  370. })
  371. }
  372. func TestVNetGather_TURNConnectionLeak(t *testing.T) {
  373. report := test.CheckRoutines(t)
  374. defer report()
  375. turnServerURL := &stun.URI{
  376. Scheme: stun.SchemeTypeTURN,
  377. Host: vnetSTUNServerIP,
  378. Port: vnetSTUNServerPort,
  379. Username: "user",
  380. Password: "pass",
  381. Proto: stun.ProtoTypeUDP,
  382. }
  383. // buildVNet with a Symmetric NATs for both LANs
  384. natType := &vnet.NATType{
  385. MappingBehavior: vnet.EndpointAddrPortDependent,
  386. FilteringBehavior: vnet.EndpointAddrPortDependent,
  387. }
  388. v, err := buildVNet(natType, natType)
  389. if !assert.NoError(t, err, "should succeed") {
  390. return
  391. }
  392. defer v.close()
  393. cfg0 := &AgentConfig{
  394. Urls: []*stun.URI{
  395. turnServerURL,
  396. },
  397. NetworkTypes: supportedNetworkTypes(),
  398. MulticastDNSMode: MulticastDNSModeDisabled,
  399. NAT1To1IPs: []string{vnetGlobalIPA},
  400. Net: v.net0,
  401. }
  402. aAgent, err := NewAgent(cfg0)
  403. if !assert.NoError(t, err, "should succeed") {
  404. return
  405. }
  406. aAgent.gatherCandidatesRelay(context.Background(), []*stun.URI{turnServerURL})
  407. // Assert relay conn leak on close.
  408. assert.NoError(t, aAgent.Close())
  409. }