test_dos.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  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 "microdesc.h"
  12. #include "networkstatus.h"
  13. #include "nodelist.h"
  14. #include "routerlist.h"
  15. #include "test.h"
  16. #include "log_test_helpers.h"
  17. static networkstatus_t *dummy_ns = NULL;
  18. static networkstatus_t *
  19. mock_networkstatus_get_latest_consensus(void)
  20. {
  21. return dummy_ns;
  22. }
  23. static networkstatus_t *
  24. mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
  25. {
  26. tor_assert(f == FLAV_MICRODESC);
  27. return dummy_ns;
  28. }
  29. /* Number of address a single node_t can have. Default to the production
  30. * value. This is to control the size of the bloom filter. */
  31. static int addr_per_node = 2;
  32. static int
  33. mock_get_estimated_address_per_node(void)
  34. {
  35. return addr_per_node;
  36. }
  37. static unsigned int
  38. mock_enable_dos_protection(const networkstatus_t *ns)
  39. {
  40. (void) ns;
  41. return 1;
  42. }
  43. /** Test that the connection tracker of the DoS subsystem will block clients
  44. * who try to establish too many connections */
  45. static void
  46. test_dos_conn_creation(void *arg)
  47. {
  48. (void) arg;
  49. MOCK(get_param_cc_enabled, mock_enable_dos_protection);
  50. MOCK(get_param_conn_enabled, mock_enable_dos_protection);
  51. /* Initialize test data */
  52. or_connection_t or_conn;
  53. time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
  54. tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr,
  55. "18.0.0.1"));
  56. tor_addr_t *addr = &or_conn.real_addr;
  57. /* Get DoS subsystem limits */
  58. dos_init();
  59. uint32_t max_concurrent_conns = get_param_conn_max_concurrent_count(NULL);
  60. /* Introduce new client */
  61. geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
  62. { /* Register many conns from this client but not enough to get it blocked */
  63. unsigned int i;
  64. for (i = 0; i < max_concurrent_conns; i++) {
  65. dos_new_client_conn(&or_conn);
  66. }
  67. }
  68. /* Check that new conns are still permitted */
  69. tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
  70. dos_conn_addr_get_defense_type(addr));
  71. /* Register another conn and check that new conns are not allowed anymore */
  72. dos_new_client_conn(&or_conn);
  73. tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
  74. dos_conn_addr_get_defense_type(addr));
  75. /* Close a client conn and see that a new conn will be permitted again */
  76. dos_close_client_conn(&or_conn);
  77. tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
  78. dos_conn_addr_get_defense_type(addr));
  79. /* Register another conn and see that defense measures get reactivated */
  80. dos_new_client_conn(&or_conn);
  81. tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
  82. dos_conn_addr_get_defense_type(addr));
  83. done:
  84. dos_free_all();
  85. }
  86. /** Helper mock: Place a fake IP addr for this channel in <b>addr_out</b> */
  87. static int
  88. mock_channel_get_addr_if_possible(channel_t *chan, tor_addr_t *addr_out)
  89. {
  90. (void)chan;
  91. tt_int_op(AF_INET,OP_EQ, tor_addr_parse(addr_out, "18.0.0.1"));
  92. return 1;
  93. done:
  94. return 0;
  95. }
  96. /** Test that the circuit tracker of the DoS subsystem will block clients who
  97. * try to establish too many circuits. */
  98. static void
  99. test_dos_circuit_creation(void *arg)
  100. {
  101. (void) arg;
  102. unsigned int i;
  103. MOCK(get_param_cc_enabled, mock_enable_dos_protection);
  104. MOCK(get_param_conn_enabled, mock_enable_dos_protection);
  105. MOCK(channel_get_addr_if_possible,
  106. mock_channel_get_addr_if_possible);
  107. /* Initialize channels/conns/circs that will be used */
  108. channel_t *chan = tor_malloc_zero(sizeof(channel_t));
  109. channel_init(chan);
  110. chan->is_client = 1;
  111. /* Initialize test data */
  112. or_connection_t or_conn;
  113. time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
  114. tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr,
  115. "18.0.0.1"));
  116. tor_addr_t *addr = &or_conn.real_addr;
  117. /* Get DoS subsystem limits */
  118. dos_init();
  119. uint32_t max_circuit_count = get_param_cc_circuit_burst(NULL);
  120. uint32_t min_conc_conns_for_cc =
  121. get_param_cc_min_concurrent_connection(NULL);
  122. /* Introduce new client and establish enough connections to activate the
  123. * circuit counting subsystem */
  124. geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
  125. for (i = 0; i < min_conc_conns_for_cc ; i++) {
  126. dos_new_client_conn(&or_conn);
  127. }
  128. /* Register new circuits for this client and conn, but not enough to get
  129. * detected as dos */
  130. for (i=0; i < max_circuit_count-1; i++) {
  131. dos_cc_new_create_cell(chan);
  132. }
  133. /* see that we didn't get detected for dosing */
  134. tt_int_op(DOS_CC_DEFENSE_NONE, OP_EQ, dos_cc_get_defense_type(chan));
  135. /* Register another CREATE cell that will push us over the limit. Check that
  136. * the cell gets refused. */
  137. dos_cc_new_create_cell(chan);
  138. tt_int_op(DOS_CC_DEFENSE_REFUSE_CELL, OP_EQ, dos_cc_get_defense_type(chan));
  139. /* TODO: Wait a few seconds before sending the cell, and check that the
  140. buckets got refilled properly. */
  141. /* TODO: Actually send a Tor cell (instead of calling the DoS function) and
  142. * check that it will get refused */
  143. done:
  144. tor_free(chan);
  145. dos_free_all();
  146. }
  147. /** Test that the DoS subsystem properly refills the circuit token buckets. */
  148. static void
  149. test_dos_bucket_refill(void *arg)
  150. {
  151. (void) arg;
  152. int i;
  153. /* For this test, this variable is set to the current circ count of the token
  154. * bucket. */
  155. uint32_t current_circ_count;
  156. MOCK(get_param_cc_enabled, mock_enable_dos_protection);
  157. MOCK(get_param_conn_enabled, mock_enable_dos_protection);
  158. MOCK(channel_get_addr_if_possible,
  159. mock_channel_get_addr_if_possible);
  160. time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
  161. update_approx_time(now);
  162. /* Initialize channels/conns/circs that will be used */
  163. channel_t *chan = tor_malloc_zero(sizeof(channel_t));
  164. channel_init(chan);
  165. chan->is_client = 1;
  166. or_connection_t or_conn;
  167. tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.real_addr,
  168. "18.0.0.1"));
  169. tor_addr_t *addr = &or_conn.real_addr;
  170. /* Initialize DoS subsystem and get relevant limits */
  171. dos_init();
  172. uint32_t max_circuit_count = get_param_cc_circuit_burst(NULL);
  173. uint64_t circ_rate = get_circuit_rate_per_second();
  174. /* Check that the circuit rate is a positive number and smaller than the max
  175. * circuit count */
  176. tt_u64_op(circ_rate, OP_GT, 1);
  177. tt_u64_op(circ_rate, OP_LT, max_circuit_count);
  178. /* Register this client */
  179. geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
  180. dos_new_client_conn(&or_conn);
  181. /* Fetch this client from the geoip cache and get its DoS structs */
  182. clientmap_entry_t *entry = geoip_lookup_client(addr, NULL,
  183. GEOIP_CLIENT_CONNECT);
  184. tt_assert(entry);
  185. dos_client_stats_t* dos_stats = &entry->dos_stats;
  186. /* Check that the circuit bucket is still uninitialized */
  187. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, 0);
  188. /* Send a create cell: then check that the circ token bucket got initialized
  189. * and one circ was subtracted. */
  190. dos_cc_new_create_cell(chan);
  191. current_circ_count = max_circuit_count - 1;
  192. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  193. /* Now send 29 more CREATEs and ensure that the bucket is missing 30
  194. * tokens */
  195. for (i=0; i < 29; i++) {
  196. dos_cc_new_create_cell(chan);
  197. current_circ_count--;
  198. }
  199. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  200. /* OK! Progress time forward one sec, refill the bucket and check that the
  201. * refill happened correctly. */
  202. now += 1;
  203. update_approx_time(now);
  204. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  205. /* check refill */
  206. current_circ_count += circ_rate;
  207. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  208. /* Now send as many CREATE cells as needed to deplete our token bucket
  209. * completely */
  210. for (; current_circ_count != 0; current_circ_count--) {
  211. dos_cc_new_create_cell(chan);
  212. }
  213. tt_uint_op(current_circ_count, OP_EQ, 0);
  214. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  215. /* Now progress time a week forward, and check that the token bucket does not
  216. * have more than max_circs allowance, even tho we let it simmer for so
  217. * long. */
  218. now += 604800; /* a week */
  219. update_approx_time(now);
  220. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  221. current_circ_count += max_circuit_count;
  222. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  223. /* Now send as many CREATE cells as needed to deplete our token bucket
  224. * completely */
  225. for (; current_circ_count != 0; current_circ_count--) {
  226. dos_cc_new_create_cell(chan);
  227. }
  228. tt_uint_op(current_circ_count, OP_EQ, 0);
  229. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  230. /* Now use a very large time, and check that the token bucket does not have
  231. * more than max_circs allowance, even tho we let it simmer for so long. */
  232. now = INT32_MAX; /* 2038? */
  233. update_approx_time(now);
  234. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  235. current_circ_count += max_circuit_count;
  236. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  237. /* Now send as many CREATE cells as needed to deplete our token bucket
  238. * completely */
  239. for (; current_circ_count != 0; current_circ_count--) {
  240. dos_cc_new_create_cell(chan);
  241. }
  242. tt_uint_op(current_circ_count, OP_EQ, 0);
  243. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  244. /* Now use a very small time, and check that the token bucket has exactly
  245. * the max_circs allowance, because backward clock jumps are rare. */
  246. now = INT32_MIN; /* 19?? */
  247. update_approx_time(now);
  248. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  249. current_circ_count += max_circuit_count;
  250. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  251. /* Now send as many CREATE cells as needed to deplete our token bucket
  252. * completely */
  253. for (; current_circ_count != 0; current_circ_count--) {
  254. dos_cc_new_create_cell(chan);
  255. }
  256. tt_uint_op(current_circ_count, OP_EQ, 0);
  257. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  258. /* Progress time forward one sec again, refill the bucket and check that the
  259. * refill happened correctly. */
  260. now += 1;
  261. update_approx_time(now);
  262. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  263. /* check refill */
  264. current_circ_count += circ_rate;
  265. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  266. /* Now send as many CREATE cells as needed to deplete our token bucket
  267. * completely */
  268. for (; current_circ_count != 0; current_circ_count--) {
  269. dos_cc_new_create_cell(chan);
  270. }
  271. tt_uint_op(current_circ_count, OP_EQ, 0);
  272. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  273. /* Now use a very large time (again), and check that the token bucket does
  274. * not have more than max_circs allowance, even tho we let it simmer for so
  275. * long. */
  276. now = INT32_MAX; /* 2038? */
  277. update_approx_time(now);
  278. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  279. current_circ_count += max_circuit_count;
  280. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  281. /* Now send as many CREATE cells as needed to deplete our token bucket
  282. * completely */
  283. for (; current_circ_count != 0; current_circ_count--) {
  284. dos_cc_new_create_cell(chan);
  285. }
  286. tt_uint_op(current_circ_count, OP_EQ, 0);
  287. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  288. /* This code resets the time to zero with 32-bit time_t, which triggers the
  289. * code that initialises the bucket. */
  290. #if SIZEOF_TIME_T == 8
  291. /* Now use a very very small time, and check that the token bucket has
  292. * exactly the max_circs allowance, because backward clock jumps are rare.
  293. */
  294. now = (time_t)INT64_MIN; /* ???? */
  295. update_approx_time(now);
  296. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  297. current_circ_count += max_circuit_count;
  298. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  299. /* Now send as many CREATE cells as needed to deplete our token bucket
  300. * completely */
  301. for (; current_circ_count != 0; current_circ_count--) {
  302. dos_cc_new_create_cell(chan);
  303. }
  304. tt_uint_op(current_circ_count, OP_EQ, 0);
  305. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  306. /* Progress time forward one sec again, refill the bucket and check that the
  307. * refill happened correctly. */
  308. now += 1;
  309. update_approx_time(now);
  310. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  311. /* check refill */
  312. current_circ_count += circ_rate;
  313. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  314. /* Now send as many CREATE cells as needed to deplete our token bucket
  315. * completely */
  316. for (; current_circ_count != 0; current_circ_count--) {
  317. dos_cc_new_create_cell(chan);
  318. }
  319. tt_uint_op(current_circ_count, OP_EQ, 0);
  320. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  321. /* Now use a very very small time, and check that the token bucket has
  322. * exactly the max_circs allowance, because backward clock jumps are rare.
  323. */
  324. now = (time_t)INT64_MIN; /* ???? */
  325. update_approx_time(now);
  326. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  327. current_circ_count += max_circuit_count;
  328. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  329. /* Now send as many CREATE cells as needed to deplete our token bucket
  330. * completely */
  331. for (; current_circ_count != 0; current_circ_count--) {
  332. dos_cc_new_create_cell(chan);
  333. }
  334. tt_uint_op(current_circ_count, OP_EQ, 0);
  335. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  336. /* Now use a very very large time, and check that the token bucket does not
  337. * have more than max_circs allowance, even tho we let it simmer for so
  338. * long. */
  339. now = (time_t)INT64_MAX; /* ???? */
  340. update_approx_time(now);
  341. cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
  342. current_circ_count += max_circuit_count;
  343. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  344. /* Now send as many CREATE cells as needed to deplete our token bucket
  345. * completely */
  346. for (; current_circ_count != 0; current_circ_count--) {
  347. dos_cc_new_create_cell(chan);
  348. }
  349. tt_uint_op(current_circ_count, OP_EQ, 0);
  350. tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
  351. #endif
  352. done:
  353. tor_free(chan);
  354. dos_free_all();
  355. }
  356. /* Test if we avoid counting a known relay. */
  357. static void
  358. test_known_relay(void *arg)
  359. {
  360. clientmap_entry_t *entry = NULL;
  361. routerstatus_t *rs = NULL; microdesc_t *md = NULL; routerinfo_t *ri = NULL;
  362. (void) arg;
  363. MOCK(networkstatus_get_latest_consensus,
  364. mock_networkstatus_get_latest_consensus);
  365. MOCK(networkstatus_get_latest_consensus_by_flavor,
  366. mock_networkstatus_get_latest_consensus_by_flavor);
  367. MOCK(get_estimated_address_per_node,
  368. mock_get_estimated_address_per_node);
  369. MOCK(get_param_cc_enabled, mock_enable_dos_protection);
  370. dos_init();
  371. dummy_ns = tor_malloc_zero(sizeof(*dummy_ns));
  372. dummy_ns->flavor = FLAV_MICRODESC;
  373. dummy_ns->routerstatus_list = smartlist_new();
  374. /* Setup an OR conn so we can pass it to the DoS subsystem. */
  375. or_connection_t or_conn;
  376. tor_addr_parse(&or_conn.real_addr, "42.42.42.42");
  377. rs = tor_malloc_zero(sizeof(*rs));
  378. rs->addr = tor_addr_to_ipv4h(&or_conn.real_addr);
  379. crypto_rand(rs->identity_digest, sizeof(rs->identity_digest));
  380. smartlist_add(dummy_ns->routerstatus_list, rs);
  381. /* This will make the nodelist bloom filter very large
  382. * (the_nodelist->node_addrs) so we will fail the contain test rarely. */
  383. addr_per_node = 1024;
  384. nodelist_set_consensus(dummy_ns);
  385. /* We have now a node in our list so we'll make sure we don't count it as a
  386. * client connection. */
  387. geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &or_conn.real_addr, NULL, 0);
  388. /* Suppose we have 5 connections in rapid succession, the counter should
  389. * always be 0 because we should ignore this. */
  390. dos_new_client_conn(&or_conn);
  391. dos_new_client_conn(&or_conn);
  392. dos_new_client_conn(&or_conn);
  393. dos_new_client_conn(&or_conn);
  394. dos_new_client_conn(&or_conn);
  395. entry = geoip_lookup_client(&or_conn.real_addr, NULL, GEOIP_CLIENT_CONNECT);
  396. tt_assert(entry);
  397. /* We should have a count of 0. */
  398. tt_uint_op(entry->dos_stats.concurrent_count, OP_EQ, 0);
  399. /* To make sure that his is working properly, make a unknown client
  400. * connection and see if we do get it. */
  401. tor_addr_parse(&or_conn.real_addr, "42.42.42.43");
  402. geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &or_conn.real_addr, NULL, 0);
  403. dos_new_client_conn(&or_conn);
  404. dos_new_client_conn(&or_conn);
  405. entry = geoip_lookup_client(&or_conn.real_addr, NULL, GEOIP_CLIENT_CONNECT);
  406. tt_assert(entry);
  407. /* We should have a count of 2. */
  408. tt_uint_op(entry->dos_stats.concurrent_count, OP_EQ, 2);
  409. done:
  410. routerstatus_free(rs); routerinfo_free(ri); microdesc_free(md);
  411. smartlist_clear(dummy_ns->routerstatus_list);
  412. networkstatus_vote_free(dummy_ns);
  413. dos_free_all();
  414. UNMOCK(networkstatus_get_latest_consensus);
  415. UNMOCK(networkstatus_get_latest_consensus_by_flavor);
  416. UNMOCK(get_estimated_address_per_node);
  417. UNMOCK(get_param_cc_enabled);
  418. }
  419. struct testcase_t dos_tests[] = {
  420. { "conn_creation", test_dos_conn_creation, TT_FORK, NULL, NULL },
  421. { "circuit_creation", test_dos_circuit_creation, TT_FORK, NULL, NULL },
  422. { "bucket_refill", test_dos_bucket_refill, TT_FORK, NULL, NULL },
  423. { "known_relay" , test_known_relay, TT_FORK,
  424. NULL, NULL },
  425. END_OF_TESTCASES
  426. };