test_dos.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /* Copyright (c) 2018, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define DOS_PRIVATE
  4. #define TOR_CHANNEL_INTERNAL_
  5. #define CIRCUITLIST_PRIVATE
  6. #include "or.h"
  7. #include "dos.h"
  8. #include "circuitlist.h"
  9. #include "geoip.h"
  10. #include "channel.h"
  11. #include "test.h"
  12. #include "log_test_helpers.h"
  13. static unsigned int
  14. mock_enable_dos_protection(const networkstatus_t *ns)
  15. {
  16. (void) ns;
  17. return 1;
  18. }
  19. /** Test that the connection tracker of the DoS subsystem will block clients
  20. * who try to establish too many connections */
  21. static void
  22. test_dos_conn_creation(void *arg)
  23. {
  24. (void) arg;
  25. MOCK(get_param_cc_enabled, mock_enable_dos_protection);
  26. MOCK(get_param_conn_enabled, mock_enable_dos_protection);
  27. /* Initialize test data */
  28. or_connection_t or_conn;
  29. time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
  30. tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr,
  31. "18.0.0.1"));
  32. tor_addr_t *addr = &or_conn.real_addr;
  33. /* Get DoS subsystem limits */
  34. dos_init();
  35. uint32_t max_concurrent_conns = get_param_conn_max_concurrent_count(NULL);
  36. /* Introduce new client */
  37. geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
  38. { /* Register many conns from this client but not enough to get it blocked */
  39. unsigned int i;
  40. for (i = 0; i < max_concurrent_conns; i++) {
  41. dos_new_client_conn(&or_conn);
  42. }
  43. }
  44. /* Check that new conns are still permitted */
  45. tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
  46. dos_conn_addr_get_defense_type(addr));
  47. /* Register another conn and check that new conns are not allowed anymore */
  48. dos_new_client_conn(&or_conn);
  49. tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
  50. dos_conn_addr_get_defense_type(addr));
  51. /* Close a client conn and see that a new conn will be permitted again */
  52. dos_close_client_conn(&or_conn);
  53. tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
  54. dos_conn_addr_get_defense_type(addr));
  55. /* Register another conn and see that defense measures get reactivated */
  56. dos_new_client_conn(&or_conn);
  57. tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
  58. dos_conn_addr_get_defense_type(addr));
  59. done:
  60. dos_free_all();
  61. }
  62. /** Helper mock: Place a fake IP addr for this channel in <b>addr_out</b> */
  63. static int
  64. mock_channel_get_addr_if_possible(channel_t *chan, tor_addr_t *addr_out)
  65. {
  66. (void)chan;
  67. tt_int_op(AF_INET,OP_EQ, tor_addr_parse(addr_out, "18.0.0.1"));
  68. return 1;
  69. done:
  70. return 0;
  71. }
  72. /** Test that the circuit tracker of the DoS subsystem will block clients who
  73. * try to establish too many circuits. */
  74. static void
  75. test_dos_circuit_creation(void *arg)
  76. {
  77. (void) arg;
  78. unsigned int i;
  79. MOCK(get_param_cc_enabled, mock_enable_dos_protection);
  80. MOCK(get_param_conn_enabled, mock_enable_dos_protection);
  81. MOCK(channel_get_addr_if_possible,
  82. mock_channel_get_addr_if_possible);
  83. /* Initialize channels/conns/circs that will be used */
  84. channel_t *chan = tor_malloc_zero(sizeof(channel_t));
  85. channel_init(chan);
  86. chan->is_client = 1;
  87. /* Initialize test data */
  88. or_connection_t or_conn;
  89. time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
  90. tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr,
  91. "18.0.0.1"));
  92. tor_addr_t *addr = &or_conn.real_addr;
  93. /* Get DoS subsystem limits */
  94. dos_init();
  95. uint32_t max_circuit_count = get_param_cc_circuit_burst(NULL);
  96. uint32_t min_conc_conns_for_cc =
  97. get_param_cc_min_concurrent_connection(NULL);
  98. /* Introduce new client and establish enough connections to activate the
  99. * circuit counting subsystem */
  100. geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
  101. for (i = 0; i < min_conc_conns_for_cc ; i++) {
  102. dos_new_client_conn(&or_conn);
  103. }
  104. /* Register new circuits for this client and conn, but not enough to get
  105. * detected as dos */
  106. for (i=0; i < max_circuit_count-1; i++) {
  107. dos_cc_new_create_cell(chan);
  108. }
  109. /* see that we didn't get detected for dosing */
  110. tt_int_op(DOS_CC_DEFENSE_NONE, OP_EQ, dos_cc_get_defense_type(chan));
  111. /* Register another CREATE cell that will push us over the limit. Check that
  112. * the cell gets refused. */
  113. dos_cc_new_create_cell(chan);
  114. tt_int_op(DOS_CC_DEFENSE_REFUSE_CELL, OP_EQ, dos_cc_get_defense_type(chan));
  115. /* TODO: Wait a few seconds before sending the cell, and check that the
  116. buckets got refilled properly. */
  117. /* TODO: Actually send a Tor cell (instead of calling the DoS function) and
  118. * check that it will get refused */
  119. done:
  120. tor_free(chan);
  121. dos_free_all();
  122. }
  123. /** Test that the DoS subsystem properly refills the circuit token buckets. */
  124. static void
  125. test_dos_bucket_refill(void *arg)
  126. {
  127. (void) arg;
  128. int i;
  129. /* For this test, this variable is set to the current circ count of the token
  130. * bucket. */
  131. uint32_t current_circ_count;
  132. MOCK(get_param_cc_enabled, mock_enable_dos_protection);
  133. MOCK(get_param_conn_enabled, mock_enable_dos_protection);
  134. MOCK(channel_get_addr_if_possible,
  135. mock_channel_get_addr_if_possible);
  136. time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
  137. update_approx_time(now);
  138. /* Initialize channels/conns/circs that will be used */
  139. channel_t *chan = tor_malloc_zero(sizeof(channel_t));
  140. channel_init(chan);
  141. chan->is_client = 1;
  142. or_connection_t or_conn;
  143. tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr,
  144. "18.0.0.1"));
  145. tor_addr_t *addr = &or_conn.real_addr;
  146. /* Initialize DoS subsystem and get relevant limits */
  147. dos_init();
  148. uint32_t max_circuit_count = get_param_cc_circuit_burst(NULL);
  149. uint64_t circ_rate = get_circuit_rate_per_second();
  150. /* Check that the circuit rate is a positive number and smaller than the max
  151. * circuit count */
  152. tt_u64_op(circ_rate, OP_GT, 1);
  153. tt_u64_op(circ_rate, OP_LT, max_circuit_count);
  154. /* Register this client */
  155. geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
  156. dos_new_client_conn(&or_conn);
  157. /* Fetch this client from the geoip cache and get its DoS structs */
  158. clientmap_entry_t *entry = geoip_lookup_client(addr, NULL,
  159. GEOIP_CLIENT_CONNECT);
  160. tt_assert(entry);
  161. dos_client_stats_t* dos_stats = &entry->dos_stats;
  162. /* Check that the circuit bucket is still uninitialized */
  163. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, 0);
  164. /* Send a create cell: then check that the circ token bucket got initialized
  165. * and one circ was subtracted. */
  166. dos_cc_new_create_cell(chan);
  167. current_circ_count = max_circuit_count - 1;
  168. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  169. /* Now send 29 more CREATEs and ensure that the bucket is missing 30
  170. * tokens */
  171. for (i=0; i < 29; i++) {
  172. dos_cc_new_create_cell(chan);
  173. current_circ_count--;
  174. }
  175. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  176. /* OK! Progress time forward one sec, refill the bucket and check that the
  177. * refill happened correctly. */
  178. now += 1;
  179. update_approx_time(now);
  180. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  181. /* check refill */
  182. current_circ_count += circ_rate;
  183. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  184. /* Now send as many CREATE cells as needed to deplete our token bucket
  185. * completely */
  186. for (; current_circ_count != 0; current_circ_count--) {
  187. dos_cc_new_create_cell(chan);
  188. }
  189. tt_uint_op(current_circ_count, OP_EQ, 0);
  190. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  191. /* Now progress time a week forward, and check that the token bucket does not
  192. * have more than max_circs allowance, even tho we let it simmer for so
  193. * long. */
  194. now += 604800; /* a week */
  195. update_approx_time(now);
  196. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  197. current_circ_count += max_circuit_count;
  198. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  199. /* Now send as many CREATE cells as needed to deplete our token bucket
  200. * completely */
  201. for (; current_circ_count != 0; current_circ_count--) {
  202. dos_cc_new_create_cell(chan);
  203. }
  204. tt_uint_op(current_circ_count, OP_EQ, 0);
  205. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  206. /* Now use a very large time, and check that the token bucket does not have
  207. * more than max_circs allowance, even tho we let it simmer for so long. */
  208. now = INT32_MAX; /* 2038? */
  209. update_approx_time(now);
  210. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  211. current_circ_count += max_circuit_count;
  212. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  213. /* Now send as many CREATE cells as needed to deplete our token bucket
  214. * completely */
  215. for (; current_circ_count != 0; current_circ_count--) {
  216. dos_cc_new_create_cell(chan);
  217. }
  218. tt_uint_op(current_circ_count, OP_EQ, 0);
  219. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  220. /* Now use a very small time, and check that the token bucket has exactly
  221. * the max_circs allowance, because backward clock jumps are rare. */
  222. now = INT32_MIN; /* 19?? */
  223. update_approx_time(now);
  224. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  225. current_circ_count += max_circuit_count;
  226. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  227. /* Now send as many CREATE cells as needed to deplete our token bucket
  228. * completely */
  229. for (; current_circ_count != 0; current_circ_count--) {
  230. dos_cc_new_create_cell(chan);
  231. }
  232. tt_uint_op(current_circ_count, OP_EQ, 0);
  233. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  234. /* Progress time forward one sec again, refill the bucket and check that the
  235. * refill happened correctly. */
  236. now += 1;
  237. update_approx_time(now);
  238. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  239. /* check refill */
  240. current_circ_count += circ_rate;
  241. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  242. /* Now send as many CREATE cells as needed to deplete our token bucket
  243. * completely */
  244. for (; current_circ_count != 0; current_circ_count--) {
  245. dos_cc_new_create_cell(chan);
  246. }
  247. tt_uint_op(current_circ_count, OP_EQ, 0);
  248. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  249. /* Now use a very large time (again), and check that the token bucket does
  250. * not have more than max_circs allowance, even tho we let it simmer for so
  251. * long. */
  252. now = INT32_MAX; /* 2038? */
  253. update_approx_time(now);
  254. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  255. current_circ_count += max_circuit_count;
  256. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  257. /* Now send as many CREATE cells as needed to deplete our token bucket
  258. * completely */
  259. for (; current_circ_count != 0; current_circ_count--) {
  260. dos_cc_new_create_cell(chan);
  261. }
  262. tt_uint_op(current_circ_count, OP_EQ, 0);
  263. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  264. /* This code resets the time to zero with 32-bit time_t, which triggers the
  265. * code that initialises the bucket. */
  266. #if SIZEOF_TIME_T == 8
  267. /* Now use a very very small time, and check that the token bucket has
  268. * exactly the max_circs allowance, because backward clock jumps are rare.
  269. */
  270. now = (time_t)INT64_MIN; /* ???? */
  271. update_approx_time(now);
  272. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  273. current_circ_count += max_circuit_count;
  274. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  275. /* Now send as many CREATE cells as needed to deplete our token bucket
  276. * completely */
  277. for (; current_circ_count != 0; current_circ_count--) {
  278. dos_cc_new_create_cell(chan);
  279. }
  280. tt_uint_op(current_circ_count, OP_EQ, 0);
  281. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  282. /* Progress time forward one sec again, refill the bucket and check that the
  283. * refill happened correctly. */
  284. now += 1;
  285. update_approx_time(now);
  286. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  287. /* check refill */
  288. current_circ_count += circ_rate;
  289. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  290. /* Now send as many CREATE cells as needed to deplete our token bucket
  291. * completely */
  292. for (; current_circ_count != 0; current_circ_count--) {
  293. dos_cc_new_create_cell(chan);
  294. }
  295. tt_uint_op(current_circ_count, OP_EQ, 0);
  296. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  297. /* Now use a very very small time, and check that the token bucket has
  298. * exactly the max_circs allowance, because backward clock jumps are rare.
  299. */
  300. now = (time_t)INT64_MIN; /* ???? */
  301. update_approx_time(now);
  302. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  303. current_circ_count += max_circuit_count;
  304. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  305. /* Now send as many CREATE cells as needed to deplete our token bucket
  306. * completely */
  307. for (; current_circ_count != 0; current_circ_count--) {
  308. dos_cc_new_create_cell(chan);
  309. }
  310. tt_uint_op(current_circ_count, OP_EQ, 0);
  311. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  312. /* Now use a very very large time, and check that the token bucket does not
  313. * have more than max_circs allowance, even tho we let it simmer for so
  314. * long. */
  315. now = (time_t)INT64_MAX; /* ???? */
  316. update_approx_time(now);
  317. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  318. current_circ_count += max_circuit_count;
  319. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  320. /* Now send as many CREATE cells as needed to deplete our token bucket
  321. * completely */
  322. for (; current_circ_count != 0; current_circ_count--) {
  323. dos_cc_new_create_cell(chan);
  324. }
  325. tt_uint_op(current_circ_count, OP_EQ, 0);
  326. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  327. #endif
  328. done:
  329. tor_free(chan);
  330. dos_free_all();
  331. }
  332. struct testcase_t dos_tests[] = {
  333. { "conn_creation", test_dos_conn_creation, TT_FORK, NULL, NULL },
  334. { "circuit_creation", test_dos_circuit_creation, TT_FORK, NULL, NULL },
  335. { "bucket_refill", test_dos_bucket_refill, TT_FORK, NULL, NULL },
  336. END_OF_TESTCASES
  337. };