diff -ru httpd-2.2.14.original/include/ap_listen.h httpd-2.2.14.just_tproxy/include/ap_listen.h
--- httpd-2.2.14.original/include/ap_listen.h	2007-05-09 21:35:45.000000000 +0200
+++ httpd-2.2.14.just_tproxy/include/ap_listen.h	2010-03-01 11:13:56.000000000 +0100
@@ -68,6 +68,10 @@
      * The default protocol for this listening socket.
      */
     const char* protocol;
+    /**
+     * Set IP_TRANSPARENT option for socket (tproxy support)
+     */
+    int transparent;
 };
 
 /**
diff -ru httpd-2.2.14.original/modules/proxy/mod_proxy.c httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy.c
--- httpd-2.2.14.original/modules/proxy/mod_proxy.c	2009-01-31 21:58:07.000000000 +0100
+++ httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy.c	2010-03-01 11:13:55.000000000 +0100
@@ -1133,6 +1133,8 @@
     ps->proxy_status = (overrides->proxy_status_set == 0) ? base->proxy_status : overrides->proxy_status;
     ps->proxy_status_set = overrides->proxy_status_set || base->proxy_status_set;
     ps->pool = p;
+    ps->tproxy = (overrides->tproxy_set != 0) ? overrides->tproxy: base->tproxy;
+    ps->tproxy_set = overrides->tproxy_set || base->tproxy_set;
     return ps;
 }
 
@@ -1909,6 +1911,18 @@
     *new_space = dir_config;
 }
 
+static const char *
+    set_tproxy(cmd_parms *parms, void *dummy, int flag)
+{
+    proxy_server_conf *psf =
+    ap_get_module_config(parms->server->module_config, &proxy_module);
+
+    psf->tproxy = flag;
+    psf->tproxy_set = 1;
+
+    return NULL;
+}
+
 static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg)
 {
     const char *errmsg;
@@ -2112,6 +2126,8 @@
      "A balancer or worker name with list of params"),
     AP_INIT_TAKE1("ProxyFtpDirCharset", set_ftp_directory_charset, NULL,
      RSRC_CONF|ACCESS_CONF, "Define the character set for proxied FTP listings"),
+    AP_INIT_FLAG("ProxyTProxy", set_tproxy, NULL, RSRC_CONF,
+     "on if the proxy should use client IP to connect to the origin server"),
     {NULL}
 };
 
diff -ru httpd-2.2.14.original/modules/proxy/mod_proxy.h httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy.h
--- httpd-2.2.14.original/modules/proxy/mod_proxy.h	2008-11-11 21:04:34.000000000 +0100
+++ httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy.h	2010-03-01 11:13:55.000000000 +0100
@@ -193,6 +193,8 @@
     } proxy_status;             /* Status display options */
     char proxy_status_set;
     apr_pool_t *pool;           /* Pool used for allocating this struct */
+    int tproxy;                 /* true if tproxy is enabled */
+    char tproxy_set;
 } proxy_server_conf;
 
 
@@ -714,6 +716,7 @@
  * @param conn    acquired connection
  * @param worker  connection worker
  * @param s       current server record
+ * @param remote_addr  client addr
  * @return        OK or HTTP_XXX error
  * @note In case the socket already exists for conn, just check the link
  * status.
@@ -721,7 +724,9 @@
 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
                                             proxy_conn_rec *conn,
                                             proxy_worker *worker,
-                                            server_rec *s);
+                                            server_rec *s,
+                                            apr_sockaddr_t *remote_addr);
+
 /**
  * Make a connection record for backend connection
  * @param proxy_function calling proxy scheme (http, ajp, ...)
diff -ru httpd-2.2.14.original/modules/proxy/mod_proxy_ajp.c httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy_ajp.c
--- httpd-2.2.14.original/modules/proxy/mod_proxy_ajp.c	2009-04-25 12:04:21.000000000 +0200
+++ httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy_ajp.c	2010-03-01 11:13:55.000000000 +0100
@@ -673,7 +673,7 @@
             break;
 
         /* Step Two: Make the Connection */
