[tor-commits] [tor/master] Merge branch 'ticket24902_029_05' into ticket24902_033_02

nickm at torproject.org nickm at torproject.org
Tue Jan 30 23:18:27 UTC 2018


commit cd81403cc0d73d53cb7f3650b38d49c54100af25
Merge: 03ab24b44 9aca7d473
Author: David Goulet <dgoulet at torproject.org>
Date:   Tue Jan 30 09:33:12 2018 -0500

    Merge branch 'ticket24902_029_05' into ticket24902_033_02

 changes/ticket24902    |  13 +
 doc/tor.1.txt          |  88 ++++++
 src/common/log.c       |   2 +-
 src/common/torlog.h    |   4 +-
 src/or/channel.c       |   9 +-
 src/or/channel.h       |   3 +-
 src/or/command.c       |  13 +
 src/or/config.c        |  25 ++
 src/or/connection.c    |  16 ++
 src/or/dos.c           | 737 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/or/dos.h           | 140 ++++++++++
 src/or/geoip.c         |  63 +++--
 src/or/geoip.h         |  27 ++
 src/or/include.am      |   2 +
 src/or/main.c          |   2 +
 src/or/networkstatus.c |   2 +
 src/or/or.h            |  33 +++
 src/or/rendmid.c       |  12 +
 src/or/status.c        |   2 +
 src/test/include.am    |   1 +
 src/test/test.c        |   1 +
 src/test/test.h        |   1 +
 src/test/test_dos.c    | 248 +++++++++++++++++
 23 files changed, 1410 insertions(+), 34 deletions(-)

diff --cc doc/tor.1.txt
index ef3d1eb9e,58997cdf3..5ad818365
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@@ -2749,9 -2438,97 +2749,97 @@@ The following options are used to confi
      non-anonymous HiddenServiceSingleHopMode. Enables direct connections in the
      server-side hidden service protocol.  If you are using this option,
      you need to disable all client-side services on your Tor instance,
 -    including setting SOCKSPort to "0".
 -    (Default: 0)
 +    including setting SOCKSPort to "0". Can not be changed while tor is
 +    running. (Default: 0)
  
+ DENIAL OF SERVICE MITIGATION OPTIONS
+ ------------------------------------
+ 
+ The following options are useful only for a public relay. They control the
+ Denial of Service mitigation subsystem.
+ 
+ [[DoSCircuitCreationEnabled]] **DoSCircuitCreationEnabled** **0**|**1**|**auto**::
+ 
+     Enable circuit creation DoS mitigation. If enabled, tor will cache client
+     IPs along with statistics in order to detect circuit DoS attacks. If an
+     address is positively identified, tor will activate defenses against the
+     address. See the DoSCircuitCreationDefenseType option for more details.
+     This is a client to relay detection only. "auto" means use the consensus
+     parameter.
+     (Default: auto)
+ 
+ [[DoSCircuitCreationMinConnections]] **DoSCircuitCreationMinConnections** __NUM__::
+ 
+     Minimum threshold of concurrent connections before a client address can be
+     flagged as executing a circuit creation DoS. In other words, once a client
+     address reaches the circuit rate and has a minimum of NUM concurrent
+     connections, a detection is positive. "0" means use the consensus
+     parameter.
+     (Default: 0)
+ 
+ [[DoSCircuitCreationRate]] **DoSCircuitCreationRate** __NUM__::
+ 
+     The allowed circuit creation rate per second applied per client IP
+     address. If this option is 0, it obeys a consensus parameter. (Default: 0)
+ 
+ [[DoSCircuitCreationBurst]] **DoSCircuitCreationBurst** __NUM__::
+ 
+     The allowed circuit creation burst per client IP address. If the circuit
+     rate and the burst are reached, a client is marked as executing a circuit
+     creation DoS. "0" means use the consensus parameter.
+     (Default: 0)
+ 
+ [[DoSCircuitCreationDefenseType]] **DoSCircuitCreationDefenseType** __NUM__::
+ 
+     This is the type of defense applied to a detected client address. The
+     possible values are:
+ 
+       1: No defense.
+       2: Refuse circuit creation for the DoSCircuitCreationDefenseTimePeriod period of time.
+ +
+     "0" means use the consensus parameter.
+     (Default: 0)
+ 
+ [[DoSCircuitCreationDefenseTimePeriod]] **DoSCircuitCreationDefenseTimePeriod** __NUM__::
+ 
+     The base time period that the DoS defense is activated for. The actual
+     value is selected randomly for each activation from NUM+1 to 3/2 * NUM.
+     "0" means use the consensus parameter.
+     (Default: 0)
+ 
+ [[DoSConnectionEnabled]] **DoSConnectionEnabled** **0**|**1**|**auto**::
+ 
+     Enable the connection DoS mitigation. For client address only, this allows
+     tor to mitigate against large number of concurrent connections made by a
+     single IP address. "auto" means use the consensus parameter.
+     (Default: auto)
+ 
+ [[DoSConnectionMaxConcurrentCount]] **DoSConnectionMaxConcurrentCount** __NUM__::
+ 
+     The maximum threshold of concurrent connection from a client IP address.
+     Above this limit, a defense selected by DoSConnectionDefenseType is
+     applied. "0" means use the consensus parameter.
+     (Default: 0)
+ 
+ [[DoSConnectionDefenseType]] **DoSConnectionDefenseType** __NUM__::
+ 
+     This is the type of defense applied to a detected client address for the
+     connection mitigation. The possible values are:
+ 
+       1: No defense.
+       2: Immediately close new connections.
+ +
+     "0" means use the consensus parameter.
+     (Default: 0)
+ 
+ [[DoSRefuseSingleHopClientRendezvous]] **DoSRefuseSingleHopClientRendezvous** **0**|**1**|**auto**::
+ 
+     Refuse establishment of rendezvous points for single hop clients. In other
+     words, if a client directly connects to the relay and sends an
+     ESTABLISH_RENDEZVOUS cell, it is silently dropped. "auto" means use the
+     consensus parameter.
+     (Default: auto)
+ 
  TESTING NETWORK OPTIONS
  -----------------------
  
