[tor-commits] [snowflake/master] Extract remote address from ICE candidates

cohosh at torproject.org cohosh at torproject.org
Mon Oct 5 21:03:42 UTC 2020


commit d7aa9b835645bc52c29ba13cdab461fe0d0e4e66
Author: Cecylia Bocovich <cohosh at torproject.org>
Date:   Wed Sep 30 10:10:29 2020 -0400

    Extract remote address from ICE candidates
    
    Parse the received ICE candidates as well as the Connection Data
    field for a non-local IP address to pass to the bridge. This fixes
    bug #33157.
---
 proxy/proxy-go_test.go | 126 +++++++++++++++++++++++++++++++++++++++++++++----
 proxy/snowflake.go     |  41 ++++++++++++++--
 2 files changed, 154 insertions(+), 13 deletions(-)

diff --git a/proxy/proxy-go_test.go b/proxy/proxy-go_test.go
index 168ca25..1218289 100644
--- a/proxy/proxy-go_test.go
+++ b/proxy/proxy-go_test.go
@@ -64,6 +64,51 @@ m=audio 49170 RTP/AVP 0
 m=video 51372 RTP/AVP 99
 a=rtpmap:99 h263-1998/90000
 `, net.ParseIP("224.2.17.12")},
+		// local addresses only
+		{`v=0
+o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5
+s=SDP Seminar
+i=A Seminar on the session description protocol
+u=http://www.example.com/seminars/sdp.pdf
+e=j.doe at example.com (Jane Doe)
+c=IN IP4 10.47.16.5/127
+t=2873397496 2873404696
+a=recvonly
+m=audio 49170 RTP/AVP 0
+m=video 51372 RTP/AVP 99
+a=rtpmap:99 h263-1998/90000
+`, nil},
+		// Remote IP in candidate attribute only
+		{`v=0
+o=- 4358805017720277108 2 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=group:BUNDLE data
+a=msid-semantic: WMS
+m=application 56688 DTLS/SCTP 5000
+c=IN IP4 0.0.0.0
+a=candidate:3769337065 1 udp 2122260223 1.2.3.4 56688 typ host generation 0 network-id 1 network-cost 50
+a=ice-ufrag:aMAZ
+a=ice-pwd:jcHb08Jjgrazp2dzjdrvPPvV
+a=ice-options:trickle
+a=fingerprint:sha-256 C8:88:EE:B9:E7:02:2E:21:37:ED:7A:D1:EB:2B:A3:15:A2:3B:5B:1C:3D:D4:D5:1F:06:CF:52:40:03:F8:DD:66
+a=setup:actpass
+a=mid:data
+a=sctpmap:5000 webrtc-datachannel 1024
+`, net.ParseIP("1.2.3.4")},
+		// Unspecified address
+		{`v=0
+o=jdoe 2890844526 2890842807 IN IP4 0.0.0.0
+s=SDP Seminar
+i=A Seminar on the session description protocol
+u=http://www.example.com/seminars/sdp.pdf
+e=j.doe at example.com (Jane Doe)
+t=2873397496 2873404696
+a=recvonly
+m=audio 49170 RTP/AVP 0
+m=video 51372 RTP/AVP 99
+a=rtpmap:99 h263-1998/90000
+`, nil},
 		// Missing c= line
 		{`v=0
 o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5
@@ -78,22 +123,64 @@ m=video 51372 RTP/AVP 99
 a=rtpmap:99 h263-1998/90000
 `, nil},
 		// Single line, IP address only
-		{`c=IN IP4 224.2.1.1
+		{`v=0
+o=- 4358805017720277108 2 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=group:BUNDLE data
+a=msid-semantic: WMS
+m=application 56688 DTLS/SCTP 5000
+c=IN IP4 224.2.1.1
 `, net.ParseIP("224.2.1.1")},
 		// Same, with TTL
