Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07be626842 | ||
|
|
3bb164395e | ||
|
|
bc2568a172 | ||
|
|
5ec74880d8 | ||
|
|
f84fd7c9a2 | ||
|
|
6521d7a27a | ||
|
|
813607fbc3 | ||
|
|
843644f806 | ||
|
|
19fa0eb25f | ||
|
|
b4df287228 | ||
|
|
5ce41edc03 | ||
|
|
a3cfb50b4d | ||
|
|
25494acace | ||
|
|
a98dae1fb6 | ||
|
|
1a7abab570 | ||
|
|
42b7a57f01 | ||
|
|
02f9fbe5fc | ||
|
|
69fe066777 | ||
|
|
74417abc9c | ||
|
|
ba7524a419 | ||
|
|
b55aafb997 | ||
|
|
deeb7a76a2 | ||
|
|
ee8aaa4e7e | ||
|
|
605d59a45c | ||
|
|
b85c991b6e | ||
|
|
0d3658adf0 | ||
|
|
0b22209c96 | ||
|
|
e44a1f3e14 | ||
|
|
aa614f82f9 | ||
|
|
c03d410b0a | ||
|
|
e190167bfc | ||
|
|
31e72dce1c | ||
|
|
b8105fc558 | ||
|
|
e73c10fd80 | ||
|
|
a122a259c0 | ||
|
|
7c4894d3b8 | ||
|
|
533c2a1034 | ||
|
|
5611d544d6 |
@@ -1,4 +1,4 @@
|
|||||||
FROM nginx:stable-alpine
|
FROM nginx:1.20.0-alpine
|
||||||
|
|
||||||
COPY nginx-keys/ /tmp/nginx-keys
|
COPY nginx-keys/ /tmp/nginx-keys
|
||||||
COPY compile.sh /tmp/compile.sh
|
COPY compile.sh /tmp/compile.sh
|
||||||
@@ -16,10 +16,13 @@ COPY lua/ /opt/lua
|
|||||||
COPY prepare.sh /tmp/prepare.sh
|
COPY prepare.sh /tmp/prepare.sh
|
||||||
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
|
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
|
||||||
|
|
||||||
|
# fix CVE-2021-20205
|
||||||
|
RUN apk add "libjpeg-turbo>=2.1.0-r0"
|
||||||
|
|
||||||
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
|
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
|
||||||
|
|
||||||
EXPOSE 8080/tcp 8443/tcp
|
EXPOSE 8080/tcp 8443/tcp
|
||||||
|
|
||||||
USER nginx
|
USER nginx:nginx
|
||||||
|
|
||||||
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]
|
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM amd64/nginx:stable-alpine
|
FROM amd64/nginx:1.20.0-alpine
|
||||||
|
|
||||||
COPY nginx-keys/ /tmp/nginx-keys
|
COPY nginx-keys/ /tmp/nginx-keys
|
||||||
COPY compile.sh /tmp/compile.sh
|
COPY compile.sh /tmp/compile.sh
|
||||||
@@ -16,10 +16,13 @@ COPY lua/ /opt/lua
|
|||||||
COPY prepare.sh /tmp/prepare.sh
|
COPY prepare.sh /tmp/prepare.sh
|
||||||
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
|
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
|
||||||
|
|
||||||
|
# fix CVE-2021-20205
|
||||||
|
RUN apk add "libjpeg-turbo>=2.1.0-r0"
|
||||||
|
|
||||||
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
|
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
|
||||||
|
|
||||||
EXPOSE 8080/tcp 8443/tcp
|
EXPOSE 8080/tcp 8443/tcp
|
||||||
|
|
||||||
USER nginx
|
USER nginx:nginx
|
||||||
|
|
||||||
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]
|
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ FROM alpine AS builder
|
|||||||
ENV QEMU_URL https://github.com/balena-io/qemu/releases/download/v4.0.0%2Bbalena2/qemu-4.0.0.balena2-arm.tar.gz
|
ENV QEMU_URL https://github.com/balena-io/qemu/releases/download/v4.0.0%2Bbalena2/qemu-4.0.0.balena2-arm.tar.gz
|
||||||
RUN apk add curl && curl -L ${QEMU_URL} | tar zxvf - -C . --strip-components 1
|
RUN apk add curl && curl -L ${QEMU_URL} | tar zxvf - -C . --strip-components 1
|
||||||
|
|
||||||
FROM arm32v7/nginx:stable-alpine
|
FROM arm32v7/nginx:1.20.0-alpine
|
||||||
|
|
||||||
COPY --from=builder qemu-arm-static /usr/bin
|
COPY --from=builder qemu-arm-static /usr/bin
|
||||||
|
|
||||||
@@ -23,10 +23,13 @@ COPY lua/ /opt/lua
|
|||||||
COPY prepare.sh /tmp/prepare.sh
|
COPY prepare.sh /tmp/prepare.sh
|
||||||
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
|
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
|
||||||
|
|
||||||
|
# fix CVE-2021-20205
|
||||||
|
RUN apk add "libjpeg-turbo>=2.1.0-r0"
|
||||||
|
|
||||||
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
|
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
|
||||||
|
|
||||||
EXPOSE 8080/tcp 8443/tcp
|
EXPOSE 8080/tcp 8443/tcp
|
||||||
|
|
||||||
USER nginx
|
USER nginx:nginx
|
||||||
|
|
||||||
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]
|
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ FROM alpine AS builder
|
|||||||
ENV QEMU_URL https://github.com/balena-io/qemu/releases/download/v4.0.0%2Bbalena2/qemu-4.0.0.balena2-aarch64.tar.gz
|
ENV QEMU_URL https://github.com/balena-io/qemu/releases/download/v4.0.0%2Bbalena2/qemu-4.0.0.balena2-aarch64.tar.gz
|
||||||
RUN apk add curl && curl -L ${QEMU_URL} | tar zxvf - -C . --strip-components 1
|
RUN apk add curl && curl -L ${QEMU_URL} | tar zxvf - -C . --strip-components 1
|
||||||
|
|
||||||
FROM arm64v8/nginx:stable-alpine
|
FROM arm64v8/nginx:1.20.0-alpine
|
||||||
|
|
||||||
COPY --from=builder qemu-aarch64-static /usr/bin
|
COPY --from=builder qemu-aarch64-static /usr/bin
|
||||||
|
|
||||||
@@ -23,10 +23,13 @@ COPY lua/ /opt/lua
|
|||||||
COPY prepare.sh /tmp/prepare.sh
|
COPY prepare.sh /tmp/prepare.sh
|
||||||
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
|
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
|
||||||
|
|
||||||
|
# fix CVE-2021-20205
|
||||||
|
RUN apk add "libjpeg-turbo>=2.1.0-r0"
|
||||||
|
|
||||||
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
|
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
|
||||||
|
|
||||||
EXPOSE 8080/tcp 8443/tcp
|
EXPOSE 8080/tcp 8443/tcp
|
||||||
|
|
||||||
USER nginx
|
USER nginx:nginx
|
||||||
|
|
||||||
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]
|
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM i386/nginx:stable-alpine
|
FROM i386/nginx:1.20.0-alpine
|
||||||
|
|
||||||
COPY nginx-keys/ /tmp/nginx-keys
|
COPY nginx-keys/ /tmp/nginx-keys
|
||||||
COPY compile.sh /tmp/compile.sh
|
COPY compile.sh /tmp/compile.sh
|
||||||
@@ -16,10 +16,13 @@ COPY lua/ /opt/lua
|
|||||||
COPY prepare.sh /tmp/prepare.sh
|
COPY prepare.sh /tmp/prepare.sh
|
||||||
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
|
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
|
||||||
|
|
||||||
|
# fix CVE-2021-20205
|
||||||
|
RUN apk add "libjpeg-turbo>=2.1.0-r0"
|
||||||
|
|
||||||
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
|
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
|
||||||
|
|
||||||
EXPOSE 8080/tcp 8443/tcp
|
EXPOSE 8080/tcp 8443/tcp
|
||||||
|
|
||||||
USER nginx
|
USER nginx:nginx
|
||||||
|
|
||||||
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]
|
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]
|
||||||
|
|||||||
96
README.md
96
README.md
@@ -3,12 +3,16 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://img.shields.io/badge/bunkerized--nginx-1.2.3-blue" />
|
<img src="https://img.shields.io/badge/bunkerized--nginx-1.2.4-blue" />
|
||||||
<img src="https://img.shields.io/badge/nginx-1.18.0-blue" />
|
<img src="https://img.shields.io/badge/nginx-1.20.0-blue" />
|
||||||
<img src="https://img.shields.io/github/last-commit/bunkerity/bunkerized-nginx" />
|
<img src="https://img.shields.io/github/last-commit/bunkerity/bunkerized-nginx" />
|
||||||
<a href="https://matrix.to/#/#bunkerized-nginx:matrix.org"><img src="https://img.shields.io/badge/matrix%20chat-%23bunkerized--nginx%3Amatrix.org-blue" /></a>
|
|
||||||
<img src="https://img.shields.io/github/workflow/status/bunkerity/bunkerized-nginx/Automatic%20test?label=automatic%20test" />
|
<img src="https://img.shields.io/github/workflow/status/bunkerity/bunkerized-nginx/Automatic%20test?label=automatic%20test" />
|
||||||
<img src="https://img.shields.io/docker/cloud/build/bunkerity/bunkerized-nginx" />
|
<img src="https://img.shields.io/docker/cloud/build/bunkerity/bunkerized-nginx" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://matrix.to/#/#bunkerized-nginx:matrix.org"><img src="https://img.shields.io/badge/matrix%20chat-%23bunkerized--nginx%3Amatrix.org-blue" /></a>
|
||||||
|
<a href="https://www.bunkerity.com"><img src="https://img.shields.io/badge/website-www.bunkerity.com-blue" /></a>
|
||||||
<a href="https://twitter.com/bunkerity"><img src="https://img.shields.io/twitter/follow/bunkerity?style=social" /></a>
|
<a href="https://twitter.com/bunkerity"><img src="https://img.shields.io/twitter/follow/bunkerity?style=social" /></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -34,9 +38,13 @@ Fooling automated tools/scanners :
|
|||||||
|
|
||||||
<img src="https://github.com/bunkerity/bunkerized-nginx/blob/master/demo.gif?raw=true" />
|
<img src="https://github.com/bunkerity/bunkerized-nginx/blob/master/demo.gif?raw=true" />
|
||||||
|
|
||||||
|
You can find a live demo at https://demo-nginx.bunkerity.com, feel free to do some security tests.
|
||||||
|
|
||||||
# Table of contents
|
# Table of contents
|
||||||
|
<details>
|
||||||
|
<summary>Click to show</summary>
|
||||||
|
|
||||||
- [Table of contents](#table-of-contents)
|
- [Table of contents](#table-of-contents)
|
||||||
- [Live demo](#live-demo)
|
|
||||||
- [Quickstart guide](#quickstart-guide)
|
- [Quickstart guide](#quickstart-guide)
|
||||||
* [Run HTTP server with default settings](#run-http-server-with-default-settings)
|
* [Run HTTP server with default settings](#run-http-server-with-default-settings)
|
||||||
* [In combination with PHP](#in-combination-with-php)
|
* [In combination with PHP](#in-combination-with-php)
|
||||||
@@ -85,9 +93,7 @@ Fooling automated tools/scanners :
|
|||||||
* [Logrotate](#logrotate)
|
* [Logrotate](#logrotate)
|
||||||
* [Cron jobs](#cron-jobs)
|
* [Cron jobs](#cron-jobs)
|
||||||
* [Misc](#misc-2)
|
* [Misc](#misc-2)
|
||||||
|
</details>
|
||||||
# Live demo
|
|
||||||
You can find a live demo at https://demo-nginx.bunkerity.com.
|
|
||||||
|
|
||||||
# Quickstart guide
|
# Quickstart guide
|
||||||
|
|
||||||
@@ -440,15 +446,32 @@ When `USE_ANTIBOT` is set to *captcha*, every users visiting your website must c
|
|||||||
|
|
||||||
## Hardening
|
## Hardening
|
||||||
|
|
||||||
|
### Drop capabilities
|
||||||
By default, *bunkerized-nginx* runs as non-root user inside the container and should not use any of the default [capabilities](https://docs.docker.com/engine/security/#linux-kernel-capabilities) allowed by Docker. You can safely remove all capabilities to harden the container :
|
By default, *bunkerized-nginx* runs as non-root user inside the container and should not use any of the default [capabilities](https://docs.docker.com/engine/security/#linux-kernel-capabilities) allowed by Docker. You can safely remove all capabilities to harden the container :
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker run ... --drop-cap=all ... bunkerity/bunkerized-nginx
|
docker run ... --drop-cap=all ... bunkerity/bunkerized-nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### User namespace remap
|
||||||
|
Another hardening trick is [user namespace remapping](https://docs.docker.com/engine/security/userns-remap/) : it allows you to map the UID/GID of users inside a container to another UID/GID on the host. For example, you can map the user nginx with UID/GID 101 inside the container to a non-existent user with UID/GID 100101 on the host.
|
||||||
|
|
||||||
|
Let's assume you have the /etc/subuid and /etc/subgid files like this :
|
||||||
|
```
|
||||||
|
user:100000:65536
|
||||||
|
```
|
||||||
|
It means that everything done inside the container will be remapped to UID/GID 100101 (100000 + 101) on the host.
|
||||||
|
|
||||||
|
Please note that you must set the rights on the volumes (e.g. : /etc/letsencrypt, /www, ...) according to the remapped UID/GID :
|
||||||
|
```shell
|
||||||
|
$ chown root:100101 /path/to/letsencrypt
|
||||||
|
$ chmod 770 /path/to/letsencrypt
|
||||||
|
$ docker run ... -v /path/to/letsencrypt:/etc/letsencrypt ... bunkerity/bunkerized-nginx
|
||||||
|
```
|
||||||
|
|
||||||
# Tutorials and examples
|
# Tutorials and examples
|
||||||
|
|
||||||
You will find some docker-compose examples in the [examples directory](https://github.com/bunkerity/bunkerized-nginx/tree/master/examples).
|
You will find some docker-compose examples in the [examples directory](https://github.com/bunkerity/bunkerized-nginx/tree/master/examples) and tutorials on our [blog](https://www.bunkerity.com/blog).
|
||||||
|
|
||||||
# Include custom configurations
|
# Include custom configurations
|
||||||
Custom configurations files (ending with .conf suffix) can be added in some directory inside the container :
|
Custom configurations files (ending with .conf suffix) can be added in some directory inside the container :
|
||||||
@@ -648,11 +671,10 @@ Only valid when `USE_REVERSE_PROXY` is set to *yes*. Set it to *yes* when the co
|
|||||||
You can set multiple url/host by adding a suffix number to the variable name like this : `REVERSE_PROXY_WS_1`, `REVERSE_PROXY_WS_2`, `REVERSE_PROXY_WS_3`, ...
|
You can set multiple url/host by adding a suffix number to the variable name like this : `REVERSE_PROXY_WS_1`, `REVERSE_PROXY_WS_2`, `REVERSE_PROXY_WS_3`, ...
|
||||||
|
|
||||||
`REVERSE_PROXY_HEADERS`
|
`REVERSE_PROXY_HEADERS`
|
||||||
Values : *\<list of custom headers separated with a semicolon\>*
|
Values : *\<list of custom headers separated with a semicolon like this : header1 value1;header2 value2...\>*
|
||||||
Examples : Access-Control-Allow-Origin 'https://mydomain.dev'; Custom_Api_Header 'test';
|
Default value :
|
||||||
Default value : ""
|
|
||||||
Context : *global*, *multisite*
|
Context : *global*, *multisite*
|
||||||
Only valid when `USE_REVERSE_PROXY` is set to *yes*. Set it to *yes* when the corresponding `REVERSE_PROXY_HOST` is a WebSocket server.
|
Only valid when `USE_REVERSE_PROXY` is set to *yes*.
|
||||||
You can set multiple url/host by adding a suffix number to the variable name like this : `REVERSE_PROXY_HEADERS_1`, `REVERSE_PROXY_HEADERS_2`, `REVERSE_PROXY_HEADERS_3`, ...
|
You can set multiple url/host by adding a suffix number to the variable name like this : `REVERSE_PROXY_HEADERS_1`, `REVERSE_PROXY_HEADERS_2`, `REVERSE_PROXY_HEADERS_3`, ...
|
||||||
|
|
||||||
`PROXY_REAL_IP`
|
`PROXY_REAL_IP`
|
||||||
@@ -876,19 +898,19 @@ If set to yes, nginx will redirect all HTTP requests to HTTPS.
|
|||||||
`USE_CUSTOM_HTTPS`
|
`USE_CUSTOM_HTTPS`
|
||||||
Values : *yes* | *no*
|
Values : *yes* | *no*
|
||||||
Default value : *no*
|
Default value : *no*
|
||||||
Context : *global*
|
Context : *global*, *multisite*
|
||||||
If set to yes, HTTPS will be enabled with certificate/key of your choice.
|
If set to yes, HTTPS will be enabled with certificate/key of your choice.
|
||||||
|
|
||||||
`CUSTOM_HTTPS_CERT`
|
`CUSTOM_HTTPS_CERT`
|
||||||
Values : *\<any valid path inside the container\>*
|
Values : *\<any valid path inside the container\>*
|
||||||
Default value :
|
Default value :
|
||||||
Context : *global*
|
Context : *global*, *multisite*
|
||||||
Full path of the certificate file to use when `USE_CUSTOM_HTTPS` is set to yes.
|
Full path of the certificate file to use when `USE_CUSTOM_HTTPS` is set to yes.
|
||||||
|
|
||||||
`CUSTOM_HTTPS_KEY`
|
`CUSTOM_HTTPS_KEY`
|
||||||
Values : *\<any valid path inside the container\>*
|
Values : *\<any valid path inside the container\>*
|
||||||
Default value :
|
Default value :
|
||||||
Context : *global*
|
Context : *global*, *multisite*
|
||||||
Full path of the key file to use when `USE_CUSTOM_HTTPS` is set to yes.
|
Full path of the key file to use when `USE_CUSTOM_HTTPS` is set to yes.
|
||||||
|
|
||||||
### Self-signed certificate
|
### Self-signed certificate
|
||||||
@@ -1173,10 +1195,10 @@ Context : *global*, *multisite*
|
|||||||
If set to *yes*, lets you define custom IP addresses to be whitelisted through the `WHITELIST_IP_LIST` environment variable.
|
If set to *yes*, lets you define custom IP addresses to be whitelisted through the `WHITELIST_IP_LIST` environment variable.
|
||||||
|
|
||||||
`WHITELIST_IP_LIST`
|
`WHITELIST_IP_LIST`
|
||||||
Values : *\<list of IP addresses separated with spaces\>*
|
Values : *\<list of IP addresses and/or network CIDR blocks separated with spaces\>*
|
||||||
Default value : *23.21.227.69 40.88.21.235 50.16.241.113 50.16.241.114 50.16.241.117 50.16.247.234 52.204.97.54 52.5.190.19 54.197.234.188 54.208.100.253 54.208.102.37 107.21.1.8*
|
Default value : *23.21.227.69 40.88.21.235 50.16.241.113 50.16.241.114 50.16.241.117 50.16.247.234 52.204.97.54 52.5.190.19 54.197.234.188 54.208.100.253 54.208.102.37 107.21.1.8*
|
||||||
Context : *global*
|
Context : *global*
|
||||||
The list of IP addresses to whitelist when `USE_WHITELIST_IP` is set to *yes*. The default list contains IP addresses of the [DuckDuckGo crawler](https://help.duckduckgo.com/duckduckgo-help-pages/results/duckduckbot/).
|
The list of IP addresses and/or network CIDR blocks to whitelist when `USE_WHITELIST_IP` is set to *yes*. The default list contains IP addresses of the [DuckDuckGo crawler](https://help.duckduckgo.com/duckduckgo-help-pages/results/duckduckbot/).
|
||||||
|
|
||||||
`USE_WHITELIST_REVERSE`
|
`USE_WHITELIST_REVERSE`
|
||||||
Values : *yes* | *no*
|
Values : *yes* | *no*
|
||||||
@@ -1196,6 +1218,12 @@ Default value :
|
|||||||
Context : *global*, *multisite*
|
Context : *global*, *multisite*
|
||||||
Whitelist user agent from being blocked by `BLOCK_USER_AGENT`.
|
Whitelist user agent from being blocked by `BLOCK_USER_AGENT`.
|
||||||
|
|
||||||
|
`WHITELIST_URI`
|
||||||
|
Values : *\<list of URI separated with spaces\>*
|
||||||
|
Default value :
|
||||||
|
Context : *global*, *multisite*
|
||||||
|
URI listed here have security checks like bad user-agents, bad IP, ... disabled. Useful when using callbacks for example.
|
||||||
|
|
||||||
### Custom blacklisting
|
### Custom blacklisting
|
||||||
|
|
||||||
`USE_BLACKLIST_IP`
|
`USE_BLACKLIST_IP`
|
||||||
@@ -1205,10 +1233,10 @@ Context : *global*, *multisite*
|
|||||||
If set to *yes*, lets you define custom IP addresses to be blacklisted through the `BLACKLIST_IP_LIST` environment variable.
|
If set to *yes*, lets you define custom IP addresses to be blacklisted through the `BLACKLIST_IP_LIST` environment variable.
|
||||||
|
|
||||||
`BLACKLIST_IP_LIST`
|
`BLACKLIST_IP_LIST`
|
||||||
Values : *\<list of IP addresses separated with spaces\>*
|
Values : *\<list of IP addresses and/or network CIDR blocks separated with spaces\>*
|
||||||
Default value :
|
Default value :
|
||||||
Context : *global*
|
Context : *global*
|
||||||
The list of IP addresses to blacklist when `USE_BLACKLIST_IP` is set to *yes*.
|
The list of IP addresses and/or network CIDR blocks to blacklist when `USE_BLACKLIST_IP` is set to *yes*.
|
||||||
|
|
||||||
`USE_BLACKLIST_REVERSE`
|
`USE_BLACKLIST_REVERSE`
|
||||||
Values : *yes* | *no*
|
Values : *yes* | *no*
|
||||||
@@ -1228,18 +1256,18 @@ The list of reverse DNS suffixes to blacklist when `USE_BLACKLIST_REVERSE` is se
|
|||||||
Values : *yes* | *no*
|
Values : *yes* | *no*
|
||||||
Default value : *yes*
|
Default value : *yes*
|
||||||
Context : *global*, *multisite*
|
Context : *global*, *multisite*
|
||||||
If set to yes, the amount of HTTP requests made by a user will be limited during a period of time.
|
If set to yes, the amount of HTTP requests made by a user for a given resource will be limited during a period of time.
|
||||||
More info rate limiting [here](https://www.nginx.com/blog/rate-limiting-nginx/).
|
More info rate limiting [here](https://www.nginx.com/blog/rate-limiting-nginx/) (the key used is $binary_remote_addr$uri).
|
||||||
|
|
||||||
`LIMIT_REQ_RATE`
|
`LIMIT_REQ_RATE`
|
||||||
Values : *Xr/s* | *Xr/m*
|
Values : *Xr/s* | *Xr/m*
|
||||||
Default value : *20r/s*
|
Default value : *1r/s*
|
||||||
Context : *global*, *multisite*
|
Context : *global*, *multisite*
|
||||||
The rate limit to apply when `USE_LIMIT_REQ` is set to *yes*. Default is 10 requests per second.
|
The rate limit to apply when `USE_LIMIT_REQ` is set to *yes*. Default is 1 request to the same URI and from the same IP per second.
|
||||||
|
|
||||||
`LIMIT_REQ_BURST`
|
`LIMIT_REQ_BURST`
|
||||||
Values : *<any valid integer\>*
|
Values : *<any valid integer\>*
|
||||||
Default value : *40*
|
Default value : *2*
|
||||||
Context : *global*, *multisite*
|
Context : *global*, *multisite*
|
||||||
The number of requests to put in queue before rejecting requests.
|
The number of requests to put in queue before rejecting requests.
|
||||||
|
|
||||||
@@ -1255,12 +1283,12 @@ The size of the cache to store information about request limiting.
|
|||||||
Values : *yes* | *no*
|
Values : *yes* | *no*
|
||||||
Default value : *yes*
|
Default value : *yes*
|
||||||
Context : *global*, *multisite*
|
Context : *global*, *multisite*
|
||||||
If set to yes, the number of connections made by an ip will be limited during a period of time. (ie. Very small/weak ddos protection)
|
If set to yes, the number of connections made by an ip will be limited during a period of time. (ie. very small/weak ddos protection)
|
||||||
More info connections limiting [here](http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html).
|
More info connections limiting [here](http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html).
|
||||||
|
|
||||||
`LIMIT_CONN_MAX`
|
`LIMIT_CONN_MAX`
|
||||||
Values : *<any valid integer\>*
|
Values : *<any valid integer\>*
|
||||||
Default value : *40*
|
Default value : *50*
|
||||||
Context : *global*, *multisite*
|
Context : *global*, *multisite*
|
||||||
The maximum number of connections per ip to put in queue before rejecting requests.
|
The maximum number of connections per ip to put in queue before rejecting requests.
|
||||||
|
|
||||||
@@ -1290,7 +1318,7 @@ Only allow specific countries accessing your website. Use 2 letters country code
|
|||||||
Values : *\<any valid IP/hostname\>*
|
Values : *\<any valid IP/hostname\>*
|
||||||
Default value :
|
Default value :
|
||||||
Context : *global*, *multisite*
|
Context : *global*, *multisite*
|
||||||
Set the IP/hostname address of a remote PHP-FPM to execute .php files. See `USE_PHP` if you want to run a PHP-FPM instance on the same container as bunkerized-nginx.
|
Set the IP/hostname address of a remote PHP-FPM to execute .php files.
|
||||||
|
|
||||||
`REMOTE_PHP_PATH`
|
`REMOTE_PHP_PATH`
|
||||||
Values : *\<any valid absolute path\>*
|
Values : *\<any valid absolute path\>*
|
||||||
@@ -1358,6 +1386,14 @@ Default value : *yes*
|
|||||||
Context : *global*
|
Context : *global*
|
||||||
If set to yes, ClamAV will automatically remove the detected files.
|
If set to yes, ClamAV will automatically remove the detected files.
|
||||||
|
|
||||||
|
## Syslog
|
||||||
|
|
||||||
|
`REMOTE_SYSLOG`
|
||||||
|
Values : *\<any IP/hostname\>*
|
||||||
|
Default value :
|
||||||
|
Context : *global*
|
||||||
|
When defined, rsyslog will send logs (access.log and error.log) to the corresponding IP/hostname using syslog UDP protocol.
|
||||||
|
|
||||||
## Logrotate
|
## Logrotate
|
||||||
|
|
||||||
`LOGROTATE_MINSIZE`
|
`LOGROTATE_MINSIZE`
|
||||||
@@ -1453,3 +1489,9 @@ Values : *random* | *\<any valid URI path\>*
|
|||||||
Default value : *random*
|
Default value : *random*
|
||||||
Context : *global*
|
Context : *global*
|
||||||
Set it to a random path when you use *bunkerized-nginx* with *autoconf* feature in swarm mode. More info [here](#swarm-mode).
|
Set it to a random path when you use *bunkerized-nginx* with *autoconf* feature in swarm mode. More info [here](#swarm-mode).
|
||||||
|
|
||||||
|
`API_WHITELIST_IP`
|
||||||
|
Values : *\<list of IP/CIDR separated with space\>*
|
||||||
|
Default value : *192.168.0.0/16 172.16.0.0/12 10.0.0.0/8*
|
||||||
|
Context : *global*
|
||||||
|
List of IP/CIDR block allowed to send API order using the `API_URI` uri.
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ class AutoConf :
|
|||||||
self.__sites = {}
|
self.__sites = {}
|
||||||
self.__config = Config(self.__swarm, api)
|
self.__config = Config(self.__swarm, api)
|
||||||
|
|
||||||
|
def get_server(self, id) :
|
||||||
|
if id in self.__servers :
|
||||||
|
return self.__servers[id]
|
||||||
|
return False
|
||||||
|
|
||||||
def reload(self) :
|
def reload(self) :
|
||||||
return self.__config.reload(self.__instances)
|
return self.__config.reload(self.__instances)
|
||||||
|
|
||||||
@@ -60,9 +65,9 @@ class AutoConf :
|
|||||||
self.__instances[id] = instance
|
self.__instances[id] = instance
|
||||||
if self.__swarm and len(self.__instances) == 1 :
|
if self.__swarm and len(self.__instances) == 1 :
|
||||||
if self.__config.initconf(self.__instances) :
|
if self.__config.initconf(self.__instances) :
|
||||||
utils.log("[*] initial config succeeded")
|
utils.log("[*] Initial config succeeded")
|
||||||
else :
|
else :
|
||||||
utils.log("[!] initial config failed")
|
utils.log("[!] Initial config failed")
|
||||||
utils.log("[*] bunkerized-nginx instance created : " + name + " / " + id)
|
utils.log("[*] bunkerized-nginx instance created : " + name + " / " + id)
|
||||||
elif event == "start" :
|
elif event == "start" :
|
||||||
self.__instances[id].reload()
|
self.__instances[id].reload()
|
||||||
@@ -82,10 +87,12 @@ class AutoConf :
|
|||||||
def __process_server(self, instance, event, id, name, labels) :
|
def __process_server(self, instance, event, id, name, labels) :
|
||||||
vars = { k.replace("bunkerized-nginx.", "", 1) : v for k, v in labels.items() if k.startswith("bunkerized-nginx.")}
|
vars = { k.replace("bunkerized-nginx.", "", 1) : v for k, v in labels.items() if k.startswith("bunkerized-nginx.")}
|
||||||
if event == "create" :
|
if event == "create" :
|
||||||
|
utils.log("[*] Generating config for " + vars["SERVER_NAME"] + " ...")
|
||||||
if self.__config.generate(self.__instances, vars) :
|
if self.__config.generate(self.__instances, vars) :
|
||||||
utils.log("[*] Generated config for " + vars["SERVER_NAME"])
|
utils.log("[*] Generated config for " + vars["SERVER_NAME"])
|
||||||
self.__servers[id] = instance
|
self.__servers[id] = instance
|
||||||
if self.__swarm :
|
if self.__swarm :
|
||||||
|
utils.log("[*] Activating config for " + vars["SERVER_NAME"] + " ...")
|
||||||
if self.__config.activate(self.__instances, vars) :
|
if self.__config.activate(self.__instances, vars) :
|
||||||
utils.log("[*] Activated config for " + vars["SERVER_NAME"])
|
utils.log("[*] Activated config for " + vars["SERVER_NAME"])
|
||||||
else :
|
else :
|
||||||
@@ -95,6 +102,7 @@ class AutoConf :
|
|||||||
elif event == "start" :
|
elif event == "start" :
|
||||||
if id in self.__servers :
|
if id in self.__servers :
|
||||||
self.__servers[id].reload()
|
self.__servers[id].reload()
|
||||||
|
utils.log("[*] Activating config for " + vars["SERVER_NAME"] + " ...")
|
||||||
if self.__config.activate(self.__instances, vars) :
|
if self.__config.activate(self.__instances, vars) :
|
||||||
utils.log("[*] Activated config for " + vars["SERVER_NAME"])
|
utils.log("[*] Activated config for " + vars["SERVER_NAME"])
|
||||||
else :
|
else :
|
||||||
@@ -102,6 +110,7 @@ class AutoConf :
|
|||||||
elif event == "die" :
|
elif event == "die" :
|
||||||
if id in self.__servers :
|
if id in self.__servers :
|
||||||
self.__servers[id].reload()
|
self.__servers[id].reload()
|
||||||
|
utils.log("[*] Deactivating config for " + vars["SERVER_NAME"])
|
||||||
if self.__config.deactivate(self.__instances, vars) :
|
if self.__config.deactivate(self.__instances, vars) :
|
||||||
utils.log("[*] Deactivated config for " + vars["SERVER_NAME"])
|
utils.log("[*] Deactivated config for " + vars["SERVER_NAME"])
|
||||||
else :
|
else :
|
||||||
@@ -109,11 +118,13 @@ class AutoConf :
|
|||||||
elif event == "destroy" or event == "remove" :
|
elif event == "destroy" or event == "remove" :
|
||||||
if id in self.__servers :
|
if id in self.__servers :
|
||||||
if self.__swarm :
|
if self.__swarm :
|
||||||
|
utils.log("[*] Deactivating config for " + vars["SERVER_NAME"])
|
||||||
if self.__config.deactivate(self.__instances, vars) :
|
if self.__config.deactivate(self.__instances, vars) :
|
||||||
utils.log("[*] Deactivated config for " + vars["SERVER_NAME"])
|
utils.log("[*] Deactivated config for " + vars["SERVER_NAME"])
|
||||||
else :
|
else :
|
||||||
utils.log("[!] Can't deactivate config for " + vars["SERVER_NAME"])
|
utils.log("[!] Can't deactivate config for " + vars["SERVER_NAME"])
|
||||||
del self.__servers[id]
|
del self.__servers[id]
|
||||||
|
utils.log("[*] Removing config for " + vars["SERVER_NAME"])
|
||||||
if self.__config.remove(vars) :
|
if self.__config.remove(vars) :
|
||||||
utils.log("[*] Removed config for " + vars["SERVER_NAME"])
|
utils.log("[*] Removed config for " + vars["SERVER_NAME"])
|
||||||
else :
|
else :
|
||||||
|
|||||||
@@ -20,25 +20,42 @@ class Config :
|
|||||||
var = var_value.split("=")[0]
|
var = var_value.split("=")[0]
|
||||||
value = var_value.replace(var + "=", "", 1)
|
value = var_value.replace(var + "=", "", 1)
|
||||||
vars[var] = value
|
vars[var] = value
|
||||||
if self.globalconf(instances) :
|
|
||||||
i = 0
|
utils.log("[*] Generating global config ...")
|
||||||
|
if not self.globalconf(instances) :
|
||||||
|
utils.log("[!] Can't generate global config")
|
||||||
|
return False
|
||||||
|
utils.log("[*] Generated global config")
|
||||||
|
|
||||||
|
if "SERVER_NAME" in vars and vars["SERVER_NAME"] != "" :
|
||||||
|
for server in vars["SERVER_NAME"].split(" ") :
|
||||||
|
vars_site = vars.copy()
|
||||||
|
vars_site["SERVER_NAME"] = server
|
||||||
|
utils.log("[*] Generating config for " + vars["SERVER_NAME"] + " ...")
|
||||||
|
if not self.generate(instances, vars_site) or not self.activate(instances, vars_site, reload=False) :
|
||||||
|
utils.log("[!] Can't generate/activate site config for " + server)
|
||||||
|
return False
|
||||||
|
utils.log("[*] Generated config for " + vars["SERVER_NAME"])
|
||||||
|
with open("/etc/nginx/autoconf", "w") as f :
|
||||||
|
f.write("ok")
|
||||||
|
|
||||||
|
utils.log("[*] Waiting for bunkerized-nginx tasks ...")
|
||||||
|
i = 1
|
||||||
started = False
|
started = False
|
||||||
while i < 10 :
|
while i <= 10 :
|
||||||
|
time.sleep(i)
|
||||||
if self.__ping(instances) :
|
if self.__ping(instances) :
|
||||||
started = True
|
started = True
|
||||||
break
|
break
|
||||||
i = i + 1
|
i = i + 1
|
||||||
utils.log("[!] Waiting " + str(i) + " seconds before retrying to contact nginx instances")
|
utils.log("[!] Waiting " + str(i) + " seconds before retrying to contact bunkerized-nginx tasks")
|
||||||
time.sleep(i)
|
|
||||||
if started :
|
if started :
|
||||||
|
utils.log("[*] bunkerized-nginx tasks started")
|
||||||
proc = subprocess.run(["/bin/su", "-s", "/opt/entrypoint/jobs.sh", "nginx"], env=vars, capture_output=True)
|
proc = subprocess.run(["/bin/su", "-s", "/opt/entrypoint/jobs.sh", "nginx"], env=vars, capture_output=True)
|
||||||
return proc.returncode == 0
|
return proc.returncode == 0
|
||||||
else :
|
else :
|
||||||
utils.log("[!] bunkerized-nginx instances are not started")
|
utils.log("[!] bunkerized-nginx tasks are not started")
|
||||||
else :
|
|
||||||
utils.log("[!] Can't generate global conf")
|
|
||||||
except Exception as e :
|
except Exception as e :
|
||||||
traceback.print_exc()
|
|
||||||
utils.log("[!] Error while initializing config : " + str(e))
|
utils.log("[!] Error while initializing config : " + str(e))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -54,12 +71,11 @@ class Config :
|
|||||||
vars[var] = value
|
vars[var] = value
|
||||||
proc = subprocess.run(["/bin/su", "-s", "/opt/entrypoint/global-config.sh", "nginx"], env=vars, capture_output=True)
|
proc = subprocess.run(["/bin/su", "-s", "/opt/entrypoint/global-config.sh", "nginx"], env=vars, capture_output=True)
|
||||||
if proc.returncode == 0 :
|
if proc.returncode == 0 :
|
||||||
with open("/etc/nginx/autoconf", "w") as f :
|
|
||||||
f.write("ok")
|
|
||||||
return True
|
return True
|
||||||
|
else :
|
||||||
|
utils.log("[*] Error while generating global config : return code = " + str(proc.returncode))
|
||||||
except Exception as e :
|
except Exception as e :
|
||||||
traceback.print_exc()
|
utils.log("[!] Exception while generating global config : " + str(e))
|
||||||
utils.log("[!] Error while generating global config : " + str(e))
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def generate(self, instances, vars) :
|
def generate(self, instances, vars) :
|
||||||
@@ -79,61 +95,76 @@ class Config :
|
|||||||
vars_defaults.update(vars_instances)
|
vars_defaults.update(vars_instances)
|
||||||
vars_defaults.update(vars)
|
vars_defaults.update(vars)
|
||||||
# Call site-config.sh to generate the config
|
# Call site-config.sh to generate the config
|
||||||
proc = subprocess.run(["/bin/su", "-s", "/bin/sh", "-c", "/opt/entrypoint/site-config.sh" + " " + vars["SERVER_NAME"], "nginx"], env=vars_defaults, capture_output=True)
|
proc = subprocess.run(["/bin/su", "-s", "/bin/sh", "-c", "/opt/entrypoint/site-config.sh" + " \"" + vars["SERVER_NAME"] + "\"", "nginx"], env=vars_defaults, capture_output=True)
|
||||||
if proc.returncode == 0 and vars_defaults["MULTISITE"] == "yes" and self.__swarm :
|
if proc.returncode == 0 and vars_defaults["MULTISITE"] == "yes" and self.__swarm :
|
||||||
proc = subprocess.run(["/bin/su", "-s", "/opt/entrypoint/multisite-config.sh", "nginx"], env=vars_defaults, capture_output=True)
|
proc = subprocess.run(["/bin/su", "-s", "/opt/entrypoint/multisite-config.sh", "nginx"], env=vars_defaults, capture_output=True)
|
||||||
return proc.returncode == 0
|
if proc.returncode == 0 :
|
||||||
return proc.returncode == 0
|
return True
|
||||||
|
utils.log("[!] Error while generating site config for " + vars["SERVER_NAME"] + " : return code = " + str(proc.returncode))
|
||||||
except Exception as e :
|
except Exception as e :
|
||||||
traceback.print_exc()
|
utils.log("[!] Exception while generating site config : " + str(e))
|
||||||
utils.log("[!] Error while generating site config : " + str(e))
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def activate(self, instances, vars) :
|
def activate(self, instances, vars, reload=True) :
|
||||||
try :
|
try :
|
||||||
|
# Get first server name
|
||||||
|
first_server_name = vars["SERVER_NAME"].split(" ")[0]
|
||||||
|
|
||||||
# Check if file exists
|
# Check if file exists
|
||||||
if not os.path.isfile("/etc/nginx/" + vars["SERVER_NAME"] + "/server.conf") :
|
if not os.path.isfile("/etc/nginx/" + first_server_name + "/server.conf") :
|
||||||
utils.log("[!] /etc/nginx/" + vars["SERVER_NAME"] + "/server.conf doesn't exist")
|
utils.log("[!] /etc/nginx/" + first_server_name + "/server.conf doesn't exist")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Include the server conf
|
# Include the server conf
|
||||||
utils.replace_in_file("/etc/nginx/nginx.conf", "}", "include /etc/nginx/" + vars["SERVER_NAME"] + "/server.conf;\n}")
|
utils.replace_in_file("/etc/nginx/nginx.conf", "}", "include /etc/nginx/" + first_server_name + "/server.conf;\n}")
|
||||||
|
|
||||||
|
# Reload
|
||||||
|
if not reload or self.reload(instances) :
|
||||||
|
return True
|
||||||
|
|
||||||
return self.reload(instances)
|
|
||||||
except Exception as e :
|
except Exception as e :
|
||||||
traceback.print_exc()
|
utils.log("[!] Exception while activating config : " + str(e))
|
||||||
utils.log("[!] Error while activating config : " + str(e))
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def deactivate(self, instances, vars) :
|
def deactivate(self, instances, vars) :
|
||||||
try :
|
try :
|
||||||
|
# Get first server name
|
||||||
|
first_server_name = vars["SERVER_NAME"].split(" ")[0]
|
||||||
|
|
||||||
# Check if file exists
|
# Check if file exists
|
||||||
if not os.path.isfile("/etc/nginx/" + vars["SERVER_NAME"] + "/server.conf") :
|
if not os.path.isfile("/etc/nginx/" + first_server_name + "/server.conf") :
|
||||||
utils.log("[!] /etc/nginx/" + vars["SERVER_NAME"] + "/server.conf doesn't exist")
|
utils.log("[!] /etc/nginx/" + first_server_name + "/server.conf doesn't exist")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Remove the include
|
# Remove the include
|
||||||
utils.replace_in_file("/etc/nginx/nginx.conf", "include /etc/nginx/" + vars["SERVER_NAME"] + "/server.conf;\n", "")
|
utils.replace_in_file("/etc/nginx/nginx.conf", "include /etc/nginx/" + first_server_name + "/server.conf;\n", "")
|
||||||
|
|
||||||
return self.reload(instances)
|
# Reload
|
||||||
|
if self.reload(instances) :
|
||||||
|
return True
|
||||||
|
|
||||||
except Exception as e :
|
except Exception as e :
|
||||||
traceback.print_exc()
|
utils.log("[!] Exception while deactivating config : " + str(e))
|
||||||
utils.log("[!] Error while deactivating config : " + str(e))
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def remove(self, instances, vars) :
|
def remove(self, vars) :
|
||||||
try :
|
try :
|
||||||
|
# Get first server name
|
||||||
|
first_server_name = vars["SERVER_NAME"].split(" ")[0]
|
||||||
|
|
||||||
# Check if file exists
|
# Check if file exists
|
||||||
if not os.path.isfile("/etc/nginx/" + vars["SERVER_NAME"] + "/server.conf") :
|
if not os.path.isfile("/etc/nginx/" + first_server_name + "/server.conf") :
|
||||||
utils.log("[!] /etc/nginx/" + vars["SERVER_NAME"] + "/server.conf doesn't exist")
|
utils.log("[!] /etc/nginx/" + first_server_name + "/server.conf doesn't exist")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Remove the folder
|
# Remove the folder
|
||||||
shutil.rmtree("/etc/nginx/" + vars["SERVER_NAME"])
|
shutil.rmtree("/etc/nginx/" + first_server_name)
|
||||||
return True
|
return True
|
||||||
except Exception as e :
|
except Exception as e :
|
||||||
utils.log("[!] Error while deactivating config : " + str(e))
|
utils.log("[!] Error while deactivating config : " + str(e))
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def reload(self, instances) :
|
def reload(self, instances) :
|
||||||
@@ -149,7 +180,7 @@ class Config :
|
|||||||
instance.reload()
|
instance.reload()
|
||||||
# Reload via API
|
# Reload via API
|
||||||
if self.__swarm :
|
if self.__swarm :
|
||||||
# Send POST request on http://serviceName.NodeID.TaskID:8000/reload
|
# Send POST request on http://serviceName.NodeID.TaskID:8000/action
|
||||||
name = instance.name
|
name = instance.name
|
||||||
for task in instance.tasks() :
|
for task in instance.tasks() :
|
||||||
if task["Status"]["State"] != "running" :
|
if task["Status"]["State"] != "running" :
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ RUN apk add py3-pip apache2-utils bash certbot curl logrotate openssl && \
|
|||||||
mkdir /opt/scripts && \
|
mkdir /opt/scripts && \
|
||||||
addgroup -g 101 nginx && \
|
addgroup -g 101 nginx && \
|
||||||
adduser -h /var/cache/nginx -g nginx -s /sbin/nologin -G nginx -D -H -u 101 nginx && \
|
adduser -h /var/cache/nginx -g nginx -s /sbin/nologin -G nginx -D -H -u 101 nginx && \
|
||||||
|
mkdir /etc/letsencrypt && \
|
||||||
|
chown root:nginx /etc/letsencrypt && \
|
||||||
|
chmod 770 /etc/letsencrypt && \
|
||||||
mkdir /var/log/letsencrypt && \
|
mkdir /var/log/letsencrypt && \
|
||||||
chown root:nginx /var/log/letsencrypt && \
|
chown root:nginx /var/log/letsencrypt && \
|
||||||
chmod 770 /var/log/letsencrypt && \
|
chmod 770 /var/log/letsencrypt && \
|
||||||
@@ -25,7 +28,11 @@ RUN apk add py3-pip apache2-utils bash certbot curl logrotate openssl && \
|
|||||||
chown root:nginx /var/log/jobs.log && \
|
chown root:nginx /var/log/jobs.log && \
|
||||||
chmod 770 /var/log/jobs.log && \
|
chmod 770 /var/log/jobs.log && \
|
||||||
chown -R root:nginx /opt/confs/nginx && \
|
chown -R root:nginx /opt/confs/nginx && \
|
||||||
chmod -R 770 /opt/confs/nginx
|
chmod -R 770 /opt/confs/nginx && \
|
||||||
|
mkdir /acme-challenge && \
|
||||||
|
chown root:nginx /acme-challenge && \
|
||||||
|
chmod 770 /acme-challenge
|
||||||
|
|
||||||
|
|
||||||
COPY autoconf/misc/logrotate.conf /etc/logrotate.conf
|
COPY autoconf/misc/logrotate.conf /etc/logrotate.conf
|
||||||
COPY scripts/* /opt/scripts/
|
COPY scripts/* /opt/scripts/
|
||||||
|
|||||||
@@ -9,8 +9,12 @@ RUN apk add py3-pip apache2-utils bash certbot curl logrotate openssl && \
|
|||||||
mkdir /opt/entrypoint && \
|
mkdir /opt/entrypoint && \
|
||||||
mkdir -p /opt/confs/site && \
|
mkdir -p /opt/confs/site && \
|
||||||
mkdir -p /opt/confs/global && \
|
mkdir -p /opt/confs/global && \
|
||||||
|
mkdir /opt/scripts && \
|
||||||
addgroup -g 101 nginx && \
|
addgroup -g 101 nginx && \
|
||||||
adduser -h /var/cache/nginx -g nginx -s /sbin/nologin -G nginx -D -H -u 101 nginx && \
|
adduser -h /var/cache/nginx -g nginx -s /sbin/nologin -G nginx -D -H -u 101 nginx && \
|
||||||
|
mkdir /etc/letsencrypt && \
|
||||||
|
chown root:nginx /etc/letsencrypt && \
|
||||||
|
chmod 770 /etc/letsencrypt && \
|
||||||
mkdir /var/log/letsencrypt && \
|
mkdir /var/log/letsencrypt && \
|
||||||
chown root:nginx /var/log/letsencrypt && \
|
chown root:nginx /var/log/letsencrypt && \
|
||||||
chmod 770 /var/log/letsencrypt && \
|
chmod 770 /var/log/letsencrypt && \
|
||||||
@@ -24,7 +28,10 @@ RUN apk add py3-pip apache2-utils bash certbot curl logrotate openssl && \
|
|||||||
chown root:nginx /var/log/jobs.log && \
|
chown root:nginx /var/log/jobs.log && \
|
||||||
chmod 770 /var/log/jobs.log && \
|
chmod 770 /var/log/jobs.log && \
|
||||||
chown -R root:nginx /opt/confs/nginx && \
|
chown -R root:nginx /opt/confs/nginx && \
|
||||||
chmod -R 770 /opt/confs/nginx
|
chmod -R 770 /opt/confs/nginx && \
|
||||||
|
mkdir /acme-challenge && \
|
||||||
|
chown root:nginx /acme-challenge && \
|
||||||
|
chmod 770 /acme-challenge
|
||||||
|
|
||||||
COPY autoconf/misc/logrotate.conf /etc/logrotate.conf
|
COPY autoconf/misc/logrotate.conf /etc/logrotate.conf
|
||||||
COPY scripts/* /opt/scripts/
|
COPY scripts/* /opt/scripts/
|
||||||
|
|||||||
@@ -15,8 +15,12 @@ RUN apk add py3-pip apache2-utils bash certbot curl logrotate openssl && \
|
|||||||
mkdir /opt/entrypoint && \
|
mkdir /opt/entrypoint && \
|
||||||
mkdir -p /opt/confs/site && \
|
mkdir -p /opt/confs/site && \
|
||||||
mkdir -p /opt/confs/global && \
|
mkdir -p /opt/confs/global && \
|
||||||
|
mkdir /opt/scripts && \
|
||||||
addgroup -g 101 nginx && \
|
addgroup -g 101 nginx && \
|
||||||
adduser -h /var/cache/nginx -g nginx -s /sbin/nologin -G nginx -D -H -u 101 nginx && \
|
adduser -h /var/cache/nginx -g nginx -s /sbin/nologin -G nginx -D -H -u 101 nginx && \
|
||||||
|
mkdir /etc/letsencrypt && \
|
||||||
|
chown root:nginx /etc/letsencrypt && \
|
||||||
|
chmod 770 /etc/letsencrypt && \
|
||||||
mkdir /var/log/letsencrypt && \
|
mkdir /var/log/letsencrypt && \
|
||||||
chown root:nginx /var/log/letsencrypt && \
|
chown root:nginx /var/log/letsencrypt && \
|
||||||
chmod 770 /var/log/letsencrypt && \
|
chmod 770 /var/log/letsencrypt && \
|
||||||
@@ -30,7 +34,10 @@ RUN apk add py3-pip apache2-utils bash certbot curl logrotate openssl && \
|
|||||||
chown root:nginx /var/log/jobs.log && \
|
chown root:nginx /var/log/jobs.log && \
|
||||||
chmod 770 /var/log/jobs.log && \
|
chmod 770 /var/log/jobs.log && \
|
||||||
chown -R root:nginx /opt/confs/nginx && \
|
chown -R root:nginx /opt/confs/nginx && \
|
||||||
chmod -R 770 /opt/confs/nginx
|
chmod -R 770 /opt/confs/nginx && \
|
||||||
|
mkdir /acme-challenge && \
|
||||||
|
chown root:nginx /acme-challenge && \
|
||||||
|
chmod 770 /acme-challenge
|
||||||
|
|
||||||
COPY autoconf/misc/logrotate.conf /etc/logrotate.conf
|
COPY autoconf/misc/logrotate.conf /etc/logrotate.conf
|
||||||
COPY scripts/* /opt/scripts/
|
COPY scripts/* /opt/scripts/
|
||||||
|
|||||||
@@ -15,8 +15,12 @@ RUN apk add py3-pip apache2-utils bash certbot curl logrotate openssl && \
|
|||||||
mkdir /opt/entrypoint && \
|
mkdir /opt/entrypoint && \
|
||||||
mkdir -p /opt/confs/site && \
|
mkdir -p /opt/confs/site && \
|
||||||
mkdir -p /opt/confs/global && \
|
mkdir -p /opt/confs/global && \
|
||||||
|
mkdir /opt/scripts && \
|
||||||
addgroup -g 101 nginx && \
|
addgroup -g 101 nginx && \
|
||||||
adduser -h /var/cache/nginx -g nginx -s /sbin/nologin -G nginx -D -H -u 101 nginx && \
|
adduser -h /var/cache/nginx -g nginx -s /sbin/nologin -G nginx -D -H -u 101 nginx && \
|
||||||
|
mkdir /etc/letsencrypt && \
|
||||||
|
chown root:nginx /etc/letsencrypt && \
|
||||||
|
chmod 770 /etc/letsencrypt && \
|
||||||
mkdir /var/log/letsencrypt && \
|
mkdir /var/log/letsencrypt && \
|
||||||
chown root:nginx /var/log/letsencrypt && \
|
chown root:nginx /var/log/letsencrypt && \
|
||||||
chmod 770 /var/log/letsencrypt && \
|
chmod 770 /var/log/letsencrypt && \
|
||||||
@@ -30,7 +34,10 @@ RUN apk add py3-pip apache2-utils bash certbot curl logrotate openssl && \
|
|||||||
chown root:nginx /var/log/jobs.log && \
|
chown root:nginx /var/log/jobs.log && \
|
||||||
chmod 770 /var/log/jobs.log && \
|
chmod 770 /var/log/jobs.log && \
|
||||||
chown -R root:nginx /opt/confs/nginx && \
|
chown -R root:nginx /opt/confs/nginx && \
|
||||||
chmod -R 770 /opt/confs/nginx
|
chmod -R 770 /opt/confs/nginx && \
|
||||||
|
mkdir /acme-challenge && \
|
||||||
|
chown root:nginx /acme-challenge && \
|
||||||
|
chmod 770 /acme-challenge
|
||||||
|
|
||||||
COPY autoconf/misc/logrotate.conf /etc/logrotate.conf
|
COPY autoconf/misc/logrotate.conf /etc/logrotate.conf
|
||||||
COPY scripts/* /opt/scripts/
|
COPY scripts/* /opt/scripts/
|
||||||
|
|||||||
@@ -9,8 +9,12 @@ RUN apk add py3-pip apache2-utils bash certbot curl logrotate openssl && \
|
|||||||
mkdir /opt/entrypoint && \
|
mkdir /opt/entrypoint && \
|
||||||
mkdir -p /opt/confs/site && \
|
mkdir -p /opt/confs/site && \
|
||||||
mkdir -p /opt/confs/global && \
|
mkdir -p /opt/confs/global && \
|
||||||
|
mkdir /opt/scripts && \
|
||||||
addgroup -g 101 nginx && \
|
addgroup -g 101 nginx && \
|
||||||
adduser -h /var/cache/nginx -g nginx -s /sbin/nologin -G nginx -D -H -u 101 nginx && \
|
adduser -h /var/cache/nginx -g nginx -s /sbin/nologin -G nginx -D -H -u 101 nginx && \
|
||||||
|
mkdir /etc/letsencrypt && \
|
||||||
|
chown root:nginx /etc/letsencrypt && \
|
||||||
|
chmod 770 /etc/letsencrypt && \
|
||||||
mkdir /var/log/letsencrypt && \
|
mkdir /var/log/letsencrypt && \
|
||||||
chown root:nginx /var/log/letsencrypt && \
|
chown root:nginx /var/log/letsencrypt && \
|
||||||
chmod 770 /var/log/letsencrypt && \
|
chmod 770 /var/log/letsencrypt && \
|
||||||
@@ -24,7 +28,10 @@ RUN apk add py3-pip apache2-utils bash certbot curl logrotate openssl && \
|
|||||||
chown root:nginx /var/log/jobs.log && \
|
chown root:nginx /var/log/jobs.log && \
|
||||||
chmod 770 /var/log/jobs.log && \
|
chmod 770 /var/log/jobs.log && \
|
||||||
chown -R root:nginx /opt/confs/nginx && \
|
chown -R root:nginx /opt/confs/nginx && \
|
||||||
chmod -R 770 /opt/confs/nginx
|
chmod -R 770 /opt/confs/nginx && \
|
||||||
|
mkdir /acme-challenge && \
|
||||||
|
chown root:nginx /acme-challenge && \
|
||||||
|
chmod 770 /acme-challenge
|
||||||
|
|
||||||
COPY autoconf/misc/logrotate.conf /etc/logrotate.conf
|
COPY autoconf/misc/logrotate.conf /etc/logrotate.conf
|
||||||
COPY scripts/* /opt/scripts/
|
COPY scripts/* /opt/scripts/
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ with lock :
|
|||||||
|
|
||||||
# Process events received from Docker
|
# Process events received from Docker
|
||||||
try :
|
try :
|
||||||
|
utils.log("[*] Listening for Docker events ...")
|
||||||
for event in client.events(decode=True) :
|
for event in client.events(decode=True) :
|
||||||
|
|
||||||
# Process only container/service events
|
# Process only container/service events
|
||||||
@@ -53,10 +54,14 @@ try :
|
|||||||
# Get Container/Service object
|
# Get Container/Service object
|
||||||
try :
|
try :
|
||||||
if swarm :
|
if swarm :
|
||||||
server = client.services.get(service_id=event["Actor"]["ID"])
|
id = service_id=event["Actor"]["ID"]
|
||||||
|
server = client.services.get(service_id=id)
|
||||||
else :
|
else :
|
||||||
server = client.containers.get(event["id"])
|
id = event["id"]
|
||||||
|
server = client.containers.get(id)
|
||||||
except docker.errors.NotFound as e :
|
except docker.errors.NotFound as e :
|
||||||
|
server = autoconf.get_server(id)
|
||||||
|
if not server :
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Process the event
|
# Process the event
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
echo "[*] Starting autoconf ..."
|
echo "[*] Starting autoconf ..."
|
||||||
|
|
||||||
|
# check permissions
|
||||||
|
su -s "/opt/entrypoint/permissions.sh" nginx
|
||||||
|
if [ "$?" -ne 0 ] ; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$SWARM_MODE" = "yes" ] ; then
|
if [ "$SWARM_MODE" = "yes" ] ; then
|
||||||
cp -r /opt/confs/nginx/* /etc/nginx
|
cp -r /opt/confs/nginx/* /etc/nginx
|
||||||
chown -R root:nginx /etc/nginx
|
chown -R root:nginx /etc/nginx
|
||||||
|
|||||||
@@ -136,6 +136,10 @@ sed -i 's/^API_KEY=.*/API_KEY=%CROWDSEC_KEY%/' /usr/local/lib/lua/crowdsec/crowd
|
|||||||
sed -i 's/require "lrucache"/require "resty.lrucache"/' /usr/local/lib/lua/crowdsec/CrowdSec.lua
|
sed -i 's/require "lrucache"/require "resty.lrucache"/' /usr/local/lib/lua/crowdsec/CrowdSec.lua
|
||||||
sed -i 's/require "config"/require "crowdsec.config"/' /usr/local/lib/lua/crowdsec/CrowdSec.lua
|
sed -i 's/require "config"/require "crowdsec.config"/' /usr/local/lib/lua/crowdsec/CrowdSec.lua
|
||||||
cd /tmp
|
cd /tmp
|
||||||
|
git_secure_clone https://github.com/hamishforbes/lua-resty-iputils.git 3151d6485e830421266eee5c0f386c32c835dba4
|
||||||
|
cd lua-resty-iputils
|
||||||
|
make LUA_LIB_DIR=/usr/local/lib/lua install
|
||||||
|
cd /tmp
|
||||||
git_secure_clone https://github.com/openresty/lua-nginx-module.git 2d23bc4f0a29ed79aaaa754c11bffb1080aa44ba
|
git_secure_clone https://github.com/openresty/lua-nginx-module.git 2d23bc4f0a29ed79aaaa754c11bffb1080aa44ba
|
||||||
export LUAJIT_LIB=/usr/local/lib
|
export LUAJIT_LIB=/usr/local/lib
|
||||||
export LUAJIT_INC=/usr/local/include/luajit-2.1
|
export LUAJIT_INC=/usr/local/include/luajit-2.1
|
||||||
@@ -153,7 +157,7 @@ fi
|
|||||||
tar -xvzf nginx-${NGINX_VERSION}.tar.gz
|
tar -xvzf nginx-${NGINX_VERSION}.tar.gz
|
||||||
cd nginx-$NGINX_VERSION
|
cd nginx-$NGINX_VERSION
|
||||||
CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p')
|
CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p')
|
||||||
CONFARGS=${CONFARGS/-Os -fomit-frame-pointer/-Os}
|
CONFARGS=${CONFARGS/-Os -fomit-frame-pointer -g/-Os}
|
||||||
./configure $CONFARGS --add-dynamic-module=/tmp/ModSecurity-nginx --add-dynamic-module=/tmp/headers-more-nginx-module --add-dynamic-module=/tmp/ngx_http_geoip2_module --add-dynamic-module=/tmp/nginx_cookie_flag_module --add-dynamic-module=/tmp/lua-nginx-module --add-dynamic-module=/tmp/ngx_brotli
|
./configure $CONFARGS --add-dynamic-module=/tmp/ModSecurity-nginx --add-dynamic-module=/tmp/headers-more-nginx-module --add-dynamic-module=/tmp/ngx_http_geoip2_module --add-dynamic-module=/tmp/nginx_cookie_flag_module --add-dynamic-module=/tmp/lua-nginx-module --add-dynamic-module=/tmp/ngx_brotli
|
||||||
make -j $NTASK modules
|
make -j $NTASK modules
|
||||||
cp ./objs/*.so /usr/lib/nginx/modules
|
cp ./objs/*.so /usr/lib/nginx/modules
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ rewrite_by_lua_block {
|
|||||||
if api.is_api_call(api_uri) then
|
if api.is_api_call(api_uri) then
|
||||||
ngx.header.content_type = 'text/plain'
|
ngx.header.content_type = 'text/plain'
|
||||||
if api.do_api_call(api_uri) then
|
if api.do_api_call(api_uri) then
|
||||||
ngx.log(ngx.WARN, "[API] API call " .. ngx.var.request_uri .. " successfull from " .. ngx.var.remote_addr)
|
ngx.log(ngx.NOTICE, "[API] API call " .. ngx.var.request_uri .. " successfull from " .. ngx.var.remote_addr)
|
||||||
ngx.say("ok")
|
ngx.say("ok")
|
||||||
else
|
else
|
||||||
ngx.log(ngx.WARN, "[API] API call " .. ngx.var.request_uri .. " failed from " .. ngx.var.remote_addr)
|
ngx.log(ngx.WARN, "[API] API call " .. ngx.var.request_uri .. " failed from " .. ngx.var.remote_addr)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ rewrite_by_lua_block {
|
|||||||
if api.is_api_call(api_uri) then
|
if api.is_api_call(api_uri) then
|
||||||
ngx.header.content_type = 'text/plain'
|
ngx.header.content_type = 'text/plain'
|
||||||
if api.do_api_call(api_uri) then
|
if api.do_api_call(api_uri) then
|
||||||
ngx.log(ngx.WARN, "[API] API call " .. ngx.var.request_uri .. " successfull from " .. ngx.var.remote_addr)
|
ngx.log(ngx.NOTICE, "[API] API call " .. ngx.var.request_uri .. " successfull from " .. ngx.var.remote_addr)
|
||||||
ngx.say("ok")
|
ngx.say("ok")
|
||||||
else
|
else
|
||||||
ngx.log(ngx.WARN, "[API] API call " .. ngx.var.request_uri .. " failed from " .. ngx.var.remote_addr)
|
ngx.log(ngx.WARN, "[API] API call " .. ngx.var.request_uri .. " failed from " .. ngx.var.remote_addr)
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ init_by_lua_block {
|
|||||||
ngx.log(ngx.ERR, "[Crowdsec] " .. err)
|
ngx.log(ngx.ERR, "[Crowdsec] " .. err)
|
||||||
error()
|
error()
|
||||||
end
|
end
|
||||||
ngx.log(ngx.ERR, "[Crowdsec] Initialisation done")
|
ngx.log(ngx.NOTICE, "[Crowdsec] Initialisation done")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ http {
|
|||||||
# write logs to local syslog
|
# write logs to local syslog
|
||||||
log_format logf '%LOG_FORMAT%';
|
log_format logf '%LOG_FORMAT%';
|
||||||
access_log syslog:server=unix:/tmp/log,nohostname,facility=local0,severity=notice logf;
|
access_log syslog:server=unix:/tmp/log,nohostname,facility=local0,severity=notice logf;
|
||||||
error_log syslog:server=unix:/tmp/log,nohostname,facility=local0 warn;
|
error_log syslog:server=unix:/tmp/log,nohostname,facility=local0 notice;
|
||||||
|
|
||||||
# temp paths
|
# temp paths
|
||||||
proxy_temp_path /tmp/proxy_temp;
|
proxy_temp_path /tmp/proxy_temp;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ location = %ANTIBOT_URI% {
|
|||||||
local cookie = require "cookie"
|
local cookie = require "cookie"
|
||||||
local captcha = require "captcha"
|
local captcha = require "captcha"
|
||||||
if not cookie.is_set("uri") then
|
if not cookie.is_set("uri") then
|
||||||
ngx.log(ngx.WARN, "[ANTIBOT] captcha fail (1) for " .. ngx.var.remote_addr)
|
ngx.log(ngx.NOTICE, "[ANTIBOT] captcha fail (1) for " .. ngx.var.remote_addr)
|
||||||
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
end
|
end
|
||||||
local img, res = captcha.get_challenge()
|
local img, res = captcha.get_challenge()
|
||||||
@@ -22,19 +22,19 @@ location = %ANTIBOT_URI% {
|
|||||||
local cookie = require "cookie"
|
local cookie = require "cookie"
|
||||||
local captcha = require "captcha"
|
local captcha = require "captcha"
|
||||||
if not cookie.is_set("captchares") then
|
if not cookie.is_set("captchares") then
|
||||||
ngx.log(ngx.WARN, "[ANTIBOT] captcha fail (2) for " .. ngx.var.remote_addr)
|
ngx.log(ngx.NOTICE, "[ANTIBOT] captcha fail (2) for " .. ngx.var.remote_addr)
|
||||||
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
end
|
end
|
||||||
ngx.req.read_body()
|
ngx.req.read_body()
|
||||||
local args, err = ngx.req.get_post_args(1)
|
local args, err = ngx.req.get_post_args(1)
|
||||||
if err == "truncated" or not args or not args["captcha"] then
|
if err == "truncated" or not args or not args["captcha"] then
|
||||||
ngx.log(ngx.WARN, "[ANTIBOT] captcha fail (3) for " .. ngx.var.remote_addr)
|
ngx.log(ngx.NOTICE, "[ANTIBOT] captcha fail (3) for " .. ngx.var.remote_addr)
|
||||||
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
end
|
end
|
||||||
local captcha_user = args["captcha"]
|
local captcha_user = args["captcha"]
|
||||||
local check = captcha.check(captcha_user, cookie.get("captchares"))
|
local check = captcha.check(captcha_user, cookie.get("captchares"))
|
||||||
if not check then
|
if not check then
|
||||||
ngx.log(ngx.WARN, "[ANTIBOT] captcha fail (4) for " .. ngx.var.remote_addr)
|
ngx.log(ngx.NOTICE, "[ANTIBOT] captcha fail (4) for " .. ngx.var.remote_addr)
|
||||||
return ngx.redirect("%ANTIBOT_URI%")
|
return ngx.redirect("%ANTIBOT_URI%")
|
||||||
end
|
end
|
||||||
cookie.set({captcha = "ok"})
|
cookie.set({captcha = "ok"})
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ location = %ANTIBOT_URI% {
|
|||||||
local cookie = require "cookie"
|
local cookie = require "cookie"
|
||||||
local recaptcha = require "recaptcha"
|
local recaptcha = require "recaptcha"
|
||||||
if not cookie.is_set("uri") then
|
if not cookie.is_set("uri") then
|
||||||
ngx.log(ngx.WARN, "[ANTIBOT] recaptcha fail (1) for " .. ngx.var.remote_addr)
|
ngx.log(ngx.NOTICE, "[ANTIBOT] recaptcha fail (1) for " .. ngx.var.remote_addr)
|
||||||
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
end
|
end
|
||||||
local code = recaptcha.get_code("%ANTIBOT_URI%", "%ANTIBOT_RECAPTCHA_SITEKEY%")
|
local code = recaptcha.get_code("%ANTIBOT_URI%", "%ANTIBOT_RECAPTCHA_SITEKEY%")
|
||||||
@@ -20,19 +20,19 @@ location = %ANTIBOT_URI% {
|
|||||||
local cookie = require "cookie"
|
local cookie = require "cookie"
|
||||||
local recaptcha = require "recaptcha"
|
local recaptcha = require "recaptcha"
|
||||||
if not cookie.is_set("uri") then
|
if not cookie.is_set("uri") then
|
||||||
ngx.log(ngx.WARN, "[ANTIBOT] recaptcha fail (2) for " .. ngx.var.remote_addr)
|
ngx.log(ngx.NOTICE, "[ANTIBOT] recaptcha fail (2) for " .. ngx.var.remote_addr)
|
||||||
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
end
|
end
|
||||||
ngx.req.read_body()
|
ngx.req.read_body()
|
||||||
local args, err = ngx.req.get_post_args(1)
|
local args, err = ngx.req.get_post_args(1)
|
||||||
if err == "truncated" or not args or not args["token"] then
|
if err == "truncated" or not args or not args["token"] then
|
||||||
ngx.log(ngx.WARN, "[ANTIBOT] recaptcha fail (3) for " .. ngx.var.remote_addr)
|
ngx.log(ngx.NOTICE, "[ANTIBOT] recaptcha fail (3) for " .. ngx.var.remote_addr)
|
||||||
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
end
|
end
|
||||||
local token = args["token"]
|
local token = args["token"]
|
||||||
local check = recaptcha.check(token, "%ANTIBOT_RECAPTCHA_SECRET%")
|
local check = recaptcha.check(token, "%ANTIBOT_RECAPTCHA_SECRET%")
|
||||||
if check < %ANTIBOT_RECAPTCHA_SCORE% then
|
if check < %ANTIBOT_RECAPTCHA_SCORE% then
|
||||||
ngx.log(ngx.WARN, "[ANTIBOT] recaptcha fail (4) for " .. ngx.var.remote_addr .. " (score = " .. tostring(check) .. ")")
|
ngx.log(ngx.NOTICE, "[ANTIBOT] recaptcha fail (4) for " .. ngx.var.remote_addr .. " (score = " .. tostring(check) .. ")")
|
||||||
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
end
|
end
|
||||||
cookie.set({recaptcha = "ok"})
|
cookie.set({recaptcha = "ok"})
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
location ~* \.(%CLIENT_CACHE_EXTENSIONS%)$ {
|
etag %CLIENT_CACHE_ETAG%;
|
||||||
etag %CLIENT_CACHE_ETAG%;
|
set $cache "";
|
||||||
add_header Cache-Control "%CLIENT_CACHE_CONTROL%";
|
if ($uri ~* \.(%CLIENT_CACHE_EXTENSIONS%)$) {
|
||||||
|
set $cache "%CLIENT_CACHE_CONTROL%";
|
||||||
}
|
}
|
||||||
|
add_header Cache-Control $cache;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ local use_antibot_captcha = %USE_ANTIBOT_CAPTCHA%
|
|||||||
local use_antibot_recaptcha = %USE_ANTIBOT_RECAPTCHA%
|
local use_antibot_recaptcha = %USE_ANTIBOT_RECAPTCHA%
|
||||||
|
|
||||||
-- include LUA code
|
-- include LUA code
|
||||||
|
|
||||||
local whitelist = require "whitelist"
|
local whitelist = require "whitelist"
|
||||||
local blacklist = require "blacklist"
|
local blacklist = require "blacklist"
|
||||||
local dnsbl = require "dnsbl"
|
local dnsbl = require "dnsbl"
|
||||||
@@ -31,11 +30,7 @@ local recaptcha = require "recaptcha"
|
|||||||
-- user variables
|
-- user variables
|
||||||
local antibot_uri = "%ANTIBOT_URI%"
|
local antibot_uri = "%ANTIBOT_URI%"
|
||||||
local whitelist_user_agent = {%WHITELIST_USER_AGENT%}
|
local whitelist_user_agent = {%WHITELIST_USER_AGENT%}
|
||||||
|
local whitelist_uri = {%WHITELIST_URI%}
|
||||||
-- check if it's let's encrypt bot
|
|
||||||
if use_lets_encrypt and string.match(ngx.var.request_uri, "^/.well-known/acme-challenge/") then
|
|
||||||
ngx.exit(ngx.OK)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check if already in whitelist cache
|
-- check if already in whitelist cache
|
||||||
if use_whitelist_ip and whitelist.ip_cached_ok() then
|
if use_whitelist_ip and whitelist.ip_cached_ok() then
|
||||||
@@ -72,6 +67,19 @@ if use_whitelist_reverse and not whitelist.reverse_cached() then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- check if URI is whitelisted
|
||||||
|
for k, v in pairs(whitelist_uri) do
|
||||||
|
if ngx.var.request_uri == v then
|
||||||
|
ngx.log(ngx.NOTICE, "[WHITELIST] URI " .. v .. " is whitelisted")
|
||||||
|
ngx.exit(ngx.OK)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check if it's certbot
|
||||||
|
if use_lets_encrypt and string.match(ngx.var.request_uri, "^/.well-known/acme-challenge/") then
|
||||||
|
ngx.exit(ngx.OK)
|
||||||
|
end
|
||||||
|
|
||||||
-- check if IP is blacklisted (only if not in cache)
|
-- check if IP is blacklisted (only if not in cache)
|
||||||
if use_blacklist_ip and not blacklist.ip_cached() then
|
if use_blacklist_ip and not blacklist.ip_cached() then
|
||||||
if blacklist.check_ip() then
|
if blacklist.check_ip() then
|
||||||
@@ -88,32 +96,29 @@ end
|
|||||||
|
|
||||||
-- check if user-agent is allowed
|
-- check if user-agent is allowed
|
||||||
if use_user_agent and ngx.var.bad_user_agent == "yes" then
|
if use_user_agent and ngx.var.bad_user_agent == "yes" then
|
||||||
local headers = ngx.req.get_headers()
|
local block = false
|
||||||
local ua = headers["User-Agent"]
|
for k, v in pairs(whitelist_user_agent) do
|
||||||
if not whitelist_user_agent ~= "" then
|
if string.match(ngx.var.http_user_agent, v) then
|
||||||
local k_ua_white, v_ua_white = next(whitelist_user_agent, nil)
|
ngx.log(ngx.NOTICE, "[ALLOW] User-Agent " .. ngx.var.http_user_agent .. " is whitelisted")
|
||||||
while v_ua_white do
|
block = false
|
||||||
local rst_whitelist = string.match(ua, v_ua_white)
|
break
|
||||||
if rst_whitelist ~= nil and rst_whitelist ~= "" then
|
|
||||||
ngx.log(ngx.WARN, "[ALLOW] User-Agent " .. ngx.var.http_user_agent .. " is whitelisted")
|
|
||||||
ngx.exit(ngx.OK)
|
|
||||||
end
|
|
||||||
k_ua_white, v_ua_white = next(whitelist_user_agent, k_ua_white)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
ngx.log(ngx.WARN, "[BLOCK] User-Agent " .. ngx.var.http_user_agent .. " is blacklisted")
|
if block then
|
||||||
|
ngx.log(ngx.NOTICE, "[BLOCK] User-Agent " .. ngx.var.http_user_agent .. " is blacklisted")
|
||||||
ngx.exit(ngx.HTTP_FORBIDDEN)
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check if referrer is allowed
|
-- check if referrer is allowed
|
||||||
if use_referrer and ngx.var.bad_referrer == "yes" then
|
if use_referrer and ngx.var.bad_referrer == "yes" then
|
||||||
ngx.log(ngx.WARN, "[BLOCK] Referrer " .. ngx.var.http_referer .. " is blacklisted")
|
ngx.log(ngx.NOTICE, "[BLOCK] Referrer " .. ngx.var.http_referer .. " is blacklisted")
|
||||||
ngx.exit(ngx.HTTP_FORBIDDEN)
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check if country is allowed
|
-- check if country is allowed
|
||||||
if use_country and ngx.var.allowed_country == "no" then
|
if use_country and ngx.var.allowed_country == "no" then
|
||||||
ngx.log(ngx.WARN, "[BLOCK] Country of " .. ngx.var.remote_addr .. " is blacklisted")
|
ngx.log(ngx.NOTICE, "[BLOCK] Country of " .. ngx.var.remote_addr .. " is blacklisted")
|
||||||
ngx.exit(ngx.HTTP_FORBIDDEN)
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -131,7 +136,7 @@ if use_crowdsec then
|
|||||||
ngx.log(ngx.ERR, "[Crowdsec] " .. err)
|
ngx.log(ngx.ERR, "[Crowdsec] " .. err)
|
||||||
end
|
end
|
||||||
if not ok then
|
if not ok then
|
||||||
ngx.log(ngx.ERR, "[Crowdsec] denied '" .. ngx.var.remote_addr .. "'")
|
ngx.log(ngx.NOTICE, "[Crowdsec] denied '" .. ngx.var.remote_addr .. "'")
|
||||||
ngx.exit(ngx.HTTP_FORBIDDEN)
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -143,7 +148,7 @@ if use_antibot_cookie then
|
|||||||
cookie.set({uri = ngx.var.request_uri})
|
cookie.set({uri = ngx.var.request_uri})
|
||||||
return ngx.redirect(antibot_uri)
|
return ngx.redirect(antibot_uri)
|
||||||
end
|
end
|
||||||
ngx.log(ngx.WARN, "[ANTIBOT] cookie fail for " .. ngx.var.remote_addr)
|
ngx.log(ngx.NOTICE, "[ANTIBOT] cookie fail for " .. ngx.var.remote_addr)
|
||||||
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||||
else
|
else
|
||||||
if ngx.var.request_uri == antibot_uri then
|
if ngx.var.request_uri == antibot_uri then
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ SecResponseBodyLimitAction ProcessPartial
|
|||||||
|
|
||||||
# log usefull stuff
|
# log usefull stuff
|
||||||
SecAuditEngine RelevantOnly
|
SecAuditEngine RelevantOnly
|
||||||
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
|
|
||||||
SecAuditLogType Serial
|
SecAuditLogType Serial
|
||||||
SecAuditLog /var/log/nginx/modsec_audit.log
|
SecAuditLog /var/log/nginx/modsec_audit.log
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
location %REVERSE_PROXY_URL% {
|
location %REVERSE_PROXY_URL% {
|
||||||
|
etag off;
|
||||||
proxy_pass %REVERSE_PROXY_HOST%;
|
proxy_pass %REVERSE_PROXY_HOST%;
|
||||||
%REVERSE_PROXY_HEADERS%
|
%REVERSE_PROXY_HEADERS%
|
||||||
%REVERSE_PROXY_WS%
|
%REVERSE_PROXY_WS%
|
||||||
|
|||||||
@@ -102,11 +102,11 @@ BLACKLIST_REVERSE_LIST="${BLACKLIST_REVERSE_LIST-.shodan.io}"
|
|||||||
USE_DNSBL="${USE_DNSBL-yes}"
|
USE_DNSBL="${USE_DNSBL-yes}"
|
||||||
DNSBL_LIST="${DNSBL_LIST-bl.blocklist.de problems.dnsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org}"
|
DNSBL_LIST="${DNSBL_LIST-bl.blocklist.de problems.dnsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org}"
|
||||||
USE_LIMIT_REQ="${USE_LIMIT_REQ-yes}"
|
USE_LIMIT_REQ="${USE_LIMIT_REQ-yes}"
|
||||||
LIMIT_REQ_RATE="${LIMIT_REQ_RATE-20r/s}"
|
LIMIT_REQ_RATE="${LIMIT_REQ_RATE-1r/s}"
|
||||||
LIMIT_REQ_BURST="${LIMIT_REQ_BURST-40}"
|
LIMIT_REQ_BURST="${LIMIT_REQ_BURST-2}"
|
||||||
LIMIT_REQ_CACHE="${LIMIT_REQ_CACHE-10m}"
|
LIMIT_REQ_CACHE="${LIMIT_REQ_CACHE-10m}"
|
||||||
USE_LIMIT_CONN="${USE_LIMIT_CONN-yes}"
|
USE_LIMIT_CONN="${USE_LIMIT_CONN-yes}"
|
||||||
LIMIT_CONN_MAX="${LIMIT_CONN_MAX-40}"
|
LIMIT_CONN_MAX="${LIMIT_CONN_MAX-50}"
|
||||||
LIMIT_CONN_CACHE="${LIMIT_CONN_CACHE-10m}"
|
LIMIT_CONN_CACHE="${LIMIT_CONN_CACHE-10m}"
|
||||||
PROXY_REAL_IP="${PROXY_REAL_IP-no}"
|
PROXY_REAL_IP="${PROXY_REAL_IP-no}"
|
||||||
PROXY_REAL_IP_FROM="${PROXY_REAL_IP_FROM-192.168.0.0/16 172.16.0.0/12 10.0.0.0/8}"
|
PROXY_REAL_IP_FROM="${PROXY_REAL_IP_FROM-192.168.0.0/16 172.16.0.0/12 10.0.0.0/8}"
|
||||||
@@ -128,4 +128,5 @@ ANTIBOT_SESSION_SECRET="${ANTIBOT_SESSION_SECRET-random}"
|
|||||||
USE_CROWDSEC="${USE_CROWDSEC-no}"
|
USE_CROWDSEC="${USE_CROWDSEC-no}"
|
||||||
USE_API="${USE_API-no}"
|
USE_API="${USE_API-no}"
|
||||||
API_URI="${API_URI-random}"
|
API_URI="${API_URI-random}"
|
||||||
|
API_WHITELIST_IP="${API_WHITELIST_IP-192.168.0.0/16 172.16.0.0/12 10.0.0.0/8}"
|
||||||
SWARM_MODE="${SWARM_MODE-no}"
|
SWARM_MODE="${SWARM_MODE-no}"
|
||||||
|
|||||||
@@ -52,6 +52,16 @@ if [ ! -f "/opt/installed" ] ; then
|
|||||||
|
|
||||||
echo "[*] Configuring bunkerized-nginx ..."
|
echo "[*] Configuring bunkerized-nginx ..."
|
||||||
|
|
||||||
|
# check permissions
|
||||||
|
if [ "$SWARM_MODE" = "no" ] ; then
|
||||||
|
/opt/entrypoint/permissions.sh
|
||||||
|
else
|
||||||
|
/opt/entrypoint/permissions-swarm.sh
|
||||||
|
fi
|
||||||
|
if [ "$?" -ne 0 ] ; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# logs config
|
# logs config
|
||||||
/opt/entrypoint/logs.sh
|
/opt/entrypoint/logs.sh
|
||||||
|
|
||||||
@@ -122,7 +132,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# list of log files to display
|
# list of log files to display
|
||||||
LOGS="/var/log/access.log /var/log/error.log /var/log/jobs.log"
|
LOGS="/var/log/access.log /var/log/error.log /var/log/jobs.log /var/log/nginx/modsec_audit.log"
|
||||||
|
|
||||||
# start fail2ban
|
# start fail2ban
|
||||||
if [ "$USE_FAIL2BAN" = "yes" ] ; then
|
if [ "$USE_FAIL2BAN" = "yes" ] ; then
|
||||||
|
|||||||
@@ -10,14 +10,18 @@
|
|||||||
cp /opt/confs/global/* /etc/nginx/
|
cp /opt/confs/global/* /etc/nginx/
|
||||||
|
|
||||||
# include server block(s)
|
# include server block(s)
|
||||||
if [ "$MULTISITE" = "yes" ] ; then
|
if [ "$SWARM_MODE" = "no" ] ; then
|
||||||
|
if [ "$MULTISITE" = "yes" ] ; then
|
||||||
includes=""
|
includes=""
|
||||||
for server in $SERVER_NAME ; do
|
for server in $SERVER_NAME ; do
|
||||||
includes="${includes}include /etc/nginx/${server}/server.conf;\n"
|
includes="${includes}include /etc/nginx/${server}/server.conf;\n"
|
||||||
done
|
done
|
||||||
replace_in_file "/etc/nginx/nginx.conf" "%INCLUDE_SERVER%" "$includes"
|
replace_in_file "/etc/nginx/nginx.conf" "%INCLUDE_SERVER%" "$includes"
|
||||||
else
|
else
|
||||||
replace_in_file "/etc/nginx/nginx.conf" "%INCLUDE_SERVER%" "include /etc/nginx/server.conf;"
|
replace_in_file "/etc/nginx/nginx.conf" "%INCLUDE_SERVER%" "include /etc/nginx/server.conf;"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
replace_in_file "/etc/nginx/nginx.conf" "%INCLUDE_SERVER%" ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# setup default server block if multisite
|
# setup default server block if multisite
|
||||||
@@ -171,7 +175,7 @@ fi
|
|||||||
|
|
||||||
# request limiting
|
# request limiting
|
||||||
if [ "$(has_value USE_LIMIT_REQ yes)" != "" ] ; then
|
if [ "$(has_value USE_LIMIT_REQ yes)" != "" ] ; then
|
||||||
replace_in_file "/etc/nginx/nginx.conf" "%LIMIT_REQ_ZONE%" "limit_req_zone \$binary_remote_addr zone=limit:${LIMIT_REQ_CACHE} rate=${LIMIT_REQ_RATE};"
|
replace_in_file "/etc/nginx/nginx.conf" "%LIMIT_REQ_ZONE%" "limit_req_zone \$binary_remote_addr\$uri zone=limit:${LIMIT_REQ_CACHE} rate=${LIMIT_REQ_RATE};"
|
||||||
else
|
else
|
||||||
replace_in_file "/etc/nginx/nginx.conf" "%LIMIT_REQ_ZONE%" ""
|
replace_in_file "/etc/nginx/nginx.conf" "%LIMIT_REQ_ZONE%" ""
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -19,3 +19,10 @@ touch /var/log/jobs.log
|
|||||||
replace_in_file "/etc/logrotate.conf" "%LOGROTATE_MAXAGE%" "$LOGROTATE_MAXAGE"
|
replace_in_file "/etc/logrotate.conf" "%LOGROTATE_MAXAGE%" "$LOGROTATE_MAXAGE"
|
||||||
replace_in_file "/etc/logrotate.conf" "%LOGROTATE_MINSIZE%" "$LOGROTATE_MINSIZE"
|
replace_in_file "/etc/logrotate.conf" "%LOGROTATE_MINSIZE%" "$LOGROTATE_MINSIZE"
|
||||||
echo "$LOGROTATE_CRON /opt/scripts/logrotate.sh > /dev/null 2>&1" >> /etc/crontabs/nginx
|
echo "$LOGROTATE_CRON /opt/scripts/logrotate.sh > /dev/null 2>&1" >> /etc/crontabs/nginx
|
||||||
|
|
||||||
|
# setup rsyslog
|
||||||
|
if [ "$REMOTE_SYSLOG" != "" ] ; then
|
||||||
|
replace_in_file "/etc/rsyslog.conf" "%REMOTE_SYSLOG%" "local0.* @${REMOTE_SYSLOG};rawFormat"
|
||||||
|
else
|
||||||
|
replace_in_file "/etc/rsyslog.conf" "%REMOTE_SYSLOG%" ""
|
||||||
|
fi
|
||||||
|
|||||||
@@ -38,3 +38,9 @@ if [ "$(has_value USE_CROWDSEC yes)" != "" ] ; then
|
|||||||
replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_HOST%" "$CROWDSEC_HOST"
|
replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_HOST%" "$CROWDSEC_HOST"
|
||||||
replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_KEY%" "$CROWDSEC_KEY"
|
replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_KEY%" "$CROWDSEC_KEY"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Whitelist IP for API
|
||||||
|
if [ "$USE_API" = "yes" ] ; then
|
||||||
|
list=$(spaces_to_lua "$API_WHITELIST_IP")
|
||||||
|
replace_in_file "/usr/local/lib/lua/api.lua" "%API_WHITELIST_IP%" "$list"
|
||||||
|
fi
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ if [ "$MULTISITE" = "yes" ] ; then
|
|||||||
fi
|
fi
|
||||||
SERVER_PREFIX="/etc/nginx/${server}/"
|
SERVER_PREFIX="/etc/nginx/${server}/"
|
||||||
if grep "/etc/letsencrypt/live" ${SERVER_PREFIX}https.conf > /dev/null && [ ! -f /etc/letsencrypt/live/${server}/fullchain.pem ] ; then
|
if grep "/etc/letsencrypt/live" ${SERVER_PREFIX}https.conf > /dev/null && [ ! -f /etc/letsencrypt/live/${server}/fullchain.pem ] ; then
|
||||||
/opt/scripts/certbot-new.sh "$server" "$(cat ${SERVER_PREFIX}email-lets-encrypt.txt)"
|
domains=$(cat ${SERVER_PREFIX}server.conf | sed -nE 's/^.*server_name (.*);$/\1/p' | sed "s/ /,/g")
|
||||||
|
/opt/scripts/certbot-new.sh "$domains" "$(cat ${SERVER_PREFIX}email-lets-encrypt.txt)"
|
||||||
fi
|
fi
|
||||||
if grep "modsecurity.conf" ${SERVER_PREFIX}server.conf > /dev/null ; then
|
if grep "modsecurity.conf" ${SERVER_PREFIX}server.conf > /dev/null ; then
|
||||||
modsec_custom=""
|
modsec_custom=""
|
||||||
|
|||||||
25
entrypoint/permissions-swarm.sh
Normal file
25
entrypoint/permissions-swarm.sh
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# /etc/letsencrypt
|
||||||
|
if [ ! -r "/etc/letsencrypt" ] || [ ! -x "/etc/letsencrypt" ] ; then
|
||||||
|
echo "[!] WARNING - wrong permissions on /etc/letsencrypt"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# /www
|
||||||
|
if [ ! -r "/www" ] || [ ! -x "/www" ] ; then
|
||||||
|
echo "[!] ERROR - wrong permissions on /www"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# /etc/nginx
|
||||||
|
if [ ! -r "/etc/nginx" ] || [ ! -x "/etc/nginx" ] ; then
|
||||||
|
echo "[!] ERROR - wrong permissions on /etc/nginx"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
# /acme-challenge
|
||||||
|
if [ ! -r "/acme-challenge" ] || [ ! -x "/acme-challenge" ] ; then
|
||||||
|
echo "[!] ERROR - wrong permissions on /acme-challenge"
|
||||||
|
exit 4
|
||||||
|
fi
|
||||||
29
entrypoint/permissions.sh
Normal file
29
entrypoint/permissions.sh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# /etc/letsencrypt
|
||||||
|
if [ ! -w "/etc/letsencrypt" ] || [ ! -r "/etc/letsencrypt" ] || [ ! -x "/etc/letsencrypt" ] ; then
|
||||||
|
echo "[!] WARNING - wrong permissions on /etc/letsencrypt"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "/usr/sbin/nginx" ] ; then
|
||||||
|
# /www
|
||||||
|
if [ ! -r "/www" ] || [ ! -x "/www" ] ; then
|
||||||
|
echo "[!] ERROR - wrong permissions on /www"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# /acme-challenge
|
||||||
|
if [ ! -w "/acme-challenge" ] || [ ! -r "/acme-challenge" ] || [ ! -x "/acme-challenge" ] ; then
|
||||||
|
echo "[!] ERROR - wrong permissions on /acme-challenge"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
# /etc/nginx
|
||||||
|
if [ ! -w "/etc/nginx" ] || [ ! -r "/etc/nginx" ] || [ ! -x "/etc/nginx" ] ; then
|
||||||
|
echo "[!] ERROR - wrong permissions on /etc/nginx"
|
||||||
|
exit 4
|
||||||
|
fi
|
||||||
|
|
||||||
@@ -9,16 +9,14 @@
|
|||||||
# get nginx path and override multisite variables
|
# get nginx path and override multisite variables
|
||||||
NGINX_PREFIX="/etc/nginx/"
|
NGINX_PREFIX="/etc/nginx/"
|
||||||
if [ "$MULTISITE" = "yes" ] ; then
|
if [ "$MULTISITE" = "yes" ] ; then
|
||||||
NGINX_PREFIX="${NGINX_PREFIX}${1}/"
|
first_server=$(echo "$1" | cut -d ' ' -f 1)
|
||||||
|
NGINX_PREFIX="${NGINX_PREFIX}${first_server}/"
|
||||||
if [ ! -d "$NGINX_PREFIX" ] ; then
|
if [ ! -d "$NGINX_PREFIX" ] ; then
|
||||||
mkdir "$NGINX_PREFIX"
|
mkdir "$NGINX_PREFIX"
|
||||||
fi
|
fi
|
||||||
ROOT_FOLDER="${ROOT_FOLDER}/$1"
|
ROOT_FOLDER="${ROOT_FOLDER}/$first_server"
|
||||||
fi
|
for var in $(env | cut -d '=' -f 1 | grep -E "^${first_server}_") ; do
|
||||||
|
repl_name=$(echo "$var" | sed "s~${first_server}_~~")
|
||||||
if [ "$MULTISITE" = "yes" ] ; then
|
|
||||||
for var in $(env | cut -d '=' -f 1 | grep -E "^${1}_") ; do
|
|
||||||
repl_name=$(echo "$var" | sed "s~${1}_~~")
|
|
||||||
repl_value=$(env | grep -E "^${var}=" | sed "s~^${var}=~~")
|
repl_value=$(env | grep -E "^${var}=" | sed "s~^${var}=~~")
|
||||||
read -r "$repl_name" <<< $repl_value
|
read -r "$repl_name" <<< $repl_value
|
||||||
done
|
done
|
||||||
@@ -27,9 +25,9 @@ fi
|
|||||||
set | grep -E -v "^(HOSTNAME|PWD|PKG_RELEASE|NJS_VERSION|SHLVL|PATH|_|NGINX_VERSION|HOME)=" > "${NGINX_PREFIX}nginx.env"
|
set | grep -E -v "^(HOSTNAME|PWD|PKG_RELEASE|NJS_VERSION|SHLVL|PATH|_|NGINX_VERSION|HOME)=" > "${NGINX_PREFIX}nginx.env"
|
||||||
if [ "$MULTISITE" = "yes" ] ; then
|
if [ "$MULTISITE" = "yes" ] ; then
|
||||||
for server in $SERVER_NAME ; do
|
for server in $SERVER_NAME ; do
|
||||||
sed -i "~^${server}_.*=.*~d" "${NGINX_PREFIX}nginx.env"
|
sed -i "/^${server}_.*=.*/d" "${NGINX_PREFIX}nginx.env"
|
||||||
done
|
done
|
||||||
sed -i "~^SERVER_NAME=.*~SERVER_NAME=${1}~" "${NGINX_PREFIX}nginx.env"
|
sed -i "s~^SERVER_NAME=.*~SERVER_NAME=${1}~" "${NGINX_PREFIX}nginx.env"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# copy stub confs
|
# copy stub confs
|
||||||
@@ -38,8 +36,8 @@ cp /opt/confs/site/* "$NGINX_PREFIX"
|
|||||||
# replace paths
|
# replace paths
|
||||||
replace_in_file "${NGINX_PREFIX}server.conf" "%MAIN_LUA%" "include ${NGINX_PREFIX}main-lua.conf;"
|
replace_in_file "${NGINX_PREFIX}server.conf" "%MAIN_LUA%" "include ${NGINX_PREFIX}main-lua.conf;"
|
||||||
if [ "$MULTISITE" = "yes" ] ; then
|
if [ "$MULTISITE" = "yes" ] ; then
|
||||||
replace_in_file "${NGINX_PREFIX}server.conf" "%SERVER_CONF%" "include /server-confs/*.conf;\ninclude /server-confs/${1}/*.conf;"
|
replace_in_file "${NGINX_PREFIX}server.conf" "%SERVER_CONF%" "include /server-confs/*.conf;\ninclude /server-confs/${first_server}/*.conf;"
|
||||||
replace_in_file "${NGINX_PREFIX}server.conf" "%PRE_SERVER_CONF%" "include /pre-server-confs/*.conf;\ninclude /pre-server-confs/${1}/*.conf;"
|
replace_in_file "${NGINX_PREFIX}server.conf" "%PRE_SERVER_CONF%" "include /pre-server-confs/*.conf;\ninclude /pre-server-confs/${first_server}/*.conf;"
|
||||||
else
|
else
|
||||||
replace_in_file "${NGINX_PREFIX}server.conf" "%SERVER_CONF%" "include /server-confs/*.conf;"
|
replace_in_file "${NGINX_PREFIX}server.conf" "%SERVER_CONF%" "include /server-confs/*.conf;"
|
||||||
replace_in_file "${NGINX_PREFIX}server.conf" "%PRE_SERVER_CONF%" "include /pre-server-confs/*.conf;"
|
replace_in_file "${NGINX_PREFIX}server.conf" "%PRE_SERVER_CONF%" "include /pre-server-confs/*.conf;"
|
||||||
@@ -69,8 +67,8 @@ if [ "$USE_REVERSE_PROXY" = "yes" ] ; then
|
|||||||
if [ "$custom_headers_value" != "" ] ; then
|
if [ "$custom_headers_value" != "" ] ; then
|
||||||
IFS_=$IFS
|
IFS_=$IFS
|
||||||
IFS=';'
|
IFS=';'
|
||||||
for header_value in $(echo "$custom_headers_value") ; do
|
for header_value in $(echo $custom_headers_value) ; do
|
||||||
replace_in_file "${NGINX_PREFIX}reverse-proxy-${i}.conf" "%REVERSE_PROXY_CUSTOM_HEADERS%" "more_set_headers $header_value;\n%REVERSE_PROXY_CUSTOM_HEADERS%"
|
replace_in_file "${NGINX_PREFIX}reverse-proxy-${i}.conf" "%REVERSE_PROXY_CUSTOM_HEADERS%" "proxy_set_header $header_value;\n%REVERSE_PROXY_CUSTOM_HEADERS%"
|
||||||
done
|
done
|
||||||
IFS=$IFS_
|
IFS=$IFS_
|
||||||
fi
|
fi
|
||||||
@@ -288,6 +286,14 @@ else
|
|||||||
replace_in_file "${NGINX_PREFIX}main-lua.conf" "%WHITELIST_USER_AGENT%" ""
|
replace_in_file "${NGINX_PREFIX}main-lua.conf" "%WHITELIST_USER_AGENT%" ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# whitelist URI
|
||||||
|
if [ "$WHITELIST_URI" != "" ] ; then
|
||||||
|
list=$(spaces_to_lua "$WHITELIST_URI")
|
||||||
|
replace_in_file "${NGINX_PREFIX}main-lua.conf" "%WHITELIST_URI%" "$list"
|
||||||
|
else
|
||||||
|
replace_in_file "${NGINX_PREFIX}main-lua.conf" "%WHITELIST_URI%" ""
|
||||||
|
fi
|
||||||
|
|
||||||
# block bad referrer
|
# block bad referrer
|
||||||
if [ "$BLOCK_REFERRER" = "yes" ] ; then
|
if [ "$BLOCK_REFERRER" = "yes" ] ; then
|
||||||
replace_in_file "${NGINX_PREFIX}main-lua.conf" "%USE_REFERRER%" "true"
|
replace_in_file "${NGINX_PREFIX}main-lua.conf" "%USE_REFERRER%" "true"
|
||||||
@@ -343,8 +349,8 @@ if [ "$AUTO_LETS_ENCRYPT" = "yes" ] || [ "$USE_CUSTOM_HTTPS" = "yes" ] || [ "$GE
|
|||||||
if [ "$MULTISITE" = "no" ] ; then
|
if [ "$MULTISITE" = "no" ] ; then
|
||||||
FIRST_SERVER_NAME=$(echo "$SERVER_NAME" | cut -d " " -f 1)
|
FIRST_SERVER_NAME=$(echo "$SERVER_NAME" | cut -d " " -f 1)
|
||||||
else
|
else
|
||||||
FIRST_SERVER_NAME="$1"
|
FIRST_SERVER_NAME="$first_server"
|
||||||
EMAIL_LETS_ENCRYPT="${EMAIL_LETS_ENCRYPT-contact@$1}"
|
EMAIL_LETS_ENCRYPT="${EMAIL_LETS_ENCRYPT-contact@$first_server}"
|
||||||
echo -n "$EMAIL_LETS_ENCRYPT" > ${NGINX_PREFIX}email-lets-encrypt.txt
|
echo -n "$EMAIL_LETS_ENCRYPT" > ${NGINX_PREFIX}email-lets-encrypt.txt
|
||||||
fi
|
fi
|
||||||
replace_in_file "${NGINX_PREFIX}https.conf" "%HTTPS_CERT%" "/etc/letsencrypt/live/${FIRST_SERVER_NAME}/fullchain.pem"
|
replace_in_file "${NGINX_PREFIX}https.conf" "%HTTPS_CERT%" "/etc/letsencrypt/live/${FIRST_SERVER_NAME}/fullchain.pem"
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ services:
|
|||||||
- DISABLE_DEFAULT_SERVER=yes
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
labels:
|
labels:
|
||||||
- "bunkerized-nginx.AUTOCONF"
|
- "bunkerized-nginx.AUTOCONF"
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ services:
|
|||||||
- REDIRECT_HTTP_TO_HTTPS=yes
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
- DISABLE_DEFAULT_SERVER=yes
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
|
- USE_PROXY_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- USE_REVERSE_PROXY=yes
|
- USE_REVERSE_PROXY=yes
|
||||||
labels:
|
labels:
|
||||||
- "bunkerized-nginx.AUTOCONF"
|
- "bunkerized-nginx.AUTOCONF"
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ services:
|
|||||||
- DISABLE_DEFAULT_SERVER=yes
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- REMOTE_PHP=myphp
|
- REMOTE_PHP=myphp
|
||||||
- REMOTE_PHP_PATH=/app
|
- REMOTE_PHP_PATH=/app
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ services:
|
|||||||
- PROXY_REAL_IP=yes
|
- PROXY_REAL_IP=yes
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- REMOTE_PHP=myphp1
|
- REMOTE_PHP=myphp1
|
||||||
- REMOTE_PHP_PATH=/app
|
- REMOTE_PHP_PATH=/app
|
||||||
labels:
|
labels:
|
||||||
@@ -41,7 +40,6 @@ services:
|
|||||||
- PROXY_REAL_IP=yes
|
- PROXY_REAL_IP=yes
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- REMOTE_PHP=myphp2
|
- REMOTE_PHP=myphp2
|
||||||
- REMOTE_PHP_PATH=/app
|
- REMOTE_PHP_PATH=/app
|
||||||
labels:
|
labels:
|
||||||
|
|||||||
26
examples/certbot-wildcard/certbot-wildcard.sh
Executable file
26
examples/certbot-wildcard/certbot-wildcard.sh
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# you need to run it before starting bunkerized-nginx
|
||||||
|
# since it's manual there is no auto renew, you need to run it again before it expires
|
||||||
|
|
||||||
|
DOMAIN="*.website.com"
|
||||||
|
SERVICE="mywww"
|
||||||
|
|
||||||
|
# ask for wildcard certificate
|
||||||
|
# it's interactive and you will need to add a DNS entry
|
||||||
|
docker run --rm -it -v "${PWD}/letsencrypt:/etc/letsencrypt" certbot/certbot certonly --manual -d $DOMAIN --agree-tos
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
echo "error while getting certificate for $DOMAIN"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# fix permissions
|
||||||
|
chown -R 101:101 "${PWD}/letsencrypt"
|
||||||
|
|
||||||
|
# reload nginx if it's already running (in case of a "renew")
|
||||||
|
if [ -z `docker-compose ps -q $SERVICE` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q $SERVICE)` ]; then
|
||||||
|
echo "bunkerized-nginx is not running, skipping nginx reload"
|
||||||
|
else
|
||||||
|
echo "bunkerized-nginx is running, sending reload order"
|
||||||
|
docker-compose exec $SERVICE nginx -s reload
|
||||||
|
fi
|
||||||
39
examples/certbot-wildcard/docker-compose.yml
Normal file
39
examples/certbot-wildcard/docker-compose.yml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
mywww:
|
||||||
|
image: bunkerity/bunkerized-nginx
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 80:8080
|
||||||
|
- 443:8443
|
||||||
|
volumes:
|
||||||
|
- ./web-files:/www:ro
|
||||||
|
- ./letsencrypt:/letsencrypt:ro
|
||||||
|
environment:
|
||||||
|
- SERVER_NAME=app1.website.com app2.website.com # replace with your domains
|
||||||
|
- MULTISITE=yes
|
||||||
|
- USE_CUSTOM_HTTPS=yes
|
||||||
|
- CUSTOM_HTTPS_CERT=/letsencrypt/live/website.com/fullchain.pem
|
||||||
|
- CUSTOM_HTTPS_KEY=/letsencrypt/live/website.com/privkey.pem
|
||||||
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
|
- USE_GZIP=yes
|
||||||
|
- app1.website.com_REMOTE_PHP=myapp1
|
||||||
|
- app1.website.com_REMOTE_PHP_PATH=/app
|
||||||
|
- app2.website.com_REMOTE_PHP=myapp2
|
||||||
|
- app2.website.com_REMOTE_PHP_PATH=/app
|
||||||
|
|
||||||
|
myapp1:
|
||||||
|
image: php:fpm
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./web-files/app1.website.com:/app
|
||||||
|
|
||||||
|
myapp2:
|
||||||
|
image: php:fpm
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./web-files/app2.website.com:/app
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
echo "hello from app1 !";
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
echo "hello from app2 !";
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -1,3 +1,23 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
# first, you need to run the crowdsec service
|
||||||
|
echo "running crowdsec service ..."
|
||||||
|
docker-compose up -d mycrowdsec
|
||||||
|
|
||||||
|
# wait a little until it's up
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# get the bouncer key
|
||||||
docker-compose exec mycrowdsec cscli bouncers add MyBouncer
|
docker-compose exec mycrowdsec cscli bouncers add MyBouncer
|
||||||
|
|
||||||
|
# enter the key into the CROWDSEC_KEY environment variable
|
||||||
|
read -p -s "edit CROWDSEC_KEY env var in docker-compose.yml file and press enter"
|
||||||
|
|
||||||
|
# start all services
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# wait a little until it's up
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# restart crowdsec so it reads the log files
|
||||||
|
docker-compose restart mycrowdsec
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ services:
|
|||||||
- DISABLE_DEFAULT_SERVER=yes
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- USE_CROWDSEC=yes
|
- USE_CROWDSEC=yes
|
||||||
- CROWDSEC_HOST=http://mycrowdsec:8080
|
- CROWDSEC_HOST=http://mycrowdsec:8080
|
||||||
- CROWDSEC_KEY= # you need to generate it (see bouncer_key.sh)
|
- CROWDSEC_KEY= # you need to generate it (see bouncer_key.sh)
|
||||||
@@ -34,7 +33,7 @@ services:
|
|||||||
- net2
|
- net2
|
||||||
|
|
||||||
mycrowdsec:
|
mycrowdsec:
|
||||||
image: crowdsecurity/crowdsec:v1.0.2
|
image: crowdsecurity/crowdsec:v1.0.13
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./acquis.yaml:/etc/crowdsec/acquis.yaml
|
- ./acquis.yaml:/etc/crowdsec/acquis.yaml
|
||||||
|
|||||||
30
examples/ghost/docker-compose.yml
Normal file
30
examples/ghost/docker-compose.yml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
myreverse:
|
||||||
|
image: bunkerity/bunkerized-nginx
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 80:8080
|
||||||
|
- 443:8443
|
||||||
|
volumes:
|
||||||
|
- ./letsencrypt:/etc/letsencrypt
|
||||||
|
environment:
|
||||||
|
- SERVER_NAME=www.website.com # replace with your domain
|
||||||
|
- SERVE_FILES=no
|
||||||
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
|
- USE_PROXY_CACHE=yes
|
||||||
|
- USE_GZIP=yes
|
||||||
|
- USE_REVERSE_PROXY=yes
|
||||||
|
- REVERSE_PROXY_URL=/
|
||||||
|
- REVERSE_PROXY_HOST=http://myghost:2368/
|
||||||
|
|
||||||
|
myghost:
|
||||||
|
image: ghost:alpine
|
||||||
|
volumes:
|
||||||
|
- ./data-ghost:/var/lib/ghost/content
|
||||||
|
environment:
|
||||||
|
- url=https://www.website.com # replace with your domain
|
||||||
30
examples/gogs/docker-compose.yml
Normal file
30
examples/gogs/docker-compose.yml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
myreverse:
|
||||||
|
image: bunkerity/bunkerized-nginx
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 80:8080
|
||||||
|
- 443:8443
|
||||||
|
volumes:
|
||||||
|
- ./letsencrypt:/etc/letsencrypt
|
||||||
|
- ./modsec-crs-confs:/modsec-crs-confs:ro # fix FP with CRS
|
||||||
|
environment:
|
||||||
|
- SERVER_NAME=www.website.com # replace with your domain
|
||||||
|
- SERVE_FILES=no
|
||||||
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
|
- USE_PROXY_CACHE=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
|
- USE_GZIP=yes
|
||||||
|
- USE_REVERSE_PROXY=yes
|
||||||
|
- REVERSE_PROXY_URL=/
|
||||||
|
- REVERSE_PROXY_HOST=http://mygogs:3000/
|
||||||
|
|
||||||
|
mygogs:
|
||||||
|
image: gogs/gogs
|
||||||
|
volumes:
|
||||||
|
- ./data-gogs:/data
|
||||||
7
examples/gogs/modsec-crs-confs/gogs.conf
Normal file
7
examples/gogs/modsec-crs-confs/gogs.conf
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
SecAction \
|
||||||
|
"id:900220,\
|
||||||
|
phase:1,\
|
||||||
|
nolog,\
|
||||||
|
pass,\
|
||||||
|
t:none,\
|
||||||
|
setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |multipart/related| |text/xml| |application/xml| |application/soap+xml| |application/x-amf| |application/json| |application/cloudevents+json| |application/cloudevents-batch+json| |application/octet-stream| |application/csp-report| |application/xss-auditor-report| |text/plain| |application/x-git-upload-pack-request| |application/x-git-receive-pack-request|'"
|
||||||
45
examples/joomla/docker-compose.yml
Normal file
45
examples/joomla/docker-compose.yml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
mywww:
|
||||||
|
image: bunkerity/bunkerized-nginx
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 80:8080
|
||||||
|
- 443:8443
|
||||||
|
volumes:
|
||||||
|
- ./joomla-files:/www:ro
|
||||||
|
- ./letsencrypt:/etc/letsencrypt
|
||||||
|
environment:
|
||||||
|
- SERVER_NAME=www.website.com # replace with your domain
|
||||||
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
|
- MAX_CLIENT_SIZE=50m
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
|
- USE_GZIP=yes
|
||||||
|
- REMOTE_PHP=myjoomla
|
||||||
|
- REMOTE_PHP_PATH=/var/www/html
|
||||||
|
|
||||||
|
myjoomla:
|
||||||
|
image: joomla:fpm-alpine
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./joomla-files:/var/www/html
|
||||||
|
environment:
|
||||||
|
- JOOMLA_DB_HOST=mydb
|
||||||
|
- JOOMLA_DB_NAME=joomladb
|
||||||
|
- JOOMLA_DB_USER=user
|
||||||
|
- JOOMLA_DB_PASSWORD=db-user-pwd # replace with a stronger password (must match MYSQL_PASSWORD)
|
||||||
|
|
||||||
|
mydb:
|
||||||
|
image: mariadb
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./db-data:/var/lib/mysql
|
||||||
|
environment:
|
||||||
|
- MYSQL_ROOT_PASSWORD=db-root-pwd # replace with a stronger password
|
||||||
|
- MYSQL_DATABASE=joomladb
|
||||||
|
- MYSQL_USER=user
|
||||||
|
- MYSQL_PASSWORD=db-user-pwd # replace with a stronger password (must match JOOMLA_DB_PASSWORD)
|
||||||
@@ -18,8 +18,8 @@ services:
|
|||||||
- REDIRECT_HTTP_TO_HTTPS=yes
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
- AUTO_LETS_ENCRYPT=yes
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
- USE_PROXY_CACHE=yes
|
- USE_PROXY_CACHE=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- USE_REVERSE_PROXY=yes
|
- USE_REVERSE_PROXY=yes
|
||||||
- REVERSE_PROXY_URL=/
|
- REVERSE_PROXY_URL=/
|
||||||
- REVERSE_PROXY_HOST=http://app
|
- REVERSE_PROXY_HOST=http://app
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ services:
|
|||||||
- MAX_CLIENT_SIZE=50m
|
- MAX_CLIENT_SIZE=50m
|
||||||
- SERVE_FILES=no
|
- SERVE_FILES=no
|
||||||
- USE_PROXY_CACHE=yes
|
- USE_PROXY_CACHE=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- USE_REVERSE_PROXY=yes
|
- USE_REVERSE_PROXY=yes
|
||||||
- REVERSE_PROXY_URL=/
|
- REVERSE_PROXY_URL=/
|
||||||
- REVERSE_PROXY_HOST=https://mymoodle:8443
|
- REVERSE_PROXY_HOST=https://mymoodle:8443
|
||||||
|
|||||||
@@ -19,13 +19,11 @@ services:
|
|||||||
- DISABLE_DEFAULT_SERVER=yes
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- app1.website.com_REMOTE_PHP=myapp1
|
- app1.website.com_REMOTE_PHP=myapp1
|
||||||
- app1.website.com_REMOTE_PHP_PATH=/app
|
- app1.website.com_REMOTE_PHP_PATH=/app
|
||||||
- app2.website.com_REMOTE_PHP=myapp2
|
- app2.website.com_REMOTE_PHP=myapp2
|
||||||
- app2.website.com_REMOTE_PHP_PATH=/app
|
- app2.website.com_REMOTE_PHP_PATH=/app
|
||||||
- app3.website.com_SERVE_FILES=no
|
- app3.website.com_SERVE_FILES=no
|
||||||
- app3.website.com_USE_CLIENT_CACHE=no
|
|
||||||
- app3.website.com_USE_PROXY_CACHE=yes
|
- app3.website.com_USE_PROXY_CACHE=yes
|
||||||
- app3.website.com_USE_REVERSE_PROXY=yes
|
- app3.website.com_USE_REVERSE_PROXY=yes
|
||||||
- app3.website.com_REVERSE_PROXY_URL=/
|
- app3.website.com_REVERSE_PROXY_URL=/
|
||||||
|
|||||||
@@ -22,14 +22,13 @@ services:
|
|||||||
- DISABLE_DEFAULT_SERVER=yes
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- wp.website.com_REMOTE_PHP=mywp
|
- wp.website.com_REMOTE_PHP=mywp
|
||||||
- wp.website.com_REMOTE_PHP_PATH=/var/www/html
|
- wp.website.com_REMOTE_PHP_PATH=/var/www/html
|
||||||
- nc.website.com_REMOTE_PHP=mync
|
- nc.website.com_REMOTE_PHP=mync
|
||||||
- nc.website.com_REMOTE_PHP_PATH=/var/www/html
|
- nc.website.com_REMOTE_PHP_PATH=/var/www/html
|
||||||
- nc.website.com_LIMIT_REQ_RATE=40r/s
|
- nc.website.com_LIMIT_REQ_RATE=5r/s
|
||||||
- nc.website.com_LIMIT_REQ_BURST=60
|
- nc.website.com_LIMIT_REQ_BURST=10
|
||||||
- nc.website.com_ALLOWED_METHODS=GET|POST|HEAD|PROPFIND|DELETE|PUT|MKCOL|MOVE|COPY|PROPPATCH|REPORT
|
- nc.website.com_ALLOWED_METHODS=GET|POST|HEAD|COPY|DELETE|LOCK|MKCOL|MOVE|PROPFIND|PROPPATCH|PUT|UNLOCK|OPTIONS
|
||||||
- nc.website.com_X_FRAME_OPTIONS=SAMEORIGIN
|
- nc.website.com_X_FRAME_OPTIONS=SAMEORIGIN
|
||||||
- nc.website.com_FAIL2BAN_STATUS_CODE=400|401|403|405|444
|
- nc.website.com_FAIL2BAN_STATUS_CODE=400|401|403|405|444
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
SecRuleRemoveById 921110
|
SecRuleRemoveById 921110
|
||||||
|
SecRule REQUEST_FILENAME "@contains /remote.php/webdav" "id:1,ctl:ruleRemoveByTag=OWASP_CRS"
|
||||||
|
|||||||
@@ -1 +1,4 @@
|
|||||||
|
SecRule REQUEST_FILENAME "/wp-admin/admin-ajax.php" "id:1,ctl:ruleRemoveByTag=attack-xss,ctl:ruleRemoveByTag=attack-rce"
|
||||||
|
SecRule REQUEST_FILENAME "/wp-admin/options.php" "id:2,ctl:ruleRemoveByTag=attack-xss"
|
||||||
|
SecRule REQUEST_FILENAME "^/wp-json/yoast" "id:3,ctl:ruleRemoveById=930120"
|
||||||
SecRuleRemoveById 953120
|
SecRuleRemoveById 953120
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
pass,\
|
pass,\
|
||||||
t:none,\
|
t:none,\
|
||||||
setvar:'tx.allowed_methods=GET HEAD POST PROPFIND DELETE PUT MKCOL MOVE COPY PROPPATCH REPORT'"
|
setvar:'tx.allowed_methods=GET POST HEAD COPY DELETE LOCK MKCOL MOVE PROPFIND PROPPATCH PUT UNLOCK OPTIONS'"
|
||||||
|
|||||||
@@ -23,16 +23,15 @@ services:
|
|||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- REMOTE_PHP=mync
|
- REMOTE_PHP=mync
|
||||||
- REMOTE_PHP_PATH=/var/www/html
|
- REMOTE_PHP_PATH=/var/www/html
|
||||||
- LIMIT_REQ_RATE=40r/s
|
- LIMIT_REQ_RATE=5r/s
|
||||||
- LIMIT_REQ_BURST=60
|
- LIMIT_REQ_BURST=10
|
||||||
- ALLOWED_METHODS=GET|POST|HEAD|PROPFIND|DELETE|PUT|MKCOL|MOVE|COPY|PROPPATCH|REPORT
|
- ALLOWED_METHODS=GET|POST|HEAD|COPY|DELETE|LOCK|MKCOL|MOVE|PROPFIND|PROPPATCH|PUT|UNLOCK|OPTIONS
|
||||||
- X_FRAME_OPTIONS=SAMEORIGIN
|
- X_FRAME_OPTIONS=SAMEORIGIN
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- FAIL2BAN_STATUS_CODE=400|401|403|405|444
|
- FAIL2BAN_STATUS_CODE=400|401|403|405|444
|
||||||
|
|
||||||
mync:
|
mync:
|
||||||
image: nextcloud:20-fpm
|
image: nextcloud:21-fpm
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./nc-files:/var/www/html
|
- ./nc-files:/var/www/html
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
SecRuleRemoveById 921110
|
SecRuleRemoveById 921110
|
||||||
|
SecRule REQUEST_FILENAME "@contains /remote.php/webdav" "id:1,ctl:ruleRemoveByTag=OWASP_CRS"
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
pass,\
|
pass,\
|
||||||
t:none,\
|
t:none,\
|
||||||
setvar:'tx.allowed_methods=GET HEAD POST PROPFIND DELETE PUT MKCOL MOVE COPY PROPPATCH REPORT'"
|
setvar:'tx.allowed_methods=GET POST HEAD COPY DELETE LOCK MKCOL MOVE PROPFIND PROPPATCH PUT UNLOCK OPTIONS'"
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ services:
|
|||||||
- ALLOWED_METHODS=GET|POST|HEAD|PUT|DELETE
|
- ALLOWED_METHODS=GET|POST|HEAD|PUT|DELETE
|
||||||
- SERVE_FILES=no
|
- SERVE_FILES=no
|
||||||
- USE_PROXY_CACHE=yes
|
- USE_PROXY_CACHE=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- USE_REVERSE_PROXY=yes
|
- USE_REVERSE_PROXY=yes
|
||||||
- REVERSE_PROXY_URL=/
|
- REVERSE_PROXY_URL=/
|
||||||
- REVERSE_PROXY_HOST=https://mypassbolt
|
- REVERSE_PROXY_HOST=https://mypassbolt
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ services:
|
|||||||
- MAX_CLIENT_SIZE=50m
|
- MAX_CLIENT_SIZE=50m
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- REMOTE_PHP=myprestashop
|
- REMOTE_PHP=myprestashop
|
||||||
- REMOTE_PHP_PATH=/var/www/html
|
- REMOTE_PHP_PATH=/var/www/html
|
||||||
|
- LIMIT_REQ_RATE=5r/s
|
||||||
|
- LIMIT_REQ_BURST=10
|
||||||
|
|
||||||
myprestashop:
|
myprestashop:
|
||||||
image: prestashop/prestashop:1.7-fpm
|
image: prestashop/prestashop:1.7-fpm
|
||||||
|
|||||||
46
examples/redmine/docker-compose.yml
Normal file
46
examples/redmine/docker-compose.yml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
myreverse:
|
||||||
|
image: bunkerity/bunkerized-nginx
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 80:8080
|
||||||
|
- 443:8443
|
||||||
|
volumes:
|
||||||
|
- ./letsencrypt:/etc/letsencrypt
|
||||||
|
environment:
|
||||||
|
- SERVER_NAME=www.website.com # replace with your domain
|
||||||
|
- SERVE_FILES=no
|
||||||
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
|
- USE_PROXY_CACHE=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
|
- USE_GZIP=yes
|
||||||
|
- USE_REVERSE_PROXY=yes
|
||||||
|
- REVERSE_PROXY_URL=/
|
||||||
|
- REVERSE_PROXY_HOST=http://myredmine:3000/
|
||||||
|
|
||||||
|
myredmine:
|
||||||
|
image: redmine
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./redmine-data:/usr/src/redmine/files
|
||||||
|
environment:
|
||||||
|
- REDMINE_DB_MYSQL=mydb
|
||||||
|
- REDMINE_DB_DATABASE=redminedb
|
||||||
|
- REDMINE_DB_USERNAME=user
|
||||||
|
- REDMINE_DB_PASSWORD=db-user-pwd # replace with a stronger password (must match MYSQL_PASSWORD)
|
||||||
|
|
||||||
|
mydb:
|
||||||
|
image: mariadb
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./db-data:/var/lib/mysql
|
||||||
|
environment:
|
||||||
|
- MYSQL_ROOT_PASSWORD=db-root-pwd # replace with a stronger password
|
||||||
|
- MYSQL_DATABASE=redminedb
|
||||||
|
- MYSQL_USER=user
|
||||||
|
- MYSQL_PASSWORD=db-user-pwd # replace with a stronger password (must match REDMINE_DB_PASSWORD)
|
||||||
@@ -18,8 +18,8 @@ services:
|
|||||||
- REDIRECT_HTTP_TO_HTTPS=yes
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
- AUTO_LETS_ENCRYPT=yes
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
- USE_PROXY_CACHE=yes
|
- USE_PROXY_CACHE=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- USE_REVERSE_PROXY=yes
|
- USE_REVERSE_PROXY=yes
|
||||||
- app1.website.com_REVERSE_PROXY_URL=/
|
- app1.website.com_REVERSE_PROXY_URL=/
|
||||||
- app1.website.com_REVERSE_PROXY_HOST=http://app1:3000
|
- app1.website.com_REVERSE_PROXY_HOST=http://app1:3000
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ services:
|
|||||||
- REDIRECT_HTTP_TO_HTTPS=yes
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
- AUTO_LETS_ENCRYPT=yes
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
- USE_PROXY_CACHE=yes
|
- USE_PROXY_CACHE=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- USE_REVERSE_PROXY=yes
|
- USE_REVERSE_PROXY=yes
|
||||||
- REVERSE_PROXY_URL_1=/app1/
|
- REVERSE_PROXY_URL_1=/app1/
|
||||||
- REVERSE_PROXY_HOST_1=http://app1:3000/
|
- REVERSE_PROXY_HOST_1=http://app1:3000/
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ services:
|
|||||||
- REDIRECT_HTTP_TO_HTTPS=yes
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
- AUTO_LETS_ENCRYPT=yes
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
- USE_PROXY_CACHE=yes
|
- USE_PROXY_CACHE=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- USE_REVERSE_PROXY=yes
|
- USE_REVERSE_PROXY=yes
|
||||||
- REVERSE_PROXY_URL=/ws/
|
- REVERSE_PROXY_URL=/ws/
|
||||||
- REVERSE_PROXY_HOST=http://myws:8010/
|
- REVERSE_PROXY_HOST=http://myws:8010/
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ services:
|
|||||||
mode: host
|
mode: host
|
||||||
protocol: tcp
|
protocol: tcp
|
||||||
volumes:
|
volumes:
|
||||||
- /shared/confs:/etc/nginx:ro
|
- /shared/confs:/etc/nginx
|
||||||
- /shared/letsencrypt:/etc/letsencrypt:ro
|
- /shared/letsencrypt:/etc/letsencrypt:ro
|
||||||
- /shared/acme-challenge:/acme-challenge:ro
|
- /shared/acme-challenge:/acme-challenge:ro
|
||||||
- /shared/www:/www:ro
|
- /shared/www:/www:ro
|
||||||
@@ -45,6 +45,7 @@ services:
|
|||||||
- AUTO_LETS_ENCRYPT=yes
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
- REDIRECT_HTTP_TO_HTTPS=yes
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
- DISABLE_DEFAULT_SERVER=yes
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
networks:
|
networks:
|
||||||
- net_config
|
- net_config
|
||||||
- net_services
|
- net_services
|
||||||
@@ -86,6 +87,7 @@ services:
|
|||||||
- "node.role==worker"
|
- "node.role==worker"
|
||||||
labels:
|
labels:
|
||||||
- "bunkerized-nginx.SERVER_NAME=app2.website.com"
|
- "bunkerized-nginx.SERVER_NAME=app2.website.com"
|
||||||
|
- "bunkerized-nginx.USE_PROXY_CACHE=yes"
|
||||||
- "bunkerized-nginx.USE_REVERSE_PROXY=yes"
|
- "bunkerized-nginx.USE_REVERSE_PROXY=yes"
|
||||||
- "bunkerized-nginx.REVERSE_PROXY_URL=/"
|
- "bunkerized-nginx.REVERSE_PROXY_URL=/"
|
||||||
- "bunkerized-nginx.REVERSE_PROXY_HOST=http://app2"
|
- "bunkerized-nginx.REVERSE_PROXY_HOST=http://app2"
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ services:
|
|||||||
- REDIRECT_HTTP_TO_HTTPS=yes
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
- AUTO_LETS_ENCRYPT=yes
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
- USE_PROXY_CACHE=yes
|
- USE_PROXY_CACHE=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- USE_REVERSE_PROXY=yes
|
- USE_REVERSE_PROXY=yes
|
||||||
- REVERSE_PROXY_URL=/
|
- REVERSE_PROXY_URL=/
|
||||||
- REVERSE_PROXY_HOST=http://mytomcat:8080/sample/
|
- REVERSE_PROXY_HOST=http://mytomcat:8080/sample/
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ services:
|
|||||||
- USE_ANTIBOT=captcha
|
- USE_ANTIBOT=captcha
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- REMOTE_PHP=myphp
|
- REMOTE_PHP=myphp
|
||||||
- REMOTE_PHP_PATH=/app
|
- REMOTE_PHP_PATH=/app
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ services:
|
|||||||
- AUTO_LETS_ENCRYPT=yes
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
- REDIRECT_HTTP_TO_HTTPS=yes
|
- REDIRECT_HTTP_TO_HTTPS=yes
|
||||||
- DISABLE_DEFAULT_SERVER=yes
|
- DISABLE_DEFAULT_SERVER=yes
|
||||||
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- admin.website.com_SERVE_FILES=no
|
- admin.website.com_SERVE_FILES=no
|
||||||
- admin.website.com_USE_AUTH_BASIC=yes
|
- admin.website.com_USE_AUTH_BASIC=yes
|
||||||
- admin.website.com_AUTH_BASIC_USER=admin # change it to something hard to guess
|
- admin.website.com_AUTH_BASIC_USER=admin # change it to something hard to guess
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ services:
|
|||||||
- ./letsencrypt:/etc/letsencrypt
|
- ./letsencrypt:/etc/letsencrypt
|
||||||
- ./server-confs:/server-confs:ro # custom confs at server context for permalinks
|
- ./server-confs:/server-confs:ro # custom confs at server context for permalinks
|
||||||
- ./modsec-crs-confs:/modsec-crs-confs:ro # custom Core Rule Set confs to add Wordpress exclusions
|
- ./modsec-crs-confs:/modsec-crs-confs:ro # custom Core Rule Set confs to add Wordpress exclusions
|
||||||
|
- ./modsec-confs:/modsec-confs:ro # avoid some FP with CRS
|
||||||
environment:
|
environment:
|
||||||
- SERVER_NAME=www.website.com # replace with your domain
|
- SERVER_NAME=www.website.com # replace with your domain
|
||||||
- AUTO_LETS_ENCRYPT=yes
|
- AUTO_LETS_ENCRYPT=yes
|
||||||
@@ -21,7 +22,6 @@ services:
|
|||||||
- MAX_CLIENT_SIZE=50m
|
- MAX_CLIENT_SIZE=50m
|
||||||
- USE_CLIENT_CACHE=yes
|
- USE_CLIENT_CACHE=yes
|
||||||
- USE_GZIP=yes
|
- USE_GZIP=yes
|
||||||
- USE_BROTLI=yes
|
|
||||||
- REMOTE_PHP=mywp
|
- REMOTE_PHP=mywp
|
||||||
- REMOTE_PHP_PATH=/var/www/html
|
- REMOTE_PHP_PATH=/var/www/html
|
||||||
|
|
||||||
|
|||||||
4
examples/wordpress/modsec-confs/wordpress.conf
Normal file
4
examples/wordpress/modsec-confs/wordpress.conf
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
SecRule REQUEST_FILENAME "/wp-admin/admin-ajax.php" "id:1,ctl:ruleRemoveByTag=attack-xss,ctl:ruleRemoveByTag=attack-rce"
|
||||||
|
SecRule REQUEST_FILENAME "/wp-admin/options.php" "id:2,ctl:ruleRemoveByTag=attack-xss"
|
||||||
|
SecRule REQUEST_FILENAME "^/wp-json/yoast" "id:3,ctl:ruleRemoveById=930120"
|
||||||
|
SecRuleRemoveById 953120
|
||||||
@@ -25,3 +25,5 @@ module(load="imuxsock" SysSock.Name="/tmp/log")
|
|||||||
$template rawFormat,"%msg:2:2048%\n"
|
$template rawFormat,"%msg:2:2048%\n"
|
||||||
local0.=notice /var/log/access.log;rawFormat
|
local0.=notice /var/log/access.log;rawFormat
|
||||||
local0.*;local0.!=notice /var/log/error.log;rawFormat
|
local0.*;local0.!=notice /var/log/error.log;rawFormat
|
||||||
|
|
||||||
|
%REMOTE_SYSLOG%
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
local api_list = {}
|
local api_list = {}
|
||||||
|
local api_whitelist_ip = {%API_WHITELIST_IP%}
|
||||||
|
local iputils = require "resty.iputils"
|
||||||
|
local whitelist = iputils.parse_cidrs(api_whitelist_ip)
|
||||||
|
|
||||||
api_list["^/ping$"] = function ()
|
api_list["^/ping$"] = function ()
|
||||||
return true
|
return true
|
||||||
@@ -10,7 +13,7 @@ api_list["^/reload$"] = function ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function M.is_api_call (api_uri)
|
function M.is_api_call (api_uri)
|
||||||
if ngx.var.request_uri:sub(1, #api_uri) .. "/" == api_uri .. "/" then
|
if iputils.ip_in_cidrs(ngx.var.remote_addr, whitelist) and ngx.var.request_uri:sub(1, #api_uri) .. "/" == api_uri .. "/" then
|
||||||
for uri, code in pairs(api_list) do
|
for uri, code in pairs(api_list) do
|
||||||
if string.match(ngx.var.request_uri:sub(#api_uri + 1), uri) then
|
if string.match(ngx.var.request_uri:sub(#api_uri + 1), uri) then
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
local dns = require "dns"
|
local dns = require "dns"
|
||||||
|
local iputils = require "resty.iputils"
|
||||||
local ip_list = {%BLACKLIST_IP_LIST%}
|
local ip_list = {%BLACKLIST_IP_LIST%}
|
||||||
|
local blacklist = iputils.parse_cidrs(ip_list)
|
||||||
local reverse_list = {%BLACKLIST_REVERSE_LIST%}
|
local reverse_list = {%BLACKLIST_REVERSE_LIST%}
|
||||||
local ip = ngx.var.remote_addr
|
local ip = ngx.var.remote_addr
|
||||||
|
|
||||||
@@ -21,10 +23,10 @@ function M.reverse_cached ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function M.check_ip ()
|
function M.check_ip ()
|
||||||
for k, v in ipairs(ip_list) do
|
if #ip_list > 0 then
|
||||||
if v == ip then
|
if iputils.ip_in_cidrs(ip, blacklist) then
|
||||||
ngx.shared.blacklist_ip_cache:set(ip, "ko", 86400)
|
ngx.shared.blacklist_ip_cache:set(ip, "ko", 86400)
|
||||||
ngx.log(ngx.WARN, "ip " .. ip .. " is in blacklist")
|
ngx.log(ngx.NOTICE, "ip " .. ip .. " is in blacklist")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -33,16 +35,18 @@ function M.check_ip ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function M.check_reverse ()
|
function M.check_reverse ()
|
||||||
|
if #reverse_list > 0 then
|
||||||
local rdns = dns.get_reverse()
|
local rdns = dns.get_reverse()
|
||||||
if rdns ~= "" then
|
if rdns ~= "" then
|
||||||
for k, v in ipairs(reverse_list) do
|
for k, v in ipairs(reverse_list) do
|
||||||
if rdns:sub(-#v) == v then
|
if rdns:sub(-#v) == v then
|
||||||
ngx.shared.blacklist_reverse_cache:set(ip, "ko", 86400)
|
ngx.shared.blacklist_reverse_cache:set(ip, "ko", 86400)
|
||||||
ngx.log(ngx.WARN, "reverse " .. rdns .. " is in blacklist")
|
ngx.log(ngx.NOTICE, "reverse " .. rdns .. " is in blacklist")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
ngx.shared.blacklist_reverse_cache:set(ip, "ok", 86400)
|
ngx.shared.blacklist_reverse_cache:set(ip, "ok", 86400)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function M.check ()
|
|||||||
local a,b,c,d = v2:match("([%d]+).([%d]+).([%d]+).([%d]+)")
|
local a,b,c,d = v2:match("([%d]+).([%d]+).([%d]+).([%d]+)")
|
||||||
if a == "127" then
|
if a == "127" then
|
||||||
ngx.shared.dnsbl_cache:set(ip, "ko", 86400)
|
ngx.shared.dnsbl_cache:set(ip, "ko", 86400)
|
||||||
ngx.log(ngx.WARN, "ip " .. ip .. " is in DNSBL " .. v)
|
ngx.log(ngx.NOTICE, "ip " .. ip .. " is in DNSBL " .. v)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
local dns = require "dns"
|
local dns = require "dns"
|
||||||
|
local iputils = require "resty.iputils"
|
||||||
local ip_list = {%WHITELIST_IP_LIST%}
|
local ip_list = {%WHITELIST_IP_LIST%}
|
||||||
local reverse_list = {%WHITELIST_REVERSE_LIST%}
|
local reverse_list = {%WHITELIST_REVERSE_LIST%}
|
||||||
|
local whitelist = iputils.parse_cidrs(ip_list)
|
||||||
local ip = ngx.var.remote_addr
|
local ip = ngx.var.remote_addr
|
||||||
|
|
||||||
function M.ip_cached_ok ()
|
function M.ip_cached_ok ()
|
||||||
@@ -21,10 +23,10 @@ function M.reverse_cached ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function M.check_ip ()
|
function M.check_ip ()
|
||||||
for k, v in ipairs(ip_list) do
|
if #ip_list > 0 then
|
||||||
if v == ip then
|
if iputils.ip_in_cidrs(ip, whitelist) then
|
||||||
ngx.shared.whitelist_ip_cache:set(ip, "ok", 86400)
|
ngx.shared.whitelist_ip_cache:set(ip, "ok", 86400)
|
||||||
ngx.log(ngx.WARN, "ip " .. ip .. " is in whitelist")
|
ngx.log(ngx.NOTICE, "ip " .. ip .. " is in whitelist")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -33,6 +35,7 @@ function M.check_ip ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function M.check_reverse ()
|
function M.check_reverse ()
|
||||||
|
if #reverse_list > 0 then
|
||||||
local rdns = dns.get_reverse()
|
local rdns = dns.get_reverse()
|
||||||
if rdns ~= "" then
|
if rdns ~= "" then
|
||||||
local whitelisted = false
|
local whitelisted = false
|
||||||
@@ -47,12 +50,13 @@ function M.check_reverse ()
|
|||||||
for k, v in ipairs(ips) do
|
for k, v in ipairs(ips) do
|
||||||
if v == ip then
|
if v == ip then
|
||||||
ngx.shared.whitelist_reverse_cache:set(ip, "ok", 86400)
|
ngx.shared.whitelist_reverse_cache:set(ip, "ok", 86400)
|
||||||
ngx.log(ngx.WARN, "reverse " .. rdns .. " is in whitelist")
|
ngx.log(ngx.NOTICE, "reverse " .. rdns .. " is in whitelist")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
ngx.shared.whitelist_reverse_cache:set(ip, "ko", 86400)
|
ngx.shared.whitelist_reverse_cache:set(ip, "ko", 86400)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ chmod 770 /var/log/letsencrypt
|
|||||||
touch /var/log/clamav.log
|
touch /var/log/clamav.log
|
||||||
chown root:nginx /var/log/clamav.log
|
chown root:nginx /var/log/clamav.log
|
||||||
chmod 770 /var/log/clamav.log
|
chmod 770 /var/log/clamav.log
|
||||||
|
find /var/log -type f -exec chmod 0774 {} \;
|
||||||
|
|
||||||
# prepare /acme-challenge
|
# prepare /acme-challenge
|
||||||
mkdir /acme-challenge
|
mkdir /acme-challenge
|
||||||
@@ -67,8 +68,11 @@ chown -R root:nginx /var/run/fail2ban /var/lib/fail2ban
|
|||||||
chmod -R 770 /var/run/fail2ban /var/lib/fail2ban
|
chmod -R 770 /var/run/fail2ban /var/lib/fail2ban
|
||||||
|
|
||||||
# prepare /usr/local/lib/lua
|
# prepare /usr/local/lib/lua
|
||||||
chown root:nginx /usr/local/lib/lua
|
chown -R root:nginx /usr/local/lib/lua
|
||||||
chmod 770 /usr/local/lib/lua
|
chmod 770 /usr/local/lib/lua
|
||||||
|
find /usr/local/lib/lua -type f -name "*.conf" -exec chmod 0760 {} \;
|
||||||
|
find /usr/local/lib/lua -type f -name "*.lua" -exec chmod 0760 {} \;
|
||||||
|
find /usr/local/lib/lua -type d -exec chmod 0770 {} \;
|
||||||
|
|
||||||
# prepare /cache
|
# prepare /cache
|
||||||
mkdir /cache
|
mkdir /cache
|
||||||
|
|||||||
Reference in New Issue
Block a user