test_dos.c 18 KB

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