test_dos.c 17 KB

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