censor.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. use crate::{bridge::Bridge, config::Config};
  2. use curve25519_dalek::scalar::Scalar;
  3. use lox_cli::{get_lox_pub, networking::Networking};
  4. use lox_library::{cred::Lox, scalar_u32};
  5. use rand::Rng;
  6. use serde::Deserialize;
  7. use std::{
  8. cmp::min,
  9. collections::{HashMap, HashSet},
  10. };
  11. use troll_patrol::{get_date, positive_report::PositiveReport};
  12. pub struct Censor {
  13. // If we have a bootstrapping period, the censor does not begin
  14. // until this date.
  15. pub start_date: u32,
  16. pub known_bridges: HashSet<[u8; 20]>,
  17. // We don't actually implement the technical restriction to prevent
  18. // one Lox credential from being used to submit many reports, so we
  19. // just implement this as a map of bridge fingerprint to (most
  20. // recent Lox credential for this bridge, count of unique level 3+
  21. // credentials we have for this bridge).
  22. pub lox_credentials: HashMap<[u8; 20], (Lox, u32)>,
  23. // Map of buckets to count of censor users with that bucket. Note
  24. // that this is the count of users that have *ever* had that bucket,
  25. // so this variable should NOT be used to count the overall number
  26. // of censor agents.
  27. pub agents: HashMap<Scalar, u32>,
  28. // If censor implements random blocking, this is the date when it
  29. // will start blocking all the bridges it knows.
  30. pub delay_date: u32,
  31. // If censor implements partial blocking, what percent of
  32. // connections are blocked?
  33. pub partial_blocking_percent: f64,
  34. }
  35. impl Censor {
  36. pub fn new(config: &Config) -> Self {
  37. let start_date = get_date() + config.bootstrapping_period_duration;
  38. let mut rng = rand::thread_rng();
  39. let delay_date = if config.censor_speed == Speed::Random {
  40. let num: u32 = rng.gen_range(1..365);
  41. start_date + num
  42. } else {
  43. 0
  44. };
  45. let partial_blocking_percent = if config.censor_totality == Totality::Partial {
  46. config.censor_partial_blocking_percent
  47. } else {
  48. 1.0
  49. };
  50. Censor {
  51. start_date,
  52. known_bridges: HashSet::<[u8; 20]>::new(),
  53. lox_credentials: HashMap::<[u8; 20], (Lox, u32)>::new(),
  54. agents: HashMap::<Scalar, u32>::new(),
  55. delay_date: delay_date,
  56. partial_blocking_percent: partial_blocking_percent,
  57. }
  58. }
  59. pub fn is_active(&self) -> bool {
  60. get_date() >= self.start_date
  61. }
  62. pub fn knows_bridge(&self, fingerprint: &[u8; 20]) -> bool {
  63. self.known_bridges.contains(fingerprint)
  64. }
  65. pub fn blocks_bridge(&self, config: &Config, fingerprint: &[u8; 20]) -> bool {
  66. self.knows_bridge(fingerprint)
  67. && (config.censor_speed == Speed::Fast
  68. || config.censor_speed == Speed::Lox && self.has_lox_cred(fingerprint)
  69. || config.censor_speed == Speed::Random && self.delay_date <= get_date())
  70. }
  71. pub fn learn_bridge(&mut self, fingerprint: &[u8; 20]) {
  72. self.known_bridges.insert(*fingerprint);
  73. }
  74. pub fn has_lox_cred(&self, fingerprint: &[u8; 20]) -> bool {
  75. self.lox_credentials.contains_key(fingerprint)
  76. && self.lox_credentials.get(fingerprint).unwrap().1 > 0
  77. }
  78. pub fn give_lox_cred(&mut self, fingerprint: &[u8; 20], cred: &Lox, new_cred: bool) {
  79. // We only need one level 3+ credential per bridge. (This will
  80. // change if we restrict positive reports to one per bridge per
  81. // credential.)
  82. if scalar_u32(&cred.trust_level).unwrap() >= 3 {
  83. // We want to clone the credential, but that's not allowed,
  84. // so we're going to serialize it and then deserialize it.
  85. let cloned_cred = bincode::deserialize(&bincode::serialize(&cred).unwrap()).unwrap();
  86. // Insert the new credential and add to the count of unique
  87. // credentials we have. We assume that a duplicate
  88. // credential will never be given. If we don't want to make
  89. // this assumption, we could change the count from a u32 to
  90. // a set of credential IDs and get the count as its length.
  91. let count = match self.lox_credentials.get(fingerprint) {
  92. Some((_cred, count)) => *count,
  93. None => 0,
  94. };
  95. // Sometimes we want to add a fresh credential but assume it
  96. // has the same gamma and does not give the ability to make
  97. // more reports.
  98. let new_count = if new_cred {
  99. // If we're adding a new gamma, increase count
  100. count + 1
  101. } else {
  102. // If we're adding a fresh cred with old gamma, don't
  103. count
  104. };
  105. // Insert the new credential. We always want the newest
  106. // credential to ensure freshness.
  107. self.lox_credentials
  108. .insert(*fingerprint, (cloned_cred, new_count));
  109. }
  110. }
  111. // Get the number of agents the censor has with a given bucket
  112. pub fn num_agents(&self, bucket: &Scalar) -> u32 {
  113. match self.agents.get(bucket) {
  114. Some(v) => *v,
  115. None => 0,
  116. }
  117. }
  118. // Add to the number of agents a censor has for a given bucket
  119. pub fn add_agent(&mut self, bucket: &Scalar) {
  120. self.agents.insert(
  121. *bucket,
  122. match self.agents.get(bucket) {
  123. Some(v) => *v + 1,
  124. None => 1,
  125. },
  126. );
  127. }
  128. // Censor sends a positive report for the given bridge. Returns true
  129. // if successful, false otherwise.
  130. pub async fn send_positive_report(&self, config: &Config, fingerprint: &[u8; 20]) -> bool {
  131. // If we don't have an appropriate Lox credential, we can't send
  132. // a report. Return false.
  133. if !self.has_lox_cred(fingerprint) {
  134. return false;
  135. }
  136. let (cred, _) = &self.lox_credentials.get(fingerprint).unwrap();
  137. if let Ok(pr) = PositiveReport::from_lox_credential(
  138. *fingerprint,
  139. None,
  140. cred,
  141. get_lox_pub(&config.la_pubkeys),
  142. config.country.clone(),
  143. ) {
  144. if config
  145. .tp_net
  146. .request("/positivereport".to_string(), pr.to_json().into_bytes())
  147. .await
  148. .is_err()
  149. {
  150. // failed to send positive report
  151. return false;
  152. }
  153. }
  154. true
  155. }
  156. // Make a bunch of connections and submit positive reports if possible
  157. async fn flood(&self, config: &Config, bridges: &mut HashMap<[u8; 20], Bridge>) {
  158. // Only do this if Flooding censor
  159. if config.censor_secrecy == Secrecy::Flooding {
  160. for fingerprint in &self.known_bridges {
  161. // Only do this if we're blocking the bridge
  162. if config.censor_speed == Speed::Fast
  163. || config.censor_speed == Speed::Lox && self.has_lox_cred(fingerprint)
  164. || config.censor_speed == Speed::Random && self.delay_date <= get_date()
  165. {
  166. let bridge = bridges.get_mut(fingerprint).unwrap();
  167. // Make a bunch of connections to the bridge
  168. bridge.censor_flood(config.censor_max_connections);
  169. // If we have a lv3+ credential, submit a bunch of
  170. // positive reports
  171. if self.has_lox_cred(fingerprint) {
  172. let (_cred, cred_count) =
  173. &self.lox_credentials.get(&bridge.fingerprint).unwrap();
  174. // Reduce the number of these for efficiency. It
  175. // does not benefit the censor to submit more
  176. // than 25 positive reports under the current
  177. // detection algorithm. In practice, the censor
  178. // should submit as many reports as possible.
  179. let num_prs = if config.one_positive_report_per_cred {
  180. min(*cred_count, config.censor_max_pr)
  181. } else {
  182. config.censor_max_pr
  183. };
  184. for _ in 0..num_prs {
  185. self.send_positive_report(config, &bridge.fingerprint).await;
  186. }
  187. }
  188. }
  189. }
  190. }
  191. }
  192. // Send one positive report per connection we blocked
  193. async fn send_positive_reports(
  194. &self,
  195. config: &Config,
  196. bridges: &mut HashMap<[u8; 20], Bridge>,
  197. ) {
  198. // Only do this if Hiding censor. Flooding censors should use
  199. // flood() instead.
  200. if config.censor_secrecy == Secrecy::Hiding {
  201. for fingerprint in &self.known_bridges {
  202. // Only do this if we're blocking the bridge
  203. if self.blocks_bridge(config, fingerprint) && self.has_lox_cred(fingerprint) {
  204. let bridge = bridges.get_mut(fingerprint).unwrap();
  205. // We may be restricted to one positive report per
  206. // credential
  207. let num_reports_to_send = if config.one_positive_report_per_cred {
  208. min(
  209. bridge.total_connections - bridge.real_connections,
  210. self.lox_credentials.get(fingerprint).unwrap().1,
  211. )
  212. } else {
  213. bridge.total_connections - bridge.real_connections
  214. };
  215. for _ in 0..num_reports_to_send {
  216. self.send_positive_report(config, fingerprint).await;
  217. }
  218. }
  219. }
  220. }
  221. }
  222. fn recompute_delay(&mut self, config: &Config) {
  223. // Only do this if Random censor
  224. if config.censor_speed == Speed::Random
  225. && self.delay_date + config.censor_event_duration <= get_date()
  226. {
  227. // Compute new delay date
  228. self.delay_date = {
  229. let mut rng = rand::thread_rng();
  230. let num: u32 = rng.gen_range(1..365);
  231. get_date() + num
  232. }
  233. }
  234. }
  235. pub async fn end_of_day_tasks(
  236. &mut self,
  237. config: &Config,
  238. bridges: &mut HashMap<[u8; 20], Bridge>,
  239. ) {
  240. // This check is redundant because the simulation driver only
  241. // calls this function if the censor is active.
  242. if self.is_active() {
  243. if config.censor_secrecy == Secrecy::Flooding
  244. && !(config.censor_speed == Speed::Random && self.delay_date <= get_date())
  245. {
  246. self.flood(config, bridges).await;
  247. } else if config.censor_secrecy == Secrecy::Hiding
  248. && !(config.censor_speed == Speed::Random && self.delay_date <= get_date())
  249. {
  250. self.send_positive_reports(config, bridges).await;
  251. }
  252. self.recompute_delay(config);
  253. }
  254. }
  255. }
  256. #[derive(Clone, Copy, Debug, Deserialize, PartialEq)]
  257. pub enum Speed {
  258. Fast,
  259. Lox,
  260. Random,
  261. }
  262. #[derive(Clone, Copy, Debug, Deserialize, PartialEq)]
  263. pub enum Secrecy {
  264. Overt,
  265. Hiding,
  266. Flooding,
  267. }
  268. #[derive(Clone, Copy, Debug, Deserialize, PartialEq)]
  269. pub enum Totality {
  270. Full,
  271. Partial,
  272. Throttling,
  273. }