From cd0a968a6292e7fb2739d26c0435c881109c4caa Mon Sep 17 00:00:00 2001 From: cnderrauber Date: Thu, 29 Sep 2022 13:33:41 +0800 Subject: [PATCH] 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. --- agent.go | 3 +++ agent_config.go | 7 ++++++- gather.go | 4 ++-- gather_test.go | 2 +- gather_vnet_test.go | 30 +++++++++++++++++++++++++----- util.go | 6 +++++- 6 files changed, 42 insertions(+), 10 deletions(-) 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/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 { 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) } }