diff --git a/doc/configuration.txt b/doc/configuration.txt
index 149f330a4..5ebe3cc6d 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -275,6 +275,7 @@ option httpclose            X          X         X         X
 option httplog              X          X         X         X
 option logasap              X          X         X         -
 option nolinger             X          X         X         X
+option http_proxy           X          X         X         X
 option persist              X          -         X         X
 option redispatch           X          -         X         X
 option smtpchk              X          -         X         X
@@ -539,6 +540,15 @@ url_reg <regex>
   used any time, but it is important to remember that regex matching is slower
   than other methods. See also "path_reg" and all "url_" criteria.
 
+url_ip <ip_address>
+  Applies to the IP address parsed in HTTP request. It can be used to
+  prevent access to certain resources such as local network. It is useful
+  with option 'http_proxy'.
+
+url_port <integer>
+  Applies to the port parsed in HTTP request. It can be used to
+  prevent access to certain resources. It is useful with option 'http_proxy'.
+
 hdr <string> 
 hdr(header) <string>
   Note: all the "hdr*" matching criteria either apply to all headers, or to a
diff --git a/examples/option-http_proxy.cfg b/examples/option-http_proxy.cfg
new file mode 100644
index 000000000..8f73c3bb8
--- /dev/null
+++ b/examples/option-http_proxy.cfg
@@ -0,0 +1,53 @@
+#
+# demo config for Proxy mode
+# 
+
+global
+        maxconn         20000
+	ulimit-n	16384
+        log             127.0.0.1 local0
+        uid             200
+        gid             200
+        chroot          /var/empty
+	nbproc		4
+        daemon
+
+frontend test-proxy
+	bind		192.168.200.10:8080
+        mode            http
+        log             global
+        option          httplog
+        option          dontlognull
+        option          httpclose
+        option          nolinger
+        option          http_proxy
+        maxconn         8000
+        clitimeout      30000
+
+	# layer3: Valid users
+	acl allow_host src 192.168.200.150/32
+	block if !allow_host
+
+	# layer7: prevent private network relaying
+	acl forbidden_dst url_ip 192.168.0.0/24
+	acl forbidden_dst url_ip 172.16.0.0/12
+	acl forbidden_dst url_ip 10.0.0.0/8
+	block if forbidden_dst
+
+	default_backend test-proxy-srv
+
+
+backend test-proxy-srv
+	mode            http
+	contimeout      5000
+	srvtimeout      5000
+	retries         2
+	option          nolinger
+	option          http_proxy
+
+	# layer7: Only GET method is valid
+	acl valid_method        method GET
+	block if !valid_method
+
+	# layer7: protect bad reply
+	rspdeny ^Content-Type:[\ ]*audio/mp3
diff --git a/include/common/standard.h b/include/common/standard.h
index 90ed618a9..80f6d2a28 100644
--- a/include/common/standard.h
+++ b/include/common/standard.h
@@ -132,6 +132,11 @@ struct sockaddr_in *str2sa(char *str);
  */
 int str2net(const char *str, struct in_addr *addr, struct in_addr *mask);
 
+/*
+ * Resolve destination server from URL. Convert <str> to a sockaddr_in*.
+ */
+int url2sa(const char *url, int ulen, struct sockaddr_in *addr);
+
 /* will try to encode the string <string> replacing all characters tagged in
  * <map> with the hexadecimal representation of their ASCII-code (2 digits)
  * prefixed by <escape>, and will store the result between <start> (included)
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 6ffc264cd..2a75fad9e 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -101,6 +101,7 @@
 
 #define PR_O_TCPSPLICE	0x08000000      /* delegate data transfer to linux kernel's tcp_splice */
 #define PR_O_CONTSTATS	0x10000000	/* continous counters */
+#define PR_O_HTTP_PROXY 0x20000000	/* Enable session to use HTTP proxy operations */
 
 /* This structure is used to apply fast weighted round robin on a server group */
 struct fwrr_group {
diff --git a/src/backend.c b/src/backend.c
index 91027e817..a8676b3fa 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -936,6 +936,10 @@ int assign_server(struct session *s)
 				return SRV_STATUS_INTERNAL;
 			}
 		}