-        if (ap_proxy_connect_backend(scheme, backend, worker, r->server)) {
+        if (ap_proxy_connect_backend(scheme, backend, worker, r->server, r->connection->remote_addr)) {
             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                          "proxy: AJP: failed to make connection to backend: %s",
                          backend->hostname);
diff -ru httpd-2.2.14.original/modules/proxy/mod_proxy_ftp.c httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy_ftp.c
--- httpd-2.2.14.original/modules/proxy/mod_proxy_ftp.c	2009-09-14 22:53:28.000000000 +0200
+++ httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy_ftp.c	2010-03-01 11:13:55.000000000 +0100
@@ -1010,7 +1010,7 @@
      */
 
 
-    if (ap_proxy_connect_backend("FTP", backend, worker, r->server)) {
+    if (ap_proxy_connect_backend("FTP", backend, worker, r->server, c->remote_addr)) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                      "proxy: FTP: an error occurred creating a new connection to %pI (%s)",
                      connect_addr, connectname);
diff -ru httpd-2.2.14.original/modules/proxy/mod_proxy_http.c httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy_http.c
--- httpd-2.2.14.original/modules/proxy/mod_proxy_http.c	2009-07-10 14:22:21.000000000 +0200
+++ httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy_http.c	2010-03-01 11:13:55.000000000 +0100
@@ -1973,7 +1973,7 @@
         goto cleanup;
 
     /* Step Two: Make the Connection */
-    if (ap_proxy_connect_backend(proxy_function, backend, worker, r->server)) {
+    if (ap_proxy_connect_backend(proxy_function, backend, worker, r->server, c->remote_addr)) {
         if (r->proxyreq == PROXYREQ_PROXY)
             status = HTTP_NOT_FOUND;
         else
diff -ru httpd-2.2.14.original/modules/proxy/mod_proxy_scgi.c httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy_scgi.c
--- httpd-2.2.14.original/modules/proxy/mod_proxy_scgi.c	2009-09-24 00:20:00.000000000 +0200
+++ httpd-2.2.14.just_tproxy/modules/proxy/mod_proxy_scgi.c	2010-03-01 11:13:55.000000000 +0100
@@ -527,7 +527,7 @@
     }
 
     /* Step Two: Make the Connection */
-    if (ap_proxy_connect_backend(PROXY_FUNCTION, backend, worker, r->server)) {
+    if (ap_proxy_connect_backend(PROXY_FUNCTION, backend, worker, r->server, r->connection->remote_addr)) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                      "proxy: " PROXY_FUNCTION ": failed to make connection "
                      "to backend: %s:%u", backend->hostname, backend->port);
diff -ru httpd-2.2.14.original/modules/proxy/proxy_util.c httpd-2.2.14.just_tproxy/modules/proxy/proxy_util.c
--- httpd-2.2.14.original/modules/proxy/proxy_util.c	2009-07-03 13:57:02.000000000 +0200
+++ httpd-2.2.14.just_tproxy/modules/proxy/proxy_util.c	2010-03-01 11:13:55.000000000 +0100
@@ -2227,7 +2227,8 @@
 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
                                             proxy_conn_rec *conn,
                                             proxy_worker *worker,
-                                            server_rec *s)
+                                            server_rec *s,
+					    apr_sockaddr_t *remote_addr)
 {
     apr_status_t rv;
     int connected = 0;
@@ -2305,6 +2306,26 @@
                              " Keepalive");
             }
         }
