censor.rs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. use crate::{
  2. get_date,
  3. simulation::{bridge::Bridge, state::State},
  4. PositiveReport,
  5. };
  6. use lox_cli::{get_lox_pub, networking::Networking};
  7. use lox_library::{cred::Lox, scalar_u32};
  8. use rand::Rng;
  9. use std::collections::{HashMap, HashSet};
  10. pub struct Censor {
  11. pub country: String,
  12. pub known_bridges: HashSet<[u8; 20]>,
  13. pub lox_credentials: HashMap<[u8; 20], Lox>,
  14. // How fast does this censor block bridges after learning about them?
  15. pub speed: Speed,
  16. // If censor implements random blocking, this is the date when it
  17. // will start blocking all the bridges it knows.
  18. pub delay_date: u32,
  19. // Does the censor attempt to hide the fact that a bridge has been blocked?
  20. pub hides: Hides,
  21. // Does the censor block bridges uniformly across the country?
  22. pub totality: Totality,
  23. // If censor implements partial blocking, what percent of
  24. // connections are blocked? If totality is not partial, this is set
  25. // to 100%.
  26. pub partial_blocking_percent: f64,
  27. }
  28. impl Censor {
  29. pub fn new(country: String, speed: Speed, hides: Hides, totality: Totality) -> Self {
  30. let mut rng = rand::thread_rng();
  31. let delay_date = if speed == Speed::Random {
  32. let num: u32 = rng.gen_range(1..365);
  33. get_date() + num
  34. } else {
  35. 0
  36. };
  37. let partial_blocking_percent = if totality == Totality::Partial {
  38. let num: f64 = rng.gen_range(0.0..1.0);
  39. num
  40. } else {
  41. 1.0
  42. };
  43. Censor {
  44. country: country,
  45. known_bridges: HashSet::<[u8; 20]>::new(),
  46. lox_credentials: HashMap::<[u8; 20], Lox>::new(),
  47. speed: speed,
  48. delay_date: delay_date,
  49. hides: hides,
  50. totality: totality,
  51. partial_blocking_percent: partial_blocking_percent,
  52. }
  53. }
  54. pub fn knows_bridge(&self, fingerprint: &[u8; 20]) -> bool {
  55. self.known_bridges.contains(fingerprint)
  56. }
  57. pub fn learn_bridge(&mut self, fingerprint: &[u8; 20]) {
  58. self.known_bridges.insert(*fingerprint);
  59. }
  60. pub fn has_lox_cred(&self, fingerprint: &[u8; 20]) -> bool {
  61. self.lox_credentials.contains_key(fingerprint)
  62. }
  63. pub fn give_lox_cred(&mut self, fingerprint: &[u8; 20], cred: &Lox) {
  64. // We only need one level 3+ credential per bridge. (This will
  65. // change if we restrict positive reports to one per bridge per
  66. // credential.)
  67. if !self.has_lox_cred(fingerprint) && scalar_u32(&cred.trust_level).unwrap() >= 3 {
  68. // We want to clone the credential, but that's not allowed,
  69. // so we're going to serialize it and then deserialize it.
  70. let cloned_cred = bincode::deserialize(&bincode::serialize(&cred).unwrap()).unwrap();
  71. self.lox_credentials.insert(*fingerprint, cloned_cred);
  72. }
  73. }
  74. // Make a bunch of connections and submit positive reports if possible
  75. async fn flood(&self, state: &State, bridges: &mut HashMap<[u8; 20], Bridge>) {
  76. // Only do this if Flooding censor
  77. if self.hides == Hides::Flooding {
  78. for fingerprint in &self.known_bridges {
  79. // Only do this if we're blocking the bridge
  80. if self.speed == Speed::Fast
  81. || self.speed == Speed::Lox && self.has_lox_cred(fingerprint)
  82. || self.speed == Speed::Random && self.delay_date <= get_date()
  83. {
  84. let bridge = bridges.get_mut(fingerprint).unwrap();
  85. let mut rng = rand::thread_rng();
  86. let num_connections = rng.gen_range(1000..30000);
  87. // Make a bunch of connections to the bridge
  88. bridge.censor_flood(&self.country, num_connections);
  89. // If we have a lv3+ credential, submit a bunch of
  90. // positive reports
  91. if self.has_lox_cred(fingerprint) {
  92. let lox_pub = get_lox_pub(&state.la_pubkeys);
  93. for _ in 0..num_connections {
  94. let pr = PositiveReport::from_lox_credential(
  95. bridge.fingerprint,
  96. None,
  97. &self.lox_credentials.get(&bridge.fingerprint).unwrap(),
  98. lox_pub,
  99. self.country.clone(),
  100. )
  101. .unwrap();
  102. state
  103. .tp_net
  104. .request("/positivereport".to_string(), pr.to_json().into_bytes())
  105. .await;
  106. }
  107. }
  108. }
  109. }
  110. }
  111. }
  112. // TODO: How do we want to do this? We don't want to stop blocking
  113. // bridges the day after we start.
  114. fn recompute_delay(&mut self) {
  115. // Only do this if Random censor
  116. if self.speed == Speed::Random && self.delay_date <= get_date() {
  117. // Compute new delay date
  118. self.delay_date = {
  119. let mut rng = rand::thread_rng();
  120. let num: u32 = rng.gen_range(1..365);
  121. get_date() + num
  122. }
  123. }
  124. }
  125. pub async fn end_of_day_tasks(
  126. &mut self,
  127. state: &State,
  128. bridges: &mut HashMap<[u8; 20], Bridge>,
  129. ) {
  130. if self.hides == Hides::Flooding
  131. && !(self.speed == Speed::Random && self.delay_date <= get_date())
  132. {
  133. self.flood(state, bridges).await;
  134. }
  135. // TODO: recompute_delay sometimes
  136. //self.recompute_delay();
  137. }
  138. }
  139. #[derive(PartialEq)]
  140. pub enum Speed {
  141. Fast,
  142. Lox,
  143. Random,
  144. }
  145. #[derive(PartialEq)]
  146. pub enum Hides {
  147. Overt,
  148. Hiding,
  149. Flooding,
  150. }
  151. #[derive(PartialEq)]
  152. pub enum Totality {
  153. Full,
  154. Partial,
  155. Throttling,
  156. }