aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/tor.1.txt17
-rw-r--r--src/or/config.c8
-rw-r--r--src/or/connection_edge.c64
-rw-r--r--src/or/or.h7
4 files changed, 76 insertions, 20 deletions
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 1a5ced8496..d1556a5541 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -1196,12 +1196,12 @@ The following options are useful only for clients (that is, if
compatibility, TransListenAddress is only allowed when TransPort is just
a port number.)
-[[TransProxyType]] **TransProxyTYpe** **default**|**TPROXY**|**ipfw**::
+[[TransProxyType]] **TransProxyTYpe** **default**|**TPROXY**|**ipfw**|**pf-divert**::
TransProxyType may only be enabled when there is transparent proxy listener
enabled.
+
- Set this to TPROXY if you wish to be able to use the TPROXY Linux module to
- transparently proxy connections that are configured using the TransPort
+ Set this to "TPROXY" if you wish to be able to use the TPROXY Linux module
+ to transparently proxy connections that are configured using the TransPort
option. This setting lets the listener on the TransPort accept connections
for all addresses, even when the TransListenAddress is configured for an
internal address. Detailed information on how to configure the TPROXY
@@ -1210,8 +1210,15 @@ The following options are useful only for clients (that is, if
+
Set this option to "ipfw" to use the FreeBSD ipfw interface.
+
- Set this option to "default", or leave it unconfigured, to use regular
- IPTables on Linux, or to use pf on the *BSD operating systems.
+ On *BSD operating systems when using pf, set this to "pf-divert" to take
+ advantage of +divert-to+ rules, which do not modify the packets like
+ +rdr-to+ rules do. Detailed information on how to configure pf to use
+ +divert-to+ rules can be found in the pf.conf(5) manual page. On OpenBSD,
+ +divert-to+ is available to use on versions greater than or equal to
+ OpenBSD 4.4.
+ +
+ Set this to "default", or leave it unconfigured, to use regular IPTables
+ on Linux, or to use pf +rdr-to+ rules on *BSD systems.
+
(Default: "default".)
diff --git a/src/or/config.c b/src/or/config.c
index 55a23b1ce3..e22d3b86e0 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -1089,7 +1089,7 @@ 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 && options->TransProxyType_parsed != TPT_IPFW) {
+ 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,6 +2553,12 @@ 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")) {
+#ifdef __linux__
+ REJECT("pf is a BSD-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.");
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 2ece2e44e3..04e60b9139 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -1391,35 +1391,43 @@ 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.
- */
-static int
-connection_ap_get_original_destination(entry_connection_t *conn,
- socks_request_t *req)
+static int
+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)
+}
+
+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;
@@ -1496,6 +1504,36 @@ connection_ap_get_original_destination(entry_connection_t *conn,
req->port = ntohs(pnl.rdport);
return 0;
+}
+
+
+/** 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;
diff --git a/src/or/or.h b/src/or/or.h
index a5e2e7069d..5510af723e 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3461,7 +3461,12 @@ typedef struct {
const char *TransProxyType; /**< What kind of transparent proxy
* implementation are we using? */
/** Parsed value of TransProxyType. */
- enum { TPT_DEFAULT, TPT_TPROXY, TPT_IPFW } 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