tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_peerConnection_gatherWithStun300.html (13502B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <script type="application/javascript" src="pc.js"></script>
      5  <script type="application/javascript" src="iceTestUtils.js"></script>
      6 </head>
      7 <body>
      8 <pre id="test">
      9 <script type="application/javascript">
     10  createHTML({
     11    bug: "857668",
     12    title: "RTCPeerConnection check STUN gathering with STUN/300 responses"
     13  });
     14 
     15  /* This is pretty hairy, so some background:
     16   * Spec is here: https://datatracker.ietf.org/doc/html/rfc8489#section-10
     17   * STUN/300 responses allow a server to redirect STUN requests to one or
     18     more other servers, as ALTERNATE-SERVER attributes.
     19   * The server specifies the IP address, IP version, and port for each
     20     ALTERNATE-SERVER.
     21   * The spec allows multiple rounds of redirects, and requires the client to
     22     remember the servers it has already tried to avoid redirect loops.
     23   * For TURNS, the TURN server can also supply an ALTERNATE-DOMAIN attribute,
     24     which the client MUST use for the TLS handshake on the new target. The
     25     client does _not_ use this as an FQDN; it always uses the address in the
     26     ALTERNATE-SERVER. ALTERNATE-DOMAIN is meaningless in the non-TLS case.
     27   * STUN/300 with ALTERNATE-SERVER is only defined for the TURN Allocate
     28     message type (at least in the context of ICE). Clients are supposed to
     29     treat STUN/300 as an unrecoverable error in all other cases. The TURN spec
     30     does _not_ spell out how a client should handle multiple ALTERNATE-SERVERs.
     31     We just take the first one that we have not already tried, and that is the
     32     same IP version that we started with. This is because switching the IP
     33     version is problematic for ICE.
     34   * The test TURN server opens extra ports that will respond with redirects to
     35     the _real_ ports, but the address remains the same. This is because we
     36     cannot know ahead of time whether the machine we're running on has more
     37     than one IP address of each version. This means the test TURN server is not
     38     useful for testing cases where the address changes. Also, the test TURN
     39     server does not currently know how to respond with multiple
     40     ALTERNATE-SERVERs.
     41   * To test cases where the _address_ changes, we instead use a feature in the
     42     NAT simulator to respond with fake redirects when the destination address
     43     matches an address that we configure with a pref. This feature can add
     44     multiple ALTERNATE-SERVERs.
     45   * The test TURN server's STUN/300 responses have a proper MESSAGE-INTEGRITY,
     46     but the NAT simulator's do _not_. For now, we want both cases to work,
     47     because some servers respond with STUN/300 without including
     48     MESSAGE-INTEGRITY. This is a spec violation, even though the spec
     49     contradicts itself in non-normative language elsewhere.
     50   * Right now, neither the NAT simulator nor the test TURN server support
     51     ALTERNATE-DOMAIN.
     52  */
     53 
     54  // These are the ports the test TURN server will respond with redirects on.
     55  // The test TURN server tells us what these are in the JSON it spits out when
     56  // we start it.
     57  let turnRedirectPort;
     58  let turnsRedirectPort;
     59 
     60  // These are the addresses that we will configure the NAT simulator to
     61  // redirect to. We do DNS lookups of the host in iceServersArray (provided
     62  // by the test TURN server), and put the results here. On some platforms this
     63  // will be 127.0.0.1 and ::1, but on others we may use a real address.
     64  let redirectTargetV4;
     65 
     66  // Test TURN server tells us these in the JSON it spits out when we start it
     67  let username;
     68  let credential;
     69 
     70  // This is the address we will configure the NAT simulator to respond with
     71  // redirects for. We use an address from TEST-NET since it is really unlikely
     72  // we'll see that on a real machine, and also because we do not have
     73  // special-case code in nICEr for TEST-NET (like we do for link-local, for
     74  // example).
     75  const redirectAddressV4 = '198.51.100.1';
     76 
     77  const tests = [
     78    async function baselineV4Cases() {
     79      await checkSrflx([{urls:[`stun:${redirectTargetV4}`]}]);
     80      await checkRelayUdp([{urls:[`turn:${redirectTargetV4}`], username, credential}]);
     81      await checkRelayTcp([{urls:[`turn:${redirectTargetV4}?transport=tcp`], username, credential}]);
     82      await checkRelayUdpTcp([{urls:[`turn:${redirectTargetV4}`, `turn:${redirectTargetV4}?transport=tcp`], username, credential}]);
     83    },
     84 
     85    async function stunV4Redirect() {
     86      // This test uses the test TURN server, because nICEr drops responses
     87      // without MESSAGE-INTEGRITY on the floor _unless_ they are a STUN/300 to
     88      // an Allocate request. If we tried to use the NAT simulator for this, we
     89      // would have to wait for nICEr to time out, since the NAT simulator does
     90      // not know how to do MESSAGE-INTEGRITY.
     91      await checkNoSrflx(
     92          [{urls:[`stun:${redirectTargetV4}:${turnRedirectPort}`]}]);
     93    },
     94 
     95    async function turnV4UdpPortRedirect() {
     96      await checkRelayUdp([{urls:[`turn:${redirectTargetV4}:${turnRedirectPort}`], username, credential}]);
     97    },
     98 
     99    async function turnV4TcpPortRedirect() {
    100      await checkRelayTcp([{urls:[`turn:${redirectTargetV4}:${turnRedirectPort}?transport=tcp`], username, credential}]);
    101    },
    102 
    103    async function turnV4UdpTcpPortRedirect() {
    104      await checkRelayUdpTcp([{urls:[`turn:${redirectTargetV4}:${turnRedirectPort}`, `turn:${redirectTargetV4}:${turnRedirectPort}?transport=tcp`], username, credential}]);
    105    },
    106 
    107    async function turnV4UdpAddressRedirect() {
    108      await pushPrefs(
    109          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    110          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectTargetV4}`]);
    111      await checkRelayUdp([{urls:[`turn:${redirectAddressV4}`], username, credential}]);
    112      await SpecialPowers.popPrefEnv();
    113    },
    114 
    115    async function turnV4TcpAddressRedirect() {
    116      await pushPrefs(
    117          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    118          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectTargetV4}`]);
    119      await checkRelayTcp([{urls:[`turn:${redirectAddressV4}?transport=tcp`], username, credential}]);
    120      await SpecialPowers.popPrefEnv();
    121    },
    122 
    123    async function turnV4UdpTcpAddressRedirect() {
    124      await pushPrefs(
    125          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    126          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectTargetV4}`]);
    127      await checkRelayUdpTcp([{urls:[`turn:${redirectAddressV4}`, `turn:${redirectAddressV4}?transport=tcp`], username, credential}]);
    128      await SpecialPowers.popPrefEnv();
    129    },
    130 
    131    async function turnV4UdpEmptyRedirect() {
    132      await pushPrefs(
    133          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    134          ['media.peerconnection.nat_simulator.redirect_targets', '']);
    135      await checkNoRelay([{urls:[`turn:${redirectAddressV4}`], username, credential}]);
    136      await SpecialPowers.popPrefEnv();
    137    },
    138 
    139    async function turnV4TcpEmptyRedirect() {
    140      await pushPrefs(
    141          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    142          ['media.peerconnection.nat_simulator.redirect_targets', '']);
    143      await checkNoRelay([{urls:[`turn:${redirectAddressV4}?transport=tcp`], username, credential}]);
    144      await SpecialPowers.popPrefEnv();
    145    },
    146 
    147    async function turnV4UdpTcpEmptyRedirect() {
    148      await pushPrefs(
    149          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    150          ['media.peerconnection.nat_simulator.redirect_targets', '']);
    151      await checkNoRelay([{urls:[`turn:${redirectAddressV4}`, `turn:${redirectAddressV4}?transport=tcp`], username, credential}]);
    152      await SpecialPowers.popPrefEnv();
    153    },
    154 
    155    async function turnV4UdpAddressAndPortRedirect() {
    156      // This should result in two rounds of redirection; the first is by
    157      // address, the second is by port.
    158      await pushPrefs(
    159          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    160          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectTargetV4}`]);
    161      await checkRelayUdp([{urls:[`turn:${redirectAddressV4}:${turnRedirectPort}`], username, credential}]);
    162      await SpecialPowers.popPrefEnv();
    163    },
    164 
    165    async function turnV4TcpAddressAndPortRedirect() {
    166      // This should result in two rounds of redirection; the first is by
    167      // address, the second is by port.
    168      await pushPrefs(
    169          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    170          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectTargetV4}`]);
    171      await checkRelayTcp([{urls:[`turn:${redirectAddressV4}:${turnRedirectPort}?transport=tcp`], username, credential}]);
    172      await SpecialPowers.popPrefEnv();
    173    },
    174 
    175    async function turnV4UdpTcpAddressAndPortRedirect() {
    176      // This should result in two rounds of redirection; the first is by
    177      // address, the second is by port.
    178      await pushPrefs(
    179          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    180          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectTargetV4}`]);
    181      await checkRelayUdpTcp([{urls:[`turn:${redirectAddressV4}:${turnRedirectPort}`, `turn:${redirectAddressV4}:${turnRedirectPort}?transport=tcp`], username, credential}]);
    182      await SpecialPowers.popPrefEnv();
    183    },
    184 
    185    async function turnV4UdpRedirectLoop() {
    186      await pushPrefs(
    187          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    188          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectAddressV4}`]);
    189      // If we don't detect the loop, gathering will not finish
    190      await checkNoRelay([{urls:[`turn:${redirectAddressV4}`], username, credential}]);
    191      await SpecialPowers.popPrefEnv();
    192    },
    193 
    194    async function turnV4TcpRedirectLoop() {
    195      await pushPrefs(
    196          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    197          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectAddressV4}`]);
    198      // If we don't detect the loop, gathering will not finish
    199      await checkNoRelay([{urls:[`turn:${redirectAddressV4}?transport=tcp`], username, credential}]);
    200      await SpecialPowers.popPrefEnv();
    201    },
    202 
    203    async function turnV4UdpTcpRedirectLoop() {
    204      await pushPrefs(
    205          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    206          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectAddressV4}`]);
    207      // If we don't detect the loop, gathering will not finish
    208      await checkNoRelay([{urls:[`turn:${redirectAddressV4}`, `turn:${redirectAddressV4}?transport=tcp`], username, credential}]);
    209      await SpecialPowers.popPrefEnv();
    210    },
    211 
    212    async function turnV4UdpMultipleAddressRedirect() {
    213      await pushPrefs(
    214          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    215          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectAddressV4},${redirectTargetV4}`]);
    216      await checkRelayUdp([{urls:[`turn:${redirectAddressV4}`], username, credential}]);
    217      await SpecialPowers.popPrefEnv();
    218    },
    219 
    220    async function turnV4TcpMultipleAddressRedirect() {
    221      await pushPrefs(
    222          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    223          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectAddressV4},${redirectTargetV4}`]);
    224      await checkRelayTcp([{urls:[`turn:${redirectAddressV4}?transport=tcp`], username, credential}]);
    225      await SpecialPowers.popPrefEnv();
    226    },
    227 
    228    async function turnV4UdpTcpMultipleAddressRedirect() {
    229      await pushPrefs(
    230          ['media.peerconnection.nat_simulator.redirect_address', `${redirectAddressV4}`],
    231          ['media.peerconnection.nat_simulator.redirect_targets', `${redirectAddressV4},${redirectTargetV4}`]);
    232      await checkRelayUdpTcp([{urls:[`turn:${redirectAddressV4}`, `turn:${redirectAddressV4}?transport=tcp`], username, credential}]);
    233      await SpecialPowers.popPrefEnv();
    234    },
    235  ];
    236 
    237  runNetworkTest(async () => {
    238    const turnServer = iceServersArray.find(server => "username" in server);
    239    username = turnServer.username;
    240    credential = turnServer.credential;
    241    // Special props, non-standard
    242    turnRedirectPort = turnServer.turn_redirect_port;
    243    turnsRedirectPort = turnServer.turns_redirect_port;
    244    // Just use the first url. It might make sense to look for TURNS first,
    245    // since that will always use a hostname, but on CI we don't have TURNS
    246    // support anyway (see bug 1323439).
    247    const turnHostname = getTurnHostname(turnServer.urls[0]);
    248    redirectTargetV4 = await dnsLookupV4(turnHostname);
    249 
    250    await pushPrefs(
    251        ['media.peerconnection.ice.obfuscate_host_addresses', false],
    252        ['media.peerconnection.nat_simulator.filtering_type', 'ENDPOINT_INDEPENDENT'],
    253        ['media.peerconnection.nat_simulator.mapping_type', 'ENDPOINT_INDEPENDENT'],
    254        ['media.peerconnection.ice.loopback', true],
    255        ['media.getusermedia.insecure.enabled', true]);
    256 
    257    for (const test of tests) {
    258      info(`Running test: ${test.name}`);
    259      await test();
    260      info(`Done running test: ${test.name}`);
    261    }
    262 
    263    await SpecialPowers.popPrefEnv();
    264  }, { useIceServer: true });
    265 
    266 </script>
    267 </pre>
    268 </body>
    269 </html>