circuit: Implement haproxy

This commit is contained in:
Suphanat Chunhapanya
2019-08-23 11:44:49 +08:00
committed by Nick Mathewson
parent 52e59640f9
commit 119004e87d
10 changed files with 133 additions and 7 deletions
+2
View File
@@ -63,6 +63,7 @@ LIBTOR_APP_A_SOURCES = \
src/core/proto/proto_cell.c \
src/core/proto/proto_control0.c \
src/core/proto/proto_ext_or.c \
src/core/proto/proto_haproxy.c \
src/core/proto/proto_http.c \
src/core/proto/proto_socks.c \
src/feature/api/tor_api.c \
@@ -295,6 +296,7 @@ noinst_HEADERS += \
src/core/proto/proto_cell.h \
src/core/proto/proto_control0.h \
src/core/proto/proto_ext_or.h \
src/core/proto/proto_haproxy.h \
src/core/proto/proto_http.h \
src/core/proto/proto_socks.h \
src/feature/api/tor_api_internal.h \
+47 -1
View File
@@ -83,6 +83,7 @@
#include "core/or/reasons.h"
#include "core/or/relay.h"
#include "core/or/crypt_path.h"
#include "core/proto/proto_haproxy.h"
#include "core/proto/proto_http.h"
#include "core/proto/proto_socks.h"
#include "feature/client/dnsserv.h"
@@ -2317,7 +2318,11 @@ conn_get_proxy_type(const connection_t *conn)
return PROXY_SOCKS4;
else if (options->Socks5Proxy)
return PROXY_SOCKS5;
else
else if (options->TCPProxy) {
/* The only supported protocol in TCPProxy is haproxy. */
tor_assert(options->TCPProxyProtocol == TCP_PROXY_PROTOCOL_HAPROXY);
return PROXY_HAPROXY;
} else
return PROXY_NONE;
}
@@ -2489,6 +2494,35 @@ connection_socks5_proxy_connect(connection_t *conn)
return 0;
}
/** Write a proxy request of haproxy to conn for conn->addr:conn->port.
*
* Returns -1 if conn->addr is incompatible with the proxy protocol, and
* 0 otherwise.
*/
static int
connection_haproxy_proxy_connect(connection_t *conn)
{
int ret = 0;
tor_addr_port_t *addr_port = tor_addr_port_new(&conn->addr, conn->port);
char *buf = haproxy_format_proxy_header_line(addr_port);
if (buf == NULL) {
ret = -1;
goto done;
}
connection_buf_add(buf, strlen(buf), conn);
/* In haproxy, we don't have to wait for the response, but we wait for ack.
* So we can set the state to be PROXY_HAPROXY_WAIT_FOR_FLUSH. */
conn->proxy_state = PROXY_HAPROXY_WAIT_FOR_FLUSH;
ret = 0;
done:
tor_free(buf);
tor_free(addr_port);
return ret;
}
/** Write a proxy request of <b>type</b> (socks4, socks5, https, haproxy)
* to conn for conn->addr:conn->port, authenticating with the auth details
* given in the configuration (if available). SOCKS 5 and HTTP CONNECT
@@ -2519,6 +2553,10 @@ connection_proxy_connect(connection_t *conn, int type)
ret = connection_socks5_proxy_connect(conn);
break;
case PROXY_HAPROXY:
ret = connection_haproxy_proxy_connect(conn);
break;
default:
log_err(LD_BUG, "Invalid proxy protocol, %d", type);
tor_fragile_assert();
@@ -5498,6 +5536,13 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
*port = options->Socks5ProxyPort;
*proxy_type = PROXY_SOCKS5;
return 0;
} else if (options->TCPProxy) {
tor_addr_copy(addr, &options->TCPProxyAddr);
*port = options->TCPProxyPort;
/* The only supported protocol in TCPProxy is haproxy. */
tor_assert(options->TCPProxyProtocol == TCP_PROXY_PROTOCOL_HAPROXY);
*proxy_type = PROXY_HAPROXY;
return 0;
}
tor_addr_make_unspec(addr);
@@ -5535,6 +5580,7 @@ proxy_type_to_string(int proxy_type)
case PROXY_CONNECT: return "HTTP";
case PROXY_SOCKS4: return "SOCKS4";
case PROXY_SOCKS5: return "SOCKS5";
case PROXY_HAPROXY: return "HAPROXY";
case PROXY_PLUGGABLE: return "pluggable transports SOCKS";
case PROXY_NONE: return "NULL";
default: tor_assert(0);
+3 -1
View File
@@ -75,8 +75,10 @@ struct buf_t;
#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 6
/* We use a SOCKS5 proxy and we just sent our CONNECT command. */
#define PROXY_SOCKS5_WANT_CONNECT_OK 7
/* We use an HAPROXY proxy and we just sent the proxy header. */
#define PROXY_HAPROXY_WAIT_FOR_FLUSH 8
/* We use a proxy and we CONNECTed successfully!. */
#define PROXY_CONNECTED 8
#define PROXY_CONNECTED 9
/** State for any listener connection. */
#define LISTENER_STATE_READY 0
+14 -1
View File
@@ -726,6 +726,18 @@ connection_or_finished_flushing(or_connection_t *conn)
switch (conn->base_.state) {
case OR_CONN_STATE_PROXY_HANDSHAKING:
/* PROXY_HAPROXY gets connected by receiving an ack. */
if (conn->proxy_type == PROXY_HAPROXY) {
tor_assert(TO_CONN(conn)->proxy_state == PROXY_HAPROXY_WAIT_FOR_FLUSH);
TO_CONN(conn)->proxy_state = PROXY_CONNECTED;
if (connection_tls_start_handshake(conn, 0) < 0) {
/* TLS handshaking error of some kind. */
connection_or_close_for_error(conn, 0);
return -1;
}
break;
}
case OR_CONN_STATE_OPEN:
case OR_CONN_STATE_OR_HANDSHAKING_V2:
case OR_CONN_STATE_OR_HANDSHAKING_V3:
@@ -765,8 +777,9 @@ connection_or_finished_connecting(or_connection_t *or_conn)
return -1;
}
connection_start_reading(conn);
connection_or_change_state(or_conn, OR_CONN_STATE_PROXY_HANDSHAKING);
connection_start_reading(conn);
return 0;
}
+3 -2
View File
@@ -168,12 +168,13 @@ struct curve25519_public_key_t;
#define PROXY_CONNECT 1
#define PROXY_SOCKS4 2
#define PROXY_SOCKS5 3
/* !!!! If there is ever a PROXY_* type over 3, we must grow the proxy_type
#define PROXY_HAPROXY 4
/* !!!! If there is ever a PROXY_* type over 7, we must grow the proxy_type
* field in or_connection_t */
/* Pluggable transport proxy type. Don't use this in or_connection_t,
* instead use the actual underlying proxy type (see above). */
#define PROXY_PLUGGABLE 4
#define PROXY_PLUGGABLE 5
/** How many circuits do we want simultaneously in-progress to handle
* a given stream? */
+1 -1
View File
@@ -58,7 +58,7 @@ struct or_connection_t {
/** True iff this is an outgoing connection. */
unsigned int is_outgoing:1;
unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */
unsigned int proxy_type:3; /**< One of PROXY_NONE...PROXY_HAPROXY */
unsigned int wide_circ_ids:1;
/** True iff this connection has had its bootstrap failure logged with
* control_event_bootstrap_problem. */
+5 -1
View File
@@ -4,7 +4,11 @@ orconfig.h
lib/crypt_ops/*.h
lib/buf/*.h
lib/malloc/*.h
lib/string/*.h
lib/net/address.h
trunnel/*.h
core/proto/*.h
core/proto/*.h
+45
View File
@@ -0,0 +1,45 @@
/* Copyright (c) 2019, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define PROTO_HAPROXY_PRIVATE
#include "lib/malloc/malloc.h"
#include "lib/net/address.h"
#include "lib/string/printf.h"
#include "core/proto/proto_haproxy.h"
/** Return a newly allocated PROXY header null-terminated string. Returns NULL
* if addr_port->addr is incompatible with the proxy protocol.
*/
char *
haproxy_format_proxy_header_line(const tor_addr_port_t *addr_port)
{
tor_assert(addr_port);
sa_family_t family = tor_addr_family(&addr_port->addr);
const char *family_string = NULL;
const char *src_addr_string = NULL;
switch (family) {
case AF_INET:
family_string = "TCP4";
src_addr_string = "0.0.0.0";
break;
case AF_INET6:
family_string = "TCP6";
src_addr_string = "::";
break;
default:
/* Unknown family. */
return NULL;
}
char *buf;
char addrbuf[TOR_ADDR_BUF_LEN];
tor_addr_to_str(addrbuf, &addr_port->addr, sizeof(addrbuf), 0);
tor_asprintf(&buf, "PROXY %s %s %s 0 %d\r\n", family_string, src_addr_string,
addrbuf, addr_port->port);
return buf;
}
+12
View File
@@ -0,0 +1,12 @@
/* Copyright (c) 2019, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_PROTO_HAPROXY_H
#define TOR_PROTO_HAPROXY_H
struct tor_addr_port_t;
char *haproxy_format_proxy_header_line(
const struct tor_addr_port_t *addr_port);
#endif /* !defined(TOR_PROTO_HAPROXY_H) */
@@ -45,6 +45,7 @@ using_proxy(const bt_orconn_t *bto)
case PROXY_CONNECT:
case PROXY_SOCKS4:
case PROXY_SOCKS5:
case PROXY_HAPROXY:
return true;
default:
return false;