Commit e9b1d061 authored by Nick Mathewson's avatar Nick Mathewson 🥔
Browse files

Merge remote-tracking branch 'dgoulet/ticket18693_029_01'

parents 2a3b6517 382a2895
Loading
Loading
Loading
Loading

changes/feature18693

0 → 100644
+5 −0
Original line number Diff line number Diff line
  o Minor feature (port flags):
    - Add *Port flags NoDNSRequest and NoOnionTraffic, and
      the synthetic flag OnionTrafficOnly, which is equivalent to
      NoDNSRequest, NoIPv4Traffic, and NoIPv6Traffic.
      Closes enhancement 18693; patch by "teor".
+16 −1
Original line number Diff line number Diff line
@@ -1083,7 +1083,18 @@ The following options are useful only for clients (that is, if
        IPv6.)
    **PreferIPv6**;;
        Tells exits that, if a host has both an IPv4 and an IPv6 address,
        we would prefer to connect to it via IPv6. (IPv4 is the default.) +
        we would prefer to connect to it via IPv6. (IPv4 is the default.)
    **NoDNSRequest**;;
        Do not ask exits to resolve DNS addresses in SOCKS5 requests. Tor will
        connect to IPv4 addresses, IPv6 addresses (if IPv6Traffic is set) and
        .onion addresses.
    **NoOnionTraffic**;;
        Do not connect to .onion addresses in SOCKS5 requests.
    **OnionTrafficOnly**;;
        Tell the tor client to only connect to .onion addresses in response to
        SOCKS5 requests on this connection. This is equivalent to NoDNSRequest,
        NoIPv4Traffic, NoIPv6Traffic. The corresponding NoOnionTrafficOnly
        flag is not supported.
    **CacheIPv4DNS**;;
        Tells the client to remember IPv4 DNS answers we receive from exit
        nodes via this connection. (On by default.)
@@ -1125,6 +1136,10 @@ The following options are useful only for clients (that is, if
        authentication" when IsolateSOCKSAuth is disabled, or when this
        option is set.

    Flags are processed left to right. If flags conflict, the last flag on the
    line is used, and all earlier flags are ignored. No error is issued for
    conflicting flags.

[[SocksListenAddress]] **SocksListenAddress** __IP__[:__PORT__]::
    Bind to this address to listen for connections from Socks-speaking
    applications. (Default: 127.0.0.1) You can also specify a port (e.g.
+44 −6
Original line number Diff line number Diff line
@@ -6054,6 +6054,8 @@ port_cfg_new(size_t namelen)
  tor_assert(namelen <= SIZE_T_CEILING - sizeof(port_cfg_t) - 1);
  port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t) + namelen + 1);
  cfg->entry_cfg.ipv4_traffic = 1;
  cfg->entry_cfg.dns_request = 1;
  cfg->entry_cfg.onion_traffic = 1;
  cfg->entry_cfg.cache_ipv4_answers = 1;
  cfg->entry_cfg.prefer_ipv6_virtaddr = 1;
  return cfg;
@@ -6324,8 +6326,7 @@ parse_port_config(smartlist_t *out,
      tor_addr_make_unspec(&cfg->addr); /* Server ports default to 0.0.0.0 */
      cfg->server_cfg.no_listen = 1;
      cfg->server_cfg.bind_ipv4_only = 1;
      cfg->entry_cfg.ipv4_traffic = 1;
      cfg->entry_cfg.prefer_ipv6_virtaddr = 1;
      /* cfg->entry_cfg defaults are already set by port_cfg_new */
      smartlist_add(out, cfg);
    }

