dos.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /* Copyright (c) 2018, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /*
  4. * \file dos.c
  5. * \brief Implement Denial of Service mitigation subsystem.
  6. */
  7. #define DOS_PRIVATE
  8. #include "or.h"
  9. #include "channel.h"
  10. #include "config.h"
  11. #include "geoip.h"
  12. #include "main.h"
  13. #include "networkstatus.h"
  14. #include "dos.h"
  15. /*
  16. * Circuit creation denial of service mitigation.
  17. *
  18. * Namespace used for this mitigation framework is "dos_cc_" where "cc" is for
  19. * Circuit Creation.
  20. */
  21. /* Is the circuit creation DoS mitigation enabled? */
  22. static unsigned int dos_cc_enabled = 0;
  23. /* Consensus parameters. They can be changed when a new consensus arrives.
  24. * They are initialized with the hardcoded default values. */
  25. static uint32_t dos_cc_min_concurrent_conn;
  26. static uint32_t dos_cc_circuit_rate_tenths;
  27. static uint32_t dos_cc_circuit_burst;
  28. static dos_cc_defense_type_t dos_cc_defense_type;
  29. static int32_t dos_cc_defense_time_period;
  30. /*
  31. * Concurrent connection denial of service mitigation.
  32. *
  33. * Namespace used for this mitigation framework is "dos_conn_".
  34. */
  35. /* Is the connection DoS mitigation enabled? */
  36. static unsigned int dos_conn_enabled = 0;
  37. /* Consensus parameters. They can be changed when a new consensus arrives.
  38. * They are initialized with the hardcoded default values. */
  39. static uint32_t dos_conn_max_concurrent_count;
  40. static dos_conn_defense_type_t dos_conn_defense_type;
  41. /*
  42. * General interface of the denial of service mitigation subsystem.
  43. */
  44. /* Return true iff the circuit creation mitigation is enabled. We look at the
  45. * consensus for this else a default value is returned. */
  46. MOCK_IMPL(STATIC unsigned int,
  47. get_param_cc_enabled, (const networkstatus_t *ns))
  48. {
  49. if (get_options()->DoSCircuitCreationEnabled != -1) {
  50. return get_options()->DoSCircuitCreationEnabled;
  51. }
  52. return !!networkstatus_get_param(ns, "DoSCircuitCreationEnabled",
  53. DOS_CC_ENABLED_DEFAULT, 0, 1);
  54. }
  55. /* Return the parameter for the minimum concurrent connection at which we'll
  56. * start counting circuit for a specific client address. */
  57. STATIC uint32_t
  58. get_param_cc_min_concurrent_connection(const networkstatus_t *ns)
  59. {
  60. if (get_options()->DoSCircuitCreationMinConnections) {
  61. return get_options()->DoSCircuitCreationMinConnections;
  62. }
  63. return networkstatus_get_param(ns, "DoSCircuitCreationMinConnections",
  64. DOS_CC_MIN_CONCURRENT_CONN_DEFAULT,
  65. 1, INT32_MAX);
  66. }
  67. /* Return the parameter for the time rate that is how many circuits over this
  68. * time span. */
  69. static uint32_t
  70. get_param_cc_circuit_rate_tenths(const networkstatus_t *ns)
  71. {
  72. /* This is in seconds. */
  73. if (get_options()->DoSCircuitCreationRateTenths) {
  74. return get_options()->DoSCircuitCreationRateTenths;
  75. }
  76. return networkstatus_get_param(ns, "DoSCircuitCreationRateTenths",
  77. DOS_CC_CIRCUIT_RATE_TENTHS_DEFAULT,
  78. 1, INT32_MAX);
  79. }
  80. /* Return the parameter for the maximum circuit count for the circuit time
  81. * rate. */
  82. STATIC uint32_t
  83. get_param_cc_circuit_burst(const networkstatus_t *ns)
  84. {
  85. if (get_options()->DoSCircuitCreationBurst) {
  86. return get_options()->DoSCircuitCreationBurst;
  87. }
  88. return networkstatus_get_param(ns, "DoSCircuitCreationBurst",
  89. DOS_CC_CIRCUIT_BURST_DEFAULT,
  90. 1, INT32_MAX);
  91. }
  92. /* Return the consensus parameter of the circuit creation defense type. */
  93. static uint32_t
  94. get_param_cc_defense_type(const networkstatus_t *ns)
  95. {
  96. if (get_options()->DoSCircuitCreationDefenseType) {
  97. return get_options()->DoSCircuitCreationDefenseType;
  98. }
  99. return networkstatus_get_param(ns, "DoSCircuitCreationDefenseType",
  100. DOS_CC_DEFENSE_TYPE_DEFAULT,
  101. DOS_CC_DEFENSE_NONE, DOS_CC_DEFENSE_MAX);
  102. }
  103. /* Return the consensus parameter of the defense time period which is how much
  104. * time should we defend against a malicious client address. */
  105. static int32_t
  106. get_param_cc_defense_time_period(const networkstatus_t *ns)
  107. {
  108. /* Time in seconds. */
  109. if (get_options()->DoSCircuitCreationDefenseTimePeriod) {
  110. return get_options()->DoSCircuitCreationDefenseTimePeriod;
  111. }
  112. return networkstatus_get_param(ns, "DoSCircuitCreationDefenseTimePeriod",
  113. DOS_CC_DEFENSE_TIME_PERIOD_DEFAULT,
  114. 0, INT32_MAX);
  115. }
  116. /* Return true iff connection mitigation is enabled. We look at the consensus
  117. * for this else a default value is returned. */
  118. MOCK_IMPL(STATIC unsigned int,
  119. get_param_conn_enabled, (const networkstatus_t *ns))
  120. {
  121. if (get_options()->DoSConnectionEnabled != -1) {
  122. return get_options()->DoSConnectionEnabled;
  123. }
  124. return !!networkstatus_get_param(ns, "DoSConnectionEnabled",
  125. DOS_CONN_ENABLED_DEFAULT, 0, 1);
  126. }
  127. /* Return the consensus parameter for the maximum concurrent connection
  128. * allowed. */
  129. STATIC uint32_t
  130. get_param_conn_max_concurrent_count(const networkstatus_t *ns)
  131. {
  132. if (get_options()->DoSConnectionMaxConcurrentCount) {
  133. return get_options()->DoSConnectionMaxConcurrentCount;
  134. }
  135. return networkstatus_get_param(ns, "DoSConnectionMaxConcurrentCount",
  136. DOS_CONN_MAX_CONCURRENT_COUNT_DEFAULT,
  137. 1, INT32_MAX);
  138. }
  139. /* Return the consensus parameter of the connection defense type. */
  140. static uint32_t
  141. get_param_conn_defense_type(const networkstatus_t *ns)
  142. {
  143. if (get_options()->DoSConnectionDefenseType) {
  144. return get_options()->DoSConnectionDefenseType;
  145. }
  146. return networkstatus_get_param(ns, "DoSConnectionDefenseType",
  147. DOS_CONN_DEFENSE_TYPE_DEFAULT,
  148. DOS_CONN_DEFENSE_NONE, DOS_CONN_DEFENSE_MAX);
  149. }
  150. /* Set circuit creation parameters located in the consensus or their default
  151. * if none are present. Called at initialization or when the consensus
  152. * changes. */
  153. static void
  154. set_dos_parameters(const networkstatus_t *ns)
  155. {
  156. /* Get the default consensus param values. */
  157. dos_cc_enabled = get_param_cc_enabled(ns);
  158. dos_cc_min_concurrent_conn = get_param_cc_min_concurrent_connection(ns);
  159. dos_cc_circuit_rate_tenths = get_param_cc_circuit_rate_tenths(ns);
  160. dos_cc_circuit_burst = get_param_cc_circuit_burst(ns);
  161. dos_cc_defense_time_period = get_param_cc_defense_time_period(ns);
  162. dos_cc_defense_type = get_param_cc_defense_type(ns);
  163. /* Connection detection. */
  164. dos_conn_enabled = get_param_conn_enabled(ns);
  165. dos_conn_max_concurrent_count = get_param_conn_max_concurrent_count(ns);
  166. dos_conn_defense_type = get_param_conn_defense_type(ns);
  167. }
  168. /* Free everything for the circuit creation DoS mitigation subsystem. */
  169. static void
  170. cc_free_all(void)
  171. {
  172. /* If everything is freed, the circuit creation subsystem is not enabled. */
  173. dos_cc_enabled = 0;
  174. }
  175. /* Called when the consensus has changed. Do appropriate actions for the
  176. * circuit creation subsystem. */
  177. static void
  178. cc_consensus_has_changed(const networkstatus_t *ns)
  179. {
  180. /* Looking at the consensus, is the circuit creation subsystem enabled? If
  181. * not and it was enabled before, clean it up. */
  182. if (dos_cc_enabled && !get_param_cc_enabled(ns)) {
  183. cc_free_all();
  184. }
  185. }
  186. /* Concurrent connection private API. */
  187. /* Free everything for the connection DoS mitigation subsystem. */
  188. static void
  189. conn_free_all(void)
  190. {
  191. dos_conn_enabled = 0;
  192. }
  193. /* Called when the consensus has changed. Do appropriate actions for the
  194. * connection mitigation subsystem. */
  195. static void
  196. conn_consensus_has_changed(const networkstatus_t *ns)
  197. {
  198. /* Looking at the consensus, is the connection mitigation subsystem enabled?
  199. * If not and it was enabled before, clean it up. */
  200. if (dos_conn_enabled && !get_param_conn_enabled(ns)) {
  201. conn_free_all();
  202. }
  203. }
  204. /* General private API */
  205. /* Return true iff we have at least one DoS detection enabled. This is used to
  206. * decide if we need to allocate any kind of high level DoS object. */
  207. static inline int
  208. dos_is_enabled(void)
  209. {
  210. return (dos_cc_enabled || dos_conn_enabled);
  211. }
  212. /* Circuit creation public API. */
  213. /* Concurrent connection detection public API. */
  214. /* General API */
  215. /* Called when a new client connection has been established on the given
  216. * address. */
  217. void
  218. dos_new_client_conn(or_connection_t *or_conn)
  219. {
  220. clientmap_entry_t *entry;
  221. tor_assert(or_conn);
  222. /* Past that point, we know we have at least one DoS detection subsystem
  223. * enabled so we'll start allocating stuff. */
  224. if (!dos_is_enabled()) {
  225. goto end;
  226. }
  227. /* We are only interested in client connection from the geoip cache. */
  228. entry = geoip_lookup_client(&or_conn->real_addr, NULL,
  229. GEOIP_CLIENT_CONNECT);
  230. if (BUG(entry == NULL)) {
  231. /* Should never happen because we note down the address in the geoip
  232. * cache before this is called. */
  233. goto end;
  234. }
  235. entry->dos_stats.concurrent_count++;
  236. or_conn->tracked_for_dos_mitigation = 1;
  237. log_debug(LD_DOS, "Client address %s has now %u concurrent connections.",
  238. fmt_addr(&or_conn->real_addr),
  239. entry->dos_stats.concurrent_count);
  240. end:
  241. return;
  242. }
  243. /* Called when a client connection for the given IP address has been closed. */
  244. void
  245. dos_close_client_conn(const or_connection_t *or_conn)
  246. {
  247. clientmap_entry_t *entry;
  248. tor_assert(or_conn);
  249. /* We have to decrement the count on tracked connection only even if the
  250. * subsystem has been disabled at runtime because it might be re-enabled
  251. * after and we need to keep a synchronized counter at all time. */
  252. if (!or_conn->tracked_for_dos_mitigation) {
  253. goto end;
  254. }
  255. /* We are only interested in client connection from the geoip cache. */
  256. entry = geoip_lookup_client(&or_conn->real_addr, NULL,
  257. GEOIP_CLIENT_CONNECT);
  258. if (entry == NULL) {
  259. /* This can happen because we can close a connection before the channel
  260. * got to be noted down in the geoip cache. */
  261. goto end;
  262. }
  263. /* Extra super duper safety. Going below 0 means an underflow which could
  264. * lead to most likely a false positive. In theory, this should never happen
  265. * but lets be extra safe. */
  266. if (BUG(entry->dos_stats.concurrent_count == 0)) {
  267. goto end;
  268. }
  269. entry->dos_stats.concurrent_count--;
  270. log_debug(LD_DOS, "Client address %s has lost a connection. Concurrent "
  271. "connections are now at %u",
  272. fmt_addr(&or_conn->real_addr),
  273. entry->dos_stats.concurrent_count);
  274. end:
  275. return;
  276. }
  277. /* Called when the consensus has changed. We might have new consensus
  278. * parameters to look at. */
  279. void
  280. dos_consensus_has_changed(const networkstatus_t *ns)
  281. {
  282. cc_consensus_has_changed(ns);
  283. conn_consensus_has_changed(ns);
  284. /* We were already enabled or we just became enabled but either way, set the
  285. * consensus parameters for all subsystems. */
  286. set_dos_parameters(ns);
  287. }
  288. /* Return true iff the DoS mitigation subsystem is enabled. */
  289. int
  290. dos_enabled(void)
  291. {
  292. return dos_is_enabled();
  293. }
  294. /* Free everything from the Denial of Service subsystem. */
  295. void
  296. dos_free_all(void)
  297. {
  298. /* Free the circuit creation mitigation subsystem. It is safe to do this
  299. * even if it wasn't initialized. */
  300. cc_free_all();
  301. /* Free the connection mitigation subsystem. It is safe to do this even if
  302. * it wasn't initialized. */
  303. conn_free_all();
  304. }
  305. /* Initialize the Denial of Service subsystem. */
  306. void
  307. dos_init(void)
  308. {
  309. /* To initialize, we only need to get the parameters. */
  310. set_dos_parameters(NULL);
  311. }