+		else if (s->be->options & PR_O_HTTP_PROXY) {
+			if (!s->srv_addr.sin_addr.s_addr)
+				return SRV_STATUS_NOSRV;
+		}
 		else if (!*(int *)&s->be->dispatch_addr.sin_addr &&
 			 !(s->fe->options & PR_O_TRANSP)) {
 			return SRV_STATUS_NOSRV;
@@ -999,6 +1003,10 @@ int assign_server_address(struct session *s)
 			return SRV_STATUS_INTERNAL;
 		}
 	}
+	else if (s->be->options & PR_O_HTTP_PROXY) {
+		/* If HTTP PROXY option is set, then server is already assigned
+		 * during incoming client request parsing. */
+	}
 	else {
 		/* no server and no LB algorithm ! */
 		return SRV_STATUS_INTERNAL;
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 47530120d..affb9569a 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -97,6 +97,7 @@ static const struct {
 	{ "keepalive",    PR_O_KEEPALIVE,  PR_CAP_NONE, 0 },
 	{ "httpclose",    PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
 	{ "nolinger",     PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
+	{ "http_proxy",	  PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
 	{ "logasap",      PR_O_LOGASAP,    PR_CAP_FE, 0 },
 	{ "contstats",    PR_O_CONTSTATS,  PR_CAP_FE, 0 },
 	{ "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
@@ -2473,7 +2474,7 @@ int readcfgfile(const char *file)
 		}
 		else if (curproxy->cap & PR_CAP_BE &&
 			 ((curproxy->mode != PR_MODE_HEALTH) &&
-			  !(curproxy->options & PR_O_TRANSP) &&
+			  !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
 			  !(curproxy->lbprm.algo & BE_LB_ALGO) &&
 			  (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
 			Alert("parsing %s : %s '%s' has no dispatch address and is not in transparent or balance mode.\n",
diff --git a/src/client.c b/src/client.c
index 2ee41a6f8..73c889555 100644
--- a/src/client.c
+++ b/src/client.c
@@ -522,6 +522,7 @@ acl_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir,
 	return 1;
 }
 
+
 /* set test->i to the number of connexions to the proxy */
 static int
 acl_fetch_dconn(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -534,14 +535,14 @@ acl_fetch_dconn(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* Note: must not be declared <const> as its list will be overwritten */
 static struct acl_kw_list acl_kws = {{ },{
-	{ "src_port",   acl_parse_int,   acl_fetch_sport,  acl_match_int },
-	{ "src",        acl_parse_ip,    acl_fetch_src,    acl_match_ip  },
-	{ "dst",        acl_parse_ip,    acl_fetch_dst,    acl_match_ip  },
-	{ "dst_port",   acl_parse_int,   acl_fetch_dport,  acl_match_int },
+	{ "src_port",   acl_parse_int,   acl_fetch_sport,    acl_match_int },
+	{ "src",        acl_parse_ip,    acl_fetch_src,      acl_match_ip  },
+	{ "dst",        acl_parse_ip,    acl_fetch_dst,      acl_match_ip  },
+	{ "dst_port",   acl_parse_int,   acl_fetch_dport,    acl_match_int },
 #if 0
-	{ "src_limit",  acl_parse_int,   acl_fetch_sconn,  acl_match_int },
+	{ "src_limit",  acl_parse_int,   acl_fetch_sconn,    acl_match_int },
 #endif
-	{ "dst_conn",   acl_parse_int,   acl_fetch_dconn,  acl_match_int },
+	{ "dst_conn",   acl_parse_int,   acl_fetch_dconn,    acl_match_int },
 	{ NULL, NULL, NULL, NULL },
 }};
 
diff --git a/src/proto_http.c b/src/proto_http.c
index 372743146..59b9055f6 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1476,7 +1476,7 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx
 	msg->msg_state = HTTP_MSG_ERROR;
 	return;
 }
-    
+
 /*
  * manages the client FSM and its socket. BTW, it also tries to handle the
  * cookie. It returns 1 if a state has changed (and a resync may be needed),
@@ -1908,8 +1908,13 @@ int process_cli(struct session *t)
 		 * may have separate values for ->fe, ->be.
 		 */
 
-
-
+		/*
+		 * If HTTP PROXY is set we simply get remote server address
+		 * parsing incoming request.
+		 */
+		if ((t->be->options & PR_O_HTTP_PROXY) && !(t->flags & SN_ADDR_SET)) {
+			url2sa(req->data + msg->sl.rq.u, msg->sl.rq.u_l, &t->srv_addr);
+		}
 
 		/*
 		 * 7: the appsession cookie was looked up very early in 1.2,
@@ -4950,6 +4955,57 @@ acl_fetch_url(struct proxy *px, struct session *l4, void *l7, int dir,
 	return 1;
 }
 
+static int
+acl_fetch_url_ip(struct proxy *px, struct session *l4, void *l7, int dir,
+		 struct acl_expr *expr, struct acl_test *test)
+{
+	struct http_txn *txn = l7;
+
+	if (txn->req.msg_state != HTTP_MSG_BODY)
+		return 0;
+	if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
+		/* ensure the indexes are not affected */
+		return 0;
+
+	/* Parse HTTP request */
+	url2sa(txn->req.sol + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->srv_addr);
+	test->ptr = (void *)&((struct sockaddr_in *)&l4->srv_addr)->sin_addr;
+	test->i = AF_INET;
+
+	/*
+	 * If we are parsing url in frontend space, we prepare backend stage
+	 * to not parse again the same url ! optimization lazyness...
+	 */
+	if (px->options & PR_O_HTTP_PROXY)
+		l4->flags |= SN_ADDR_SET;
+
+	test->flags = ACL_TEST_F_READ_ONLY;
+	return 1;
+}
+
+static int
+acl_fetch_url_port(struct proxy *px, struct session *l4, void *l7, int dir,
+		   struct acl_expr *expr, struct acl_test *test)
+{
+	struct http_txn *txn = l7;
+
+	if (txn->req.msg_state != HTTP_MSG_BODY)
+		return 0;
+	if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
+		/* ensure the indexes are not affected */
+		return 0;
+
+	/* Same optimization as url_ip */
+	url2sa(txn->req.sol + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->srv_addr);
+	test->i = ntohs(((struct sockaddr_in *)&l4->srv_addr)->sin_port);
+
+	if (px->options & PR_O_HTTP_PROXY)
+		l4->flags |= SN_ADDR_SET;
+
+	test->flags = ACL_TEST_F_READ_ONLY;
+	return 1;
+}
+
 /* 5. Check on HTTP header. A pointer to the beginning of the value is returned.
  * This generic function is used by both acl_fetch_chdr() and acl_fetch_shdr().
  */
@@ -5186,13 +5242,15 @@ static struct acl_kw_list acl_kws = {{ },{
 	{ "resp_ver",   acl_parse_ver,   acl_fetch_stver,  acl_match_str  },
 	{ "status",     acl_parse_int,   acl_fetch_stcode, acl_match_int  },
 
-	{ "url",        acl_parse_str,   acl_fetch_url,    acl_match_str  },
-	{ "url_beg",    acl_parse_str,   acl_fetch_url,    acl_match_beg  },
-	{ "url_end",    acl_parse_str,   acl_fetch_url,    acl_match_end  },
-	{ "url_sub",    acl_parse_str,   acl_fetch_url,    acl_match_sub  },
-	{ "url_dir",    acl_parse_str,   acl_fetch_url,    acl_match_dir  },
-	{ "url_dom",    acl_parse_str,   acl_fetch_url,    acl_match_dom  },
-	{ "url_reg",    acl_parse_reg,   acl_fetch_url,    acl_match_reg  },
+	{ "url",        acl_parse_str,   acl_fetch_url,      acl_match_str  },
+	{ "url_beg",    acl_parse_str,   acl_fetch_url,      acl_match_beg  },
+	{ "url_end",    acl_parse_str,   acl_fetch_url,      acl_match_end  },
+	{ "url_sub",    acl_parse_str,   acl_fetch_url,      acl_match_sub  },
+	{ "url_dir",    acl_parse_str,   acl_fetch_url,      acl_match_dir  },
+	{ "url_dom",    acl_parse_str,   acl_fetch_url,      acl_match_dom  },
+	{ "url_reg",    acl_parse_reg,   acl_fetch_url,      acl_match_reg  },
+	{ "url_ip",     acl_parse_ip,    acl_fetch_url_ip,   acl_match_ip   },
+	{ "url_port",   acl_parse_int,   acl_fetch_url_port, acl_match_int  },
 
 	{ "hdr",        acl_parse_str,   acl_fetch_chdr,    acl_match_str },
 	{ "hdr_reg",    acl_parse_reg,   acl_fetch_chdr,    acl_match_reg },
diff --git a/src/standard.c b/src/standard.c
index 1e631301c..d245949a9 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -202,6 +202,100 @@ int str2net(const char *str, struct in_addr *addr, struct in_addr *mask)
 	goto out_free;
 }
 
+
+/*
+ * Parse IP address found in url.
+ */
+static int url2ip(const char *addr, struct in_addr *dst)
+{
+	int saw_digit, octets, ch;
+	u_char tmp[4], *tp;
+	const char *cp = addr;
+
+	saw_digit = 0;
+	octets = 0;
+	*(tp = tmp) = 0;
+
+	while (*addr) {
+		unsigned char digit = (ch = *addr++) - '0';
+		if (digit > 9 && ch != '.')
+			break;
+		if (digit <= 9) {
+			u_int new = *tp * 10 + digit;
+			if (new > 255)
+				return 0;
+			*tp = new;
+			if (!saw_digit) {
+				if (++octets > 4)
+					return 0;
+				saw_digit = 1;
+			}
+		} else if (ch == '.' && saw_digit) {
+			if (octets == 4)
+				return 0;
+			*++tp = 0;
+			saw_digit = 0;
+		} else
+			return 0;
+	}
+
+	if (octets < 4)
+		return 0;
+
+	memcpy(&dst->s_addr, tmp, 4);
+	return addr-cp-1;
+}
+
+/*
+ * Resolve destination server from URL. Convert <str> to a sockaddr_in*.
+ */
+int url2sa(const char *url, int ulen, struct sockaddr_in *addr)
+{
+	const char *curr = url, *cp = url;
+	int ret, url_code = 0;
+	unsigned int http_code = 0;
+
+	/* Cleanup the room */
+	addr->sin_family = AF_INET;
+	addr->sin_addr.s_addr = 0;
+	addr->sin_port = 0;
+
+	/* Firstly, try to find :// pattern */
+	while (curr < url+ulen && url_code != 0x3a2f2f) {
+		url_code = ((url_code & 0xffff) << 8);
+		url_code += (unsigned char)*curr++;
+	}
+
+	/* Secondly, if :// pattern is found, verify parsed stuff
+	 * before pattern is matching our http pattern.
+	 * If so parse ip address and port in uri.
+	 * 
+	 * WARNING: Current code doesn't support dynamic async dns resolver.
+	 */
+	if (url_code == 0x3a2f2f) {
+		while (cp < curr - 3)
+			http_code = (http_code << 8) + *cp++;
+		http_code |= 0x20202020;			/* Turn everything to lower case */
+		
+		/* HTTP url matching */
+		if (http_code == 0x68747470) {
+			/* We are looking for IP address. If you want to parse and
+			 * resolve hostname found in url, you can use str2sa(), but
+			 * be warned this can slow down global daemon performances
+			 * while handling lagging dns responses.
+			 */
+			ret = url2ip(curr, &addr->sin_addr);
+			if (!ret)
+				return -1;
+			curr += ret;
+			addr->sin_port = (*curr == ':') ? htons(str2uic(++curr)) : htons(80);
+		}
+		return 0;
+	}
+
+	return -1;
+}
+
 /* will try to encode the string <string> replacing all characters tagged in
  * <map> with the hexadecimal representation of their ASCII-code (2 digits)
  * prefixed by <escape>, and will store the result between <start> (included)