+
+        /* TProxy support */
+        if (conf->tproxy) {
+            if ((rv = apr_socket_opt_set(newsock, APR_IP_TRANSPARENT, 1)) != APR_SUCCESS) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+                             "apr_socket_opt_set(APR_IP_TRANSPARENT): Failed to set");
+            }
+
+            if ((rv = apr_socket_opt_set(newsock, APR_SO_REUSEADDR, 1)) != APR_SUCCESS) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+                             "apr_socket_opt_set(APR_SO_REUSE_ADDR): Failed to set");
+            }
+
+            if ((rv = apr_socket_bind(newsock, remote_addr)) != APR_SUCCESS) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+                "proxy: error binding to socket %pI", remote_addr);
+                return HTTP_INTERNAL_SERVER_ERROR;
+            }
+        }
+
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                      "proxy: %s: fam %d socket created to connect to %s",
                      proxy_function, backend_addr->family, worker->hostname);
diff -ru httpd-2.2.14.original/os/unix/unixd.c httpd-2.2.14.just_tproxy/os/unix/unixd.c
--- httpd-2.2.14.original/os/unix/unixd.c	2008-09-18 20:42:18.000000000 +0200
+++ httpd-2.2.14.just_tproxy/os/unix/unixd.c	2010-03-01 11:13:54.000000000 +0100
@@ -49,6 +49,7 @@
 #endif
 #ifdef HAVE_SYS_PRCTL_H
 #include <sys/prctl.h>
+#include <sys/capability.h> /* The original patch included sys/capability.h, but this file doesn't exist on my system */
 #endif
 
 unixd_config_rec unixd_config;
@@ -60,6 +61,34 @@
  * with different sets of groups for each.
  */
 
