aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCecylia Bocovich <cohosh@torproject.org>2020-09-30 10:10:29 -0400
committerCecylia Bocovich <cohosh@torproject.org>2020-10-05 17:02:57 -0400
commitd7aa9b835645bc52c29ba13cdab461fe0d0e4e66 (patch)
treed575091f568208da693087944d105a0cff931035
parent8467c01e9e88523fcdef22fed8efadbd07484966 (diff)
downloadsnowflake-d7aa9b835645bc52c29ba13cdab461fe0d0e4e66.tar.gz
snowflake-d7aa9b835645bc52c29ba13cdab461fe0d0e4e66.zip
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.
-rw-r--r--proxy/proxy-go_test.go126
-rw-r--r--proxy/snowflake.go41
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@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@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
}