diff --git a/changes/10267_tproxy b/changes/10267_tproxy new file mode 100644 index 0000000000..f65e4a2c5d --- /dev/null +++ b/changes/10267_tproxy @@ -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". diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 1cc8f841ce..1a5ced8496 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -1196,7 +1196,7 @@ 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**:: +[[TransProxyType]] **TransProxyTYpe** **default**|**TPROXY**|**ipfw**:: TransProxyType may only be enabled when there is transparent proxy listener enabled. + @@ -1208,8 +1208,10 @@ The following options are useful only for clients (that is, if feature can be found in the Linux kernel source tree in the file Documentation/networking/tproxy.txt. + - Set this to "default", or leave it unconfigured, to use regular IPTables - on Linux, or to use pf on the *BSD operating systems. + 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. + (Default: "default".) diff --git a/src/or/config.c b/src/or/config.c index 4a6b30172c..55a23b1ce3 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) { + if (options->TransPort_set && options->TransProxyType_parsed != TPT_IPFW) { if (get_pf_socket() < 0) { *msg = tor_strdup("Unable to open /dev/pf for transparent proxy."); goto rollback; @@ -2558,6 +2558,12 @@ options_validate(or_options_t *old_options, or_options_t *options, 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"); diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 41ca6119b0..ddeac10381 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1435,6 +1435,29 @@ 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 (proxy_sa->sa_family == AF_INET) { + struct sockaddr_in *dest_addr4 = (struct sockaddr_in *)proxy_sa; + tor_addr_from_ipv4n(&addr, dest_addr4->sin_addr.s_addr); + req->port = ntohs(dest_addr4->sin_port); + } else if (proxy_sa->sa_family == AF_INET6) { + struct sockaddr_in6 *dest_addr6 = (struct sockaddr_in6 *)proxy_sa; + tor_addr_from_in6(&addr, &dest_addr6->sin6_addr); + req->port = ntohs(dest_addr6->sin6_port); + } else { + 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; diff --git a/src/or/or.h b/src/or/or.h index 38ab1767e0..a5e2e7069d 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3461,7 +3461,7 @@ 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_TPROXY, TPT_IPFW } 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