Explorar el Código

ipfw TransPort support on FreeBSD (10267)

This isn't on by default; to get it, you need to set "TransProxyType
ipfw".  (The original patch had automatic detection for whether
/dev/pf is present and openable, but that seems marginally fragile.)
Nick Mathewson hace 10 años
padre
commit
3e4680f312
Se han modificado 5 ficheros con 40 adiciones y 5 borrados
  1. 4 0
      changes/10267_tproxy
  2. 5 3
      doc/tor.1.txt
  3. 7 1
      src/or/config.c
  4. 23 0
      src/or/connection_edge.c
  5. 1 1
      src/or/or.h

+ 4 - 0
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".

+ 5 - 3
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
     compatibility, TransListenAddress is only allowed when TransPort is just
     a port number.)
     a port number.)
 
 
-[[TransProxyType]] **TransProxyTYpe** **default**|**TPROXY**::
+[[TransProxyType]] **TransProxyTYpe** **default**|**TPROXY**|**ipfw**::
     TransProxyType may only be enabled when there is transparent proxy listener
     TransProxyType may only be enabled when there is transparent proxy listener
     enabled.
     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
     feature can be found in the Linux kernel source tree in the file
     Documentation/networking/tproxy.txt.
     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".)
     (Default: "default".)
 
 

+ 7 - 1
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)
 #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_IPFW) {
     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;
@@ -2558,6 +2558,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
       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");

+ 23 - 0
src/or/connection_edge.c

@@ -1435,6 +1435,29 @@ 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 (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));
   memset(&pnl, 0, sizeof(pnl));
   pnl.proto           = IPPROTO_TCP;
   pnl.proto           = IPPROTO_TCP;
   pnl.direction       = PF_OUT;
   pnl.direction       = PF_OUT;

+ 1 - 1
src/or/or.h

@@ -3461,7 +3461,7 @@ 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_TPROXY, TPT_IPFW } 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