<div dir="ltr">Hi,<div><br></div><div>I tried this with 1.2.6 and it works just fine. Have you given this any scrutiny in real life production systems?</div><div><br></div><div style>Thx,</div><div style>ssehic</div></div>
<div class="gmail_extra"><br clear="all"><div><br>Best regards,<br><br>Srebrenko Sehic<br>Armorlogic<br><br>Phone: +45 70 27 77 32<br>Mobile: +45 26 10 02 76<br><br><a href="http://www.armorlogic.com" target="_blank">http://www.armorlogic.com</a></div>
<br><br><div class="gmail_quote">On Thu, Oct 28, 2010 at 4:14 PM, David Gwynne <span dir="ltr"><<a href="mailto:loki@animata.net" target="_blank">loki@animata.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
openbsd has a setsockopt option called SO_BINDANY that allows a<br>
process to bind to any ip address, even if it is not local to the<br>
system. the patch below uses it to allow nginx to connect to a<br>
backend server using the ip of the client making the request.<br>
<br>
my main goal here is to allow the backend server to know the ip of<br>
the client actually making the request without having to look at<br>
extra hhtp headers<br>
<br>
i thought id throw this out there to get some help since this is<br>
my first attempt at tweaking nginx. there are a few issues with<br>
this implementation:<br>
<br>
1. it is completely specific to openbsd.<br>
2. it needs root privileges to use the SO_BINDANY sockopt.<br>
3. im not sure if connections to backends are cached. if so then<br>
it is probable that a different client will reuse a previous clients<br>
proxy connection, so it will appear that the same client made both<br>
requests to the backend.<br>
<br>
to use this you just configure nginx to run as root and add<br>
"proxy_transparent on" to the sections you want this feature enabled<br>
on. you will need to add appropriate "pass out proto tcp divert-reply"<br>
rules to pf for the SO_BINDANY sockopt to work too.<br>
<br>
if anyone has some tips on how to handle problems 2 and 3 i would<br>
be grateful.<br>
<br>
cheers,<br>
dlg<br>
<br>
<br>
--- src/event/ngx_event_connect.c.orig Thu Nov 26 04:03:59 2009<br>
+++ src/event/ngx_event_connect.c Thu Oct 28 23:22:37 2010<br>
@@ -11,7 +11,7 @@<br>
<br>
<br>
ngx_int_t<br>
-ngx_event_connect_peer(ngx_peer_connection_t *pc)<br>
+ngx_event_connect_peer(ngx_peer_connection_t *pc, ngx_connection_t *cc)<br>
{<br>
int rc;<br>
ngx_int_t event;<br>
@@ -20,6 +20,7 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)<br>
ngx_socket_t s;<br>
ngx_event_t *rev, *wev;<br>
ngx_connection_t *c;<br>
+ int bindany;<br>
<br>
rc = pc->get(pc, pc->data);<br>
if (rc != NGX_OK) {<br>
@@ -46,6 +47,40 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)<br>
}<br>
<br>
return NGX_ERROR;<br>
+ }<br>
+<br>
+ if (cc != NULL) {<br>
+ bindany = 1;<br>
+ if (setsockopt(s, SOL_SOCKET, SO_BINDANY,<br>
+ &bindany, sizeof(bindany)) == -1)<br>
+ {<br>
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,<br>
+ "setsockopt(SO_BINDANY) failed");<br>
+<br>
+ ngx_free_connection(c);<br>
+<br>
+ if (ngx_close_socket(s) == -1) {<br>
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,<br>
+ ngx_close_socket_n " failed");<br>
+ }<br>
+<br>
+ return NGX_ERROR;<br>
+ }<br>
+<br>
+ if (bind(s, cc->sockaddr, cc->socklen) == -1)<br>
+ {<br>
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,<br>
+ "bind() failed");<br>
+<br>
+ ngx_free_connection(c);<br>
+<br>
+ if (ngx_close_socket(s) == -1) {<br>
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,<br>
+ ngx_close_socket_n " failed");<br>
+ }<br>
+<br>
+ return NGX_ERROR;<br>
+ }<br>
}<br>
<br>
if (pc->rcvbuf) {<br>
--- src/event/ngx_event_connect.h.orig Tue Nov 3 01:24:02 2009<br>
+++ src/event/ngx_event_connect.h Thu Oct 28 23:22:37 2010<br>
@@ -68,7 +68,8 @@ struct ngx_peer_connection_s {<br>
};<br>
<br>
<br>
-ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc);<br>
+ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc,<br>
+ ngx_connection_t *cc);<br>
ngx_int_t ngx_event_get_peer(ngx_peer_connection_t *pc, void *data);<br>
<br>
<br>
--- src/http/modules/ngx_http_proxy_module.c.orig Mon May 24 21:01:05 2010<br>
+++ src/http/modules/ngx_http_proxy_module.c Thu Oct 28 23:42:10 2010<br>
@@ -71,6 +71,7 @@ typedef struct {<br>
ngx_http_proxy_vars_t vars;<br>
<br>
ngx_flag_t redirect;<br>
+ ngx_flag_t transparent;<br>
<br>
ngx_uint_t headers_hash_max_size;<br>
ngx_uint_t headers_hash_bucket_size;<br>
@@ -196,6 +197,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {<br>
0,<br>
NULL },<br>
<br>
+ { ngx_string("proxy_transparent"),<br>
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,<br>
+ ngx_conf_set_flag_slot,<br>
+ NGX_HTTP_LOC_CONF_OFFSET,<br>
+ offsetof(ngx_http_proxy_loc_conf_t, transparent),<br>
+ NULL },<br>
+<br>
{ ngx_string("proxy_store"),<br>
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,<br>
ngx_http_proxy_store,<br>
@@ -626,6 +634,7 @@ ngx_http_proxy_handler(ngx_http_request_t *r)<br>
u->abort_request = ngx_http_proxy_abort_request;<br>
u->finalize_request = ngx_http_proxy_finalize_request;<br>
r->state = 0;<br>
+ r->transparent = (plcf->transparent == 1);<br>
<br>
if (plcf->redirects) {<br>
u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;<br>
@@ -1940,6 +1949,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)<br>
conf->upstream.cyclic_temp_file = 0;<br>
<br>
conf->redirect = NGX_CONF_UNSET;<br>
+ conf->transparent = NGX_CONF_UNSET;<br>
conf->upstream.change_buffering = 1;<br>
<br>
conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;<br>
@@ -2214,6 +2224,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *pa<br>
}<br>
}<br>
}<br>
+<br>
+ ngx_conf_merge_value(conf->transparent, prev->transparent, 0);<br>
<br>
/* STUB */<br>
if (prev->proxy_lengths) {<br>
--- src/http/ngx_http_request.h.orig Mon May 24 22:35:10 2010<br>
+++ src/http/ngx_http_request.h Thu Oct 28 23:22:37 2010<br>
@@ -511,6 +511,8 @@ struct ngx_http_request_s {<br>
unsigned stat_writing:1;<br>
#endif<br>
<br>
+ unsigned transparent:1;<br>
+<br>
/* used to parse HTTP headers */<br>
<br>
ngx_uint_t state;<br>
--- src/http/ngx_http_upstream.c.orig Mon May 24 22:35:10 2010<br>
+++ src/http/ngx_http_upstream.c Thu Oct 28 23:22:37 2010<br>
@@ -1066,7 +1066,8 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_h<br>
u->state->response_sec = tp->sec;<br>
u->state->response_msec = tp->msec;<br>
<br>
- rc = ngx_event_connect_peer(&u->peer);<br>
+ rc = ngx_event_connect_peer(&u->peer, r->transparent ?<br>
+ r->connection : NULL);<br>
<br>
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,<br>
"http upstream connect: %i", rc);<br>
--- src/mail/ngx_mail_auth_http_module.c.orig Fri May 14 19:56:37 2010<br>
+++ src/mail/ngx_mail_auth_http_module.c Thu Oct 28 23:22:37 2010<br>
@@ -191,7 +191,7 @@ ngx_mail_auth_http_init(ngx_mail_session_t *s)<br>
ctx->peer.log = s->connection->log;<br>
ctx->peer.log_error = NGX_ERROR_ERR;<br>
<br>
- rc = ngx_event_connect_peer(&ctx->peer);<br>
+ rc = ngx_event_connect_peer(&ctx->peer, NULL);<br>
<br>
if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {<br>
if (ctx->peer.connection) {<br>
--- src/mail/ngx_mail_proxy_module.c.orig Thu Oct 28 23:32:15 2010<br>
+++ src/mail/ngx_mail_proxy_module.c Thu Oct 28 23:30:53 2010<br>
@@ -147,7 +147,7 @@ ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t<br>
p->upstream.log = s->connection->log;<br>
p->upstream.log_error = NGX_ERROR_ERR;<br>
<br>
- rc = ngx_event_connect_peer(&p->upstream);<br>
+ rc = ngx_event_connect_peer(&p->upstream, NULL);<br>
<br>
if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {<br>
ngx_mail_proxy_internal_server_error(s);<br>
<br>
_______________________________________________<br>
nginx-devel mailing list<br>
<a href="mailto:nginx-devel@nginx.org">nginx-devel@nginx.org</a><br>
<a href="http://nginx.org/mailman/listinfo/nginx-devel" target="_blank">http://nginx.org/mailman/listinfo/nginx-devel</a><br>
</blockquote></div><br></div>