-		{`c=IN IP4 224.2.1.1/127
+		{`v=0
+o=- 4358805017720277108 2 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=group:BUNDLE data
+a=msid-semantic: WMS
+m=application 56688 DTLS/SCTP 5000
+c=IN IP4 224.2.1.1/127
 `, net.ParseIP("224.2.1.1")},
 		// Same, with TTL and multicast addresses
-		{`c=IN IP4 224.2.1.1/127/3
+		{`v=0
+o=- 4358805017720277108 2 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=group:BUNDLE data
+a=msid-semantic: WMS
+m=application 56688 DTLS/SCTP 5000
+c=IN IP4 224.2.1.1/127/3
 `, net.ParseIP("224.2.1.1")},
 		// IPv6, address only
-		{`c=IN IP6 FF15::101
+		{`v=0
+o=- 4358805017720277108 2 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=group:BUNDLE data
+a=msid-semantic: WMS
+m=application 56688 DTLS/SCTP 5000
+c=IN IP6 FF15::101
 `, net.ParseIP("ff15::101")},
 		// Same, with multicast addresses
-		{`c=IN IP6 FF15::101/3
+		{`v=0
+o=- 4358805017720277108 2 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=group:BUNDLE data
+a=msid-semantic: WMS
+m=application 56688 DTLS/SCTP 5000
+c=IN IP6 FF15::101/3
 `, net.ParseIP("ff15::101")},
 		// Multiple c= lines
-		{`c=IN IP4 1.2.3.4
+		{`v=0
+o=- 4358805017720277108 2 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=group:BUNDLE data
+a=msid-semantic: WMS
+m=application 56688 DTLS/SCTP 5000
+c=IN IP4 1.2.3.4
 c=IN IP4 5.6.7.8
 `, net.ParseIP("1.2.3.4")},
 		// Modified from SDP sent by snowflake-client.
@@ -116,13 +203,34 @@ a=mid:data
 a=sctpmap:5000 webrtc-datachannel 1024
 `, net.ParseIP("1.2.3.4")},
 		// Improper character within IPv4
-		{`c=IN IP4 224.2z.1.1
+		{`v=0
+o=- 4358805017720277108 2 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=group:BUNDLE data
+a=msid-semantic: WMS
+m=application 56688 DTLS/SCTP 5000
+c=IN IP4 224.2z.1.1
 `, nil},
 		// Improper character within IPv6
-		{`c=IN IP6 ff15:g::101
+		{`v=0
+o=- 4358805017720277108 2 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=group:BUNDLE data
+a=msid-semantic: WMS
+m=application 56688 DTLS/SCTP 5000
+c=IN IP6 ff15:g::101
 `, nil},
 		// Bogus "IP7" addrtype
-		{`c=IN IP7 1.2.3.4
+		{`v=0
+o=- 4358805017720277108 2 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=group:BUNDLE data
+a=msid-semantic: WMS
+m=application 56688 DTLS/SCTP 5000
+c=IN IP7 1.2.3.4
 `, nil},
 	}
 
diff --git a/proxy/snowflake.go b/proxy/snowflake.go
index b880b36..ac85527 100644
--- a/proxy/snowflake.go
+++ b/proxy/snowflake.go
@@ -24,6 +24,7 @@ import (
 	"git.torproject.org/pluggable-transports/snowflake.git/common/util"
 	"git.torproject.org/pluggable-transports/snowflake.git/common/websocketconn"
 	"github.com/gorilla/websocket"
+	"github.com/pion/sdp/v2"
 	"github.com/pion/webrtc/v2"
 )
 
@@ -65,15 +66,47 @@ var remoteIPPatterns = []*regexp.Regexp{
 	regexp.MustCompile(`(?m)^c=IN IP6 ([0-9A-Fa-f:.]+)(?:\/\d+)?(:? |\r?\n)`),
 }
 
-// https://tools.ietf.org/html/rfc4566#section-5.7
-func remoteIPFromSDP(sdp string) net.IP {
+// Checks whether an IP address is a remote address for the client
+func isRemoteAddress(ip net.IP) bool {
+	return !(util.IsLocal(ip) || ip.IsUnspecified() || ip.IsLoopback())
+}
+
+func remoteIPFromSDP(str string) net.IP {
+	// Look for remote IP in "a=candidate" attribute fields
+	// https://tools.ietf.org/html/rfc5245#section-15.1
+	var desc sdp.SessionDescription
+	err := desc.Unmarshal([]byte(str))
+	if err != nil {
+		log.Println("Error parsing SDP: ", err.Error())
+		return nil
+	}
+	for _, m := range desc.MediaDescriptions {
+		for _, a := range m.Attributes {
+			if a.IsICECandidate() {
+				ice, err := a.ToICECandidate()
+				if err == nil {
+					ip := net.ParseIP(ice.Address)
+					if ip != nil && isRemoteAddress(ip) {
+						return ip
+					}
+				}
+			}
+		}
+	}
+	// Finally look for remote IP in "c=" Connection Data field
+	// https://tools.ietf.org/html/rfc4566#section-5.7
 	for _, pattern := range remoteIPPatterns {
-		m := pattern.FindStringSubmatch(sdp)
+		m := pattern.FindStringSubmatch(str)
 		if m != nil {
 			// Ignore parsing errors, ParseIP returns nil.
-			return net.ParseIP(m[1])
+			ip := net.ParseIP(m[1])
+			if ip != nil && isRemoteAddress(ip) {
+				return ip
+			}
+
 		}
 	}
+
 	return nil
 }
 



More information about the tor-commits mailing list