Repository: pion/ice
Pull request #478 (2022-09-29 05:37:22)

Add IPFilter to AgentConfig
When machine's network interface have more than one ip address and user don't want expose one of these ips to remote peer, interface filter can't work in this case, so add a ip filter for that.



codecov[bot]: # [Codecov](https://codecov.io/gh/pion/ice/pull/478?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion) Report
Base: **77.86**% // Head: **24.43**% // Decreases project coverage by **`-53.42%`** :warning:
> Coverage data is based on head [(`95e1654`)](https://codecov.io/gh/pion/ice/pull/478?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion) compared to base [(`12148c5`)](https://codecov.io/gh/pion/ice/commit/12148c5d62514bcfc88b2c47a6a7a56a7774e3a3?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion).
> Patch coverage: 0.00% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff             @@
##           master     #478       +/-   ##
===========================================
- Coverage   77.86%   24.43%   -53.43%     
===========================================
  Files          38       37        -1     
  Lines        4292     4264       -28     
===========================================
- Hits         3342     1042     -2300     
- Misses        733     3182     +2449     
+ Partials      217       40      -177     
```

| Flag | Coverage Δ | |
|---|---|---|
| go | `?` | |
| wasm | `24.43% <0.00%> (-0.02%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/pion/ice/pull/478?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion) | Coverage Δ | |
|---|---|---|
| [agent.go](https://codecov.io/gh/pion/ice/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion#diff-YWdlbnQuZ28=) | `0.00% <ø> (-82.04%)` | :arrow_down: |
| [agent\_config.go](https://codecov.io/gh/pion/ice/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion#diff-YWdlbnRfY29uZmlnLmdv) | `0.00% <ø> (-82.15%)` | :arrow_down: |
| [gather.go](https://codecov.io/gh/pion/ice/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion#diff-Z2F0aGVyLmdv) | `0.00% <0.00%> (-65.36%)` | :arrow_down: |
| [util.go](https://codecov.io/gh/pion/ice/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion#diff-dXRpbC5nbw==) | `12.88% <0.00%> (-61.66%)` | :arrow_down: |
| [selection.go](https://codecov.io/gh/pion/ice/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion#diff-c2VsZWN0aW9uLmdv) | `0.00% <0.00%> (-84.19%)` | :arrow_down: |
| [agent\_stats.go](https://codecov.io/gh/pion/ice/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion#diff-YWdlbnRfc3RhdHMuZ28=) | `0.00% <0.00%> (-83.51%)` | :arrow_down: |
| [candidate\_peer\_reflexive.go](https://codecov.io/gh/pion/ice/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion#diff-Y2FuZGlkYXRlX3BlZXJfcmVmbGV4aXZlLmdv) | `0.00% <0.00%> (-80.65%)` | :arrow_down: |
| [transport.go](https://codecov.io/gh/pion/ice/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion#diff-dHJhbnNwb3J0Lmdv) | `0.00% <0.00%> (-79.73%)` | :arrow_down: |
| ... and [19 more](https://codecov.io/gh/pion/ice/pull/478/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion) | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/pion/ice/pull/478?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pion).


Patch:
diff --git a/agent.go b/agent.go
index 54728a2..eb66de8 100644
--- a/agent.go
+++ b/agent.go
@@ -129,6 +129,7 @@ type Agent struct {
 	udpMuxSrflx UniversalUDPMux
 
 	interfaceFilter func(string) bool
+	ipFilter        func(net.IP) bool
 
 	insecureSkipVerify bool
 
@@ -313,6 +314,8 @@ func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit
 
 		interfaceFilter: config.InterfaceFilter,
 
+		ipFilter: config.IPFilter,
+
 		insecureSkipVerify: config.InsecureSkipVerify,
 	}
 
diff --git a/agent_config.go b/agent_config.go
index 08aa158..7e5cedd 100644
--- a/agent_config.go
+++ b/agent_config.go
@@ -1,6 +1,7 @@
 package ice
 
 import (
+	"net"
 	"time"
 
 	"github.com/pion/logging"
@@ -132,10 +133,14 @@ type AgentConfig struct {
 	// (see github.com/pion/transport/vnet)
 	Net *vnet.Net
 
-	// InterfaceFilter is a function that you can use in order to  whitelist or blacklist
+	// InterfaceFilter is a function that you can use in order to whitelist or blacklist
 	// the interfaces which are used to gather ICE candidates.
 	InterfaceFilter func(string) bool
 
+	// IPFilter is a function that you can use in order to whitelist or blacklist
+	// the ips which are used to gather ICE candidates.
+	IPFilter func(net.IP) bool
+
 	// InsecureSkipVerify controls if self-signed certificates are accepted when connecting
 	// to TURN servers via TLS or DTLS
 	InsecureSkipVerify bool
diff --git a/gather.go b/gather.go
index b83237d..a370f42 100644
--- a/gather.go
+++ b/gather.go
@@ -149,7 +149,7 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ
 		delete(networks, udp)
 	}
 
-	localIPs, err := localInterfaces(a.net, a.interfaceFilter, networkTypes)
+	localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, networkTypes)
 	if err != nil {
 		a.log.Warnf("failed to iterate local interfaces, host candidates will not be gathered %s", err)
 		return
@@ -273,7 +273,7 @@ func (a *Agent) gatherCandidatesLocalUDPMux(ctx context.Context) error { //nolin
 		return errUDPMuxDisabled
 	}
 
-	localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.networkTypes)
+	localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, a.networkTypes)
 	switch {
 	case err != nil:
 		return err
diff --git a/util.go b/util.go
index af4c30c..011fd8c 100644
--- a/util.go
+++ b/util.go
@@ -132,7 +132,7 @@ func stunRequest(read func([]byte) (int, error), write func([]byte) (int, error)
 	return res, nil
 }
 
-func localInterfaces(vnet *vnet.Net, interfaceFilter func(string) bool, networkTypes []NetworkType) ([]net.IP, error) { //nolint:gocognit
+func localInterfaces(vnet *vnet.Net, interfaceFilter func(string) bool, ipFilter func(net.IP) bool, networkTypes []NetworkType) ([]net.IP, error) { //nolint:gocognit
 	ips := []net.IP{}
 	ifaces, err := vnet.Interfaces()
 	if err != nil {
@@ -189,6 +189,10 @@ func localInterfaces(vnet *vnet.Net, interfaceFilter func(string) bool, networkT
 				continue
 			}
 
+			if ipFilter != nil && !ipFilter(ip) {
+				continue
+			}
+
 			ips = append(ips, ip)
 		}
 	}


Test patch:
diff --git a/gather_test.go b/gather_test.go
index 6ce344c..901c290 100644
--- a/gather_test.go
+++ b/gather_test.go
@@ -31,7 +31,7 @@ func TestListenUDP(t *testing.T) {
 	a, err := NewAgent(&AgentConfig{})
 	assert.NoError(t, err)
 
-	localIPs, err := localInterfaces(a.net, a.interfaceFilter, []NetworkType{NetworkTypeUDP4})
+	localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4})
 	assert.NotEqual(t, len(localIPs), 0, "localInterfaces found no interfaces, unable to test")
 	assert.NoError(t, err)
 
diff --git a/gather_vnet_test.go b/gather_vnet_test.go
index fff589e..f03771a 100644
--- a/gather_vnet_test.go
+++ b/gather_vnet_test.go
@@ -29,7 +29,7 @@ func TestVNetGather(t *testing.T) {
 		})
 		assert.NoError(t, err)
 
-		localIPs, err := localInterfaces(a.net, a.interfaceFilter, []NetworkType{NetworkTypeUDP4})
+		localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4})
 		if len(localIPs) > 0 {
 			t.Fatal("should return no local IP")
 		} else if err != nil {
@@ -69,7 +69,7 @@ func TestVNetGather(t *testing.T) {
 		})
 		assert.NoError(t, err)
 
-		localIPs, err := localInterfaces(a.net, a.interfaceFilter, []NetworkType{NetworkTypeUDP4})
+		localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4})
 		if len(localIPs) == 0 {
 			t.Fatal("should have one local IP")
 		} else if err != nil {
@@ -112,7 +112,7 @@ func TestVNetGather(t *testing.T) {
 			t.Fatalf("Failed to create agent: %s", err)
 		}
 
-		localIPs, err := localInterfaces(a.net, a.interfaceFilter, []NetworkType{NetworkTypeUDP4})
+		localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4})
 		if len(localIPs) == 0 {
 			t.Fatal("localInterfaces found no interfaces, unable to test")
 		} else if err != nil {
@@ -385,7 +385,7 @@ func TestVNetGatherWithInterfaceFilter(t *testing.T) {
 		})
 		assert.NoError(t, err)
 
-		localIPs, err := localInterfaces(a.net, a.interfaceFilter, []NetworkType{NetworkTypeUDP4})
+		localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4})
 		if err != nil {
 			t.Fatal(err)
 		} else if len(localIPs) != 0 {
@@ -395,6 +395,26 @@ func TestVNetGatherWithInterfaceFilter(t *testing.T) {
 		assert.NoError(t, a.Close())
 	})
 
+	t.Run("IPFilter should exclude the IP", func(t *testing.T) {
+		a, err := NewAgent(&AgentConfig{
+			Net: nw,
+			IPFilter: func(ip net.IP) bool {
+				assert.Equal(t, net.IP{1, 2, 3, 1}, ip)
+				return false
+			},
+		})
+		assert.NoError(t, err)
+
+		localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4})
+		if err != nil {
+			t.Fatal(err)
+		} else if len(localIPs) != 0 {
+			t.Fatal("IPFilter should have excluded everything")
+		}
+
+		assert.NoError(t, a.Close())
+	})
+
 	t.Run("InterfaceFilter should not exclude the interface", func(t *testing.T) {
 		a, err := NewAgent(&AgentConfig{
 			Net: nw,
@@ -405,7 +425,7 @@ func TestVNetGatherWithInterfaceFilter(t *testing.T) {
 		})
 		assert.NoError(t, err)
 
-		localIPs, err := localInterfaces(a.net, a.interfaceFilter, []NetworkType{NetworkTypeUDP4})
+		localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, []NetworkType{NetworkTypeUDP4})
 		if err != nil {
 			t.Fatal(err)
 		} else if len(localIPs) == 0 {