diff --cc src/common/log.c
index ac6d07a92,4db1c9f0d..d59e5a403
--- a/src/common/log.c
+++ b/src/common/log.c
@@@ -1263,7 -1177,7 +1263,7 @@@ static const char *domain_list[] = 
    "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
    "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
    "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", "CHANNEL",
-   "SCHED", "GUARD", "CONSDIFF", NULL
 -  "SCHED", "DOS", NULL
++  "SCHED", "GUARD", "CONSDIFF", "DOS", NULL
  };
  
  /** Return a bitmask for the log domain for which <b>domain</b> is the name,
diff --cc src/common/torlog.h
index b7d033adb,20b7d938f..cadfe3b87
--- a/src/common/torlog.h
+++ b/src/common/torlog.h
@@@ -99,12 -99,10 +99,14 @@@
  #define LD_CHANNEL   (1u<<21)
  /** Scheduler */
  #define LD_SCHED     (1u<<22)
 +/** Guard nodes */
 +#define LD_GUARD     (1u<<23)
 +/** Generation and application of consensus diffs. */
 +#define LD_CONSDIFF  (1u<<24)
+ /** Denial of Service mitigation. */
 -#define LD_DOS       (1u<<23)
++#define LD_DOS       (1u<<25)
  /** Number of logging domains in the code. */
- #define N_LOGGING_DOMAINS 25
 -#define N_LOGGING_DOMAINS 24
++#define N_LOGGING_DOMAINS 26
  
  /** This log message is not safe to send to a callback-based logger
   * immediately.  Used as a flag, not a log domain. */
