Browse Source

Add a torrc option to specify the bind address of managed proxies.

George Kadianakis 11 years ago
parent
commit
f88c303869
6 changed files with 125 additions and 1 deletions
  1. 4 0
      changes/bug7013
  2. 5 0
      doc/tor.1.txt
  3. 101 0
      src/or/config.c
  4. 2 0
      src/or/config.h
  5. 3 0
      src/or/or.h
  6. 10 1
      src/or/statefile.c

+ 4 - 0
changes/bug7013

@@ -0,0 +1,4 @@
+  o Minor features:
+    - Add a new torrc option 'ServerTransportListenAddr' which allows
+      users to select the address where their pluggable transports
+      will listen for connections.

+ 5 - 0
doc/tor.1.txt

@@ -181,6 +181,11 @@ GENERAL OPTIONS
     using __options__ as its command-line options, and expects to receive
     using __options__ as its command-line options, and expects to receive
     proxied client traffic from it.
     proxied client traffic from it.
 
 
+**ServerTransportListenAddr** __transport__ __IP__:__PORT__::
+    When this option is set, Tor will suggest __IP__:__PORT__ as the
+    listening address of any pluggable transport proxy that tries to
+    launch __transport__.
+
 **ConnLimit** __NUM__::
 **ConnLimit** __NUM__::
     The minimum number of file descriptors that must be available to the Tor
     The minimum number of file descriptors that must be available to the Tor
     process before it will start. Tor will ask the OS for as many file
     process before it will start. Tor will ask the OS for as many file

+ 101 - 0
src/or/config.c

@@ -273,6 +273,7 @@ static config_var_t option_vars_[] = {
   V(HTTPSProxy,                  STRING,   NULL),
   V(HTTPSProxy,                  STRING,   NULL),
   V(HTTPSProxyAuthenticator,     STRING,   NULL),
   V(HTTPSProxyAuthenticator,     STRING,   NULL),
   VAR("ServerTransportPlugin",   LINELIST, ServerTransportPlugin,  NULL),
   VAR("ServerTransportPlugin",   LINELIST, ServerTransportPlugin,  NULL),
+  V(ServerTransportListenAddr,   LINELIST, NULL),
   V(Socks4Proxy,                 STRING,   NULL),
   V(Socks4Proxy,                 STRING,   NULL),
   V(Socks5Proxy,                 STRING,   NULL),
   V(Socks5Proxy,                 STRING,   NULL),
   V(Socks5ProxyUsername,         STRING,   NULL),
   V(Socks5ProxyUsername,         STRING,   NULL),
@@ -462,6 +463,9 @@ static int parse_bridge_line(const char *line, int validate_only);
 static int parse_client_transport_line(const char *line, int validate_only);
 static int parse_client_transport_line(const char *line, int validate_only);
 
 
 static int parse_server_transport_line(const char *line, int validate_only);
 static int parse_server_transport_line(const char *line, int validate_only);
+static char *get_bindaddr_from_transport_listen_line(const char *line,
+                                                     const char *transport);
+
 static int parse_dir_server_line(const char *line,
 static int parse_dir_server_line(const char *line,
                                  dirinfo_type_t required_type,
                                  dirinfo_type_t required_type,
                                  int validate_only);
                                  int validate_only);
@@ -2879,6 +2883,22 @@ options_validate(or_options_t *old_options, or_options_t *options,
                escaped(options->ServerTransportPlugin->value));
                escaped(options->ServerTransportPlugin->value));
   }
   }
 
 
+  for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
+    /** If get_bindaddr_from_transport_listen_line() fails with
+        'transport' being NULL, it means that something went wrong
+        while parsing the ServerTransportListenAddr line. */
+    char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
+    if (!bindaddr)
+      REJECT("ServerTransportListenAddr did not parse. See logs for details.");
+    tor_free(bindaddr);
+  }
+
+  if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
+    log_notice(LD_GENERAL, "You need at least a single managed-proxy to "
+               "specify a transport listen address. The "
+               "ServerTransportListenAddr line will be ignored.");
+  }
+
   if (options->ConstrainedSockets) {
   if (options->ConstrainedSockets) {
     /* If the user wants to constrain socket buffer use, make sure the desired
     /* If the user wants to constrain socket buffer use, make sure the desired
      * limit is between MIN|MAX_TCPSOCK_BUFFER in k increments. */
      * limit is between MIN|MAX_TCPSOCK_BUFFER in k increments. */
@@ -4117,6 +4137,87 @@ parse_client_transport_line(const char *line, int validate_only)
   return r;
   return r;
 }
 }
 
 
