[tor-bugs] #33157 [Circumvention/Snowflake]: Client generates SDP with "IN IP4 0.0.0.0", causing proxy to send "client_ip=0.0.0.0" and bridge to send "USERADDR 0.0.0.0:1"

Tor Bug Tracker & Wiki blackhole at torproject.org
Wed Feb 5 06:27:18 UTC 2020


#33157: Client generates SDP with "IN IP4 0.0.0.0", causing proxy to send
"client_ip=0.0.0.0" and bridge to send "USERADDR 0.0.0.0:1"
-----------------------------------------+--------------------
     Reporter:  dcf                      |      Owner:  (none)
         Type:  defect                   |     Status:  new
     Priority:  Medium                   |  Milestone:
    Component:  Circumvention/Snowflake  |    Version:
     Severity:  Normal                   |   Keywords:
Actual Points:                           |  Parent ID:
       Points:                           |   Reviewer:
      Sponsor:                           |
-----------------------------------------+--------------------
 There is a pipeline of relaying the client IP address:
  * The proxy infers the client's IP address by grepping it out of the SDP
 during ICE negotiation ([https://gitweb.torproject.org/pluggable-
 transports/snowflake.git/tree/proxy/proxypair.js?h=webext-0.2.1#n108
 proxy], [https://gitweb.torproject.org/pluggable-
 transports/snowflake.git/tree/proxy-go/snowflake.go?h=webext-0.2.1#n112
 proxy-go]) and attaches it to the WebSocket connection as a URL query
 parameter `?client_ip=A.B.C.D`.
  * The bridge [https://gitweb.torproject.org/pluggable-
 transports/snowflake.git/tree/server/server.go?h=webext-0.2.1#n110 parses]
 the `client_ip` query parameter and passes it on to tor with a `USERADDR
 A.B.C.D:1` command on the
 [https://gitweb.torproject.org/torspec.git/tree/proposals/196-transport-
 control-ports.txt?id=8f094d7485ff87bb1e62f5854c9972c3e5c9e15f#n97
 ExtORPort].
  * tor does geoip lookups and aggregates statistics and ultimately sends
 them to Tor Metrics for [https://metrics.torproject.org/userstats-bridge-
 country.html country-specific graphs].

 It looks like the pion SDP code puts `0.0.0.0` in the place where proxy
 and proxy-go look for the remote IP address. This causes the proxy to send
 `?client_ip=0.0.0.0` to the bridge, and the bridge to send `USERADDR
 0.0.0.0:1` to tor. I'm not sure that this happens every time; see below
 for bridge-extra-infos output.

 I found it while testing proxy-go with a localhost client and a patch
 like:
 {{{#!diff
 --- a/proxy-go/snowflake.go
 +++ b/proxy-go/snowflake.go
 @@ -22,3 +22,3 @@ import (
         "git.torproject.org/pluggable-
 transports/snowflake.git/common/messages"
 -       "git.torproject.org/pluggable-
 transports/snowflake.git/common/safelog"
 +       _ "git.torproject.org/pluggable-
 transports/snowflake.git/common/safelog"
         "git.torproject.org/pluggable-
 transports/snowflake.git/common/websocketconn"
 @@ -93,3 +93,3 @@ func (c *webRTCConn) Write(b []byte) (int, error) {
         // log.Printf("webrtc Write %d %+q", len(b), string(b))
 -       log.Printf("Write %d bytes --> WebRTC", len(b))
 +       // log.Printf("Write %d bytes --> WebRTC", len(b))
         if c.dc != nil {
 @@ -114,2 +114,3 @@ func (c *webRTCConn) RemoteAddr() net.Addr {
         clientIP := remoteIPFromSDP(c.pc.RemoteDescription().SDP)
 +       log.Printf("RemoteAddr %+q", c.pc.RemoteDescription().SDP)
         if clientIP == nil {
 @@ -322,3 +323,3 @@ func makePeerConnectionFromOffer(sdp
 *webrtc.SessionDescription, config webrtc.C
                 dc.OnMessage(func(msg webrtc.DataChannelMessage) {
 -                       log.Printf("OnMessage <--- %d bytes",
 len(msg.Data))
 +                       // log.Printf("OnMessage <--- %d bytes",
 len(msg.Data))
                         var n int
 @@ -432,3 +433,4 @@ func main() {
         //We want to send the log output through our scrubber first
 -       log.SetOutput(&safelog.LogScrubber{Output: logOutput})
 +       // log.SetOutput(&safelog.LogScrubber{Output: logOutput})
 +       log.SetOutput(logOutput)
 }}}

 For example, the beginning of an SDP string for me is
 {{{
 v=0
 o=- 34318359 1580881353 IN IP4 0.0.0.0
 s=-
 t=0 0
 a=fingerprint:sha-256
 80:EE:E6:8D:55:07:CB:52:58:7A:CC:61:70:F9:F3:65:DB:4B:D3:69:CB:F9:68:C8:5F:E3:06:3D:D3:90:C1:E6
 a=group:BUNDLE 0
 m=application 9 DTLS/SCTP 5000
 c=IN IP4 0.0.0.0
 }}}

 The client IP address inference, implemented in #18628, was always a bit
 of a hack, but it was effective enough, as evidenced by country counts in
 comment:4:ticket:29734. I just now looked at
 [https://collector.torproject.org/archive/bridge-descriptors/extra-infos
 /bridge-extra-infos-2020-02.tar.xz bridge-extra-infos-2020-02.tar.xz] and
 it seems that we are still sometimes getting identified countries, but the
 largest count belongs to `??`.
 {{{
 $ tar -O -xf bridge-extra-infos-2020-02.tar.xz | grep -A 24 '^extra-info
 flakey 5481936581E23D2D178105D44DB6915AB06BFB7F$' | grep -E
 '^dirreq-v3-reqs '
 dirreq-v3-reqs ??=16,tr=16,cn=8,de=8,eg=8,in=8,ir=8,ph=8,us=8
 dirreq-v3-reqs ??=16,tr=16,cn=8,de=8,eg=8,in=8,ir=8,ph=8,us=8
 dirreq-v3-reqs ??=24,cn=8,es=8,fr=8,ir=8,tr=8
 dirreq-v3-reqs ??=48,tr=16,ar=8,ca=8,eg=8,gb=8,ir=8,us=8
 dirreq-v3-reqs ??=16,tr=16,cn=8,de=8,eg=8,in=8,ir=8,ph=8,us=8
 dirreq-v3-reqs ??=24,cn=8,es=8,fr=8,ir=8,tr=8
 dirreq-v3-reqs ??=48,tr=16,ar=8,ca=8,eg=8,gb=8,ir=8,us=8
 dirreq-v3-reqs ??=24,cn=8,es=8,fr=8,ir=8,tr=8
 dirreq-v3-reqs ??=24,cn=8,es=8,fr=8,ir=8,tr=8
 dirreq-v3-reqs ??=24,cn=8,es=8,fr=8,ir=8,tr=8
 dirreq-v3-reqs ??=48,tr=16,ar=8,ca=8,eg=8,gb=8,ir=8,us=8
 dirreq-v3-reqs ??=16,tr=16,cn=8,de=8,eg=8,in=8,ir=8,ph=8,us=8
 dirreq-v3-reqs ??=24,cn=8,es=8,fr=8,ir=8,tr=8
 dirreq-v3-reqs ??=48,tr=16,ar=8,ca=8,eg=8,gb=8,ir=8,us=8
 dirreq-v3-reqs ??=16,tr=16,cn=8,de=8,eg=8,in=8,ir=8,ph=8,us=8
 dirreq-v3-reqs ??=16,tr=16,cn=8,de=8,eg=8,in=8,ir=8,ph=8,us=8
 dirreq-v3-reqs ??=24,cn=8,es=8,fr=8,ir=8,tr=8
 dirreq-v3-reqs ??=16,tr=16,cn=8,de=8,eg=8,in=8,ir=8,ph=8,us=8
 dirreq-v3-reqs ??=24,cn=8,es=8,fr=8,ir=8,tr=8
 dirreq-v3-reqs ??=24,tr=16,fr=8,om=8,ru=8,us=8
 dirreq-v3-reqs ??=16,tr=16,cn=8,de=8,eg=8,in=8,ir=8,ph=8,us=8
 dirreq-v3-reqs ??=48,tr=16,ar=8,ca=8,eg=8,gb=8,ir=8,us=8
 }}}

 Maybe it happens only intermittently. pion/sdp
 [https://github.com/pion/sdp/blob/06fd9e503a8f545f663a757afb09b1e1833c7b2d/jsep.go#L56
 sets] `UnicastAddress: "0.0.0.0"` unconditionally and I don't see where it
 is ever modified. Maybe the others are older non-pion clients?

 A little searching indicates that `IN IP4 0.0.0.0` has something to do
 with trickle ICE:
  * https://bugzilla.mozilla.org/show_bug.cgi?id=1192813#c14

 It seems that ultimately, we need a more reliable way for the proxy to
 infer the client's external IP address.

--
Ticket URL: <https://trac.torproject.org/projects/tor/ticket/33157>
Tor Bug Tracker & Wiki <https://trac.torproject.org/>
The Tor Project: anonymity online


More information about the tor-bugs mailing list