This commit is contained in:
Mario Fetka 2020-04-01 17:29:03 +02:00
parent 55fe1fbbdc
commit 8882e698cf
7 changed files with 39 additions and 96 deletions

View File

@ -12,11 +12,11 @@ all: .libs/mod_proxy_protocol.so
# build the so in the current directory # build the so in the current directory
.libs/mod_proxy_protocol.so: mod_proxy_protocol.c .libs/mod_proxy_protocol.so: mod_proxy_protocol.c
$(APXS) -c -Wc,-Wall mod_proxy_protocol.c $(APXS) -c mod_proxy_protocol.c
# install the so - usually needs root access # install the so - usually needs root access
install: .libs/mod_proxy_protocol.so install: .libs/mod_proxy_protocol.so
$(APXS) -i mod_proxy_protocol.la $(APXS) -i mod_proxy_protocol.c
# generate the html doc # generate the html doc
docs: mod_proxy_protocol.html docs: mod_proxy_protocol.html

View File

@ -4,10 +4,6 @@ This is an [Apache](http://httpd.apache.org/) module that implements the
server side of HAProxy's server side of HAProxy's
[Proxy Protocol](http://blog.haproxy.com/haproxy/proxy-protocol/). [Proxy Protocol](http://blog.haproxy.com/haproxy/proxy-protocol/).
Note: as of Apache 2.4.30 this code has been merged into
[mod_remoteip](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html),
with the `ProxyProtocol` directive renamed to `RemoteIPProxyProtocol`.
## Build and Install ## Build and Install
You'll need the apache development packages installed (typically something You'll need the apache development packages installed (typically something

12
debian/changelog vendored
View File

@ -1,15 +1,3 @@
mod-proxy-protocol (0.2-2) UNRELEASED; urgency=medium
* Add patch for CVE-2019-10097
-- Mario Fetka <mario.fetka@gmail.com> Wed, 12 Feb 2020 11:54:28 +0100
mod-proxy-protocol (0.2-1) xenial; urgency=low
* Merged patch to fix http/2 issues.
-- Roadrunner2 <roadrunner2@github.com> Tue, 20 Mar 2018 02:11:49 -0700
mod-proxy-protocol (0.1-1) trusty; urgency=low mod-proxy-protocol (0.1-1) trusty; urgency=low
* Initial release * Initial release

2
debian/control vendored
View File

@ -8,7 +8,7 @@ Homepage: https://github.com/roadrunner2/mod-proxy-protocol
Package: libapache2-mod-proxy-protocol Package: libapache2-mod-proxy-protocol
Architecture: amd64 Architecture: amd64
Depends: ${shlibs:Depends}, ${misc:Depends}, apache2-api-20120211 Depends: ${shlibs:Depends}, ${misc:Depends}, apache2-api-20120211, apache2 (>= 2.4.0)
Description: Apache module for proxy protocol Description: Apache module for proxy protocol
The proxy protocol is a way for upstream proxies and load-balancers to The proxy protocol is a way for upstream proxies and load-balancers to
for the ip-address of the client to the server. This package contains for the ip-address of the client to the server. This package contains

1
debian/docs vendored
View File

@ -1,4 +1,5 @@
README.md README.md
mod_proxy_protocol.xml mod_proxy_protocol.xml
mod_proxy_protocol.xml.meta mod_proxy_protocol.xml.meta
mod_proxy_protocol.html
debian/README.Debian debian/README.Debian

2
debian/rules vendored
View File

@ -4,7 +4,7 @@
build: build:
dh_testdir dh_testdir
make all # docs make all docs
clean: clean:
dh_testdir dh_testdir

View File

@ -80,37 +80,6 @@ static int pp_hook_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
return OK; return OK;
} }
#if !(APR_VERSION_AT_LEAST(1,5,0))
static APR_DECLARE(int) apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr)
{
static const char inaddr_any[
#if APR_HAVE_IPV6
sizeof(struct in6_addr)
#else
sizeof(struct in_addr)
#endif
] = {0};
if (addr->ipaddr_ptr /* IP address initialized */
&& addr->ipaddr_len <= sizeof inaddr_any) { /* else bug elsewhere? */
if (!memcmp(inaddr_any, addr->ipaddr_ptr, addr->ipaddr_len)) {
return 1;
}
#if APR_HAVE_IPV6
if (addr->family == AF_INET6
&& IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr)) {
struct in_addr *v4 = (struct in_addr *)&((apr_uint32_t *)addr->ipaddr_ptr)[3];
if (!memcmp(inaddr_any, v4, sizeof *v4)) {
return 1;
}
}
#endif
}
return 0;
}
#endif
/* Similar apr_sockaddr_equal, except that it compares ports too. */ /* Similar apr_sockaddr_equal, except that it compares ports too. */
static int pp_sockaddr_equal(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2) static int pp_sockaddr_equal(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2)
{ {
@ -123,19 +92,37 @@ static int pp_sockaddr_equal(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2)
static int pp_sockaddr_compat(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2) static int pp_sockaddr_compat(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2)
{ {
/* test exact address equality */ /* test exact address equality */
#if !(APR_VERSION_AT_LEAST(1,5,0))
apr_sockaddr_t addr0;
static const char inaddr_any[ sizeof(struct in_addr) ] = {0};
#endif
if (apr_sockaddr_equal(addr1, addr2) && if (apr_sockaddr_equal(addr1, addr2) &&
(addr1->port == addr2->port || addr1->port == 0 || addr2->port == 0)) { (addr1->port == addr2->port || addr1->port == 0 || addr2->port == 0)) {
return 1; return 1;
} }
#if APR_VERSION_AT_LEAST(1,5,0)
/* test address wildcards */ /* test address wildcards */
if (apr_sockaddr_is_wildcard(addr1) && if (apr_sockaddr_is_wildcard(addr1) &&
(addr1->port == 0 || addr1->port == addr2->port)) { (addr1->port == 0 || addr1->port == addr2->port)) {
#else
addr0.ipaddr_ptr = &inaddr_any;
addr0.ipaddr_len = addr1->ipaddr_len;
if (apr_sockaddr_equal(&addr0, addr1) &&
(addr1->port == 0 || addr1->port == addr2->port)) {
#endif
return 1; return 1;
} }
#if APR_VERSION_AT_LEAST (1,5,0)
if (apr_sockaddr_is_wildcard(addr2) && if (apr_sockaddr_is_wildcard(addr2) &&
(addr2->port == 0 || addr2->port == addr1->port)) { (addr2->port == 0 || addr2->port == addr1->port)) {
#else
addr0.ipaddr_len = addr2->ipaddr_len;
if (apr_sockaddr_equal(&addr0, addr2) &&
(addr2->port == 0 || addr2->port == addr1->port)) {
#endif
return 1; return 1;
} }
@ -333,18 +320,6 @@ static int pp_hook_pre_connection(conn_rec *c, void *csd)
pp_config *conf; pp_config *conf;
pp_conn_config *conn_conf; pp_conn_config *conn_conf;
/* Establish master config in slave connections, so that request
* processing finds it. */
if (c->master != NULL) {
conn_conf = ap_get_module_config(c->master->conn_config,
&proxy_protocol_module);
if (conn_conf) {
ap_set_module_config(c->conn_config, &proxy_protocol_module,
conn_conf);
}
return DECLINED;
}
/* check if we're enabled for this connection */ /* check if we're enabled for this connection */
conf = ap_get_module_config(ap_server_conf->module_config, conf = ap_get_module_config(ap_server_conf->module_config,
&proxy_protocol_module); &proxy_protocol_module);
@ -404,7 +379,7 @@ static pp_parse_status_t pp_process_v1_header(conn_rec *c,
proxy_header *hdr, apr_size_t len, proxy_header *hdr, apr_size_t len,
apr_size_t *hdr_len) apr_size_t *hdr_len)
{ {
char *end, *word, *host, *valid_addr_chars, *saveptr; char *end, *next, *word, *host, *valid_addr_chars, *saveptr;
char buf[sizeof(hdr->v1.line)]; char buf[sizeof(hdr->v1.line)];
apr_port_t port; apr_port_t port;
apr_status_t ret; apr_status_t ret;
@ -513,6 +488,8 @@ static pp_parse_status_t pp_process_v2_header(conn_rec *c,
proxy_header *hdr) proxy_header *hdr)
{ {
apr_status_t ret; apr_status_t ret;
struct in_addr *in_addr;
struct in6_addr *in6_addr;
switch (hdr->v2.ver_cmd & 0xF) { switch (hdr->v2.ver_cmd & 0xF) {
case 0x01: /* PROXY command */ case 0x01: /* PROXY command */
@ -550,17 +527,18 @@ static pp_parse_status_t pp_process_v2_header(conn_rec *c,
break; break;
default: default:
/* unsupported protocol */ /* unsupported protocol, keep local connection address */
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(10183) return HDR_DONE;
"RemoteIPProxyProtocol: unsupported protocol %.2hx",
(unsigned short)hdr->v2.fam);
return HDR_ERROR;
} }
break; /* we got a sockaddr now */ break; /* we got a sockaddr now */
case 0x00: /* LOCAL command */
/* keep local connection address for LOCAL */
return HDR_DONE;
default: default:
/* not a supported command */ /* not a supported command */
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c,
"ProxyProtocol: unsupported command %.2hx", "ProxyProtocol: unsupported command %.2hx",
hdr->v2.ver_cmd); hdr->v2.ver_cmd);
return HDR_ERROR; return HDR_ERROR;
@ -645,25 +623,12 @@ static apr_status_t pp_input_filter(ap_filter_t *f,
/* try to read a header's worth of data */ /* try to read a header's worth of data */
while (!ctx->done) { while (!ctx->done) {
if (APR_BRIGADE_EMPTY(ctx->bb)) { if (APR_BRIGADE_EMPTY(ctx->bb)) {
apr_off_t got, want = ctx->need - ctx->rcvd; ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block,
ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, want); ctx->need - ctx->rcvd);
if (ret != APR_SUCCESS) { if (ret != APR_SUCCESS) {
ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10184)
"failed reading input");
return ret; return ret;
} }
ret = apr_brigade_length(ctx->bb, 1, &got);
if (ret || got > want) {
ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10185)
"RemoteIPProxyProtocol header too long, "
"got %" APR_OFF_T_FMT " expected %" APR_OFF_T_FMT,
got, want);
f->c->aborted = 1;
return APR_ECONNABORTED;
} }
}
if (APR_BRIGADE_EMPTY(ctx->bb)) { if (APR_BRIGADE_EMPTY(ctx->bb)) {
return APR_EOF; return APR_EOF;
} }
@ -707,20 +672,13 @@ static apr_status_t pp_input_filter(ap_filter_t *f,
ctx->rcvd, &ctx->need); ctx->rcvd, &ctx->need);
} }
else if (ctx->version == 2) { else if (ctx->version == 2) {
proxy_header *hdr = (proxy_header *) ctx->header;
if (ctx->rcvd >= MIN_V2_HDR_LEN) { if (ctx->rcvd >= MIN_V2_HDR_LEN) {
ctx->need = MIN_V2_HDR_LEN + ntohs(hdr->v2.len); ctx->need = MIN_V2_HDR_LEN +
if (ctx->need > sizeof(proxy_v2)) { ntohs(((proxy_header *) ctx->header)->v2.len);
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(10186)
"RemoteIPProxyProtocol protocol header length too long");
f->c->aborted = 1;
apr_brigade_destroy(ctx->bb);
return APR_ECONNABORTED;
}
} }
if (ctx->rcvd >= ctx->need) { if (ctx->rcvd >= ctx->need) {
psts = pp_process_v2_header(f->c, conn_conf, hdr); psts = pp_process_v2_header(f->c, conn_conf,
(proxy_header *) ctx->header);
} }
} }
else { else {