"(Socks|Control|etc)Port auto" now tells Tor to open an arbitrary port

This is the major part of the implementation for trac issue 3076.
This commit is contained in:
Nick Mathewson 2011-05-02 15:05:10 -04:00
parent e0d5a6e184
commit 5fec8fe559
5 changed files with 90 additions and 56 deletions

5
changes/feature3076 Normal file
View File

@ -0,0 +1,5 @@
o Minor features
- The options SocksPort, ControlPort, and so on now all accept an
optional value "auto" that opens a socket on an OS-selected port.

View File

@ -145,13 +145,15 @@ Other options can be specified either on the command-line (--option
all sockets will be set to this limit. Must be a value between 2048 and
262144, in 1024 byte increments. Default of 8192 is recommended.
**ControlPort** __Port__::
**ControlPort** __PORT__|**auto**::
If set, Tor will accept connections on this port and allow those
connections to control the Tor process using the Tor Control Protocol
(described in control-spec.txt). Note: unless you also specify one of
**HashedControlPassword** or **CookieAuthentication**, setting this option will
**HashedControlPassword** or **CookieAuthentication**, setting this
option will
cause Tor to allow any process on the local host to control it. This
option is required for many Tor controllers; most use the value of 9051.
Set it to "auto" to have Tor pick a port for you. (Default: 0).
**ControlListenAddress** __IP__[:__PORT__]::
Bind the controller listener to this address. If you specify a port, bind
@ -647,10 +649,11 @@ The following options are useful only for clients (that is, if
the same circuit. Currently, two addresses are "too close" if they lie in
the same /16 range. (Default: 1)
**SocksPort** __PORT__::
**SocksPort** __PORT__|**auto**::
Advertise this port to listen for connections from Socks-speaking
applications. Set this to 0 if you don't want to allow application
connections. (Default: 9050)
connections via SOCKS. Set it to "auto" to have Tor pick a port for
you. (Default: 9050)
**SocksListenAddress** __IP__[:__PORT__]::
Bind to this address to listen for connections from Socks-speaking
@ -759,23 +762,25 @@ The following options are useful only for clients (that is, if
operating as a relay, and it will never use the public key step if it
doesn't yet know the onion key of the first hop. (Default: 1)
**TransPort** __PORT__::
**TransPort** __PORT__|**auto**::
If non-zero, enables transparent proxy support on __PORT__ (by convention,
9040). Requires OS support for transparent proxies, such as BSDs' pf or
Linux's IPTables. If you're planning to use Tor as a transparent proxy for
a network, you'll want to examine and change VirtualAddrNetwork from the
default setting. You'll also want to set the TransListenAddress option for
the network you'd like to proxy. (Default: 0).
the network you'd like to proxy. Set it to "auto" to have Tor pick a
port for you. (Default: 0).
**TransListenAddress** __IP__[:__PORT__]::
Bind to this address to listen for transparent proxy connections. (Default:
127.0.0.1). This is useful for exporting a transparent proxy server to an
entire network.
**NATDPort** __PORT__::
**NATDPort** __PORT__|**auto**::
Allow old versions of ipfw (as included in old versions of FreeBSD, etc.)
to send connections through Tor using the NATD protocol. This option is
only for people who cannot use TransPort.
only for people who cannot use TransPort. Set it to "auto" to have Tor
pick a port for you. (Default: 0)
**NATDListenAddress** __IP__[:__PORT__]::
Bind to this address to listen for NATD connections. (Default: 127.0.0.1).
@ -791,9 +796,10 @@ The following options are useful only for clients (that is, if
A comma-separated list of suffixes to use with **AutomapHostsOnResolve**.
The "." suffix is equivalent to "all addresses." (Default: .exit,.onion).
**DNSPort** __PORT__::
**DNSPort** __PORT__|**auto**::
If non-zero, Tor listens for UDP DNS requests on this port and resolves
them anonymously. (Default: 0).
them anonymously. Set it to "auto" to have Tor pick a port for
you. (Default: 0).
**DNSListenAddress** __IP__[:__PORT__]::
Bind to this address to listen for DNS connections. (Default: 127.0.0.1).
@ -945,8 +951,10 @@ is non-zero):
**NumCPUs** __num__::
How many processes to use at once for decrypting onionskins. (Default: 1)
**ORPort** __PORT__::
Advertise this port to listen for connections from Tor clients and servers.
**ORPort** __PORT__|**auto**::
Advertise this port to listen for connections from Tor clients and
servers. This option is required to be a Tor server.
Set it to "auto" to have Tor pick a port for you. (Default: 0).
**ORListenAddress** __IP__[:__PORT__]::
Bind to this IP address to listen for connections from Tor clients and
@ -1158,8 +1166,9 @@ if DirPort is non-zero):
Minimum uptime of a v2 hidden service directory to be accepted as such by
authoritative directories. (Default: 24 hours)
**DirPort** __PORT__::
Advertise the directory service on this port.
**DirPort** __PORT__|**auto**::
If this option is nonzero, advertise the directory service on this port.
Set it to "auto" to have Tor pick a port for you. (Default: 0)
**DirListenAddress** __IP__[:__PORT__]::
Bind the directory service to this address. If you specify a port, bind to

View File

@ -43,6 +43,8 @@ typedef enum config_type_t {
CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */
CONFIG_TYPE_FILENAME, /**< A filename: some prefixes get expanded. */
CONFIG_TYPE_UINT, /**< A non-negative integer less than MAX_INT */
CONFIG_TYPE_PORT, /**< A port from 1...65535, 0 for "not set", or
* "auto". */
CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/
CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/
CONFIG_TYPE_DOUBLE, /**< A floating-point value */
@ -203,7 +205,7 @@ static config_var_t _option_vars[] = {
V(ConstrainedSockSize, MEMUNIT, "8192"),
V(ContactInfo, STRING, NULL),
V(ControlListenAddress, LINELIST, NULL),
V(ControlPort, UINT, "0"),
V(ControlPort, PORT, "0"),
V(ControlSocket, LINELIST, NULL),
V(CookieAuthentication, BOOL, "0"),
V(CookieAuthFileGroupReadable, BOOL, "0"),
@ -215,7 +217,7 @@ static config_var_t _option_vars[] = {
V(DirListenAddress, LINELIST, NULL),
OBSOLETE("DirFetchPeriod"),
V(DirPolicy, LINELIST, NULL),
V(DirPort, UINT, "0"),
V(DirPort, PORT, "0"),
V(DirPortFrontPage, FILENAME, NULL),
OBSOLETE("DirPostPeriod"),
OBSOLETE("DirRecordUsageByCountry"),
@ -225,7 +227,7 @@ static config_var_t _option_vars[] = {
V(DirReqStatistics, BOOL, "0"),
VAR("DirServer", LINELIST, DirServers, NULL),
V(DisableAllSwap, BOOL, "0"),
V(DNSPort, UINT, "0"),
V(DNSPort, PORT, "0"),
V(DNSListenAddress, LINELIST, NULL),
V(DownloadExtraInfo, BOOL, "0"),
V(EnforceDistinctSubnets, BOOL, "1"),
@ -304,7 +306,7 @@ static config_var_t _option_vars[] = {
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"),
V(NATDListenAddress, LINELIST, NULL),
V(NATDPort, UINT, "0"),
V(NATDPort, PORT, "0"),
V(Nickname, STRING, NULL),
V(WarnUnsafeSocks, BOOL, "1"),
OBSOLETE("NoPublish"),
@ -312,7 +314,7 @@ static config_var_t _option_vars[] = {
V(NumCPUs, UINT, "1"),
V(NumEntryGuards, UINT, "3"),
V(ORListenAddress, LINELIST, NULL),
V(ORPort, UINT, "0"),
V(ORPort, PORT, "0"),
V(OutboundBindAddress, STRING, NULL),
OBSOLETE("PathlenCoinWeight"),
V(PerConnBWBurst, MEMUNIT, "0"),
@ -355,7 +357,7 @@ static config_var_t _option_vars[] = {
V(ShutdownWaitLength, INTERVAL, "30 seconds"),
V(SocksListenAddress, LINELIST, NULL),
V(SocksPolicy, LINELIST, NULL),
V(SocksPort, UINT, "9050"),
V(SocksPort, PORT, "9050"),
V(SocksTimeout, INTERVAL, "2 minutes"),
OBSOLETE("StatusFetchPeriod"),
V(StrictNodes, BOOL, "0"),
@ -366,7 +368,7 @@ static config_var_t _option_vars[] = {
V(TrackHostExitsExpire, INTERVAL, "30 minutes"),
OBSOLETE("TrafficShaping"),
V(TransListenAddress, LINELIST, NULL),
V(TransPort, UINT, "0"),
V(TransPort, PORT, "0"),
V(TunnelDirConns, BOOL, "1"),
V(UpdateBridgesFromAuthority, BOOL, "0"),
V(UseBridges, BOOL, "0"),
@ -1689,8 +1691,16 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
switch (var->type) {
case CONFIG_TYPE_PORT:
if (!strcasecmp(c->value, "auto")) {
*(int *)lvalue = CFG_AUTO_PORT;
break;
}
/* fall through */
case CONFIG_TYPE_UINT:
i = (int)tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL);
i = (int)tor_parse_long(c->value, 10, 0,
var->type==CONFIG_TYPE_PORT ? 65535 : INT_MAX,
&ok, NULL);
if (!ok) {
tor_asprintf(msg,
"Int keyword '%s %s' is malformed or out of bounds.",
@ -1998,6 +2008,12 @@ get_assigned_option(config_format_t *fmt, void *options,
}
escape_val = 0; /* Can't need escape. */
break;
case CONFIG_TYPE_PORT:
if (*(int*)value == CFG_AUTO_PORT) {
result->value = tor_strdup("auto");
escape_val = 0;
break;
}
case CONFIG_TYPE_INTERVAL:
case CONFIG_TYPE_UINT:
/* This means every or_options_t uint or bool element
@ -2227,6 +2243,7 @@ option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
break;
case CONFIG_TYPE_INTERVAL:
case CONFIG_TYPE_UINT:
case CONFIG_TYPE_PORT:
case CONFIG_TYPE_BOOL:
*(int*)lvalue = 0;
break;
@ -2851,9 +2868,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
tor_assert(msg);
*msg = NULL;
if (options->ORPort < 0 || options->ORPort > 65535)
REJECT("ORPort option out of bounds.");
if (server_mode(options) &&
(!strcmpstart(uname, "Windows 95") ||
!strcmpstart(uname, "Windows 98") ||
@ -2968,18 +2982,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
#endif
if (options->SocksPort < 0 || options->SocksPort > 65535)
REJECT("SocksPort option out of bounds.");
if (options->DNSPort < 0 || options->DNSPort > 65535)
REJECT("DNSPort option out of bounds.");
if (options->TransPort < 0 || options->TransPort > 65535)
REJECT("TransPort option out of bounds.");
if (options->NATDPort < 0 || options->NATDPort > 65535)
REJECT("NATDPort option out of bounds.");
if (options->SocksPort == 0 && options->TransPort == 0 &&
options->NATDPort == 0 && options->ORPort == 0 &&
options->DNSPort == 0 && !options->RendConfigLines)
@ -2988,12 +2990,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
"undefined, and there aren't any hidden services configured. "
"Tor will still run, but probably won't do anything.");
if (options->ControlPort < 0 || options->ControlPort > 65535)
REJECT("ControlPort option out of bounds.");
if (options->DirPort < 0 || options->DirPort > 65535)
REJECT("DirPort option out of bounds.");
#ifndef USE_TRANSPARENT
if (options->TransPort || options->TransListenAddress)
REJECT("TransPort and TransListenAddress are disabled in this build.");
@ -5238,6 +5234,7 @@ getinfo_helper_config(control_connection_t *conn,
case CONFIG_TYPE_STRING: type = "String"; break;
case CONFIG_TYPE_FILENAME: type = "Filename"; break;
case CONFIG_TYPE_UINT: type = "Integer"; break;
case CONFIG_TYPE_PORT: type = "Port"; break;
case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
case CONFIG_TYPE_DOUBLE: type = "Float"; break;

View File

@ -37,7 +37,7 @@
#include "routerparse.h"
static connection_t *connection_create_listener(
struct sockaddr *listensockaddr,
const struct sockaddr *listensockaddr,
socklen_t listensocklen, int type,
char* address);
static void connection_init(time_t now, connection_t *conn, int type,
@ -759,7 +759,7 @@ connection_expire_held_open(void)
* The listenaddr struct has to be freed by the caller.
*/
static struct sockaddr_in *
create_inet_sockaddr(const char *listenaddress, uint16_t listenport,
create_inet_sockaddr(const char *listenaddress, int listenport,
char **readable_address, socklen_t *socklen_out) {
struct sockaddr_in *listenaddr = NULL;
uint32_t addr;
@ -771,8 +771,10 @@ create_inet_sockaddr(const char *listenaddress, uint16_t listenport,
"Error parsing/resolving ListenAddress %s", listenaddress);
goto err;
}
if (usePort==0)
usePort = listenport;
if (usePort==0) {
if (listenport != CFG_AUTO_PORT)
usePort = listenport;
}
listenaddr = tor_malloc_zero(sizeof(struct sockaddr_in));
listenaddr->sin_addr.s_addr = htonl(addr);
@ -858,12 +860,13 @@ warn_too_many_conns(void)
* to the conn.
*/
static connection_t *
connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen,
connection_create_listener(const struct sockaddr *listensockaddr,
socklen_t socklen,
int type, char* address)
{
connection_t *conn;
int s; /* the socket we're going to make */
uint16_t usePort = 0;
uint16_t usePort = 0, gotPort = 0;
int start_reading = 0;
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
@ -872,6 +875,7 @@ connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen,
}
if (listensockaddr->sa_family == AF_INET) {
tor_addr_t addr;
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
#ifndef MS_WINDOWS
int one=1;
@ -879,11 +883,10 @@ connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen,
if (is_tcp)
start_reading = 1;
usePort = ntohs( (uint16_t)
((struct sockaddr_in *)listensockaddr)->sin_port);
tor_addr_from_sockaddr(&addr, listensockaddr, &usePort);
log_notice(LD_NET, "Opening %s on %s:%d",
conn_type_to_string(type), address, usePort);
conn_type_to_string(type), fmt_addr(&addr), usePort);
s = tor_open_socket(PF_INET,
is_tcp ? SOCK_STREAM : SOCK_DGRAM,
@ -921,6 +924,21 @@ connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen,
goto err;
}
}
if (usePort != 0) {
gotPort = usePort;
} else {
tor_addr_t addr2;
struct sockaddr_storage ss;
socklen_t ss_len=sizeof(ss);
if (getsockname(s, (struct sockaddr*)&ss, &ss_len)<0) {
log_warn(LD_NET, "getsockname() couldn't learn address for %s: %s",
conn_type_to_string(type),
tor_socket_strerror(tor_socket_errno(s)));
gotPort = 0;
}
tor_addr_from_sockaddr(&addr2, (struct sockaddr*)&ss, &gotPort);
}
#ifdef HAVE_SYS_UN_H
} else if (listensockaddr->sa_family == AF_UNIX) {
start_reading = 1;
@ -968,7 +986,7 @@ connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen,
conn->socket_family = listensockaddr->sa_family;
conn->s = s;
conn->address = tor_strdup(address);
conn->port = usePort;
conn->port = gotPort;
if (connection_add(conn) < 0) { /* no space, forget it */
log_warn(LD_NET,"connection_add for listener failed. Giving up.");
@ -976,8 +994,9 @@ connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen,
goto err;
}
log_debug(LD_NET,"%s listening on port %u.",
conn_type_to_string(type), usePort);
log_fn(usePort==gotPort ? LOG_DEBUG : LOG_NOTICE, LD_NET,
"%s listening on port %u.",
conn_type_to_string(type), gotPort);
conn->state = LISTENER_STATE_READY;
if (start_reading) {
@ -1804,7 +1823,7 @@ retry_listeners(int type, config_line_t *cfg,
case AF_INET:
listensockaddr = (struct sockaddr *)
create_inet_sockaddr(cfg_line->value,
(uint16_t) port_option,
port_option,
&address, &listensocklen);
break;
case AF_UNIX:

View File

@ -2353,6 +2353,10 @@ typedef struct config_line_t {
typedef struct routerset_t routerset_t;
/** A magic value for the (Socks|OR|...)Port options below, telling Tor
* to pick its own port. */
#define CFG_AUTO_PORT 0xc4005e
/** Configuration options for a Tor process. */
typedef struct {
uint32_t _magic;