Compare commits

...

2 Commits

Author SHA1 Message Date
Mario Fetka
f39583fc05 Imported Upstream version 0.2 2020-04-01 17:24:46 +02:00
Mario Fetka
fe3c242f63 Imported Upstream version 0.1 2020-04-01 17:23:46 +02:00
14 changed files with 92 additions and 272 deletions

View File

@ -1,38 +0,0 @@
stages:
- build
- deploy
rpmbuild:
stage: build
image: gitlab-registry.cern.ch/cloud/ciadm
except:
- tags
script:
- if [ -z "$CI_BUILD_TAG" ]; then export CI_BUILD_TAG=$CI_DEFAULT_BUILD_TAG; fi
- export parser=(${CI_BUILD_TAG//-/ })
- sed -i s/CERN_VERSION_PLACEHOLDER/${parser[0]}/g mod_proxy_protocol.spec
- sed -i s/CERN_RELEASE_PLACEHOLDER/${parser[1]}/g mod_proxy_protocol.spec
- curl https://gitlab.cern.ch/cloud-infrastructure/cloud-dev/raw/master/gitlab/rpmbuild.sh | bash
kojicheck:
stage: build
image: gitlab-registry.cern.ch/cloud/ciadm
script:
- if [ -z "$CI_BUILD_TAG" ]; then export CI_BUILD_TAG=$CI_DEFAULT_BUILD_TAG; fi
- export parser=(${CI_BUILD_TAG//-/ })
- sed -i s/CERN_VERSION_PLACEHOLDER/${parser[0]}/g mod_proxy_protocol.spec
- sed -i s/CERN_RELEASE_PLACEHOLDER/${parser[1]}/g mod_proxy_protocol.spec
- curl https://gitlab.cern.ch/cloud-infrastructure/cloud-dev/raw/master/gitlab/kojicheck.sh | bash
kojibuild:
stage: deploy
image: gitlab-registry.cern.ch/cloud/ciadm
only:
- tags
script:
- export DIST='.el7.cern'
- if [ -z "$CI_BUILD_TAG" ]; then export CI_BUILD_TAG=$CI_DEFAULT_BUILD_TAG; fi
- export parser=(${CI_BUILD_TAG//-/ })
- sed -i s/CERN_VERSION_PLACEHOLDER/${parser[0]}/g mod_proxy_protocol.spec
- sed -i s/CERN_RELEASE_PLACEHOLDER/${parser[1]}/g mod_proxy_protocol.spec
- curl https://gitlab.cern.ch/cloud-infrastructure/cloud-dev/raw/master/gitlab/kojibuild.sh | bash

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 mod_proxy_protocol.c $(APXS) -c -Wc,-Wall 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.c $(APXS) -i mod_proxy_protocol.la
# generate the html doc # generate the html doc
docs: mod_proxy_protocol.html docs: mod_proxy_protocol.html

View File

@ -4,6 +4,10 @@ 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

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
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, apache2 (>= 2.4.0) Depends: ${shlibs:Depends}, ${misc:Depends}, apache2-api-20120211
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,5 +1,4 @@
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/lintian-overrides vendored Normal file
View File

@ -0,0 +1,2 @@
libapache2-mod-proxy-protocol: apache2-module-depends-on-real-apache2-package
libapache2-mod-proxy-protocol: copyright-should-refer-to-common-license-file-for-apache-2

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,6 +80,37 @@ 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)
{ {
@ -92,37 +123,19 @@ 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;
} }
@ -320,6 +333,18 @@ 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);
@ -379,7 +404,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, *next, *word, *host, *valid_addr_chars, *saveptr; char *end, *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;
@ -488,8 +513,6 @@ 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 */
@ -527,18 +550,17 @@ static pp_parse_status_t pp_process_v2_header(conn_rec *c,
break; break;
default: default:
/* unsupported protocol, keep local connection address */ /* unsupported protocol */
return HDR_DONE; ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(10183)
"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, ret, c, ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
"ProxyProtocol: unsupported command %.2hx", "ProxyProtocol: unsupported command %.2hx",
hdr->v2.ver_cmd); hdr->v2.ver_cmd);
return HDR_ERROR; return HDR_ERROR;
@ -623,12 +645,25 @@ 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)) {
ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, apr_off_t got, want = ctx->need - ctx->rcvd;
ctx->need - ctx->rcvd); ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, want);
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;
} }
@ -672,13 +707,20 @@ 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 + ctx->need = MIN_V2_HDR_LEN + ntohs(hdr->v2.len);
ntohs(((proxy_header *) ctx->header)->v2.len); if (ctx->need > sizeof(proxy_v2)) {
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, psts = pp_process_v2_header(f->c, conn_conf, hdr);
(proxy_header *) ctx->header);
} }
} }
else { else {

View File

@ -1,72 +0,0 @@
%{!?_httpd_apxs: %{expand: %%global _httpd_apxs %%{_sbindir}/apxs}}
%{!?_httpd_mmn: %{expand: %%global _httpd_mmn %%(cat %{_includedir}/httpd/.mmn || echo missing-httpd-devel)}}
%{!?_httpd_confdir: %{expand: %%global _httpd_confdir %%{_sysconfdir}/httpd/conf.d}}
# /etc/httpd/conf.d with httpd < 2.4 and defined as /etc/httpd/conf.modules.d with httpd >= 2.4
%{!?_httpd_modconfdir: %{expand: %%global _httpd_modconfdir %%{_sysconfdir}/httpd/conf.d}}
%{!?_httpd_moddir: %{expand: %%global _httpd_moddir %%{_libdir}/httpd/modules}}
%global cern_version CERN_VERSION_PLACEHOLDER
%global cern_release CERN_RELEASE_PLACEHOLDER
Name: mod_proxy_protocol
Summary: Apache module that implements the downstream server side of HAProxy's Proxy Protocol.
Version: %{cern_version}
Release: %{cern_release}%{?dist}
License: ASL 2.0
Group: System Environment/Daemons
Source0: %{name}-%{version}.tar.gz
BuildRequires: httpd-devel
BuildRequires: gcc
BuildRequires: libtool
Requires: httpd
Requires: httpd-mmn = %{_httpd_mmn}
# Suppress auto-provides for module DSO per
# https://fedoraproject.org/wiki/Packaging:AutoProvidesAndRequiresFiltering#Summary
%{?filter_provides_in: %filter_provides_in %{_libdir}/httpd/modules/.*\.so$}
%{?filter_setup}
%description
HAProxy's Proxy Protocol is a way for upstream proxies and load balancers to
report the IP address of the original remote client to the downstream server,
without having to modify things like HTTP headers in the actual payload.
This package contains an Apache module that implements the downstream (i.e. the
receiving) server side of this protocol, thereby allowing other modules to see
and use the actual client's IP address instead of that of the upstream proxy or
load balancer.
%prep
#%setup -q -n mod_proxy_protocol-%{version}
%setup -q -n %{name}-%{version}
%build
%{_httpd_apxs} -c mod_proxy_protocol.c
%install
rm -rf $RPM_BUILD_ROOT
install -Dm 755 .libs/mod_proxy_protocol.so $RPM_BUILD_ROOT%{_httpd_moddir}/mod_proxy_protocol.so
%if "%{_httpd_modconfdir}" == "%{_httpd_confdir}"
# httpd <= 2.2.x
cat redhat/proxy_protocol.module > unified.conf
echo >> unified.conf
cat redhat/proxy_protocol.conf >> unified.conf
touch -c -r redhat/proxy_protocol.conf unified.conf
install -Dp -m 644 unified.conf $RPM_BUILD_ROOT%{_httpd_confdir}/proxy_protocol.conf
%else
# httpd >= 2.4.x
install -Dp -m 644 redhat/proxy_protocol.module $RPM_BUILD_ROOT%{_httpd_modconfdir}/10-proxy_protocol.conf
install -Dp -m 644 redhat/proxy_protocol.conf $RPM_BUILD_ROOT%{_httpd_confdir}/proxy_protocol.conf
%endif
%files
%doc README.md LICENSE
%if "%{_httpd_modconfdir}" != "%{_httpd_confdir}"
%config(noreplace) %{_httpd_modconfdir}/10-proxy_protocol.conf
%endif
%config(noreplace) %{_httpd_confdir}/proxy_protocol.conf
%{_httpd_moddir}/*.so
%changelog
* Fri Dec 09 2016 Jose Castro Leon <jose.castro.leon@cern.ch> 0.1-1
- First package release.

View File

@ -1,48 +0,0 @@
--- mod_proxy_protocol.c-orig 2016-05-19 12:58:26.902187400 +0000
+++ mod_proxy_protocol.c 2016-05-19 13:24:25.417638197 +0000
@@ -44,6 +44,7 @@
#include "ap_config.h"
#include "ap_listen.h"
#include "apr_strings.h"
+#include "apr_version.h"
module AP_MODULE_DECLARE_DATA proxy_protocol_module;
@@ -91,19 +92,37 @@
static int pp_sockaddr_compat(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2)
{
/* 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) &&
(addr1->port == addr2->port || addr1->port == 0 || addr2->port == 0)) {
return 1;
}
+#if APR_VERSION_AT_LEAST(1,5,0)
/* test address wildcards */
if (apr_sockaddr_is_wildcard(addr1) &&
(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;
}
+#if APR_VERSION_AT_LEAST (1,5,0)
if (apr_sockaddr_is_wildcard(addr2) &&
(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;
}

View File

@ -1,71 +0,0 @@
%{!?_httpd_mmn: %{expand: %%global _httpd_mmn %%(cat %{_includedir}/httpd/.mmn || echo 0-0)}}
%{!?_httpd_apxs: %{expand: %%global _httpd_apxs %%{_sbindir}/apxs}}
%{!?_httpd_confdir: %{expand: %%global _httpd_confdir %%{_sysconfdir}/httpd/conf.d}}
# /etc/httpd/conf.d with httpd < 2.4 and defined as /etc/httpd/conf.modules.d with httpd >= 2.4
%{!?_httpd_modconfdir: %{expand: %%global _httpd_modconfdir %%{_sysconfdir}/httpd/conf.d}}
%{!?_httpd_moddir: %{expand: %%global _httpd_moddir %%{_libdir}/httpd/modules}}
Name: mod_proxy_protocol
Summary: Apache module that implements the downstream server side of HAProxy's Proxy Protocol.
Version: 0.1
Release: 1.20141031git62d2df6%{?dist}
License: ASL 2.0
Group: System Environment/Daemons
Source0: https://github.com/roadrunner2/mod-proxy-protocol/archive/62d2df6c94eb0a18605e47f6236c08130d7e120d.tar.gz
Source1: proxy_protocol.module
Source2: proxy_protocol.conf
Patch0: mod_proxy_protocol.c-fix-apr14-compat.patch
BuildRequires: httpd-devel
Requires: httpd
URL: https://github.com/roadrunner2/mod-proxy-protocol
# Suppress auto-provides for module DSO per
# https://fedoraproject.org/wiki/Packaging:AutoProvidesAndRequiresFiltering#Summary
%{?filter_provides_in: %filter_provides_in %{_libdir}/httpd/modules/.*\.so$}
%{?filter_setup}
%description
HAProxy's Proxy Protocol is a way for upstream proxies and load balancers to
report the IP address of the original remote client to the downstream server,
without having to modify things like HTTP headers in the actual payload.
This package contains an Apache module that implements the downstream (i.e. the
receiving) server side of this protocol, thereby allowing other modules to see
and use the actual client's IP address instead of that of the upstream proxy or
load balancer.
%prep
#%setup -q -n mod_proxy_protocol-%{version}
%setup -q -n mod-proxy-protocol-62d2df6c94eb0a18605e47f6236c08130d7e120d
%patch0 -p0 -F1
%build
%{_httpd_apxs} -c mod_proxy_protocol.c
%install
rm -rf $RPM_BUILD_ROOT
install -Dm 755 .libs/mod_proxy_protocol.so $RPM_BUILD_ROOT%{_httpd_moddir}/mod_proxy_protocol.so
%if "%{_httpd_modconfdir}" == "%{_httpd_confdir}"
# httpd <= 2.2.x
cat %{SOURCE1} > unified.conf
echo >> unified.conf
cat %{SOURCE2} >> unified.conf
touch -c -r %{SOURCE1} unified.conf
install -Dp -m 644 unified.conf $RPM_BUILD_ROOT%{_httpd_confdir}/proxy_protocol.conf
%else
# httpd >= 2.4.x
install -Dp -m 644 %{SOURCE1} $RPM_BUILD_ROOT%{_httpd_modconfdir}/10-proxy_protocol.conf
install -Dp -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_httpd_confdir}/proxy_protocol.conf
%endif
%files
%doc README.md LICENSE
%if "%{_httpd_modconfdir}" != "%{_httpd_confdir}"
%config(noreplace) %{_httpd_modconfdir}/10-proxy_protocol.conf
%endif
%config(noreplace) %{_httpd_confdir}/proxy_protocol.conf
%{_httpd_moddir}/*.so
%changelog
* Fri May 20 2016 earsdown <earsdown@github.com> 0.1-1.20141031git62d2df6
- First package release. Includes mamanguy patch to fix APR 1.4.x compatibility.

View File

@ -1,3 +0,0 @@
<IfModule mod_proxy_protocol.c>
#ProxyProtocol On
</IfModule>

View File

@ -1 +0,0 @@
LoadModule proxy_protocol_module modules/mod_proxy_protocol.so