Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/http
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2014-03-17 17:41:24 +0400
committerRoman Arutyunyan <arut@nginx.com>2014-03-17 17:41:24 +0400
commit0b5f3297849c6061cf07b359e8b42768889e28cd (patch)
tree5ae00cb3fd666a763e76baef6598a2edc577734e /src/http
parent2f917b6d0636bd62ab0dfce0cad28148b0e9b002 (diff)
Added server-side support for PROXY protocol v1 (ticket #355).
Client address specified in the PROXY protocol header is now saved in the $proxy_protocol_addr variable and can be used in the realip module. This is currently not implemented for mail.
Diffstat (limited to 'src/http')
-rw-r--r--src/http/modules/ngx_http_realip_module.c18
-rw-r--r--src/http/ngx_http.c1
-rw-r--r--src/http/ngx_http_core_module.c5
-rw-r--r--src/http/ngx_http_core_module.h2
-rw-r--r--src/http/ngx_http_request.c64
-rw-r--r--src/http/ngx_http_request.h3
-rw-r--r--src/http/ngx_http_spdy.c23
-rw-r--r--src/http/ngx_http_variables.c19
8 files changed, 131 insertions, 4 deletions
diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c
index b15954759..7a6211803 100644
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -13,6 +13,7 @@
#define NGX_HTTP_REALIP_XREALIP 0
#define NGX_HTTP_REALIP_XFWD 1
#define NGX_HTTP_REALIP_HEADER 2
+#define NGX_HTTP_REALIP_PROXY 3
typedef struct {
@@ -156,6 +157,18 @@ ngx_http_realip_handler(ngx_http_request_t *r)
break;
+ case NGX_HTTP_REALIP_PROXY:
+
+ value = &r->connection->proxy_protocol_addr;
+
+ if (value->len == 0) {
+ return NGX_DECLINED;
+ }
+
+ xfwd = NULL;
+
+ break;
+
default: /* NGX_HTTP_REALIP_HEADER */
part = &r->headers_in.headers.part;
@@ -343,6 +356,11 @@ ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_OK;
}
+ if (ngx_strcmp(value[1].data, "proxy_protocol") == 0) {
+ rlcf->type = NGX_HTTP_REALIP_PROXY;
+ return NGX_CONF_OK;
+ }
+
rlcf->type = NGX_HTTP_REALIP_HEADER;
rlcf->hash = ngx_hash_strlow(value[1].data, value[1].data, value[1].len);
rlcf->header = value[1];
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index c3ac7266c..ce5adb737 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1849,6 +1849,7 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
#if (NGX_HTTP_SPDY)
addrs[i].conf.spdy = addr[i].opt.spdy;
#endif
+ addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
if (addr[i].hash.buckets == NULL
&& (addr[i].wc_head == NULL
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 74a448a88..b023bdbc8 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -4287,6 +4287,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
}
+ if (ngx_strcmp(value[n].data, "proxy_protocol") == 0) {
+ lsopt.proxy_protocol = 1;
+ continue;
+ }
+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid parameter \"%V\"", &value[n]);
return NGX_CONF_ERROR;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 220c94ee4..799d2fe0d 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -82,6 +82,7 @@ typedef struct {
unsigned ipv6only:1;
#endif
unsigned so_keepalive:2;
+ unsigned proxy_protocol:1;
int backlog;
int rcvbuf;
@@ -243,6 +244,7 @@ struct ngx_http_addr_conf_s {
#if (NGX_HTTP_SPDY)
unsigned spdy:1;
#endif
+ unsigned proxy_protocol:1;
};
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 5f2cf7d39..4bf9d1fcf 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -343,6 +343,11 @@ ngx_http_init_connection(ngx_connection_t *c)
}
#endif
+ if (hc->addr_conf->proxy_protocol) {
+ hc->proxy_protocol = 1;
+ c->log->action = "reading PROXY protocol";
+ }
+
if (rev->ready) {
/* the deferred accept(), rtsig, aio, iocp */
@@ -368,6 +373,7 @@ ngx_http_init_connection(ngx_connection_t *c)
static void
ngx_http_wait_request_handler(ngx_event_t *rev)
{
+ u_char *p;
size_t size;
ssize_t n;
ngx_buf_t *b;
@@ -458,6 +464,27 @@ ngx_http_wait_request_handler(ngx_event_t *rev)
b->last += n;
+ if (hc->proxy_protocol) {
+ hc->proxy_protocol = 0;
+
+ p = ngx_proxy_protocol_parse(c, b->pos, b->last);
+
+ if (p == NULL) {
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ b->pos = p;
+
+ if (b->pos == b->last) {
+ c->log->action = "waiting for request";
+ b->pos = b->start;
+ b->last = b->start;
+ ngx_post_event(rev, &ngx_posted_events);
+ return;
+ }
+ }
+
c->log->action = "reading client request line";
ngx_reusable_connection(c, 0);
@@ -589,7 +616,8 @@ ngx_http_create_request(ngx_connection_t *c)
static void
ngx_http_ssl_handshake(ngx_event_t *rev)
{
- u_char buf[1];
+ u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1];
+ size_t size;
ssize_t n;
ngx_err_t err;
ngx_int_t rc;
@@ -598,6 +626,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
ngx_http_ssl_srv_conf_t *sscf;
c = rev->data;
+ hc = c->data;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
"http check ssl handshake");
@@ -613,7 +642,9 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
return;
}
- n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
+ size = hc->proxy_protocol ? sizeof(buf) : 1;
+
+ n = recv(c->fd, (char *) buf, size, MSG_PEEK);
err = ngx_socket_errno;
@@ -640,12 +671,39 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
return;
}
+ if (hc->proxy_protocol) {
+ hc->proxy_protocol = 0;
+
+ p = ngx_proxy_protocol_parse(c, buf, buf + n);
+
+ if (p == NULL) {
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ size = p - buf;
+
+ if (c->recv(c, buf, size) != (ssize_t) size) {
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ c->log->action = "SSL handshaking";
+
+ if (n == (ssize_t) size) {
+ ngx_post_event(rev, &ngx_posted_events);
+ return;
+ }
+
+ n = 1;
+ buf[0] = *p;
+ }
+
if (n == 1) {
if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
"https ssl handshake: 0x%02Xd", buf[0]);
- hc = c->data;
sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
ngx_http_ssl_module);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 3b0858ace..a1295e799 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -309,8 +309,9 @@ typedef struct {
ngx_int_t nfree;
#if (NGX_HTTP_SSL)
- ngx_uint_t ssl; /* unsigned ssl:1; */
+ unsigned ssl:1;
#endif
+ unsigned proxy_protocol:1;
} ngx_http_connection_t;
diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c
index 4005bfbe7..e9bad9444 100644
--- a/src/http/ngx_http_spdy.c
+++ b/src/http/ngx_http_spdy.c
@@ -95,6 +95,8 @@ static void ngx_http_spdy_read_handler(ngx_event_t *rev);
static void ngx_http_spdy_write_handler(ngx_event_t *wev);
static void ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc);
+static u_char *ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc,
+ u_char *pos, u_char *end);
static u_char *ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc,
u_char *pos, u_char *end);
static u_char *ngx_http_spdy_state_syn_stream(ngx_http_spdy_connection_t *sc,
@@ -421,6 +423,11 @@ ngx_http_spdy_init(ngx_event_t *rev)
sc->handler = ngx_http_spdy_state_head;
+ if (hc->proxy_protocol) {
+ c->log->action = "reading PROXY protocol";
+ sc->handler = ngx_http_spdy_proxy_protocol;
+ }
+
sc->zstream_in.zalloc = ngx_http_spdy_zalloc;
sc->zstream_in.zfree = ngx_http_spdy_zfree;
sc->zstream_in.opaque = sc;
@@ -810,6 +817,22 @@ ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc)
static u_char *
+ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc, u_char *pos,
+ u_char *end)
+{
+ pos = ngx_proxy_protocol_parse(sc->connection, pos, end);
+
+ if (pos == NULL) {
+ return ngx_http_spdy_state_protocol_error(sc);
+ }
+
+ sc->connection->log->action = "processing SPDY";
+
+ return ngx_http_spdy_state_complete(sc, pos, end);
+}
+
+
+static u_char *
ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos,
u_char *end)
{
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 8b86d5a9a..f61862297 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -54,6 +54,8 @@ static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
@@ -183,6 +185,9 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
{ ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },
+ { ngx_string("proxy_protocol_addr"), NULL,
+ ngx_http_variable_proxy_protocol_addr, 0, 0, 0 },
+
{ ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
{ ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },
@@ -1206,6 +1211,20 @@ ngx_http_variable_remote_port(ngx_http_request_t *r,
static ngx_int_t
+ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ v->len = r->connection->proxy_protocol_addr.len;
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = r->connection->proxy_protocol_addr.data;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_variable_server_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{