diff --cc src/or/channel.c
index 345a90a00,54e10666d..094bf93e6
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@@ -1885,9 -2570,20 +1885,10 @@@ channel_do_open_actions(channel_t *chan
      router_set_status(chan->identity_digest, 1);
    } else {
      /* only report it to the geoip module if it's not a known router */
 -    if (!router_get_by_id_digest(chan->identity_digest)) {
 +    if (!connection_or_digest_is_known_relay(chan->identity_digest)) {
        if (channel_get_addr_if_possible(chan, &remote_addr)) {
          char *transport_name = NULL;
+         channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan);
          if (chan->get_transport_name(chan, &transport_name) < 0)
            transport_name = NULL;
  
diff --cc src/or/config.c
index afaf86785,3b4027433..f6875b7ed
--- a/src/or/config.c
+++ b/src/or/config.c
@@@ -81,8 -29,8 +81,9 @@@
  #include "dirserv.h"
  #include "dirvote.h"
  #include "dns.h"
+ #include "dos.h"
  #include "entrynodes.h"
 +#include "git_revision.h"
  #include "geoip.h"
  #include "hibernate.h"
  #include "main.h"
@@@ -314,8 -240,21 +315,21 @@@ static config_var_t option_vars_[] = 
    OBSOLETE("DisableIOCP"),
    OBSOLETE("DisableV2DirectoryInfo_"),
    OBSOLETE("DynamicDHGroups"),
 -  VPORT(DNSPort,                     LINELIST, NULL),
 -  V(DNSListenAddress,            LINELIST, NULL),
 +  VPORT(DNSPort),
 +  OBSOLETE("DNSListenAddress"),
+   /* DoS circuit creation options. */
+   V(DoSCircuitCreationEnabled,   AUTOBOOL, "auto"),
+   V(DoSCircuitCreationMinConnections,      UINT, "0"),
+   V(DoSCircuitCreationRate,      UINT,     "0"),
+   V(DoSCircuitCreationBurst,     UINT,     "0"),
+   V(DoSCircuitCreationDefenseType,         INT,  "0"),
+   V(DoSCircuitCreationDefenseTimePeriod,   INTERVAL, "0"),
+   /* DoS connection options. */
+   V(DoSConnectionEnabled,        AUTOBOOL, "auto"),
+   V(DoSConnectionMaxConcurrentCount,       UINT, "0"),
+   V(DoSConnectionDefenseType,    INT,      "0"),
+   /* DoS single hop client options. */
+   V(DoSRefuseSingleHopClientRendezvous,    AUTOBOOL, "auto"),
    V(DownloadExtraInfo,           BOOL,     "0"),
    V(TestingEnableConnBwEvent,    BOOL,     "0"),
    V(TestingEnableCellStatsEvent, BOOL,     "0"),
diff --cc src/or/connection.c
index a020bef77,791fd95c2..5bbb61dfa
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@@ -702,9 -687,16 +703,16 @@@ connection_free_,(connection_t *conn)
      connection_ap_warn_and_unmark_if_pending_circ(TO_ENTRY_CONN(conn),
                                                    "connection_free");
    }
 -#endif
 +#endif /* 1 */
+ 
+   /* Notify the circuit creation DoS mitigation subsystem that an OR client
+    * connection has been closed. And only do that if we track it. */
+   if (conn->type == CONN_TYPE_OR) {
+     dos_close_client_conn(TO_OR_CONN(conn));
+   }
+ 
    connection_unregister_events(conn);
 -  connection_free_(conn);
 +  connection_free_minimal(conn);
  }
  
  /**
diff --cc src/or/geoip.h
index acf61b97a,aa0fca50f..ccedc1bc1
--- a/src/or/geoip.h
+++ b/src/or/geoip.h
@@@ -19,7 -20,30 +20,30 @@@ STATIC int geoip_parse_entry(const cha
  STATIC int geoip_get_country_by_ipv4(uint32_t ipaddr);
  STATIC int geoip_get_country_by_ipv6(const struct in6_addr *addr);
  STATIC void clear_geoip_db(void);
 -#endif
 +#endif /* defined(GEOIP_PRIVATE) */
+ 
+ /** Entry in a map from IP address to the last time we've seen an incoming
+  * connection from that IP address. Used by bridges only to track which
+  * countries have them blocked, or the DoS mitigation subsystem if enabled. */
+ typedef struct clientmap_entry_t {
+   HT_ENTRY(clientmap_entry_t) node;
+   tor_addr_t addr;
+   /* Name of pluggable transport used by this client. NULL if no
+      pluggable transport was used. */
+   char *transport_name;
+ 
+   /** Time when we last saw this IP address, in MINUTES since the epoch.
+    *
+    * (This will run out of space around 4011 CE.  If Tor is still in use around
+    * 4000 CE, please remember to add more bits to last_seen_in_minutes.) */
+   unsigned int last_seen_in_minutes:30;
+   unsigned int action:2;
+ 
+   /* This object is used to keep some statistics per client address for the
+    * DoS mitigation subsystem. */
+   dos_client_stats_t dos_stats;
+ } clientmap_entry_t;
+ 
  int should_record_bridge_info(const or_options_t *options);
  int geoip_load_file(sa_family_t family, const char *filename);
  MOCK_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr));
