evaluate-blockages.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #!/usr/bin/env python3
  2. import csv
  3. import os
  4. # Algorithm used in https://research.torproject.org/techreports/blocking-2011-09-15.pdf
  5. def evaluate_loesing (fingerprint):
  6. fingerprint = fingerprint.upper()
  7. bridge_ips_max = None
  8. # First get the max value in whole range
  9. with open (f"data/bridge_data_cleaned/{fingerprint}", 'r') as file:
  10. bridge_data = csv.reader(file, delimiter=',')
  11. for row in bridge_data:
  12. bridge_ips_today = int(row[1])
  13. if bridge_ips_max is None:
  14. if bridge_ips_today > 0:
  15. bridge_ips_max = bridge_ips_today
  16. #print (f"{fingerprint} bridge_ips_max set to {bridge_ips_today} on {row[0]}")
  17. elif bridge_ips_today > bridge_ips_max:
  18. bridge_ips_max = bridge_ips_today
  19. #print (f"{fingerprint} bridge_ips_max set to {bridge_ips_today} on {row[0]}")
  20. # Now evaluate
  21. with open (f"data/bridge_data_cleaned/{fingerprint}", 'r') as file:
  22. bridge_data = csv.reader(file, delimiter=',')
  23. for row in bridge_data:
  24. bridge_ips_today = int(row[1])
  25. if not bridge_ips_max is None and bridge_ips_max >= 100 and bridge_ips_today <= 32:
  26. return row[0]
  27. return None
  28. # Consider a bridge blocked if it receives <= t connections in one day,
  29. # when it has previously received >= m connections. Note that t=32,
  30. # m=100 is NOT the same as Loesing's algorithm, as we consider m only
  31. # for previous days, while Loesing's algorithm considers all days within
  32. # the period. t must be less than m.
  33. def is_blocked_abs (t, m, bridge_ips_max, bridge_ips_today):
  34. if bridge_ips_max is None:
  35. return False
  36. return bridge_ips_max >= m and bridge_ips_today <= t
  37. def evaluate_abs (t, m, fingerprint):
  38. fingerprint = fingerprint.upper()
  39. bridge_ips_max = None
  40. with open (f"data/bridge_data_cleaned/{fingerprint}", 'r') as file:
  41. bridge_data = csv.reader(file, delimiter=',')
  42. for row in bridge_data:
  43. bridge_ips_today = int(row[1])
  44. if not bridge_ips_max is None:
  45. if is_blocked_abs (t, m, bridge_ips_max, bridge_ips_today):
  46. return row[0]
  47. if bridge_ips_today > bridge_ips_max:
  48. bridge_ips_max = bridge_ips_today
  49. # Start bridge_ips_max only when we have a non-zero
  50. # connection count
  51. elif bridge_ips_today > 0:
  52. bridge_ips_max = bridge_ips_today
  53. # If we got here, the bridge is not blocked
  54. return None
  55. # Consider a bridge blocked if we observe a drop of at least d from the
  56. # previous day's count. d must be at least 8.
  57. def is_blocked_rel (d, bridge_ips_yesterday, bridge_ips_today):
  58. if bridge_ips_yesterday is None:
  59. return False
  60. return bridge_ips_today <= bridge_ips_yesterday - d
  61. def evaluate_rel (d, fingerprint):
  62. fingerprint = fingerprint.upper()
  63. bridge_ips_yesterday = None
  64. bridge_ips_today = None
  65. with open (f"data/bridge_data_cleaned/{fingerprint}", 'r') as file:
  66. bridge_data = csv.reader(file, delimiter=',')
  67. for row in bridge_data:
  68. bridge_ips_today = int(row[1])
  69. if is_blocked_rel (d, bridge_ips_yesterday, bridge_ips_today):
  70. return row[0]
  71. bridge_ips_yesterday = bridge_ips_today
  72. # Remove any previous blocked_* files, start over
  73. if os.path.exists (f"data/blocked_loesing"):
  74. os.remove (f"data/blocked_loesing")
  75. for t in range (8, 40, 8):
  76. for m in range (t+8, 112, 8):
  77. if os.path.exists (f"data/blocked_abs_{t}_{m}"):
  78. os.remove (f"data/blocked_abs_{t}_{m}")
  79. for d in range (8, 112, 8):
  80. if os.path.exists (f"data/blocked_rel_{d}"):
  81. os.remove (f"data/blocked_rel_{d}")
  82. with open ("data/all-bridges", 'r') as all_bridges:
  83. for fingerprint in all_bridges:
  84. fingerprint = fingerprint.strip()
  85. if fingerprint:
  86. # Evaluate with Loesing's algorithm
  87. blocked = evaluate_loesing (fingerprint)
  88. if not blocked is None:
  89. with open (f"data/blocked_loesing", 'a') as f:
  90. f.write(f"{fingerprint},{blocked}\n")
  91. # Absolute threshold with t and m
  92. for t in range (8, 40, 8):
  93. for m in range (t+8, 112, 8):
  94. blocked = evaluate_abs (t, m, fingerprint)
  95. if not blocked is None:
  96. with open (f"data/blocked_abs_{t}_{m}", 'a') as f:
  97. f.write (f"{fingerprint},{blocked}\n")
  98. # Relative threshold with d
  99. for d in range (8, 112, 8):
  100. blocked = evaluate_rel (d, fingerprint)
  101. if not blocked is None:
  102. with open (f"data/blocked_rel_{d}", 'a') as f:
  103. f.write (f"{fingerprint},{blocked}\n")