mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 23:53:32 +01:00
r7299@Kushana: nickm | 2006-08-10 01:08:58 -0700
Patch from Tup to add support for transparent AP connections: this basically bundles the functionality of trans-proxy-tor into the tor mainline. Now hosts with compliant pf/netfilter implementations can redirect TCP connections straight to Tor without diverting through SOCKS. svn:r7007
This commit is contained in:
parent
8cbd03fdaf
commit
5cff4164a0
20
configure.in
20
configure.in
@ -56,6 +56,26 @@ if test x$eventdns = xtrue; then
|
|||||||
AC_DEFINE([USE_EVENTDNS], 1, "Define to 1 if we'll be using eventdns.c")
|
AC_DEFINE([USE_EVENTDNS], 1, "Define to 1 if we'll be using eventdns.c")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(transparent,
|
||||||
|
AC_HELP_STRING(--disable-transparent, disable transparent proxy support),
|
||||||
|
[case "${enableval}" in
|
||||||
|
yes) transparent=true ;;
|
||||||
|
no) transparent=false ;;
|
||||||
|
*) AC_MSG_ERROR(bad value for --enable-transparent) ;;
|
||||||
|
esac], [transparent=true])
|
||||||
|
if test x$transparent = xtrue; then
|
||||||
|
AC_DEFINE(USE_TRANSPARENT, 1, "Define to enable transparent proxy support")
|
||||||
|
case $host in
|
||||||
|
*-*-linux* )
|
||||||
|
AC_DEFINE(TRANS_NETFILTER, 1, "Define for transparent netfilter") ;;
|
||||||
|
*-*-openbsd*)
|
||||||
|
AC_DEFINE(TRANS_PF, 1, "Define for transparent pf")
|
||||||
|
AC_DEFINE(OPENBSD, 1, "Define to handle pf on OpenBSD properly") ;;
|
||||||
|
*-*-*bsd* )
|
||||||
|
AC_DEFINE(TRANS_PF, 1, "Define for transparent pf") ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
case $host in
|
case $host in
|
||||||
*-*-solaris* )
|
*-*-solaris* )
|
||||||
AC_DEFINE(_REENTRANT, 1, [Define on some platforms to activate x_r() functions in time.h])
|
AC_DEFINE(_REENTRANT, 1, [Define on some platforms to activate x_r() functions in time.h])
|
||||||
|
@ -235,6 +235,8 @@ static config_var_t _option_vars[] = {
|
|||||||
VAR("TrackHostExits", CSV, TrackHostExits, NULL),
|
VAR("TrackHostExits", CSV, TrackHostExits, NULL),
|
||||||
VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"),
|
VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"),
|
||||||
OBSOLETE("TrafficShaping"),
|
OBSOLETE("TrafficShaping"),
|
||||||
|
VAR("TransListenAddress", LINELIST, TransListenAddress, NULL),
|
||||||
|
VAR("TransPort", UINT, TransPort, "0"),
|
||||||
VAR("UseEntryGuards", BOOL, UseEntryGuards, "1"),
|
VAR("UseEntryGuards", BOOL, UseEntryGuards, "1"),
|
||||||
VAR("User", STRING, User, NULL),
|
VAR("User", STRING, User, NULL),
|
||||||
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
|
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
|
||||||
@ -2067,6 +2069,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
|||||||
REJECT("SocksPort must be defined if SocksListenAddress is defined.");
|
REJECT("SocksPort must be defined if SocksListenAddress is defined.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* XXX TransListenAddress should be checked here as well */
|
||||||
if (options->SocksListenAddress) {
|
if (options->SocksListenAddress) {
|
||||||
config_line_t *line = NULL;
|
config_line_t *line = NULL;
|
||||||
char *address = NULL;
|
char *address = NULL;
|
||||||
@ -2144,8 +2147,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
|||||||
if (options->SocksPort < 0 || options->SocksPort > 65535)
|
if (options->SocksPort < 0 || options->SocksPort > 65535)
|
||||||
REJECT("SocksPort option out of bounds.");
|
REJECT("SocksPort option out of bounds.");
|
||||||
|
|
||||||
if (options->SocksPort == 0 && options->ORPort == 0)
|
if (options->TransPort < 0 || options->TransPort > 65535)
|
||||||
REJECT("SocksPort and ORPort are both undefined? Quitting.");
|
REJECT("TransPort option out of bounds.");
|
||||||
|
|
||||||
|
if (options->SocksPort == 0 && options->TransPort == 0 &&
|
||||||
|
options->ORPort == 0)
|
||||||
|
REJECT("SocksPort, TransPort, and ORPort are all undefined? Quitting.");
|
||||||
|
|
||||||
if (options->ControlPort < 0 || options->ControlPort > 65535)
|
if (options->ControlPort < 0 || options->ControlPort > 65535)
|
||||||
REJECT("ControlPort option out of bounds.");
|
REJECT("ControlPort option out of bounds.");
|
||||||
@ -2153,6 +2160,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
|||||||
if (options->DirPort < 0 || options->DirPort > 65535)
|
if (options->DirPort < 0 || options->DirPort > 65535)
|
||||||
REJECT("DirPort option out of bounds.");
|
REJECT("DirPort option out of bounds.");
|
||||||
|
|
||||||
|
#ifndef USE_TRANSPARENT
|
||||||
|
if (options->TransPort || options->TransListenAddress)
|
||||||
|
REJECT("TransPort and TransListenAddress are disabled in this build.");
|
||||||
|
#endif
|
||||||
|
|
||||||
if (options->StrictExitNodes &&
|
if (options->StrictExitNodes &&
|
||||||
(!options->ExitNodes || !strlen(options->ExitNodes)) &&
|
(!options->ExitNodes || !strlen(options->ExitNodes)) &&
|
||||||
(!old_options ||
|
(!old_options ||
|
||||||
|
@ -16,7 +16,8 @@ const char connection_c_id[] =
|
|||||||
|
|
||||||
static connection_t *connection_create_listener(const char *listenaddress,
|
static connection_t *connection_create_listener(const char *listenaddress,
|
||||||
uint16_t listenport, int type);
|
uint16_t listenport, int type);
|
||||||
static int connection_init_accepted_conn(connection_t *conn);
|
static int connection_init_accepted_conn(connection_t *conn,
|
||||||
|
uint8_t listener_type);
|
||||||
static int connection_handle_listener_read(connection_t *conn, int new_type);
|
static int connection_handle_listener_read(connection_t *conn, int new_type);
|
||||||
static int connection_receiver_bucket_should_increase(or_connection_t *conn);
|
static int connection_receiver_bucket_should_increase(or_connection_t *conn);
|
||||||
static int connection_finished_flushing(connection_t *conn);
|
static int connection_finished_flushing(connection_t *conn);
|
||||||
@ -44,6 +45,7 @@ conn_type_to_string(int type)
|
|||||||
case CONN_TYPE_OR: return "OR";
|
case CONN_TYPE_OR: return "OR";
|
||||||
case CONN_TYPE_EXIT: return "Exit";
|
case CONN_TYPE_EXIT: return "Exit";
|
||||||
case CONN_TYPE_AP_LISTENER: return "Socks listener";
|
case CONN_TYPE_AP_LISTENER: return "Socks listener";
|
||||||
|
case CONN_TYPE_AP_TRANS_LISTENER: return "Transparent listener";
|
||||||
case CONN_TYPE_AP: return "Socks";
|
case CONN_TYPE_AP: return "Socks";
|
||||||
case CONN_TYPE_DIR_LISTENER: return "Directory listener";
|
case CONN_TYPE_DIR_LISTENER: return "Directory listener";
|
||||||
case CONN_TYPE_DIR: return "Directory";
|
case CONN_TYPE_DIR: return "Directory";
|
||||||
@ -69,6 +71,7 @@ conn_state_to_string(int type, int state)
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case CONN_TYPE_OR_LISTENER:
|
case CONN_TYPE_OR_LISTENER:
|
||||||
case CONN_TYPE_AP_LISTENER:
|
case CONN_TYPE_AP_LISTENER:
|
||||||
|
case CONN_TYPE_AP_TRANS_LISTENER:
|
||||||
case CONN_TYPE_DIR_LISTENER:
|
case CONN_TYPE_DIR_LISTENER:
|
||||||
case CONN_TYPE_CONTROL_LISTENER:
|
case CONN_TYPE_CONTROL_LISTENER:
|
||||||
if (state == LISTENER_STATE_READY)
|
if (state == LISTENER_STATE_READY)
|
||||||
@ -93,6 +96,7 @@ conn_state_to_string(int type, int state)
|
|||||||
break;
|
break;
|
||||||
case CONN_TYPE_AP:
|
case CONN_TYPE_AP:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
case AP_CONN_STATE_ORIGDST_WAIT:
|
||||||
case AP_CONN_STATE_SOCKS_WAIT: return "waiting for dest info";
|
case AP_CONN_STATE_SOCKS_WAIT: return "waiting for dest info";
|
||||||
case AP_CONN_STATE_RENDDESC_WAIT: return "waiting for rendezvous desc";
|
case AP_CONN_STATE_RENDDESC_WAIT: return "waiting for rendezvous desc";
|
||||||
case AP_CONN_STATE_CONTROLLER_WAIT: return "waiting for controller";
|
case AP_CONN_STATE_CONTROLLER_WAIT: return "waiting for controller";
|
||||||
@ -786,7 +790,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
|
|||||||
return 0; /* no need to tear down the parent */
|
return 0; /* no need to tear down the parent */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection_init_accepted_conn(newconn) < 0) {
|
if (connection_init_accepted_conn(newconn, conn->type) < 0) {
|
||||||
connection_mark_for_close(newconn);
|
connection_mark_for_close(newconn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -797,7 +801,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
|
|||||||
* If conn is an OR, start the tls handshake.
|
* If conn is an OR, start the tls handshake.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
connection_init_accepted_conn(connection_t *conn)
|
connection_init_accepted_conn(connection_t *conn, uint8_t listener_type)
|
||||||
{
|
{
|
||||||
connection_start_reading(conn);
|
connection_start_reading(conn);
|
||||||
|
|
||||||
@ -806,7 +810,14 @@ connection_init_accepted_conn(connection_t *conn)
|
|||||||
control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW);
|
control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW);
|
||||||
return connection_tls_start_handshake(TO_OR_CONN(conn), 1);
|
return connection_tls_start_handshake(TO_OR_CONN(conn), 1);
|
||||||
case CONN_TYPE_AP:
|
case CONN_TYPE_AP:
|
||||||
conn->state = AP_CONN_STATE_SOCKS_WAIT;
|
switch (listener_type) {
|
||||||
|
case CONN_TYPE_AP_LISTENER:
|
||||||
|
conn->state = AP_CONN_STATE_SOCKS_WAIT;
|
||||||
|
break;
|
||||||
|
case CONN_TYPE_AP_TRANS_LISTENER:
|
||||||
|
conn->state = AP_CONN_STATE_ORIGDST_WAIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CONN_TYPE_DIR:
|
case CONN_TYPE_DIR:
|
||||||
conn->purpose = DIR_PURPOSE_SERVER;
|
conn->purpose = DIR_PURPOSE_SERVER;
|
||||||
@ -1046,6 +1057,10 @@ retry_all_listeners(int force, smartlist_t *replaced_conns,
|
|||||||
options->SocksPort, "127.0.0.1", force,
|
options->SocksPort, "127.0.0.1", force,
|
||||||
replaced_conns, new_conns, 0)<0)
|
replaced_conns, new_conns, 0)<0)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress,
|
||||||
|
options->TransPort, "127.0.0.1", force,
|
||||||
|
replaced_conns, new_conns, 0)<0)
|
||||||
|
return -1;
|
||||||
if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
|
if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
|
||||||
options->ControlListenAddress,
|
options->ControlListenAddress,
|
||||||
options->ControlPort, "127.0.0.1", force,
|
options->ControlPort, "127.0.0.1", force,
|
||||||
@ -1260,6 +1275,7 @@ connection_handle_read(connection_t *conn)
|
|||||||
case CONN_TYPE_OR_LISTENER:
|
case CONN_TYPE_OR_LISTENER:
|
||||||
return connection_handle_listener_read(conn, CONN_TYPE_OR);
|
return connection_handle_listener_read(conn, CONN_TYPE_OR);
|
||||||
case CONN_TYPE_AP_LISTENER:
|
case CONN_TYPE_AP_LISTENER:
|
||||||
|
case CONN_TYPE_AP_TRANS_LISTENER:
|
||||||
return connection_handle_listener_read(conn, CONN_TYPE_AP);
|
return connection_handle_listener_read(conn, CONN_TYPE_AP);
|
||||||
case CONN_TYPE_DIR_LISTENER:
|
case CONN_TYPE_DIR_LISTENER:
|
||||||
return connection_handle_listener_read(conn, CONN_TYPE_DIR);
|
return connection_handle_listener_read(conn, CONN_TYPE_DIR);
|
||||||
@ -1896,6 +1912,7 @@ connection_is_listener(connection_t *conn)
|
|||||||
{
|
{
|
||||||
if (conn->type == CONN_TYPE_OR_LISTENER ||
|
if (conn->type == CONN_TYPE_OR_LISTENER ||
|
||||||
conn->type == CONN_TYPE_AP_LISTENER ||
|
conn->type == CONN_TYPE_AP_LISTENER ||
|
||||||
|
conn->type == CONN_TYPE_AP_TRANS_LISTENER ||
|
||||||
conn->type == CONN_TYPE_DIR_LISTENER ||
|
conn->type == CONN_TYPE_DIR_LISTENER ||
|
||||||
conn->type == CONN_TYPE_CONTROL_LISTENER)
|
conn->type == CONN_TYPE_CONTROL_LISTENER)
|
||||||
return 1;
|
return 1;
|
||||||
@ -2248,6 +2265,7 @@ assert_connection_ok(connection_t *conn, time_t now)
|
|||||||
{
|
{
|
||||||
case CONN_TYPE_OR_LISTENER:
|
case CONN_TYPE_OR_LISTENER:
|
||||||
case CONN_TYPE_AP_LISTENER:
|
case CONN_TYPE_AP_LISTENER:
|
||||||
|
case CONN_TYPE_AP_TRANS_LISTENER:
|
||||||
case CONN_TYPE_DIR_LISTENER:
|
case CONN_TYPE_DIR_LISTENER:
|
||||||
case CONN_TYPE_CONTROL_LISTENER:
|
case CONN_TYPE_CONTROL_LISTENER:
|
||||||
tor_assert(conn->state == LISTENER_STATE_READY);
|
tor_assert(conn->state == LISTENER_STATE_READY);
|
||||||
|
@ -17,6 +17,7 @@ const char connection_edge_c_id[] =
|
|||||||
static smartlist_t *redirect_exit_list = NULL;
|
static smartlist_t *redirect_exit_list = NULL;
|
||||||
|
|
||||||
static int connection_ap_handshake_process_socks(edge_connection_t *conn);
|
static int connection_ap_handshake_process_socks(edge_connection_t *conn);
|
||||||
|
static int connection_ap_process_transparent(edge_connection_t *conn);
|
||||||
|
|
||||||
/** An AP stream has failed/finished. If it hasn't already sent back
|
/** An AP stream has failed/finished. If it hasn't already sent back
|
||||||
* a socks reply, send one now (based on endreason). Also set
|
* a socks reply, send one now (based on endreason). Also set
|
||||||
@ -80,6 +81,7 @@ connection_edge_reached_eof(edge_connection_t *conn)
|
|||||||
/** Handle new bytes on conn->inbuf based on state:
|
/** Handle new bytes on conn->inbuf based on state:
|
||||||
* - If it's waiting for socks info, try to read another step of the
|
* - If it's waiting for socks info, try to read another step of the
|
||||||
* socks handshake out of conn->inbuf.
|
* socks handshake out of conn->inbuf.
|
||||||
|
* - If it's waiting for the original destination, fetch it.
|
||||||
* - If it's open, then package more relay cells from the stream.
|
* - If it's open, then package more relay cells from the stream.
|
||||||
* - Else, leave the bytes on inbuf alone for now.
|
* - Else, leave the bytes on inbuf alone for now.
|
||||||
*
|
*
|
||||||
@ -98,6 +100,12 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
case AP_CONN_STATE_ORIGDST_WAIT:
|
||||||
|
if (connection_ap_process_transparent(conn) < 0) {
|
||||||
|
/* already marked */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
case AP_CONN_STATE_OPEN:
|
case AP_CONN_STATE_OPEN:
|
||||||
case EXIT_CONN_STATE_OPEN:
|
case EXIT_CONN_STATE_OPEN:
|
||||||
if (connection_edge_package_raw_inbuf(conn, package_partial) < 0) {
|
if (connection_edge_package_raw_inbuf(conn, package_partial) < 0) {
|
||||||
@ -234,6 +242,7 @@ connection_edge_finished_flushing(edge_connection_t *conn)
|
|||||||
connection_edge_consider_sending_sendme(conn);
|
connection_edge_consider_sending_sendme(conn);
|
||||||
return 0;
|
return 0;
|
||||||
case AP_CONN_STATE_SOCKS_WAIT:
|
case AP_CONN_STATE_SOCKS_WAIT:
|
||||||
|
case AP_CONN_STATE_ORIGDST_WAIT:
|
||||||
case AP_CONN_STATE_RENDDESC_WAIT:
|
case AP_CONN_STATE_RENDDESC_WAIT:
|
||||||
case AP_CONN_STATE_CIRCUIT_WAIT:
|
case AP_CONN_STATE_CIRCUIT_WAIT:
|
||||||
case AP_CONN_STATE_CONNECT_WAIT:
|
case AP_CONN_STATE_CONNECT_WAIT:
|
||||||
@ -1216,6 +1225,89 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
|
|||||||
return 0; /* unreached but keeps the compiler happy */
|
return 0; /* unreached but keeps the compiler happy */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Fetch the original destination address and port from a
|
||||||
|
* system-specific interface and put them into a
|
||||||
|
* socks_request_t as if they came from a socks request.
|
||||||
|
*
|
||||||
|
* Return -1 if an error prevents fetching the destination,
|
||||||
|
* else return 0.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
connection_ap_get_original_destination(edge_connection_t *conn,
|
||||||
|
socks_request_t *req)
|
||||||
|
{
|
||||||
|
#ifdef TRANS_NETFILTER
|
||||||
|
/* Linux 2.4+ */
|
||||||
|
struct sockaddr_in orig_dst;
|
||||||
|
socklen_t orig_dst_len = sizeof(orig_dst);
|
||||||
|
char tmpbuf[INET_NTOA_BUF_LEN];
|
||||||
|
|
||||||
|
if (getsockopt(conn->_base.s, SOL_IP, SO_ORIGINAL_DST,
|
||||||
|
(struct sockaddr*)&orig_dst, &orig_dst_len) < 0) {
|
||||||
|
int e = tor_socket_errno(conn->_base.s);
|
||||||
|
log_warn(LD_NET, "getsockopt() failed: %s", tor_socket_strerror(e));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tor_inet_ntoa(&orig_dst.sin_addr, tmpbuf, sizeof(tmpbuf));
|
||||||
|
strlcpy(req->address, tmpbuf, sizeof(req->address));
|
||||||
|
req->port = ntohs(orig_dst.sin_port);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TRANS_PF
|
||||||
|
struct sockaddr_in proxy_addr;
|
||||||
|
socklen_t proxy_addr_len = sizeof(proxy_addr);
|
||||||
|
char tmpbuf[INET_NTOA_BUF_LEN];
|
||||||
|
struct pfioc_natlook pnl;
|
||||||
|
int pf = -1;
|
||||||
|
|
||||||
|
if (getsockname(conn->_base.s, (struct sockaddr*)&proxy_addr,
|
||||||
|
&proxy_addr_len) < 0) {
|
||||||
|
int e = tor_socket_errno(conn->_base.s);
|
||||||
|
log_warn(LD_NET, "getsockname() failed: %s", tor_socket_strerror(e));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&pnl, 0, sizeof(pnl));
|
||||||
|
pnl.af = AF_INET;
|
||||||
|
pnl.proto = IPPROTO_TCP;
|
||||||
|
pnl.direction = PF_OUT;
|
||||||
|
pnl.saddr.v4.s_addr = htonl(conn->_base.addr);
|
||||||
|
pnl.sport = htons(conn->_base.port);
|
||||||
|
pnl.daddr.v4.s_addr = proxy_addr.sin_addr.s_addr;
|
||||||
|
pnl.dport = proxy_addr.sin_port;
|
||||||
|
|
||||||
|
/* XXX We should open the /dev/pf device once and close it at cleanup time
|
||||||
|
* instead of reopening it for every connection. Ideally, it should be
|
||||||
|
* opened before dropping privs. */
|
||||||
|
#ifdef OPENBSD
|
||||||
|
/* only works on OpenBSD */
|
||||||
|
pf = open("/dev/pf", O_RDONLY);
|
||||||
|
#else
|
||||||
|
/* works on NetBSD and FreeBSD */
|
||||||
|
pf = open("/dev/pf", O_RDWR);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (pf < 0) {
|
||||||
|
log_warn(LD_NET, "open(\"/dev/pf\") failed: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(pf, DIOCNATLOOK, &pnl) < 0) {
|
||||||
|
log_warn(LD_NET, "ioctl(DIOCNATLOOK) failed: %s", strerror(errno));
|
||||||
|
close(pf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(pf);
|
||||||
|
|
||||||
|
tor_inet_ntoa(&pnl.rdaddr.v4, tmpbuf, sizeof(tmpbuf));
|
||||||
|
strlcpy(req->address, tmpbuf, sizeof(req->address));
|
||||||
|
req->port = ntohs(pnl.rdport);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** connection_edge_process_inbuf() found a conn in state
|
/** connection_edge_process_inbuf() found a conn in state
|
||||||
* socks_wait. See if conn->inbuf has the right bytes to proceed with
|
* socks_wait. See if conn->inbuf has the right bytes to proceed with
|
||||||
* the socks handshake.
|
* the socks handshake.
|
||||||
@ -1278,6 +1370,48 @@ connection_ap_handshake_process_socks(edge_connection_t *conn)
|
|||||||
return connection_ap_handshake_rewrite_and_attach(conn, NULL);
|
return connection_ap_handshake_rewrite_and_attach(conn, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** connection_edge_process_inbuf() found a conn in state
|
||||||
|
* origdst_wait. Get the original destination and
|
||||||
|
* send it to connection_ap_handshake_rewrite_and_attach().
|
||||||
|
*
|
||||||
|
* Return -1 if an unexpected error with conn (and it should be marked
|
||||||
|
* for close), else return 0.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
connection_ap_process_transparent(edge_connection_t *conn)
|
||||||
|
{
|
||||||
|
socks_request_t *socks;
|
||||||
|
or_options_t *options = get_options();
|
||||||
|
|
||||||
|
tor_assert(conn);
|
||||||
|
tor_assert(conn->_base.type == CONN_TYPE_AP);
|
||||||
|
tor_assert(conn->_base.state == AP_CONN_STATE_ORIGDST_WAIT);
|
||||||
|
tor_assert(conn->socks_request);
|
||||||
|
socks = conn->socks_request;
|
||||||
|
|
||||||
|
/* pretend that a socks handshake completed so we don't try to
|
||||||
|
* send a socks reply down a transparent conn */
|
||||||
|
socks->command = SOCKS_COMMAND_CONNECT;
|
||||||
|
socks->has_finished = 1;
|
||||||
|
|
||||||
|
log_debug(LD_APP,"entered.");
|
||||||
|
|
||||||
|
if (connection_ap_get_original_destination(conn, socks) < 0) {
|
||||||
|
log_warn(LD_APP,"Fetching original destination failed. Closing.");
|
||||||
|
connection_mark_unattached_ap(conn, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* we have the original destination */
|
||||||
|
|
||||||
|
control_event_stream_status(conn, STREAM_EVENT_NEW);
|
||||||
|
|
||||||
|
if (options->LeaveStreamsUnattached) {
|
||||||
|
conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return connection_ap_handshake_rewrite_and_attach(conn, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/** Iterate over the two bytes of stream_id until we get one that is not
|
/** Iterate over the two bytes of stream_id until we get one that is not
|
||||||
* already in use; return it. Return 0 if can't get a unique stream_id.
|
* already in use; return it. Return 0 if can't get a unique stream_id.
|
||||||
*/
|
*/
|
||||||
|
@ -1423,7 +1423,8 @@ handle_getinfo_helper(const char *question, char **answer)
|
|||||||
origin_circuit_t *origin_circ = NULL;
|
origin_circuit_t *origin_circ = NULL;
|
||||||
if (conns[i]->type != CONN_TYPE_AP ||
|
if (conns[i]->type != CONN_TYPE_AP ||
|
||||||
conns[i]->marked_for_close ||
|
conns[i]->marked_for_close ||
|
||||||
conns[i]->state == AP_CONN_STATE_SOCKS_WAIT)
|
conns[i]->state == AP_CONN_STATE_SOCKS_WAIT ||
|
||||||
|
conns[i]->state == AP_CONN_STATE_ORIGDST_WAIT)
|
||||||
continue;
|
continue;
|
||||||
conn = TO_EDGE_CONN(conns[i]);
|
conn = TO_EDGE_CONN(conns[i]);
|
||||||
switch (conn->_base.state)
|
switch (conn->_base.state)
|
||||||
|
@ -712,6 +712,7 @@ hibernate_begin(int new_state, time_t now)
|
|||||||
/* close listeners. leave control listener(s). */
|
/* close listeners. leave control listener(s). */
|
||||||
while ((conn = connection_get_by_type(CONN_TYPE_OR_LISTENER)) ||
|
while ((conn = connection_get_by_type(CONN_TYPE_OR_LISTENER)) ||
|
||||||
(conn = connection_get_by_type(CONN_TYPE_AP_LISTENER)) ||
|
(conn = connection_get_by_type(CONN_TYPE_AP_LISTENER)) ||
|
||||||
|
(conn = connection_get_by_type(CONN_TYPE_AP_TRANS_LISTENER)) ||
|
||||||
(conn = connection_get_by_type(CONN_TYPE_DIR_LISTENER))) {
|
(conn = connection_get_by_type(CONN_TYPE_DIR_LISTENER))) {
|
||||||
log_info(LD_NET,"Closing listener type %d", conn->type);
|
log_info(LD_NET,"Closing listener type %d", conn->type);
|
||||||
connection_mark_for_close(conn);
|
connection_mark_for_close(conn);
|
||||||
|
21
src/or/or.h
21
src/or/or.h
@ -113,6 +113,15 @@
|
|||||||
#error "Tor requires libevent to build."
|
#error "Tor requires libevent to build."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TRANS_NETFILTER
|
||||||
|
#include <linux/netfilter_ipv4.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TRANS_PF
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/pfvar.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../common/crypto.h"
|
#include "../common/crypto.h"
|
||||||
#include "../common/tortls.h"
|
#include "../common/tortls.h"
|
||||||
#include "../common/log.h"
|
#include "../common/log.h"
|
||||||
@ -215,7 +224,9 @@ typedef enum {
|
|||||||
#define CONN_TYPE_CONTROL_LISTENER 12
|
#define CONN_TYPE_CONTROL_LISTENER 12
|
||||||
/** Type for connections from user interface process. */
|
/** Type for connections from user interface process. */
|
||||||
#define CONN_TYPE_CONTROL 13
|
#define CONN_TYPE_CONTROL 13
|
||||||
#define _CONN_TYPE_MAX 13
|
/** Type for sockets listening for transparent proxy connections. */
|
||||||
|
#define CONN_TYPE_AP_TRANS_LISTENER 14
|
||||||
|
#define _CONN_TYPE_MAX 14
|
||||||
|
|
||||||
#define CONN_IS_EDGE(x) \
|
#define CONN_IS_EDGE(x) \
|
||||||
((x)->type == CONN_TYPE_EXIT || (x)->type == CONN_TYPE_AP)
|
((x)->type == CONN_TYPE_EXIT || (x)->type == CONN_TYPE_AP)
|
||||||
@ -283,7 +294,10 @@ typedef enum {
|
|||||||
#define AP_CONN_STATE_RESOLVE_WAIT 10
|
#define AP_CONN_STATE_RESOLVE_WAIT 10
|
||||||
/** State for a SOCKS connection: ready to send and receive. */
|
/** State for a SOCKS connection: ready to send and receive. */
|
||||||
#define AP_CONN_STATE_OPEN 11
|
#define AP_CONN_STATE_OPEN 11
|
||||||
#define _AP_CONN_STATE_MAX 11
|
/** State for a transparent proxy connection: waiting for original
|
||||||
|
* destination. */
|
||||||
|
#define AP_CONN_STATE_ORIGDST_WAIT 12
|
||||||
|
#define _AP_CONN_STATE_MAX 12
|
||||||
|
|
||||||
#define _DIR_CONN_STATE_MIN 1
|
#define _DIR_CONN_STATE_MIN 1
|
||||||
/** State for connection to directory server: waiting for connect(). */
|
/** State for connection to directory server: waiting for connect(). */
|
||||||
@ -1386,6 +1400,8 @@ typedef struct {
|
|||||||
config_line_t *DirPolicy; /**< Lists of dir policy components */
|
config_line_t *DirPolicy; /**< Lists of dir policy components */
|
||||||
/** Addresses to bind for listening for SOCKS connections. */
|
/** Addresses to bind for listening for SOCKS connections. */
|
||||||
config_line_t *SocksListenAddress;
|
config_line_t *SocksListenAddress;
|
||||||
|
/** Addresses to bind for listening for transparent connections. */
|
||||||
|
config_line_t *TransListenAddress;
|
||||||
/** Addresses to bind for listening for OR connections. */
|
/** Addresses to bind for listening for OR connections. */
|
||||||
config_line_t *ORListenAddress;
|
config_line_t *ORListenAddress;
|
||||||
/** Addresses to bind for listening for directory connections. */
|
/** Addresses to bind for listening for directory connections. */
|
||||||
@ -1407,6 +1423,7 @@ typedef struct {
|
|||||||
* length (alpha in geometric distribution). */
|
* length (alpha in geometric distribution). */
|
||||||
int ORPort; /**< Port to listen on for OR connections. */
|
int ORPort; /**< Port to listen on for OR connections. */
|
||||||
int SocksPort; /**< Port to listen on for SOCKS connections. */
|
int SocksPort; /**< Port to listen on for SOCKS connections. */
|
||||||
|
int TransPort; /**< Port to listen on for transparent connections. */
|
||||||
int ControlPort; /**< Port to listen on for control connections. */
|
int ControlPort; /**< Port to listen on for control connections. */
|
||||||
int DirPort; /**< Port to listen on for directory connections. */
|
int DirPort; /**< Port to listen on for directory connections. */
|
||||||
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
|
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
|
||||||
|
@ -845,7 +845,9 @@ connection_edge_process_relay_cell_not_open(
|
|||||||
conn->chosen_exit_name, ttl);
|
conn->chosen_exit_name, ttl);
|
||||||
}
|
}
|
||||||
circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
|
circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
|
||||||
connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_SUCCEEDED);
|
/* don't send a socks reply to transparent conns */
|
||||||
|
if (!conn->socks_request->has_finished)
|
||||||
|
connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_SUCCEEDED);
|
||||||
/* handle anything that might have queued */
|
/* handle anything that might have queued */
|
||||||
if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
|
if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
|
||||||
/* (We already sent an end cell if possible) */
|
/* (We already sent an end cell if possible) */
|
||||||
|
Loading…
Reference in New Issue
Block a user