openbsd has a setsockopt option called SO_BINDANY that allows a
process to bind to any ip address, even if it is not local to the
system. the patch below uses it to allow nginx to connect to a
backend server using the ip of the client making the request.
my main goal here is to allow the backend server to know the ip of
the client actually making the request without having to look at
extra hhtp headers
i thought id throw this out there to get some help since this is
my first attempt at tweaking nginx. there are a few issues with
this implementation:
1. it is completely specific to openbsd.
2. it needs root privileges to use the SO_BINDANY sockopt.
3. im not sure if connections to backends are cached. if so then
it is probable that a different client will reuse a previous clients
proxy connection, so it will appear that the same client made both
requests to the backend.
to use this you just configure nginx to run as root and add
"proxy_transparent on" to the sections you want this feature enabled
on. you will need to add appropriate "pass out proto tcp divert-reply"
rules to pf for the SO_BINDANY sockopt to work too.
if anyone has some tips on how to handle problems 2 and 3 i would
be grateful.
cheers,
dlg
--- src/event/ngx_event_connect.c.orig Thu Nov 26 04:03:59 2009
+++ src/event/ngx_event_connect.c Thu Oct 28 23:22:37 2010
@@ -11,7 +11,7 @@
ngx_int_t
-ngx_event_connect_peer(ngx_peer_connection_t *pc)
+ngx_event_connect_peer(ngx_peer_connection_t *pc, ngx_connection_t *cc)
{
int rc;
ngx_int_t event;
@@ -20,6 +20,7 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
ngx_socket_t s;
ngx_event_t *rev, *wev;
ngx_connection_t *c;
+ int bindany;
rc = pc->get(pc, pc->data);
if (rc != NGX_OK) {
@@ -46,6 +47,40 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
}
return NGX_ERROR;
+ }
+
+ if (cc != NULL) {
+ bindany = 1;
+ if (setsockopt(s, SOL_SOCKET, SO_BINDANY,
+ &bindany, sizeof(bindany)) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+ "setsockopt(SO_BINDANY) failed");
+
+ ngx_free_connection(c);
+
+ if (ngx_close_socket(s) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+ ngx_close_socket_n " failed");
+ }
+
+ return NGX_ERROR;
+ }
+
+ if (bind(s, cc->sockaddr, cc->socklen) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+ "bind() failed");
+
+ ngx_free_connection(c);
+
+ if (ngx_close_socket(s) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+ ngx_close_socket_n " failed");
+ }
+
+ return NGX_ERROR;
+ }
}
if (pc->rcvbuf) {
--- src/event/ngx_event_connect.h.orig Tue Nov 3 01:24:02 2009
+++ src/event/ngx_event_connect.h Thu Oct 28 23:22:37 2010
@@ -68,7 +68,8 @@ struct ngx_peer_connection_s {
};
-ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc);
+ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc,
+ ngx_connection_t *cc);
ngx_int_t ngx_event_get_peer(ngx_peer_connection_t *pc, void *data);
--- src/http/modules/ngx_http_proxy_module.c.orig Mon May 24 21:01:05 2010
+++ src/http/modules/ngx_http_proxy_module.c Thu Oct 28 23:42:10 2010
@@ -71,6 +71,7 @@ typedef struct {
ngx_http_proxy_vars_t vars;
ngx_flag_t redirect;
+ ngx_flag_t transparent;
ngx_uint_t headers_hash_max_size;
ngx_uint_t headers_hash_bucket_size;
@@ -196,6 +197,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
0,
NULL },
+ { ngx_string("proxy_transparent"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, transparent),
+ NULL },
+
{ ngx_string("proxy_store"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_proxy_store,
@@ -626,6 +634,7 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
u->abort_request = ngx_http_proxy_abort_request;
u->finalize_request = ngx_http_proxy_finalize_request;
r->state = 0;
+ r->transparent = (plcf->transparent == 1);
if (plcf->redirects) {
u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
@@ -1940,6 +1949,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cyclic_temp_file = 0;
conf->redirect = NGX_CONF_UNSET;
+ conf->transparent = NGX_CONF_UNSET;
conf->upstream.change_buffering = 1;
conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;
@@ -2214,6 +2224,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *pa
}
}
}
+
+ ngx_conf_merge_value(conf->transparent, prev->transparent, 0);
/* STUB */
if (prev->proxy_lengths) {
--- src/http/ngx_http_request.h.orig Mon May 24 22:35:10 2010
+++ src/http/ngx_http_request.h Thu Oct 28 23:22:37 2010
@@ -511,6 +511,8 @@ struct ngx_http_request_s {
unsigned stat_writing:1;
#endif
+ unsigned transparent:1;
+
/* used to parse HTTP headers */
ngx_uint_t state;
--- src/http/ngx_http_upstream.c.orig Mon May 24 22:35:10 2010
+++ src/http/ngx_http_upstream.c Thu Oct 28 23:22:37 2010
@@ -1066,7 +1066,8 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_h
u->state->response_sec = tp->sec;
u->state->response_msec = tp->msec;
- rc = ngx_event_connect_peer(&u->peer);
+ rc = ngx_event_connect_peer(&u->peer, r->transparent ?
+ r->connection : NULL);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http upstream connect: %i", rc);
--- src/mail/ngx_mail_auth_http_module.c.orig Fri May 14 19:56:37 2010
+++ src/mail/ngx_mail_auth_http_module.c Thu Oct 28 23:22:37 2010
@@ -191,7 +191,7 @@ ngx_mail_auth_http_init(ngx_mail_session_t *s)
ctx->peer.log = s->connection->log;
ctx->peer.log_error = NGX_ERROR_ERR;
- rc = ngx_event_connect_peer(&ctx->peer);
+ rc = ngx_event_connect_peer(&ctx->peer, NULL);
if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
if (ctx->peer.connection) {
--- src/mail/ngx_mail_proxy_module.c.orig Thu Oct 28 23:32:15 2010
+++ src/mail/ngx_mail_proxy_module.c Thu Oct 28 23:30:53 2010
@@ -147,7 +147,7 @@ ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t
p->upstream.log = s->connection->log;
p->upstream.log_error = NGX_ERROR_ERR;
- rc = ngx_event_connect_peer(&p->upstream);
+ rc = ngx_event_connect_peer(&p->upstream, NULL);
if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
ngx_mail_proxy_internal_server_error(s);
Hi Igor,
attached patch fixes ./configure script for less error-forgiving compilers
(like LLVM/clang) when they are used with -Werror option.
auto/types/sizeof:
- printf() is defined in missing <stdio.h> header,
- sizeof() returns size_t type, which has different signedness on different
operating systems (hence %z).
auto/unix:
- setproctitle() is defined in <stdlib.h> on both: NetBSD and OpenBSD.
Best regards,
Piotr Sikora < piotr.sikora(a)frickle.com >
Hi all, I would like to contribute a patch to provide the cached file
age as a variable $proxy_cache_age , which can then be used together
with add_header Age $proxy_cache_age.
The age calculation is not RFC2616 compliant (13.2.3) as it doesn't take
into consideration the cached origin Age header and Date. Is it feasible
to extract this from the cached headers?
--
regards,
wK
Hi, folks!
Here's the first draft of our nginx module development plan in the
next year or so:
http://agentzh.org/misc/nginx/roadmap.html
We'll keep this roadmap document up to date.
Comments and suggestions will be highly appreciated as usual :)
Cheers,
-agentzh
Hi,
I sent a while ago a patch on nginx mailing list, and recently realized
it was the wrong place. So I took the time to update and fix the old patch
for nginx current development version.
This patch basically adds an autoindex_css_file option in order to allow
some customizations in the index listing.
One thing I'm not sure about is the ngx_alloc call; I didn't find any
ngx_asprintf or such, but maybe there is some quicker/better way to do it.
Also, I didn't add the prototype declaration since it's a static function;
should I?
Regards,
--
Clément B.
Hello,
I'm trying to write my first module, so bear with me if my question feel silly.
The situation is fairly simple:
- My module accepts GET, POST and HEAD methods.
- My module can return big chunks of data for GET and POST.
- When I'm processing the GET everything is OK.
- When I'm processing a POST which does not trigger saving the body to a temp
file, everything is OK.
- When I'm processing a POST which triggers saving the body to a temp file, my
client only gets the first 65536 bytes (confirmed by both a wireshark capture
and the nginx logs).
Now, I understand nginx is happy when handling GET and "small POST" because
everything happens in the content handler which returns appropriately
NGX_AGAIN/NGX_OK/NGX_DONE. I would be happy to do the same with the
post_handler. Unfortunately the signature of the post_handler (as defined by
ngx_http_read_client_request_body) is:
typedef void (*ngx_http_client_body_handler_pt)(ngx_http_request_t *r);
and therefore I cannot return NGX_AGAIN (which would be natural).
I'll try to get some "bare-bone" code together to reproduce this but high-level
it looks like:
ngx_int_t ngx_http_xxx_handler(ngx_http_request_t *r) {
if (NGX_HTTP_GET == r->method) {
return ngx_http_xxx_do_get(r);
} else if (NGX_HTTP_POST == r->method) {
return ngx_http_xxx_do_post(r);
}
}
ngx_int_t ngx_http_xxx_do_post(ngx_http_request_t *r) {
[...]
rc = ngx_http_read_client_request_body(r, ngx_http_xxx_body_received);
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
if (rc == NGX_AGAIN) {
/* It will not call me again, but call the body_received. */
return NGX_AGAIN;
}
if (NGX_OK == rc) {
ngx_log_debug(NGX_LOG_DEBUG_HTTP, log, 0,
"Client request body already read");
return rc;
}
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
void ngx_http_xxx_body_received(ngx_http_request_t *r)
{
[...]
ngx_http_xxx_do_get(r);
}
ngx_int_t ngx_http_xxx_do_get(ngx_http_request_t *r) {
[...]
/* Prepare BIG header and response */
[...]
rc = ngx_http_send_header(r);
if (rc != NGX_OK) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"pb sending header");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
return ngx_http_output_filter(r, out_chain);
}
At this point, any help is very much appreciated.
All this is against 0.8.53 but I don't see any difference in 0.9.5 that could
impact my problem.
Antoine.
Hello list!
I first sent this mail to nginx(a)nginx.org, but realized that this list is
probably more suitable. Especially since I got no response whatsoever :)
I wanted to use my nginx logs to power click track analysis like
http://statviz.sourceforge.net/ for example, and therefore I used the
userid module.
I realized quickly that it either sets $uid_set or $uid_got, never
both, which makes it hard to get one single column in the logfile that
entails the userid.
So I devised the following patch for this purpose:
-----------------------------------8<--------------------------------------------
--- nginx-0.7.67/src/http/modules/ngx_http_userid_filter_module.c
2010-06-07
11:54:19.000000000 +0200
+++ nginx-0.7.67-martin//src/http/modules/ngx_http_userid_filter_module.c
2011-02-24
13:16:20.000000000 +0100
@@ -275,9 +275,11 @@
ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module);
- if (ctx == NULL || ctx->uid_set[3] == 0) {
- v->not_found = 1;
- return NGX_OK;
+ if (ctx == NULL) {
+ v->not_found = 1;
+ return NGX_OK;
+ } else if (ctx->uid_set[3] == 0) {
+ return ngx_http_userid_got_variable(r, v, data);
}
conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
-----------------------------------8<--------------------------------------------
Since I have no real ambition to have my own fork of nginx, I would
love to hear about the possibilities to get this modification, or
another that solves my problem in a more nginxy way, into the main
branch.
regards,
//Martin Bruse
Thank you,i modify the Makefile directly and do fixing it complains,and it works.
2011-02-28
jyf832004
发件人: Adrian Perez <the.lightman(a)gmail.com>
发送时间: 2011-02-21 20:33
主 题: Re: cross compile nginx for the arm platform
收件人: nginx-devel(a)nginx.org
On Mon, 21 Feb 2011 14:16:36 +0300
Konstantin Baryshnikov <konstantin(a)symbi.org> wrote:
> On Mon, Feb 21, 2011 at 11:59 AM, jyf832004 <jyf832004(a)163.com> wrote:
>
> > Dear sir:
> > I want nginx work in the arm platform,so I need to cross compile
> > it.But the configure of nginx isn't the same as ordinary
> > auto-tools'.So it makes me feel
> > terrible.Is there any suggestion or tutorial for that.Thanks in
> > advance.
>
> There are nginx builds in the armel debian repositories <
> http://packages.debian.org/squeeze/armel/nginx/download>, you may
> find it useful to see their deb src.
If you are using Squeeze, I tend to make more-or-less regular builds
of the latest version of Nginx with some extra modules (fancyindex,
echo, chunkin, headers_more, upstream_fair, accesskey, http_push &
auth_pam) for ARM, conveniently distributed in an APT repository [1].
Cheers,
---
[1] http://apt.igalia.com/
--
-Adrian
_______________________________________________
nginx-devel mailing list
nginx-devel(a)nginx.org
http://nginx.org/mailman/listinfo/nginx-devel
Thanks!
this blew code is in limit_req module:
static ngx_int_t
ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash,
u_char *data, size_t len, ngx_uint_t *ep)
{
..................................................................
tp = ngx_timeofday();
now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
ms = (ngx_msec_int_t) (now - lr->last);
excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;
if (excess < 0) {
excess = 0;
}
*ep = excess;
if ((ngx_uint_t) excess > lrcf->burst) {
return NGX_BUSY;
}
...............................................
}
in this code , while two or more request in one milliseconds , excess will
be greater than 0, in addition burst is 0 in default , therefore
ngx_http_limit_req_lookup
will return NGX_BUSY, nginx will send 503 to client. but this situation is
not send 503 to client. this is limit_req's bug?
--
博观约取
豆瓣:www.douban.com/people/mustang/
blog: www.pagefault.info
twitter: www.twitter.com/minibobo