commit 2cab2b49267cb5e0f7fb8f7f89926b244a2d3acb Author: Karsten Loesing karsten.loesing@gmx.net Date: Mon Jul 13 09:47:54 2020 +0200
Add ipv6.py script for tpo/metrics/trac#40002. --- tpo-metrics-trac-40002/README.md | 4 + tpo-metrics-trac-40002/ipv6.py | 173 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+)
diff --git a/tpo-metrics-trac-40002/README.md b/tpo-metrics-trac-40002/README.md new file mode 100644 index 0000000..e141b02 --- /dev/null +++ b/tpo-metrics-trac-40002/README.md @@ -0,0 +1,4 @@ +# Script that Counts IPv6 Relays in the Consensus + +See `ipv6.py` for usage information and [tpo/metrics/trac#40002](https://gitlab.torproject.org/tpo/metrics/trac/-/issues/40002) for context. + diff --git a/tpo-metrics-trac-40002/ipv6.py b/tpo-metrics-trac-40002/ipv6.py new file mode 100644 index 0000000..497ea26 --- /dev/null +++ b/tpo-metrics-trac-40002/ipv6.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python3 + +""" +---------------------------------------------------------------------------- + +This script implements Section 3 of Proposal 313: + +3. Monitoring IPv6 Relays in the Consensus + +We propose writing a script that calculates: + * the number of relays, and + * the consensus weight fraction of relays, +in the consensus that: + * have an IPv6 ORPort, + * support IPv6 reachability checks, + * support IPv6 clients, and + * support IPv6 reachability checks, and IPv6 clients. + +In order to provide easy access to these statistics, we propose +that the script should: + * download a consensus (or read an existing consensus), and + * calculate and report these statistics. + +The following consensus weight fractions should divide by the total +consensus weight: + * have an IPv6 ORPort (all relays have an IPv4 ORPort), and + * support IPv6 reachability checks (all relays support IPv4 reachability). + +The following consensus weight fractions should divide by the +"usable Guard" consensus weight: + * support IPv6 clients, and + * support IPv6 reachability checks and IPv6 clients. + +"Usable Guards" have the Guard flag, but do not have the Exit flag. If the +Guard also has the BadExit flag, the Exit flag should be ignored. + +Note that this definition of "Usable Guards" is only valid when the +consensus contains many more guards than exits. That is, Wgd must be 0 in +the consensus. (See the [Tor Directory Protocol] for more details.) + +Therefore, the script should check that Wgd is 0. If it is not, the script +should log a warning about the accuracy of the "Usable Guard" statistics. + +---------------------------------------------------------------------------- + +Copyright 2020 The Tor Project + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + +* Neither the names of the copyright owners nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------------- +""" + +import sys, stem, stem.version, stem.descriptor + +partial_support_version = stem.version.Version('0.4.4') +full_support_version = stem.version.Version('0.4.5') + +def read(consensus_filename): + + parsed_consensus = stem.descriptor.parse_file(consensus_filename, + descriptor_type = 'network-status-consensus-3 1.0') + + valid_after = None + wgd = None + + relays = [] + relays_ipv6 = [] + relays_partial = [] + relays_full = [] + guards = [] + guards_ipv6 = [] + guards_partial = [] + guards_full = [] + + for relay in parsed_consensus: + + if not valid_after: + valid_after = relay.document.valid_after + wgd = relay.document.bandwidth_weights["Wgd"] + + if relay.bandwidth is None: + continue + + has_ipv6_address = False + if relay.or_addresses: + for or_address in relay.or_addresses: + if len(or_address) == 3 and or_address[2]: + has_ipv6_address = True + is_usable_guard = False + if relay.flags: + if "Guard" in relay.flags and ( + "Exit" not in relay.flags or "BadExit" in relay.flags): + is_usable_guard = True + has_partial_support = False + has_full_support = False + if relay.version: + if relay.version >= full_support_version: + has_full_support = True + if relay.version >= partial_support_version: + has_partial_support = True + + relays.append(relay.bandwidth) + if has_ipv6_address: + relays_ipv6.append(relay.bandwidth) + if has_partial_support: + relays_partial.append(relay.bandwidth) + if has_full_support: + relays_full.append(relay.bandwidth) + if is_usable_guard: + guards.append(relay.bandwidth) + if has_ipv6_address: + guards_ipv6.append(relay.bandwidth) + if has_partial_support: + guards_partial.append(relay.bandwidth) + if has_full_support: + guards_full.append(relay.bandwidth) + + print("\nParsed consensus with valid-after time {0}:".format(valid_after)) + print(" - Consensus contains {0} relays:".format(len(relays))) + print(" - {0} of these ({1:.2f}% TCW) have an IPv6 ORPort.". + format(len(relays_ipv6), 100 * sum(relays_ipv6) / sum(relays))) + print(" - {0} of these ({1:.2f}% TCW) support at least partial IPv6 reachability checks.". + format(len(relays_partial), 100 * sum(relays_partial) / sum(relays))) + print(" - {0} of these ({1:.2f}% TCW) support full IPv6 reachability checks.". + format(len(relays_full), 100 * sum(relays_full) / sum(relays))) + print(" - Consensus contains {0} "usable guards" and Wgd={1}.". + format(len(guards), wgd)) + print(" - {0} of these ({1:.2f}% UGCW) support IPv6 clients.". + format(len(guards_ipv6), 100 * sum(guards_ipv6) / sum(guards))) + print(" - {0} of these ({1:.2f}% UGCW) support at least partial IPv6 reachability checks.". + format(len(guards_partial), 100 * sum(guards_partial) / sum(guards))) + print(" - {0} of these ({1:.2f}% UGCW) support full IPv6 reachability checks.". + format(len(guards_full), 100 * sum(guards_full) / sum(guards))) + if wgd != 0: + print(" - WARNING: "usable guards" definition is only valid when Wgd=0!") + +def main(): + if len(sys.argv) < 2: + print("Please provide one or more downloaded consensus files as arguments.") + else: + for argv in sorted(sys.argv[1:]): + read(argv) + print() + +if __name__ == '__main__': + sys.exit(main()) +
tor-commits@lists.torproject.org