mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 14:51:11 +01:00
Merge branch '10267_plus_10896_rebased_twice'
This commit is contained in:
commit
973661394a
6 changed files with 115 additions and 18 deletions
4
changes/10267_tproxy
Normal file
4
changes/10267_tproxy
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
o Minor features:
|
||||||
|
- Support the ipfw firewall interface for transparent proxy support on
|
||||||
|
FreeBSD. To enable it, set "TransProxyType ipfw" in your torrc.
|
||||||
|
Resolves ticket 10267; patch from "yurivict".
|
8
changes/10896
Normal file
8
changes/10896
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
o Minor features:
|
||||||
|
- Support OpenBSD's divert-to rules with the pf firewall, when
|
||||||
|
"TransProxyType pf-divert" is specified. This allows Tor to run a
|
||||||
|
TransPort transparent proxy port on OpenBSD 4.4 or later without
|
||||||
|
root privileges. See the pf.conf(5) manual page for information on
|
||||||
|
configuring pf to use divert-to rules. Closes ticket 10896; patch
|
||||||
|
from Dana Koch.
|
||||||
|
|
|
@ -1196,20 +1196,29 @@ The following options are useful only for clients (that is, if
|
||||||
compatibility, TransListenAddress is only allowed when TransPort is just
|
compatibility, TransListenAddress is only allowed when TransPort is just
|
||||||
a port number.)
|
a port number.)
|
||||||
|
|
||||||
[[TransProxyType]] **TransProxyTYpe** **default**|**TPROXY**::
|
[[TransProxyType]] **TransProxyTYpe** **default**|**TPROXY**|**ipfw**|**pf-divert**::
|
||||||
TransProxyType may only be enabled when there is transparent proxy listener
|
TransProxyType may only be enabled when there is transparent proxy listener
|
||||||
enabled.
|
enabled.
|
||||||
+
|
+
|
||||||
Set this to TPROXY if you wish to be able to use the TPROXY Linux module to
|
Set this to "TPROXY" if you wish to be able to use the TPROXY Linux module
|
||||||
transparently proxy connections that are configured using the TransPort
|
to transparently proxy connections that are configured using the TransPort
|
||||||
option. This setting lets the listener on the TransPort accept connections
|
option. This setting lets the listener on the TransPort accept connections
|
||||||
for all addresses, even when the TransListenAddress is configured for an
|
for all addresses, even when the TransListenAddress is configured for an
|
||||||
internal address. Detailed information on how to configure the TPROXY
|
internal address. Detailed information on how to configure the TPROXY
|
||||||
feature can be found in the Linux kernel source tree in the file
|
feature can be found in the Linux kernel source tree in the file
|
||||||
Documentation/networking/tproxy.txt.
|
Documentation/networking/tproxy.txt.
|
||||||
|
+
|
||||||
|
Set this option to "ipfw" to use the FreeBSD ipfw interface.
|
||||||
|
+
|
||||||
|
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
|
Set this to "default", or leave it unconfigured, to use regular IPTables
|
||||||
on Linux, or to use pf on the *BSD operating systems.
|
on Linux, or to use pf +rdr-to+ rules on *BSD systems.
|
||||||
+
|
+
|
||||||
(Default: "default".)
|
(Default: "default".)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
|
||||||
/* Open /dev/pf before dropping privileges. */
|
/* Open /dev/pf before dropping privileges. */
|
||||||
if (options->TransPort_set) {
|
if (options->TransPort_set &&
|
||||||
|
options->TransProxyType_parsed == TPT_DEFAULT) {
|
||||||
if (get_pf_socket() < 0) {
|
if (get_pf_socket() < 0) {
|
||||||
*msg = tor_strdup("Unable to open /dev/pf for transparent proxy.");
|
*msg = tor_strdup("Unable to open /dev/pf for transparent proxy.");
|
||||||
goto rollback;
|
goto rollback;
|
||||||
|
@ -2553,11 +2554,23 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||||
if (options->TransProxyType) {
|
if (options->TransProxyType) {
|
||||||
if (!strcasecmp(options->TransProxyType, "default")) {
|
if (!strcasecmp(options->TransProxyType, "default")) {
|
||||||
options->TransProxyType_parsed = TPT_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")) {
|
} else if (!strcasecmp(options->TransProxyType, "tproxy")) {
|
||||||
#ifndef __linux__
|
#ifndef __linux__
|
||||||
REJECT("TPROXY is a Linux-specific feature.");
|
REJECT("TPROXY is a Linux-specific feature.");
|
||||||
#else
|
#else
|
||||||
options->TransProxyType_parsed = TPT_TPROXY;
|
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
|
#endif
|
||||||
} else {
|
} else {
|
||||||
REJECT("Unrecognized value for TransProxyType");
|
REJECT("Unrecognized value for TransProxyType");
|
||||||
|
|
|
@ -1391,35 +1391,48 @@ get_pf_socket(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Fetch the original destination address and port from a
|
#if defined(TRANS_NETFILTER) || defined(TRANS_PF)
|
||||||
* system-specific interface and put them into a
|
/** Try fill in the address of <b>req</b> from the socket configured
|
||||||
* socks_request_t as if they came from a socks request.
|
* with <b>conn</b>. */
|
||||||
*
|
|
||||||
* Return -1 if an error prevents fetching the destination,
|
|
||||||
* else return 0.
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
connection_ap_get_original_destination(entry_connection_t *conn,
|
destination_from_socket(entry_connection_t *conn, socks_request_t *req)
|
||||||
socks_request_t *req)
|
|
||||||
{
|
{
|
||||||
#ifdef TRANS_NETFILTER
|
|
||||||
/* Linux 2.4+ */
|
|
||||||
struct sockaddr_storage orig_dst;
|
struct sockaddr_storage orig_dst;
|
||||||
socklen_t orig_dst_len = sizeof(orig_dst);
|
socklen_t orig_dst_len = sizeof(orig_dst);
|
||||||
tor_addr_t addr;
|
tor_addr_t addr;
|
||||||
|
|
||||||
|
#ifdef TRANS_NETFILTER
|
||||||
if (getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IP, SO_ORIGINAL_DST,
|
if (getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IP, SO_ORIGINAL_DST,
|
||||||
(struct sockaddr*)&orig_dst, &orig_dst_len) < 0) {
|
(struct sockaddr*)&orig_dst, &orig_dst_len) < 0) {
|
||||||
int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
|
int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
|
||||||
log_warn(LD_NET, "getsockopt() failed: %s", tor_socket_strerror(e));
|
log_warn(LD_NET, "getsockopt() failed: %s", tor_socket_strerror(e));
|
||||||
return -1;
|
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_from_sockaddr(&addr, (struct sockaddr*)&orig_dst, &req->port);
|
||||||
tor_addr_to_str(req->address, &addr, sizeof(req->address), 1);
|
tor_addr_to_str(req->address, &addr, sizeof(req->address), 1);
|
||||||
|
|
||||||
return 0;
|
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;
|
struct sockaddr_storage proxy_addr;
|
||||||
socklen_t proxy_addr_len = sizeof(proxy_addr);
|
socklen_t proxy_addr_len = sizeof(proxy_addr);
|
||||||
struct sockaddr *proxy_sa = (struct sockaddr*) &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;
|
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));
|
memset(&pnl, 0, sizeof(pnl));
|
||||||
pnl.proto = IPPROTO_TCP;
|
pnl.proto = IPPROTO_TCP;
|
||||||
pnl.direction = PF_OUT;
|
pnl.direction = PF_OUT;
|
||||||
|
@ -1481,6 +1509,36 @@ connection_ap_get_original_destination(entry_connection_t *conn,
|
||||||
req->port = ntohs(pnl.rdport);
|
req->port = ntohs(pnl.rdport);
|
||||||
|
|
||||||
return 0;
|
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
|
#else
|
||||||
(void)conn;
|
(void)conn;
|
||||||
(void)req;
|
(void)req;
|
||||||
|
|
|
@ -3473,7 +3473,12 @@ typedef struct {
|
||||||
const char *TransProxyType; /**< What kind of transparent proxy
|
const char *TransProxyType; /**< What kind of transparent proxy
|
||||||
* implementation are we using? */
|
* implementation are we using? */
|
||||||
/** Parsed value of TransProxyType. */
|
/** 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
|
config_line_t *NATDPort_lines; /**< Ports to listen on for transparent natd
|
||||||
* connections. */
|
* connections. */
|
||||||
config_line_t *ControlPort_lines; /**< Ports to listen on for control
|
config_line_t *ControlPort_lines; /**< Ports to listen on for control
|
||||||
|
|
Loading…
Add table
Reference in a new issue