+void
+keep_capabilities(void)
+{
+    if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "prctl Failed");
+    }
+}
+
+static void
+set_capabilities(int capability)
+{
+    cap_user_header_t head = (cap_user_header_t) calloc(1, sizeof(*head));
+    cap_user_data_t cap = (cap_user_data_t) calloc(1, sizeof(*cap));
+
+    head->version = _LINUX_CAPABILITY_VERSION;
+    head->pid = 0;
+    cap->effective = (1 << capability);
+    cap->inheritable = cap->effective;
+    cap->permitted = cap->effective;
+
+    if (capset(head, cap) != 0) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "capset Failed");
+    }
+
+    free(head);
+    free(cap);
+}
+
 static int set_group_privs(void)
 {
     if (!geteuid()) {
@@ -117,6 +146,7 @@
     if (set_group_privs()) {
         return -1;
     }
+    keep_capabilities();
 
     if (NULL != unixd_config.chroot_dir) {
         if (geteuid()) {
@@ -166,6 +196,10 @@
                     (long) unixd_config.user_id);
         return -1;
     }
+
+    /* Needed for tproxy */
+    set_capabilities(CAP_NET_ADMIN);
+
 #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
     /* this applies to Linux 2.4+ */
 #ifdef AP_MPM_WANT_SET_COREDUMPDIR
diff -ru httpd-2.2.14.original/server/listen.c httpd-2.2.14.just_tproxy/server/listen.c
--- httpd-2.2.14.original/server/listen.c	2008-12-18 18:22:54.000000000 +0100
+++ httpd-2.2.14.just_tproxy/server/listen.c	2010-03-01 11:13:58.000000000 +0100
@@ -61,6 +61,11 @@
         return stat;
     }
 #endif
+    /* Needed for tproxy; however, this code should be optionnal and depend of the configuration file */
+    if (server->transparent != 0 && (stat = apr_socket_opt_set(s, APR_IP_TRANSPARENT, 1)) != APR_SUCCESS) {
+	ap_log_error(APLOG_MARK, APLOG_CRIT, stat, p,
+		     "apr_socket_opt_set(APR_IP_TRANSPARENT): Failed to set");
+    }
 
     stat = apr_socket_opt_set(s, APR_SO_KEEPALIVE, one);
     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
@@ -242,7 +247,7 @@
 }
 
 static const char *alloc_listener(process_rec *process, char *addr,
-                                  apr_port_t port, const char* proto)
+                                  apr_port_t port, const char* proto, int transparent)
 {
     ap_listen_rec **walk, *last;
     apr_status_t status;
@@ -304,6 +309,7 @@
         new->next = 0;
         new->bind_addr = sa;
         new->protocol = apr_pstrdup(process->pool, proto);
+	new->transparent = transparent;
 
         /* Go to the next sockaddr. */
         sa = sa->next;
@@ -605,13 +611,14 @@
     apr_port_t port;
     apr_status_t rv;
     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+    int transparent = 0;
 
     if (err != NULL) {
         return err;
     }
 
-    if (argc < 1 || argc > 2) {
-        return "Listen requires 1 or 2 arguments.";
+    if (argc < 1 || argc > 3) {
+        return "Listen requires 1, 2 or 3 arguments.";
     }
 
     rv = apr_parse_addr_port(&host, &scope_id, &port, argv[0], cmd->pool);
@@ -632,19 +639,35 @@
         return "Port must be specified";
     }
 
-    if (argc != 2) {
+    if (argc < 2) {
         if (port == 443) {
             proto = "https";
         } else {
             proto = "http";
         }
     }
-    else {
+    else if (argc == 2) {
+    	if (strcasecmp(argv[1], "TProxy") == 0) {
+	    transparent = 1;
+            if (port == 443) {
+                proto = "https";
+            } else {
+                proto = "http";
+            }
+	}
+    }
+    else if (argc == 3) {
+        if (strcasecmp(argv[2], "TProxy") == 0) {
+	    transparent = 1;
+	}
+	else {
+	    return "Listen last argument must be 'TProxy' or not exist.";
+	}
         proto = apr_pstrdup(cmd->pool, argv[1]);
         ap_str_tolower(proto);
     }
 
-    return alloc_listener(cmd->server->process, host, port, proto);
+    return alloc_listener(cmd->server->process, host, port, proto, transparent);
 }
 
 AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd,
diff -ru httpd-2.2.14.original/srclib/apr/include/apr_network_io.h httpd-2.2.14.just_tproxy/srclib/apr/include/apr_network_io.h
--- httpd-2.2.14.original/srclib/apr/include/apr_network_io.h	2007-12-15 05:10:38.000000000 +0100
+++ httpd-2.2.14.just_tproxy/srclib/apr/include/apr_network_io.h	2010-03-01 11:13:55.000000000 +0100
@@ -65,6 +65,7 @@
 #define APR_SO_DEBUG         4    /**< Debug */
 #define APR_SO_NONBLOCK      8    /**< Non-blocking IO */
 #define APR_SO_REUSEADDR     16   /**< Reuse addresses */
+#define APR_IP_TRANSPARENT   32   /**< TProxy support */
 #define APR_SO_SNDBUF        64   /**< Send buffer */
 #define APR_SO_RCVBUF        128  /**< Receive buffer */
 #define APR_SO_DISCONNECTED  256  /**< Disconnected */
diff -ru httpd-2.2.14.original/srclib/apr/network_io/unix/sockopt.c httpd-2.2.14.just_tproxy/srclib/apr/network_io/unix/sockopt.c
--- httpd-2.2.14.original/srclib/apr/network_io/unix/sockopt.c	2006-08-03 12:55:31.000000000 +0200
+++ httpd-2.2.14.just_tproxy/srclib/apr/network_io/unix/sockopt.c	2010-03-01 11:13:55.000000000 +0100
@@ -17,6 +17,7 @@
 #include "apr_arch_networkio.h"
 #include "apr_strings.h"
 
+#define IP_TRANSPARENT 19
 
 static apr_status_t soblock(int sd)
 {
@@ -318,6 +319,16 @@
         return APR_ENOTIMPL;
 #endif
         break;
+    case APR_IP_TRANSPARENT:
+#ifdef IP_TRANSPARENT
+        if (setsockopt(sock->socketdes, SOL_IP, IP_TRANSPARENT, (void *)&one, sizeof(int)) == -1) {
+            return errno;
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+
     default:
         return APR_EINVAL;
     }