@@ -6396,9 +6397,11 @@ parse_port_config(smartlist_t *out,
    char *addrport;
    uint16_t ptmp=0;
    int ok;
    /* This must be kept in sync with port_cfg_new's defaults */
    int no_listen = 0, no_advertise = 0, all_addrs = 0,
      bind_ipv4_only = 0, bind_ipv6_only = 0,
      ipv4_traffic = 1, ipv6_traffic = 0, prefer_ipv6 = 0,
      ipv4_traffic = 1, ipv6_traffic = 0, prefer_ipv6 = 0, dns_request = 1,
      onion_traffic = 1,
      cache_ipv4 = 1, use_cached_ipv4 = 0,
      cache_ipv6 = 0, use_cached_ipv6 = 0,
      prefer_ipv6_automap = 1, world_writable = 0, group_writable = 0,
@@ -6584,6 +6587,24 @@ parse_port_config(smartlist_t *out,
          } else if (!strcasecmp(elt, "PreferIPv6")) {
            prefer_ipv6 = ! no;
            continue;
          } else if (!strcasecmp(elt, "DNSRequest")) {
            dns_request = ! no;
            continue;
          } else if (!strcasecmp(elt, "OnionTraffic")) {
            onion_traffic = ! no;
            continue;
          } else if (!strcasecmp(elt, "OnionTrafficOnly")) {
            /* Only connect to .onion addresses.  Equivalent to
             * NoDNSRequest, NoIPv4Traffic, NoIPv6Traffic. The option
             * NoOnionTrafficOnly is not supported, it's too confusing. */
            if (no) {
              log_warn(LD_CONFIG, "Unsupported %sPort option 'No%s'. Use "
                       "DNSRequest, IPv4Traffic, and/or IPv6Traffic instead.",
                       portname, escaped(elt));
            } else {
              ipv4_traffic = ipv6_traffic = dns_request = 0;
            }
            continue;
          }
        }
        if (!strcasecmp(elt, "CacheIPv4DNS")) {
@@ -6652,9 +6673,24 @@ parse_port_config(smartlist_t *out,
    else
      got_zero_port = 1;

    if (ipv4_traffic == 0 && ipv6_traffic == 0) {
      log_warn(LD_CONFIG, "You have a %sPort entry with both IPv4 and "
               "IPv6 disabled; that won't work.", portname);
    if (dns_request == 0 && listener_type == CONN_TYPE_AP_DNS_LISTENER) {
      log_warn(LD_CONFIG, "You have a %sPort entry with DNS disabled; that "
               "won't work.", portname);
      goto err;
    }

    if (ipv4_traffic == 0 && ipv6_traffic == 0 && onion_traffic == 0
        && listener_type != CONN_TYPE_AP_DNS_LISTENER) {
      log_warn(LD_CONFIG, "You have a %sPort entry with all of IPv4 and "
               "IPv6 and .onion disabled; that won't work.", portname);
      goto err;
    }

    if (dns_request == 1 && ipv4_traffic == 0 && ipv6_traffic == 0
        && listener_type != CONN_TYPE_AP_DNS_LISTENER) {
      log_warn(LD_CONFIG, "You have a %sPort entry with DNSRequest enabled, "
               "but IPv4 and IPv6 disabled; DNS-based sites won't work.",
               portname);
      goto err;
    }

@@ -6698,6 +6734,8 @@ parse_port_config(smartlist_t *out,
      cfg->entry_cfg.ipv4_traffic = ipv4_traffic;
      cfg->entry_cfg.ipv6_traffic = ipv6_traffic;
      cfg->entry_cfg.prefer_ipv6 = prefer_ipv6;
      cfg->entry_cfg.dns_request = dns_request;
      cfg->entry_cfg.onion_traffic = onion_traffic;
      cfg->entry_cfg.cache_ipv4_answers = cache_ipv4;
      cfg->entry_cfg.cache_ipv6_answers = cache_ipv6;
      cfg->entry_cfg.use_cached_ipv4_answers = use_cached_ipv4;
+58 −3
Original line number Diff line number Diff line
@@ -1227,7 +1227,7 @@ connection_ap_handshake_rewrite(entry_connection_t *conn,
    }

    /* Hang on, did we find an answer saying that this is a reverse lookup for
     * an internal address?  If so, we should reject it if we're condigured to
     * an internal address?  If so, we should reject it if we're configured to
     * do so. */
    if (options->ClientDNSRejectInternalAddresses) {
      /* Don't let people try to do a reverse lookup on 10.0.0.1. */
@@ -1466,14 +1466,61 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
    /* If we're running in Tor2webMode, we don't allow anything BUT .onion
     * addresses. */
    if (options->Tor2webMode) {
      log_warn(LD_APP, "Refusing to connect to non-hidden-service hostname %s "
               "because tor2web mode is enabled.",
      log_warn(LD_APP, "Refusing to connect to non-hidden-service hostname "
               "or IP address %s because tor2web mode is enabled.",
               safe_str_client(socks->address));
      connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
      return -1;
    }
#endif

    /* socks->address is a non-onion hostname or IP address.
     * If we can't do any non-onion requests, refuse the connection.
     * If we have a hostname but can't do DNS, refuse the connection.
     * If we have an IP address, but we can't use that address family,
     * refuse the connection.
     *
     * If we can do DNS requests, and we can use at least one address family,
     * then we have to resolve the address first. Then we'll know if it
     * resolves to a usable address family. */

    /* First, check if all non-onion traffic is disabled */
    if (!conn->entry_cfg.dns_request && !conn->entry_cfg.ipv4_traffic
        && !conn->entry_cfg.ipv6_traffic) {
        log_warn(LD_APP, "Refusing to connect to non-hidden-service hostname "
                 "or IP address %s because Port has OnionTrafficOnly set (or "
                 "NoDNSRequest, NoIPv4Traffic, and NoIPv6Traffic).",
                 safe_str_client(socks->address));
        connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
        return -1;
    }

    /* Then check if we have a hostname or IP address, and whether DNS or
     * the IP address family are permitted */
    tor_addr_t dummy_addr;
    int socks_family = tor_addr_parse(&dummy_addr, socks->address);
    /* family will be -1 for a non-onion hostname that's not an IP */
    if (socks_family == -1 && !conn->entry_cfg.dns_request) {
      log_warn(LD_APP, "Refusing to connect to hostname %s "
               "because Port has NoDNSRequest set.",
               safe_str_client(socks->address));
      connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
      return -1;
    } else if (socks_family == AF_INET && !conn->entry_cfg.ipv4_traffic) {
      log_warn(LD_APP, "Refusing to connect to IPv4 address %s because "
               "Port has NoIPv4Traffic set.",
               safe_str_client(socks->address));
      connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
      return -1;
    } else if (socks_family == AF_INET6 && !conn->entry_cfg.ipv6_traffic) {
      log_warn(LD_APP, "Refusing to connect to IPv6 address %s because "
               "Port has NoIPv6Traffic set.",
               safe_str_client(socks->address));
      connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
      return -1;
    }
    /* No else, we've covered all possible returned value. */

    /* See if this is a hostname lookup that we can answer immediately.
     * (For example, an attempt to look up the IP address for an IP address.)
     */
@@ -1661,6 +1708,14 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
    /* If we get here, it's a request for a .onion address! */
    tor_assert(!automap);

    /* If .onion address requests are disabled, refuse the request */
    if (!conn->entry_cfg.onion_traffic) {
      log_warn(LD_APP, "Onion address %s requested from a port with .onion "
                       "disabled", safe_str_client(socks->address));
      connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
      return -1;
    }

    /* Check whether it's RESOLVE or RESOLVE_PTR.  We don't handle those
     * for hidden service addresses. */
    if (SOCKS_COMMAND_IS_RESOLVE(socks->command)) {
+2 −0
Original line number Diff line number Diff line
@@ -1151,6 +1151,8 @@ typedef struct entry_port_cfg_t {
  unsigned int ipv4_traffic : 1;
  unsigned int ipv6_traffic : 1;
  unsigned int prefer_ipv6 : 1;
  unsigned int dns_request : 1;
  unsigned int onion_traffic : 1;

  /** For a socks listener: should we cache IPv4/IPv6 DNS information that
   * exit nodes tell us?
Loading