config: Add TCPProxy option for haproxy protocol

Read the TCPProxy option and put in or_options_t.
This commit is contained in:
Suphanat Chunhapanya
2019-08-21 14:56:32 +08:00
parent 1b07a2d7bf
commit 5a6a6ed33c
4 changed files with 99 additions and 12 deletions
+81 -8
View File
@@ -522,6 +522,7 @@ static const config_var_t option_vars_[] = {
V(Socks5Proxy, STRING, NULL),
V(Socks5ProxyUsername, STRING, NULL),
V(Socks5ProxyPassword, STRING, NULL),
V(TCPProxy, STRING, NULL),
VAR("KeyDirectory", FILENAME, KeyDirectory_option, NULL),
V(KeyDirectoryGroupReadable, BOOL, "0"),
VAR_D("HSLayer2Nodes", ROUTERSET, HSLayer2Nodes, NULL),
@@ -4150,19 +4151,28 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
if (options->TCPProxy) {
int res = parse_tcp_proxy_line(options->TCPProxy, options, msg);
if (res < 0) {
return res;
}
}
/* Check if more than one exclusive proxy type has been enabled. */
if (!!options->Socks4Proxy + !!options->Socks5Proxy +
!!options->HTTPSProxy > 1)
!!options->HTTPSProxy + !!options->TCPProxy > 1)
REJECT("You have configured more than one proxy type. "
"(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
"(Socks4Proxy|Socks5Proxy|HTTPSProxy|TCPProxy)");
/* Check if the proxies will give surprising behavior. */
if (options->HTTPProxy && !(options->Socks4Proxy ||
options->Socks5Proxy ||
options->HTTPSProxy)) {
log_warn(LD_CONFIG, "HTTPProxy configured, but no SOCKS proxy or "
"HTTPS proxy configured. Watch out: this configuration will "
"proxy unencrypted directory connections only.");
options->HTTPSProxy ||
options->TCPProxy)) {
log_warn(LD_CONFIG, "HTTPProxy configured, but no SOCKS proxy, "
"HTTPS proxy, or any other TCP proxy configured. Watch out: "
"this configuration will proxy unencrypted directory "
"connections only.");
}
if (options->Socks5ProxyUsername) {
@@ -5962,6 +5972,68 @@ parse_bridge_line(const char *line)
return bridge_line;
}
/** Parse the contents of a TCPProxy line from <b>line</b> and put it
* in <b>options</b>. Return 0 if the line is well-formed, and -1 if it
* isn't.
*
* This will mutate only options->TCPProxyProtocol, options->TCPProxyAddr,
* and options->TCPProxyPort.
*
* On error, tor_strdup an error explanation into *<b>msg</b>.
*/
STATIC int
parse_tcp_proxy_line(const char *line, or_options_t *options, char **msg)
{
int ret = 0;
tor_assert(line);
tor_assert(options);
tor_assert(msg);
smartlist_t *sl = smartlist_new();
/* Split between the protocol and the address/port. */
smartlist_split_string(sl, line, " ",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
/* The address/port is not specified. */
if (smartlist_len(sl) < 2) {
*msg = tor_strdup("TCPProxy has no address/port. Please fix.");
goto err;
}
char *protocol_string = smartlist_get(sl, 0);
char *addrport_string = smartlist_get(sl, 1);
/* The only currently supported protocol is 'haproxy'. */
if (strcasecmp(protocol_string, "haproxy")) {
*msg = tor_strdup("TCPProxy protocol is not supported. Currently "
"the only supported protocol is 'haproxy'. "
"Please fix.");
goto err;
} else {
/* Otherwise, set the correct protocol. */
options->TCPProxyProtocol = TCP_PROXY_PROTOCOL_HAPROXY;
}
/* Parse the address/port. */
if (tor_addr_port_lookup(addrport_string, &options->TCPProxyAddr,
&options->TCPProxyPort) < 0) {
*msg = tor_strdup("TCPProxy address/port failed to parse or resolve. "
"Please fix.");
goto err;
}
/* Success. */
ret = 0;
goto end;
err:
ret = -1;
end:
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_free(sl);
return ret;
}
/** Read the contents of a ClientTransportPlugin or ServerTransportPlugin
* line from <b>line</b>, depending on the value of <b>server</b>. Return 0
* if the line is well-formed, and -1 if it isn't.
@@ -6110,9 +6182,10 @@ parse_transport_line(const or_options_t *options,
/* ClientTransportPlugins connecting through a proxy is managed only. */
if (!server && (options->Socks4Proxy || options->Socks5Proxy ||
options->HTTPSProxy)) {
options->HTTPSProxy || options->TCPProxy)) {
log_warn(LD_CONFIG, "You have configured an external proxy with another "
"proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)");
"proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy|"
"TCPProxy)");
goto err;
}
+2
View File
@@ -266,6 +266,8 @@ STATIC int options_validate(or_options_t *old_options,
STATIC int parse_transport_line(const or_options_t *options,
const char *line, int validate_only,
int server);
STATIC int parse_tcp_proxy_line(const char *line, or_options_t *options,
char **msg);
STATIC int consider_adding_dir_servers(const or_options_t *options,
const or_options_t *old_options);
STATIC void add_default_trusted_dir_authorities(dirinfo_type_t type);
+11
View File
@@ -26,6 +26,12 @@ typedef enum {OUTBOUND_ADDR_EXIT, OUTBOUND_ADDR_OR,
OUTBOUND_ADDR_EXIT_AND_OR,
OUTBOUND_ADDR_MAX} outbound_addr_t;
/** Which protocol to use for TCPProxy. */
typedef enum {
/** Use the HAProxy proxy protocol. */
TCP_PROXY_PROTOCOL_HAPROXY
} tcp_proxy_protocol_t;
/** Configuration options for a Tor process. */
struct or_options_t {
uint32_t magic_;
@@ -423,6 +429,11 @@ struct or_options_t {
char *Socks5ProxyUsername; /**< Username for SOCKS5 authentication, if any */
char *Socks5ProxyPassword; /**< Password for SOCKS5 authentication, if any */
char *TCPProxy; /**< protocol and hostname:port to use as a proxy, if any. */
tcp_proxy_protocol_t TCPProxyProtocol; /**< Derived from TCPProxy. */
tor_addr_t TCPProxyAddr; /**< Derived from TCPProxy. */
uint16_t TCPProxyPort; /**< Derived from TCPProxy. */
/** List of configuration lines for replacement directory authorities.
* If you just want to replace one class of authority at a time,
* use the "Alternate*Authority" options below instead. */
+5 -4
View File
@@ -2953,7 +2953,7 @@ test_options_validate__proxy(void *ignored)
ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "You have configured more than one proxy type. "
"(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
"(Socks4Proxy|Socks5Proxy|HTTPSProxy|TCPProxy)");
tor_free(msg);
free_options_test_data(tdata);
@@ -2963,9 +2963,10 @@ test_options_validate__proxy(void *ignored)
mock_clean_saved_logs();
ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("HTTPProxy configured, but no SOCKS "
"proxy or HTTPS proxy configured. Watch out: this configuration "
"will proxy unencrypted directory connections only.\n");
expect_log_msg("HTTPProxy configured, but no SOCKS proxy, "
"HTTPS proxy, or any other TCP proxy configured. Watch out: "
"this configuration will proxy unencrypted directory "
"connections only.\n");
tor_free(msg);
free_options_test_data(tdata);