+/** Given a ServerTransportListenAddr <b>line</b>, return its
+ *  <address:port> string. Return NULL if the line was not
+ *  well-formed.
+ *
+ *  If <b>transport</b> is set, return NULL if the line is not
+ *  referring to <b>transport</b>.
+ *
+ *  The returned string is allocated on the heap and it's the
+ *  responsibility of the caller to free it. */
+static char *
+get_bindaddr_from_transport_listen_line(const char *line,const char *transport)
+{
+  smartlist_t *items = NULL;
+  const char *parsed_transport = NULL;
+  char *addrport = NULL;
+  char *addr = NULL;
+  uint16_t port = 0;
+
+  items = smartlist_new();
+  smartlist_split_string(items, line, NULL,
+                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+  if (smartlist_len(items) < 2) {
+    log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line.");
+    goto err;
+  }
+
+  parsed_transport = smartlist_get(items, 0);
+  addrport = tor_strdup(smartlist_get(items, 1));
+
+  /* If 'transport' is given, check if it matches the one on the line */
+  if (transport && strcmp(transport, parsed_transport))
+    goto err;
+
+  /* Validate addrport */
+  if (tor_addr_port_split(LOG_WARN, addrport, &addr, &port)<0) {
+    log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
+             "address '%s'", addrport);
+    goto err;
+  }
+
+  if (!port) {
+    log_warn(LD_CONFIG,
+             "ServerTransportListenAddr address '%s' has no port.", addrport);
+    goto err;
+  }
+
+  goto done;
+
+ err:
+  tor_free(addrport);
+  addrport = NULL;
+
+ done:
+  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+  smartlist_free(items);
+  tor_free(addr);
+
+  return addrport;
+}
+
+/** Given the name of a pluggable transport in <b>transport</b>, check
+ *  the configuration file to see if the user has explicitly asked for
+ *  it to listen on a specific port. Return a <address:port> string if
+ *  so, otherwise NULL. */
+char *
+get_transport_bindaddr_from_config(const char *transport)
+{
+  config_line_t *cl;
+  const or_options_t *options = get_options();
+
+  for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
+    char *bindaddr =
+      get_bindaddr_from_transport_listen_line(cl->value, transport);
+    if (bindaddr)
+      return bindaddr;
+  }
+
+  return NULL;
+}
+
 /** Read the contents of a ServerTransportPlugin line from
 /** Read the contents of a ServerTransportPlugin line from
  * <b>line</b>. Return 0 if the line is well-formed, and -1 if it
  * <b>line</b>. Return 0 if the line is well-formed, and -1 if it
  * isn't.
  * isn't.

+ 2 - 0
src/or/config.h

@@ -82,6 +82,8 @@ const char *tor_get_digests(void);
 uint32_t get_effective_bwrate(const or_options_t *options);
 uint32_t get_effective_bwrate(const or_options_t *options);
 uint32_t get_effective_bwburst(const or_options_t *options);
 uint32_t get_effective_bwburst(const or_options_t *options);
 
 
+char *get_transport_bindaddr_from_config(const char *transport);
+
 #ifdef CONFIG_PRIVATE
 #ifdef CONFIG_PRIVATE
 /* Used only by config.c and test.c */
 /* Used only by config.c and test.c */
 or_options_t *options_new(void);
 or_options_t *options_new(void);

+ 3 - 0
src/or/or.h

@@ -3218,6 +3218,9 @@ typedef struct {
   config_line_t *ServerTransportPlugin; /**< List of client
   config_line_t *ServerTransportPlugin; /**< List of client
                                            transport plugins. */
                                            transport plugins. */
 
 
+  /** List of TCP/IP addresses that transports should listen at. */
+  config_line_t *ServerTransportListenAddr;
+
   int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make
   int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make
                     * this explicit so we can change how we behave in the
                     * this explicit so we can change how we behave in the
                     * future. */
                     * future. */

+ 10 - 1
src/or/statefile.c

@@ -517,8 +517,17 @@ get_stored_bindaddr_for_server_transport(const char *transport)
 {
 {
   char *default_addrport = NULL;
   char *default_addrport = NULL;
   const char *stored_bindaddr = NULL;
   const char *stored_bindaddr = NULL;
+  config_line_t *line = NULL;
+
+  {
+    /* See if the user explicitly asked for a specific listening
+       address for this transport. */
+    char *conf_bindaddr = get_transport_bindaddr_from_config(transport);
+    if (conf_bindaddr)
+      return conf_bindaddr;
+  }
 
 
-  config_line_t *line = get_transport_in_state_by_name(transport);
+  line = get_transport_in_state_by_name(transport);
   if (!line) /* Found no references in state for this transport. */
   if (!line) /* Found no references in state for this transport. */
     goto no_bindaddr_found;
     goto no_bindaddr_found;