diff --cc src/or/main.c
index 10e606f3a,fcd8dc902..96c7e77c7
--- a/src/or/main.c
+++ b/src/or/main.c
@@@ -3483,9 -2990,7 +3484,10 @@@ tor_free_all(int postfork
    control_free_all();
    sandbox_free_getaddrinfo_cache();
    protover_free_all();
 +  bridges_free_all();
 +  consdiffmgr_free_all();
 +  hs_free_all();
+   dos_free_all();
    if (!postfork) {
      config_free_all();
      or_state_free_all();
diff --cc src/or/networkstatus.c
index aa0a8d15c,d9ae32560..77898445d
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@@ -51,8 -23,8 +51,9 @@@
  #include "directory.h"
  #include "dirserv.h"
  #include "dirvote.h"
+ #include "dos.h"
  #include "entrynodes.h"
 +#include "hibernate.h"
  #include "main.h"
  #include "microdesc.h"
  #include "networkstatus.h"
@@@ -1605,7 -1509,7 +1606,8 @@@ notify_networkstatus_changed(const netw
                               const networkstatus_t *new_c)
  {
    notify_control_networkstatus_changed(old_c, new_c);
 +  scheduler_notify_networkstatus_changed(old_c, new_c);
+   dos_consensus_has_changed(new_c);
  }
  
  /** Copy all the ancillary information (like router download status and so on)
diff --cc src/or/or.h
index c81e29c95,024a9cff0..0436533a9
--- a/src/or/or.h
+++ b/src/or/or.h
@@@ -4658,53 -4515,36 +4662,82 @@@ typedef struct 
    /** If 1, we skip all OOS checks. */
    int DisableOOSCheck;
  
 +  /** Autobool: Should we include Ed25519 identities in extend2 cells?
 +   * If -1, we should do whatever the consensus parameter says. */
 +  int ExtendByEd25519ID;
 +
 +  /** Bool (default: 1): When testing routerinfos as a directory authority,
 +   * do we enforce Ed25519 identity match? */
 +  /* NOTE: remove this option someday. */
 +  int AuthDirTestEd25519LinkKeys;
 +
 +  /** Bool (default: 0): Tells if a %include was used on torrc */
 +  int IncludeUsed;
 +
 +  /** The seconds after expiration which we as a relay should keep old
 +   * consensuses around so that we can generate diffs from them.  If 0,
 +   * use the default. */
 +  int MaxConsensusAgeForDiffs;
 +
 +  /** Bool (default: 0). Tells Tor to never try to exec another program.
 +   */
 +  int NoExec;
 +
 +  /** Have the KIST scheduler run every X milliseconds. If less than zero, do
 +   * not use the KIST scheduler but use the old vanilla scheduler instead. If
 +   * zero, do what the consensus says and fall back to using KIST as if this is
 +   * set to "10 msec" if the consensus doesn't say anything. */
 +  int KISTSchedRunInterval;
 +
 +  /** A multiplier for the KIST per-socket limit calculation. */
 +  double KISTSockBufSizeFactor;
 +
 +  /** The list of scheduler type string ordered by priority that is first one
 +   * has to be tried first. Default: KIST,KISTLite,Vanilla */
 +  smartlist_t *Schedulers;
 +  /* An ordered list of scheduler_types mapped from Schedulers. */
 +  smartlist_t *SchedulerTypes_;
 +
 +  /** List of files that were opened by %include in torrc and torrc-defaults */
 +  smartlist_t *FilesOpenedByIncludes;
 +
 +  /** If true, Tor shouldn't install any posix signal handlers, since it is
 +   * running embedded inside another process.
 +   */
 +  int DisableSignalHandlers;
++
+   /** Autobool: Is the circuit creation DoS mitigation subsystem enabled? */
+   int DoSCircuitCreationEnabled;
+   /** Minimum concurrent connection needed from one single address before any
+    * defense is used. */
+   int DoSCircuitCreationMinConnections;
+   /** Circuit rate used to refill the token bucket. */
+   int DoSCircuitCreationRate;
+   /** Maximum allowed burst of circuits. Reaching that value, the address is
+    * detected as malicious and a defense might be used. */
+   int DoSCircuitCreationBurst;
+   /** When an address is marked as malicous, what defense should be used
+    * against it. See the dos_cc_defense_type_t enum. */
+   int DoSCircuitCreationDefenseType;
+   /** For how much time (in seconds) the defense is applicable for a malicious
+    * address. A random time delta is added to the defense time of an address
+    * which will be between 1 second and half of this value. */
+   int DoSCircuitCreationDefenseTimePeriod;
+ 
+   /** Autobool: Is the DoS connection mitigation subsystem enabled? */
+   int DoSConnectionEnabled;
+   /** Maximum concurrent connection allowed per address. */
+   int DoSConnectionMaxConcurrentCount;
+   /** When an address is reaches the maximum count, what defense should be
+    * used against it. See the dos_conn_defense_type_t enum. */
+   int DoSConnectionDefenseType;
+ 
+   /** Autobool: Do we refuse single hop client rendezvous? */
+   int DoSRefuseSingleHopClientRendezvous;
  } or_options_t;
  
 +#define LOG_PROTOCOL_WARN (get_protocol_warning_severity_level())
 +
  /** Persistent state for an onion router, as saved to disk. */
  typedef struct {
    uint32_t magic_;
diff --cc src/or/rendmid.c
index 66d2f9311,441d5043c..c4a34ca62
--- a/src/or/rendmid.c
+++ b/src/or/rendmid.c
@@@ -11,7 -12,7 +12,8 @@@
  #include "circuitlist.h"
  #include "circuituse.h"
  #include "config.h"
 +#include "crypto.h"
+ #include "dos.h"
  #include "relay.h"
  #include "rendmid.h"
  #include "rephist.h"
diff --cc src/or/status.c
index 187dc4ad2,fa2238b9f..3b4c60585
--- a/src/or/status.c
+++ b/src/or/status.c
@@@ -27,8 -27,7 +27,9 @@@
  #include "hibernate.h"
  #include "rephist.h"
  #include "statefile.h"
 +#include "hs_stats.h"
 +#include "hs_service.h"
+ #include "dos.h"
  
  static void log_accounting(const time_t now, const or_options_t *options);
  #include "geoip.h"
diff --cc src/test/include.am
index a4b9705fd,91b0a5910..9783f93d5
--- a/src/test/include.am
+++ b/src/test/include.am
@@@ -114,6 -92,6 +114,7 @@@ src_test_test_SOURCES = 
  	src/test/test_dir.c \
  	src/test/test_dir_common.c \
  	src/test/test_dir_handle_get.c \
++	src/test/test_dos.c \
  	src/test/test_entryconn.c \
  	src/test/test_entrynodes.c \
  	src/test/test_guardfraction.c \
diff --cc src/test/test.c
index f225fd277,f66dee2d0..cba746517
--- a/src/test/test.c
+++ b/src/test/test.c
@@@ -1193,6 -1201,6 +1193,7 @@@ struct testgroup_t testgroups[] = 
    { "dir/", dir_tests },
    { "dir_handle_get/", dir_handle_get_tests },
    { "dir/md/", microdesc_tests },
++  { "dos/", dos_tests },
    { "entryconn/", entryconn_tests },
    { "entrynodes/", entrynodes_tests },
    { "guardfraction/", guardfraction_tests },
diff --cc src/test/test.h
index 93d527ba1,41df6b134..b41f0e54b
--- a/src/test/test.h
+++ b/src/test/test.h
@@@ -199,9 -190,9 +199,10 @@@ extern struct testcase_t container_test
  extern struct testcase_t controller_tests[];
  extern struct testcase_t controller_event_tests[];
  extern struct testcase_t crypto_tests[];
 -extern struct testcase_t dos_tests[];
 +extern struct testcase_t crypto_openssl_tests[];
  extern struct testcase_t dir_tests[];
  extern struct testcase_t dir_handle_get_tests[];
++extern struct testcase_t dos_tests[];
  extern struct testcase_t entryconn_tests[];
  extern struct testcase_t entrynodes_tests[];
  extern struct testcase_t guardfraction_tests[];





More information about the tor-commits mailing list