Merge branch '10267_plus_10896_rebased_twice'

This commit is contained in:
Nick Mathewson
2014-04-16 23:03:41 -04:00
6 changed files with 115 additions and 18 deletions
+14 -1
View File
@@ -1089,7 +1089,8 @@ options_act_reversible(const or_options_t *old_options, char **msg)
#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
/* Open /dev/pf before dropping privileges. */
if (options->TransPort_set) {
if (options->TransPort_set &&
options->TransProxyType_parsed == TPT_DEFAULT) {
if (get_pf_socket() < 0) {
*msg = tor_strdup("Unable to open /dev/pf for transparent proxy.");
goto rollback;
@@ -2553,11 +2554,23 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->TransProxyType) {
if (!strcasecmp(options->TransProxyType, "default")) {
options->TransProxyType_parsed = TPT_DEFAULT;
} else if (!strcasecmp(options->TransProxyType, "pf-divert")) {
#ifndef __OpenBSD__
REJECT("pf-divert is a OpenBSD-specific feature.");
#else
options->TransProxyType_parsed = TPT_PF_DIVERT;
#endif
} else if (!strcasecmp(options->TransProxyType, "tproxy")) {
#ifndef __linux__
REJECT("TPROXY is a Linux-specific feature.");
#else
options->TransProxyType_parsed = TPT_TPROXY;
#endif
} else if (!strcasecmp(options->TransProxyType, "ipfw")) {
#ifndef __FreeBSD__
REJECT("ipfw is a FreeBSD-specific feature.");
#else
options->TransProxyType_parsed = TPT_IPFW;
#endif
} else {
REJECT("Unrecognized value for TransProxyType");
+70 -12
View File
@@ -1391,35 +1391,48 @@ get_pf_socket(void)
}
#endif
/** 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.
*/
#if defined(TRANS_NETFILTER) || defined(TRANS_PF)
/** Try fill in the address of <b>req</b> from the socket configured
* with <b>conn</b>. */
static int
connection_ap_get_original_destination(entry_connection_t *conn,
socks_request_t *req)
destination_from_socket(entry_connection_t *conn, socks_request_t *req)
{
#ifdef TRANS_NETFILTER
/* Linux 2.4+ */
struct sockaddr_storage orig_dst;
socklen_t orig_dst_len = sizeof(orig_dst);
tor_addr_t addr;
#ifdef TRANS_NETFILTER
if (getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IP, SO_ORIGINAL_DST,
(struct sockaddr*)&orig_dst, &orig_dst_len) < 0) {
int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
log_warn(LD_NET, "getsockopt() failed: %s", tor_socket_strerror(e));
return -1;
}
#elif defined(TRANS_PF)
if (getsockname(ENTRY_TO_CONN(conn)->s, (struct sockaddr*)&orig_dst,
&orig_dst_len) < 0) {
int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
log_warn(LD_NET, "getsockname() failed: %s", tor_socket_strerror(e));
return -1;
}
#else
(void)conn;
(void)req;
log_warn(LD_BUG, "Unable to determine destination from socket.");
return -1;
#endif
tor_addr_from_sockaddr(&addr, (struct sockaddr*)&orig_dst, &req->port);
tor_addr_to_str(req->address, &addr, sizeof(req->address), 1);
return 0;
#elif defined(TRANS_PF)
}
#endif
#ifdef TRANS_PF
static int
destination_from_pf(entry_connection_t *conn, socks_request_t *req)
{
struct sockaddr_storage proxy_addr;
socklen_t proxy_addr_len = sizeof(proxy_addr);
struct sockaddr *proxy_sa = (struct sockaddr*) &proxy_addr;
@@ -1435,6 +1448,21 @@ connection_ap_get_original_destination(entry_connection_t *conn,
return -1;
}
#ifdef __FreeBSD__
if (get_options()->TransProxyType_parsed == TPT_IPFW) {
/* ipfw(8) is used and in this case getsockname returned the original
destination */
if (tor_addr_from_sockaddr(&addr, proxy_sa, &req->port) < 0) {
tor_fragile_assert();
return -1;
}
tor_addr_to_str(req->address, &addr, sizeof(req->address), 0);
return 0;
}
#endif
memset(&pnl, 0, sizeof(pnl));
pnl.proto = IPPROTO_TCP;
pnl.direction = PF_OUT;
@@ -1481,6 +1509,36 @@ connection_ap_get_original_destination(entry_connection_t *conn,
req->port = ntohs(pnl.rdport);
return 0;
}
#endif
/** 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(entry_connection_t *conn,
socks_request_t *req)
{
#ifdef TRANS_NETFILTER
return destination_from_socket(conn, req);
#elif defined(TRANS_PF)
const or_options_t *options = get_options();
if (options->TransProxyType_parsed == TPT_PF_DIVERT)
return destination_from_socket(conn, req);
if (options->TransProxyType_parsed == TPT_DEFAULT)
return destination_from_pf(conn, req);
(void)conn;
(void)req;
log_warn(LD_BUG, "Proxy destination determination mechanism %s unknown.",
options->TransProxyType);
return -1;
#else
(void)conn;
(void)req;
+6 -1
View File
@@ -3473,7 +3473,12 @@ typedef struct {
const char *TransProxyType; /**< What kind of transparent proxy
* implementation are we using? */
/** Parsed value of TransProxyType. */
enum { TPT_DEFAULT, TPT_TPROXY } TransProxyType_parsed;
enum {
TPT_DEFAULT,
TPT_PF_DIVERT,
TPT_IPFW,
TPT_TPROXY,
} TransProxyType_parsed;
config_line_t *NATDPort_lines; /**< Ports to listen on for transparent natd
* connections. */
config_line_t *ControlPort_lines; /**< Ports to listen on for control