Skip to content

Commit

Permalink
feat: run httpd rootless
Browse files Browse the repository at this point in the history
  • Loading branch information
theseion committed Apr 13, 2024
1 parent 01fce7e commit f9c6875
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 34 deletions.
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ You can achieve the same results just by getting any version you want, and using
git clone https://github.com/coreruleset/coreruleset.git myrules
cd myrules
git checkout ac2a0d1
docker run -p 80:80 -ti -e PARANOIA=4 -v rules:/opt/owasp-crs/rules:ro --rm owasp/modsecurity-crs
docker run -p 8080:8080 -ti -e PARANOIA=4 -v rules:/opt/owasp-crs/rules:ro --rm owasp/modsecurity-crs
```

## Quick reference
Expand Down Expand Up @@ -145,7 +145,7 @@ An example can be seen in the [docker-compose](https://github.com/coreruleset/mo
> 💬 What happens if I want to make changes in a different file, like `/etc/nginx/conf.d/default.conf`?
> You mount your local file, e.g. `nginx/default.conf` as the new template: `/etc/nginx/templates/conf.d/default.conf.template`. You can do this similarly with other files. Files in the templates directory will be copied and subdirectories will be preserved.
nginx is run with an **unprivileged user**. This means that we cannot bind to ports below 1024, so you might need to correct your `PORT` and `SSL_PORT` settings. Now the defaults for nginx are `8080` and `8443`.
Both nginx and httpd containers now run with an **unprivileged user**. This means that we cannot bind to ports below 1024, so you might need to correct your `PORT` and `SSL_PORT` settings. Now the defaults for both nginx and httpd are `8080` and `8443`.

### Common ENV Variables

Expand Down Expand Up @@ -181,10 +181,10 @@ These variables are common to image variants and will set defaults based on the
| APACHE_ERRORLOG_FORMAT | A string value indicating the `ErrorLogFormat` that Apache should use. (Default: `'"[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"'` |
| 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. |
| 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. |
| BACKEND_WS | A string indicating the IP/URL of the WebSocket service (Default: `ws://localhost:8080`) |
| BACKEND_WS | A string indicating the IP/URL of the WebSocket service (Default: `ws://localhost:8081`) |
| H2_PROTOCOLS | A string value indicating the protocols supported by the HTTP2 module (Default: `h2 http/1.1`) |
| 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`) |
| PORT | An int value indicating the port where the webserver is listening to | `80` | - |
| PORT | An int value indicating the port where the webserver is listening to | `8080` | - |
| 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`) |
| PROXY_PRESERVE_HOST | A string indicating the use of incoming Host HTTP request header for proxy request (Default: `on`) |
| PROXY_SSL_CA_CERT | A string indicating the path to the PEM-encoded list of accepted CA certificates for the proxied server (Default: `/etc/ssl/certs/ca-certificates.ca`) |
Expand All @@ -196,7 +196,7 @@ These variables are common to image variants and will set defaults based on the
| SERVER_TOKENS | Option defining the server information presented to clients in the `Server` HTTP response header. Also see `MODSEC_SERVER_SIGNATURE`. (Allowed values: `Full`, `Prod[uctOnly]`, `Major`, `Minor`, `Min[imal]`, `OS`. Default: `Full`). |
| SSL_ENGINE | A string indicating the SSL Engine Operation Switch (Default: `on`) |
| SSL_HONOR_CIPHER_ORDER | A string indicating if the server should [honor the cipher list provided by the client](https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslhonorcipherorder) (Allowed values: `on`, `off`. Default: `off`) |
| SSL_PORT | Port number where the SSL enabled webserver is listening | `443` | - |
| SSL_PORT | Port number where the SSL enabled webserver is listening | `8443` | - |
| SSL_SESSION_TICKETS | A string to enable or disable the use of [TLS session tickets](https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslsessiontickets) (RFC 5077). (Default: `off`) |
| TIMEOUT | Number of seconds before receiving and sending timeout (Default: `60`) |
| WORKER_CONNECTIONS | Maximum number of MPM request worker processes (Default: `400`) |
Expand Down Expand Up @@ -302,10 +302,10 @@ All these variables impact in configuration directives in the modsecurity engine
>
> ```bash
> docker build -t my-modsec .
> docker run -p 8443:443 my-modsec
> docker run -p 8443:8443 my-modsec
> ```
TLS is configured on port `443` and enabled by default.
TLS is configured on port `8443` and enabled by default.
We use sane intermediate defaults taken from the [Mozilla SSL config tool](https://ssl-config.mozilla.org/). Please review the defaults and choose the ones that best match your needs.
Expand All @@ -327,11 +327,11 @@ ModSecurity is often used in a reverse proxy setup with the following porperties
This allows one to use ModSecurity without modifying the webserver hosting the underlying application and also protects web servers that ModSecurity cannot currently be embedd into.
Tips:
* the application web server (the one receiving traffic from the reverse proxy) should not listen on a public interface. Only the reverse proxy should be exposed to the public. With Docker, this could meain setting up a network for both containers and only exposing the reverse proxy with `-p 8080:80`, for example. `docker compose` takes care of this automatically. See the `docker-compose.yaml` for an example setup.
* the application web server (the one receiving traffic from the reverse proxy) should not listen on a public interface. Only the reverse proxy should be exposed to the public. With Docker, this could meain setting up a network for both containers and only exposing the reverse proxy with `-p 8080:8080`, for example. `docker compose` takes care of this automatically. See the `docker-compose.yaml` for an example setup.
```bash
docker build -t my-modsec . -f
docker run -p 8080:80 -e BACKEND=http://example.com my-modsec
docker run -p 8080:8080 -e BACKEND=http://example.com my-modsec
```
## ServerName
Expand All @@ -340,7 +340,7 @@ It is often convenient to set your server name (set to `localhost` by defualt).

```bash
docker build -t modsec .
docker run -p 8080:80 -e SERVER_NAME=myhost my-modsec
docker run -p 8080:8080 -e SERVER_NAME=myhost my-modsec
```

## ModSecurity CRS Tuning
Expand All @@ -354,7 +354,7 @@ There are two possible ways to pass ModSecurity CRS tuning rules to the containe

```bash
docker run -dti --rm \
-p 80:80 \
-p 8080:8080 \
-v /path/to/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf:/etc/modsecurity.d/owasp-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf \
-v /path/to/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf:/etc/modsecurity.d/owasp-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf \
owasp/modsecurity-crs:apache
Expand All @@ -366,7 +366,7 @@ This example can be helpful when no volume mounts are possible (some CI pipeline

```bash
docker create -ti --name modseccrs \
-p 80:80 \
-p 8080:8080 \
owasp/modsecurity-crs:apache

docker cp /path/to/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf \
Expand All @@ -382,14 +382,14 @@ The following example illustrates how to use `docker run` with some of the varia
Some important things to note:
- Error and audit logs are enabled and mapped to files on the host, so that their contents are accessible and don't pollute the container filesystem. Docker requires these files to exist, otherwise they would be created as directories, hence the use of the `touch ...` commands.
- For containers with read-only filesystems, the volumes might have to be specified differently, e.g., using `tmpfs`. Alternatively, if only one log output is required, the output could be redirected to `stdout` (`/proc/self/fd/2`).
- The example expects a backend web server to be running at `localhost:8080`.
- The example expects a backend web server to be running at `localhost:8081`.

```bash
touch /tmp/host-fs-auditlog.log
touch /tmp/host-fs-errorlog.log
docker run \
-dti \
-p 80:80 \
-p 8080:8080 \
--rm \
-v /tmp/host-fs-auditlog.log:/var/log/modsec_audit.log \
-v /tmp/host-fs-errorlog.log:/var/log/modsec_error.log \
Expand Down Expand Up @@ -418,7 +418,7 @@ docker run \
-e TIMEOUT=60 \
-e SERVER_ADMIN=root@localhost \
-e SERVER_NAME=localhost \
-e PORT=80 \
-e PORT=8080 \
-e MODSEC_RULE_ENGINE=on \
-e MODSEC_REQ_BODY_ACCESS=on \
-e MODSEC_REQ_BODY_LIMIT=13107200 \
Expand All @@ -429,6 +429,6 @@ docker run \
-e MODSEC_PCRE_MATCH_LIMIT_RECURSION=1000 \
-e VALIDATE_UTF8_ENCODING=1 \
-e CRS_ENABLE_TEST_MARKER=1 \
-e BACKEND="http://localhost:8080" \
-e BACKEND="http://localhost:8081" \
owasp/modsecurity-crs:apache
```
25 changes: 16 additions & 9 deletions apache/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ ENV \
APACHE_ERRORLOG_FORMAT='"[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"' \
APACHE_LOGFORMAT='"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""' \
APACHE_METRICS_LOGFORMAT='"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""' \
BACKEND=http://localhost:80 \
BACKEND_WS=ws://localhost:8080 \
BACKEND=http://localhost:8080 \
BACKEND_WS=ws://localhost:8081 \
ERRORLOG='/proc/self/fd/2' \
H2_PROTOCOLS='h2 http/1.1' \
LOGLEVEL=warn \
Expand Down Expand Up @@ -109,7 +109,7 @@ ENV \
MODSEC_TMP_SAVE_UPLOADED_FILES="on" \
MODSEC_UPLOAD_DIR=/tmp/modsecurity/upload \
MUTEX='default' \
PORT=80 \
PORT=8080 \
PROXY_ERROR_OVERRIDE=on \
PROXY_PRESERVE_HOST=on \
PROXY_SSL_CA_CERT=/etc/ssl/certs/ca-certificates.crt \
Expand All @@ -133,7 +133,7 @@ ENV \
SSL_ENGINE=on \
SSL_HONOR_CIPHER_ORDER=off \
SSL_OCSP_STAPLING=On \
SSL_PORT=443 \
SSL_PORT=8443 \
SSL_PROTOCOLS="all -SSLv3 -TLSv1 -TLSv1.1" \
SSL_SESSION_TICKETS=off \
TIMEOUT=60 \
Expand All @@ -144,9 +144,9 @@ ENV \
ANOMALY_OUTBOUND=4 \
BLOCKING_PARANOIA=1

COPY --from=build /usr/local/apache2/modules/mod_security2.so /usr/local/apache2/modules/mod_security2.so
COPY --from=build /usr/local/apache2/ModSecurity-${MODSEC2_VERSION}/modsecurity.conf-recommended /etc/modsecurity.d/modsecurity.conf
COPY --from=build /usr/local/apache2/ModSecurity-${MODSEC2_VERSION}/unicode.mapping /etc/modsecurity.d/unicode.mapping
COPY --from=build /usr/local/apache2/modules/mod_security2.so /usr/local/apache2/modules/mod_security2.so
COPY --from=build /usr/local/apache2/ModSecurity-${MODSEC2_VERSION}/modsecurity.conf-recommended /etc/modsecurity.d/modsecurity.conf
COPY --from=build /usr/local/apache2/ModSecurity-${MODSEC2_VERSION}/unicode.mapping /etc/modsecurity.d/unicode.mapping
COPY --from=crs_release /opt/owasp-crs /opt/owasp-crs
COPY src/etc/modsecurity.d/*.conf /etc/modsecurity.d/
COPY src/bin/* /usr/local/bin/
Expand All @@ -173,6 +173,8 @@ RUN set -eux; \
apt-get clean; \
rm -rf /var/lib/apt/lists/*

RUN useradd --system httpd

RUN set -eux; \
mkdir -p /etc/modsecurity.d/; \
mkdir -p /tmp/modsecurity/data; \
Expand Down Expand Up @@ -204,8 +206,13 @@ RUN set -eux; \
echo 'Include conf/extra/httpd-locations.conf' >> /usr/local/apache2/conf/httpd.conf; \
echo 'Include conf/extra/httpd-modsecurity.conf' >> /usr/local/apache2/conf/httpd.conf; \
sed -i -E 's|(MaxRequestWorkers[ ]*)[0-9]*|\1${WORKER_CONNECTIONS}|' /usr/local/apache2/conf/extra/httpd-mpm.conf; \
chgrp -R 0 /var/log/ /usr/local/apache2/; \
chmod -R g=u /var/log/ /usr/local/apache2/
chown -R httpd:httpd \
/var/log/ \
/usr/local/apache2/ \
/etc/modsecurity.d \
/opt/owasp-crs

USER httpd

ENTRYPOINT ["/docker-entrypoint.sh"]

Expand Down
25 changes: 16 additions & 9 deletions apache/Dockerfile-alpine
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ ENV \
APACHE_ERRORLOG_FORMAT='"[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"' \
APACHE_LOGFORMAT='"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""' \
APACHE_METRICS_LOGFORMAT='"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""' \
BACKEND=http://localhost:80 \
BACKEND_WS=ws://localhost:8080 \
BACKEND=http://localhost:8080 \
BACKEND_WS=ws://localhost:8081 \
ERRORLOG='/proc/self/fd/2' \
H2_PROTOCOLS='h2 http/1.1' \
LOGLEVEL=warn \
Expand Down Expand Up @@ -119,7 +119,7 @@ ENV \
MODSEC_TMP_SAVE_UPLOADED_FILES="on" \
MODSEC_UPLOAD_DIR=/tmp/modsecurity/upload \
MUTEX='default' \
PORT=80 \
PORT=8080 \
PROXY_ERROR_OVERRIDE=on \
PROXY_PRESERVE_HOST=on \
PROXY_SSL_CA_CERT=/etc/ssl/certs/ca-certificates.crt \
Expand All @@ -143,7 +143,7 @@ ENV \
SSL_ENGINE=on \
SSL_HONOR_CIPHER_ORDER=off \
SSL_OCSP_STAPLING=On \
SSL_PORT=443 \
SSL_PORT=8443 \
SSL_PROTOCOLS="all -SSLv3 -TLSv1 -TLSv1.1" \
SSL_SESSION_TICKETS=off \
TIMEOUT=60 \
Expand All @@ -154,16 +154,18 @@ ENV \
ANOMALY_OUTBOUND=4 \
BLOCKING_PARANOIA=1

COPY --from=build /usr/local/apache2/modules/mod_security2.so /usr/local/apache2/modules/mod_security2.so
COPY --from=build /usr/local/apache2/ModSecurity-${MODSEC2_VERSION}/modsecurity.conf-recommended /etc/modsecurity.d/modsecurity.conf
COPY --from=build /usr/local/apache2/ModSecurity-${MODSEC2_VERSION}/unicode.mapping /etc/modsecurity.d/unicode.mapping
COPY --from=build /usr/local/apache2/modules/mod_security2.so /usr/local/apache2/modules/mod_security2.so
COPY --from=build /usr/local/apache2/ModSecurity-${MODSEC2_VERSION}/modsecurity.conf-recommended /etc/modsecurity.d/modsecurity.conf
COPY --from=build /usr/local/apache2/ModSecurity-${MODSEC2_VERSION}/unicode.mapping /etc/modsecurity.d/unicode.mapping
COPY --from=crs_release /opt/owasp-crs /opt/owasp-crs
COPY src/etc/modsecurity.d/*.conf /etc/modsecurity.d/
COPY src/bin/* /usr/local/bin/
COPY src/opt/modsecurity/activate-*.sh /opt/modsecurity/
COPY apache/conf/extra/*.conf /usr/local/apache2/conf/extra/
COPY apache/docker-entrypoint.sh /

RUN addgroup -S httpd && adduser -SH httpd httpd

RUN set -eux; \
apk add --no-cache \
ca-certificates \
Expand Down Expand Up @@ -208,8 +210,13 @@ RUN set -eux; \
mkdir -p /tmp/modsecurity/upload; \
mkdir -p /tmp/modsecurity/tmp; \
chown -R $(awk '/^User/ { print $2;}' /usr/local/apache2/conf/httpd.conf) /tmp/modsecurity /var/log/apache2; \
chgrp -R 0 /var/log/ /usr/local/apache2/; \
chmod -R g=u /var/log/ /usr/local/apache2/
chown -R httpd:httpd \
/var/log/ \
/usr/local/apache2/ \
/etc/modsecurity.d \
/opt/owasp-crs

USER httpd

HEALTHCHECK CMD /usr/local/bin/healthcheck

Expand Down

0 comments on commit f9c6875

Please sign in to comment.