Skip to content

Commit 12bc7e2

Browse files
authored
Merge pull request #372 from theseion/improve-http2-setup
feat: improve HTTP/2 configuration
2 parents 32b397c + d657062 commit 12bc7e2

9 files changed

Lines changed: 88 additions & 39 deletions

File tree

.github/workflows/verifyimage.yml

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,27 +88,90 @@ jobs:
8888
README.md \
8989
"${{ matrix.target }}.env"
9090
echo "Starting container ${{ matrix.target }}-verification"
91+
# The backend is a dummy
9192
docker run \
9293
--pull "never" \
9394
-d \
9495
--name ${{ matrix.target }}-test \
9596
--env-file "${{ matrix.target }}.env" \
97+
-p 8080:8080 \
98+
-e BACKEND=http://localhost:9999 \
9699
"${{ matrix.target }}-verification"
97-
sleep 30
98-
docker logs ${{ matrix.target }}-test
99100
100101
- name: Verify ${{ matrix.target }}
101102
run: |
102-
[ $(docker inspect ${{ matrix.target }}-test --format='{{.State.Running}}') = 'true' ]
103-
if grep -q "nginx "<<< "${{ matrix.target }}"; then
104-
curl -q -D headers.txt http://localhost:8080/?test=../../etc/passwd
103+
HOST_AND_PORT="localhost:8080"
104+
counter=10
105+
while true; do
106+
printf "Checking whether container is running..."
107+
if [ $(docker inspect ${{ matrix.target }}-test --format='{{.State.Running}}') = 'true' ]; then
108+
echo "ok"
109+
printf "Trying to connect..."
110+
if curl -s --connect-timeout 5 --max-time 1 "${HOST_AND_PORT}" > /dev/null 2>&1; then
111+
echo "ok"
112+
break
113+
fi
114+
fi
115+
116+
echo "failed"
117+
((counter--))
118+
if [ ${counter} -gt 0 ]; then
119+
echo "Will retry in 5 seconds"
120+
sleep 5
121+
else
122+
printf "No more retries. Here's the log output from the container\n\n\n"
123+
docker logs ${{ matrix.target }}-test
124+
exit 1
125+
fi
126+
done
127+
128+
if grep -q "nginx"<<< "${{ matrix.target }}"; then
129+
printf "\n\n### nginx tests ###\n\n"
130+
131+
printf "Storing headers for sample attack..."
132+
curl -s -D headers.txt -o /dev/null "${HOST_AND_PORT}/?test=../../etc/passwd"
133+
printf "...done\n\n\n"
134+
135+
printf "Check status 403..."
105136
grep -q "HTTP/1.1 403 Forbidden" headers.txt
137+
printf "yes\n\n\n"
138+
139+
printf "Check 'Access-Control-Allow-Origin' header..."
106140
grep -q "Access-Control-Allow-Origin: *" headers.txt
141+
printf "yes\n\n\n"
142+
143+
printf "Check 'Access-Control-Max-Age' header..."
107144
grep -q "Access-Control-Max-Age: 3600" headers.txt
145+
printf "yes\n\n\n"
146+
147+
printf "Check 'Access-Control-Allow-Methods' header..."
108148
grep -q "Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS" headers.txt
149+
printf "yes\n\n\n"
150+
151+
printf "Check 'Access-Control-Allow-Headers'..."
109152
grep -q "Access-Control-Allow-Headers: *" headers.txt
153+
printf "yes\n\n\n"
154+
155+
echo "### nginx tests - done ###"
110156
fi
111157
158+
printf "\n\n### generic tests ###\n\n"
159+
160+
echo "Test HTTP/2 upgrade..."
161+
curl -v --http2 --no-progress-meter -o /dev/null "${HOST_AND_PORT}" 2>&1 | tee out.txt
162+
grep -iP "< 101 Switching Protocols|< HTTP/2" < out.txt | tee out2.txt
163+
wc -l out2.txt | grep -qoP "\d+" | xargs -I % test % -eq 2
164+
rm out*.txt
165+
printf "...yes\n\n\n"
166+
167+
echo "Test HTTP/2 prior knowledge..."
168+
curl -v --http2-prior-knowledge --no-progress-meter -o /dev/null "${HOST_AND_PORT}" 2>&1 | tee out.txt
169+
grep -iq "< HTTP/2" out.txt
170+
grep -iqv "< 101 Switching Protocols" out.txt
171+
printf "...yes\n\n\n"
172+
173+
echo "### generic tests - done ###"
174+
112175
- name: Checkout CRS
113176
uses: actions/checkout@v4
114177
with:

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ These variables are common to image variants and will set defaults based on the
184184
| APACHE_LOGFORMAT | A string value indicating the LogFormat that apache should use. (Default: `'"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""'` (combined). Tip: use single quotes outside your double quoted format string.) ⚠️ Do not add a `|` as part of the log format. It is used internally. |
185185
| APACHE_METRICS_LOGFORMAT | A string value indicating the LogFormat that the additional log apache metrics should use. (Default:'"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""' (combined). Tip: use single quotes outside your double quoted format string.) ⚠️ Do not add a `|` as part of the log format. It is used internally. |
186186
| BACKEND_WS | A string indicating the IP/URL of the WebSocket service (Default: `ws://localhost:8081`) |
187-
| H2_PROTOCOLS | A string value indicating the protocols supported by the HTTP2 module (Default: `h2 http/1.1`) |
187+
| H2_DIRECT | A string indicating whether unencrypted HTTP/2 connections are allowed without upgrading from HTTP/1.1. This mode is also called "prior knowledge. (Allowed values: `on`, `off`. Default: `on`) |
188+
| H2_PROTOCOLS | A string value indicating the protocols supported by the HTTP/2 module (Default: `h2 h2c http/1.1`) |
188189
| MUTEX | Configure mutex and lock file directory for all specified mutexes (see [Mutex](https://httpd.apache.org/docs/2.4/mod/core.html#mutex)) (Default: `default`) |
189190
| PORT | An int value indicating the port where the webserver is listening to | `8080` | - |
190191
| PROXY_ERROR_OVERRIDE | A string indicating that errors from the backend services should be overridden by this proxy server (see [ProxyErrorOverride](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxyerroroverride) directive). (Allowed values: `on`, `off`. Default: `on`) |
@@ -215,6 +216,7 @@ These variables are common to image variants and will set defaults based on the
215216
| CORS_HEADER_403_CONTENT_TYPE | The value of the `Content-Type` header for `403` responses. Default: (`"text/plain"`) |
216217
| CORS_HEADER_403_MAX_AGE | The value of the [Access-Control-Max-Age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age) header for `403` responses. The number of seconds that preflight requests for this resource may be cached by the browser. (Default: `3600`) |
217218
| DNS_SERVER | Deprecated. Use `RESOLVERS`.
219+
| HTTP2 | A string value indicating whether HTTP/2 should be enabled (for all locations) (Allowed values: `on`, `off`. Default: `on`) |
218220
| KEEPALIVE_TIMEOUT | Number of seconds for a keep-alive client connection to stay open on the server side (Default: `60s`) |
219221
| NGINX_ALWAYS_TLS_REDIRECT | A string value indicating if http should redirect to https (Allowed values: `on`, `off`. Default: `off`) |
220222
| PORT | An int value indicating the port where the webserver is listening to | `8080` | We run as unprivileged user. |

apache/Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,11 @@ ENV \
7171
APACHE_ERRORLOG_FORMAT='"[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"' \
7272
APACHE_LOGFORMAT='"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""' \
7373
APACHE_METRICS_LOGFORMAT='"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""' \
74-
BACKEND=http://localhost:8080 \
74+
BACKEND=http://localhost:80 \
7575
BACKEND_WS=ws://localhost:8081 \
7676
ERRORLOG='/proc/self/fd/2' \
77-
H2_PROTOCOLS='h2 http/1.1' \
77+
H2_DIRECT=on \
78+
H2_PROTOCOLS='h2 h2c http/1.1' \
7879
LOGLEVEL=warn \
7980
METRICS_ALLOW_FROM='127.0.0.0/255.0.0.0 ::1/128' \
8081
METRICS_DENY_FROM='All' \

apache/Dockerfile-alpine

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ ENV \
8484
BACKEND=http://localhost:8080 \
8585
BACKEND_WS=ws://localhost:8081 \
8686
ERRORLOG='/proc/self/fd/2' \
87-
H2_PROTOCOLS='h2 http/1.1' \
87+
H2_DIRECT=on \
88+
H2_PROTOCOLS='h2 h2c http/1.1' \
8889
LOGLEVEL=warn \
8990
METRICS_ALLOW_FROM='127.0.0.0/255.0.0.0 ::1/128' \
9091
METRICS_DENY_FROM='All' \

apache/conf/extra/httpd-vhosts.conf

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,17 @@ SSLProxyCACertificateFile ${PROXY_SSL_CA_CERT}
3232
UseCanonicalName on
3333

3434
<VirtualHost *:${PORT}>
35-
RewriteEngine On
36-
RewriteCond %{REQUEST_URI} !^/\.well\-known/acme\-challenge/
37-
RewriteCond %{ENV:APACHE_ALWAYS_TLS_REDIRECT} on
38-
RewriteRule ^(.*)$ https://%{SERVER_NAME}:${SSL_PORT}$1 [L,R=301]
35+
Protocols ${H2_PROTOCOLS}
36+
H2Direct ${H2_DIRECT}
37+
RewriteEngine On
38+
RewriteCond %{REQUEST_URI} !^/\.well\-known/acme\-challenge/
39+
RewriteCond %{ENV:APACHE_ALWAYS_TLS_REDIRECT} on
40+
RewriteRule ^(.*)$ https://%{SERVER_NAME}:${SSL_PORT}$1 [L,R=301]
3941
</VirtualHost>
4042

4143
<VirtualHost *:${SSL_PORT}>
4244
Protocols ${H2_PROTOCOLS}
45+
H2Direct ${H2_DIRECT}
4346
SSLEngine ${SSL_ENGINE}
4447
SSLCertificateFile ${SSL_CERT}
4548
SSLCertificateKeyFile ${SSL_CERT_KEY}

docker-compose.yaml

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
11
# This docker-compose file starts owasp/modsecurity-crs
2-
#
3-
# ATTENTION!
4-
# Some of the environment variables at the bottom of this
5-
# docker-compose.yaml file and TLS are only available
6-
# for self-built images based on Dockerfile-2.9-apache,
7-
# and only if build args SETTLS and SETPROXY were set during
8-
# the build of the parent owasp/modsecurity:2.9-apache image.
9-
102
x-defaults: &default-settings
113
environment:
124
SERVERNAME: localhost
@@ -29,18 +21,6 @@ x-defaults: &default-settings
2921
# New in CRS 4
3022
REPORTING_LEVEL: 2
3123

32-
#######################################################
33-
# Reverse Proxy mode
34-
# (only available if SETPROXY was enabled during the
35-
# parent ModSecurity image)
36-
#######################################################
37-
# PROXYLOCATION: Application Backend of Reverse Proxy
38-
# PROXYLOCATION: http://app:8000/
39-
#
40-
# If needed: add own httpd-proxy.conf (only available if SETPROXY
41-
# was enabled during build of parent ModSecurity image)
42-
# - ./httpd-proxy.conf:/usr/local/apache2/conf/extra/httpd-proxy.conf
43-
4424
#######################################################
4525
# Various CRS Variables with Default Values
4626
#######################################################
@@ -73,8 +53,6 @@ x-defaults: &default-settings
7353

7454
#######################################################
7555
# Add TLS server certificate and key
76-
# (only available if SETPROXY was enabled during the
77-
# parent ModSecurity image)
7856
#######################################################
7957
# - ./server.crt:/usr/local/apache2/conf/server.crt
8058
# - ./server.key:/usr/local/apache2/conf/server.key
@@ -83,15 +61,13 @@ services:
8361
crs-apache:
8462
image: owasp/modsecurity-crs:apache
8563
ports:
86-
- "80:8080"
87-
# only available if SETTLS was enabled:
64+
- "8080:8080"
8865
- "443:8443"
8966
<<: *default-settings
9067

9168
crs-nginx:
9269
image: owasp/modsecurity-crs:nginx
9370
ports:
94-
- "80:8080"
95-
# only available if SETTLS was enabled:
71+
- "8080:8080"
9672
- "443:8443"
9773
<<: *default-settings

nginx/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ ENV \
135135
CORS_HEADER_403_MAX_AGE=3600 \
136136
CORS_HEADER_ACCESS_CONTROL_ALLOW_HEADERS="*" \
137137
ERRORLOG=/var/log/nginx/error.log \
138+
HTTP2=on \
138139
KEEPALIVE_TIMEOUT=60s \
139140
LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib \
140141
LOGLEVEL=warn \

nginx/Dockerfile-alpine

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ ENV \
136136
CORS_HEADER_403_MAX_AGE=3600 \
137137
CORS_HEADER_ACCESS_CONTROL_ALLOW_HEADERS="*" \
138138
ERRORLOG=/var/log/nginx/error.log \
139+
HTTP2=on \
139140
KEEPALIVE_TIMEOUT=60s \
140141
LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib \
141142
LOGLEVEL=warn \

nginx/templates/nginx.conf.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ http {
1414
default_type application/octet-stream;
1515
keepalive_timeout ${KEEPALIVE_TIMEOUT};
1616
sendfile on;
17+
http2 ${HTTP2};
1718

1819
resolver RESOLVERS RESOLVER_CONFIG;
1920
include /etc/nginx/conf.d/*.conf;

0 commit comments

Comments
 (0)