Update the structure and the paths

This commit is contained in:
TheophileDiot 2022-11-11 14:55:04 +01:00
parent 04578aab3f
commit edce79936a
4836 changed files with 5874 additions and 6289 deletions

View file

@ -1 +0,0 @@
CVE-2022-30065

View file

@ -1,85 +0,0 @@
FROM nginx:1.20.2-alpine AS builder
# Copy dependencies sources folder
COPY bw/deps /tmp/bunkerweb/deps
# Compile and install dependencies
RUN apk add --no-cache --virtual build bash build autoconf libtool automake geoip-dev g++ gcc curl-dev libxml2-dev pcre-dev make linux-headers musl-dev gd-dev gnupg brotli-dev openssl-dev patch readline-dev && \
mkdir -p /opt/bunkerweb/deps && \
chmod +x /tmp/bunkerweb/deps/install.sh && \
bash /tmp/bunkerweb/deps/install.sh && \
apk del build
# Copy python requirements
COPY bw/deps/requirements.txt /opt/bunkerweb/deps/requirements.txt
# Install python requirements
RUN apk add --no-cache --virtual build py3-pip g++ gcc python3-dev musl-dev libffi-dev openssl-dev cargo && \
pip install --no-cache-dir --upgrade pip && \
pip install wheel && \
mkdir /opt/bunkerweb/deps/python && \
pip install --no-cache-dir --require-hashes --target /opt/bunkerweb/deps/python -r /opt/bunkerweb/deps/requirements.txt && \
apk del build
FROM nginx:1.20.2-alpine
# Copy dependencies
COPY --from=builder /opt/bunkerweb /opt/bunkerweb
# Copy files
# can't exclude deps from . so we are copying everything by hand
COPY bw/api /opt/bunkerweb/api
COPY bw/confs /opt/bunkerweb/confs
COPY bw/core /opt/bunkerweb/core
COPY bw/cli /opt/bunkerweb/cli
COPY bw/gen /opt/bunkerweb/gen
COPY bw/helpers /opt/bunkerweb/helpers
COPY bw/loading /opt/bunkerweb/loading
COPY bw/lua /opt/bunkerweb/lua
COPY bw/misc /opt/bunkerweb/misc
COPY bw/settings.json /opt/bunkerweb/settings.json
COPY db /opt/bunkerweb/db
COPY utils /opt/bunkerweb/utils
COPY VERSION /opt/bunkerweb/VERSION
# Install runtime dependencies, pypi packages, move bwcli, create data folders and set permissions
RUN apk add --no-cache bash python3 libgcc libstdc++ openssl git && \
cp /opt/bunkerweb/helpers/bwcli /usr/local/bin && \
echo "Docker" > /opt/bunkerweb/INTEGRATION && \
for dir in $(echo "cache configs plugins www") ; do mkdir -p "/data/${dir}" && ln -s "/data/${dir}" "/opt/bunkerweb/${dir}" ; done && \
for dir in $(echo "configs/http configs/stream configs/server-http configs/server-stream configs/default-server-http configs/default-server-stream configs/modsec configs/modsec-crs cache/letsencrypt") ; do mkdir -p "/data/${dir}" ; done && \
chown -R root:nginx /data && \
chmod -R 770 /data && \
mkdir /opt/bunkerweb/tmp && \
chown -R root:nginx /opt/bunkerweb && \
find /opt/bunkerweb -type f -exec chmod 0740 {} \; && \
find /opt/bunkerweb -type d -exec chmod 0750 {} \; && \
chmod 770 /opt/bunkerweb/cache /opt/bunkerweb/tmp && \
chmod 750 /opt/bunkerweb/cli/main.py /opt/bunkerweb/gen/main.py /opt/bunkerweb/helpers/*.sh /usr/local/bin/bwcli /opt/bunkerweb/deps/python/bin/* && \
chown root:nginx /usr/local/bin/bwcli && \
chown -R nginx:nginx /etc/nginx && \
mkdir /var/log/letsencrypt /var/lib/letsencrypt && \
chown root:nginx /var/log/letsencrypt /var/lib/letsencrypt && \
chmod 770 /var/log/letsencrypt /var/lib/letsencrypt && \
chown -R root:nginx /etc/nginx && \
chmod -R 770 /etc/nginx && \
rm -f /var/log/nginx/* && \
ln -s /proc/1/fd/2 /var/log/nginx/error.log && \
ln -s /proc/1/fd/2 /var/log/nginx/modsec_audit.log && \
ln -s /proc/1/fd/1 /var/log/nginx/access.log && \
ln -s /proc/1/fd/1 /var/log/nginx/jobs.log && \
ln -s /proc/1/fd/1 /var/log/letsencrypt/letsencrypt.log && \
chmod 660 /opt/bunkerweb/INTEGRATION
# Fix CVEs
RUN apk add "freetype>=2.10.4-r3" "curl>=7.79.1-r2" "libcurl>=7.79.1-r2" "openssl>=1.1.1q-r0" "libssl1.1>=1.1.1q-r0" "libcrypto1.1>=1.1.1q-r0" "git>=2.32.3-r0" "ncurses-libs>=6.2_p20210612-r1" "ncurses-terminfo-base>=6.2_p20210612-r1" "zlib>=1.2.12-r2" "libxml2>=2.9.14-r1"
VOLUME /data /etc/nginx
EXPOSE 8080/tcp 8443/tcp
USER nginx:nginx
HEALTHCHECK --interval=10s --timeout=10s --start-period=10s --retries=6 CMD /opt/bunkerweb/helpers/healthcheck.sh
ENTRYPOINT ["/opt/bunkerweb/helpers/entrypoint.sh"]

View file

@ -1,5 +1,5 @@
<p align="center">
<img alt="BunkerWeb logo" src="https://github.com/bunkerity/bunkerweb/raw/master/logo.png" />
<img alt="BunkerWeb logo" src="https://github.com/bunkerity/bunkerweb/raw/master/misc/logo.png" />
</p>
<p align="center">

View file

@ -1 +0,0 @@
1.4.3

View file

@ -1,45 +0,0 @@
FROM python:3.11-alpine
# Copy python requirements
COPY bw/deps/requirements.txt /opt/bunkerweb/deps/requirements.txt
# Install dependencies
RUN apk add --no-cache --virtual build g++ gcc python3-dev musl-dev libffi-dev openssl-dev cargo && \
pip install --no-cache-dir --upgrade pip && \
pip install wheel && \
mkdir /opt/bunkerweb/deps/python && \
pip install --no-cache-dir --require-hashes --target /opt/bunkerweb/deps/python -r /opt/bunkerweb/deps/requirements.txt && \
apk del build
# Copy files
# can't exclude specific files/dir from . so we are copying everything by hand
COPY autoconf /opt/bunkerweb/autoconf
COPY bw/api /opt/bunkerweb/api
COPY bw/cli /opt/bunkerweb/cli
COPY bw/core /opt/bunkerweb/core
COPY bw/helpers /opt/bunkerweb/helpers
COPY bw/settings.json /opt/bunkerweb/settings.json
COPY db /opt/bunkerweb/db
COPY utils /opt/bunkerweb/utils
# Add nginx user, drop bwcli, setup data folders, permissions and logging
RUN apk add --no-cache bash && \
addgroup -g 101 nginx && \
adduser -h /var/cache/nginx -g nginx -s /bin/sh -G nginx -D -H -u 101 nginx && \
cp /opt/bunkerweb/helpers/bwcli /usr/local/bin && \
chown -R nginx:nginx /opt/bunkerweb && \
find /opt/bunkerweb -type f -exec chmod 0740 {} \; && \
find /opt/bunkerweb -type d -exec chmod 0750 {} \; && \
chmod 750 /opt/bunkerweb/cli/main.py /opt/bunkerweb/helpers/*.sh /usr/local/bin/bwcli /opt/bunkerweb/autoconf/main.py /opt/bunkerweb/deps/python/bin/* && \
chown root:nginx /usr/local/bin/bwcli
# Fix CVEs
RUN apk add "libssl1.1>=1.1.1q-r0" "libcrypto1.1>=1.1.1q-r0" "git>=2.32.3-r0" "ncurses-libs>=6.2_p20210612-r1" "ncurses-terminfo-base>=6.2_p20210612-r1" "libtirpc>=1.3.2-r1" "libtirpc-conf>=1.3.2-r1" "zlib>=1.2.12-r2" "libxml2>=2.9.14-r1"
VOLUME /data /etc/nginx
WORKDIR /opt/bunkerweb/autoconf
USER root:nginx
CMD ["python3", "/opt/bunkerweb/autoconf/main.py"]

View file

@ -1,6 +0,0 @@
{% if SERVE_FILES == "yes" +%}
root {% if ROOT_FOLDER == "" %}/opt/bunkerweb/www/{% if MULTISITE == "yes" %}{{ SERVER_NAME.split(" ")[0] }}{% endif %}{% else %}{{ ROOT_FOLDER }}{% endif %};
try_files $uri $uri/ =404;
{% else +%}
root /nowhere;
{% endif %}

View file

@ -1 +0,0 @@
sqli_fingerprints = set(["1234"])

View file

@ -1,50 +0,0 @@
"""
libinjection module for python
Copyright 2012, 2013, 2014 Nick Galbreath
nickg@client9.com
BSD License -- see COPYING.txt for details
"""
try:
from setuptools import setup, Extension
except ImportError:
from distutils.core import setup, Extension
MODULE = Extension(
"_libinjection",
[
"libinjection/libinjection_wrap.c",
"libinjection/libinjection_sqli.c",
"libinjection/libinjection_html5.c",
"libinjection/libinjection_xss.c",
],
swig_opts=["-Wextra", "-builtin"],
define_macros=[],
include_dirs=[],
libraries=[],
library_dirs=[],
)
setup(
name="libinjection",
version="3.9.1",
description="Wrapper around libinjection c-code to detect sqli",
author="Nick Galbreath",
author_email="nickg@client9.com",
url="https://libinjection.client9.com/",
ext_modules=[MODULE],
packages=["libinjection"],
long_description="""
wrapper around libinjection
""",
classifiers=[
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Topic :: Database",
"Topic :: Security",
"Operating System :: OS Independent",
"Development Status :: 3 - Alpha",
"Topic :: Internet :: Log Analysis",
"Topic :: Internet :: WWW/HTTP",
],
)

View file

@ -1,60 +0,0 @@
#!/usr/bin/env python3
"""
Small script to convert fingerprints back to SQL or SQLi
"""
import subprocess
RMAP = {
"1": "1",
"f": "convert",
"&": "and",
"v": "@version",
"n": "aname",
"s": '"1"',
"(": "(",
")": ")",
"o": "*",
"E": "select",
"U": "union",
"k": "JOIN",
"t": "binary",
",": ",",
";": ";",
"c": " -- comment",
"T": "DROP",
":": ":",
"A": "COLLATE",
"B": "group by",
"X": "/* /* nested comment */ */",
}
def fingerprint_to_sqli():
"""
main code, expects to be run in main libinjection/src directory
and hardwires "fingerprints.txt" as input file
"""
mode = "print"
fingerprints = []
with open("fingerprints.txt", "r") as openfile:
for line in openfile:
fingerprints.append(line.strip())
for fingerprint in fingerprints:
sql = []
for char in fingerprint:
sql.append(RMAP[char])
sqlstr = " ".join(sql)
if mode == "print":
print(fingerprint, " ".join(sql))
else:
args = ["./fptool", "-0", sqlstr]
actualfp = subprocess.check_output(args).strip()
if fingerprint != actualfp:
print(fingerprint, actualfp, " ".join(sql))
if __name__ == "__main__":
fingerprint_to_sqli()

View file

@ -1,491 +0,0 @@
#!/usr/bin/env python3
# pylint: disable=C0103,R0911,R0912,R0915
# disable short-variable-names, too many branches, returns, statements
"""
fingerprint fuzzer and generator
Given a fingerprint, this generates other similar fingerprints
that are functionally equivalent for SQLi detection
"""
import sys
class PermuteFingerprints(object):
"""class to mutate / fuzz fingerprints to find new SQLi"""
def __init__(self):
"""initialization"""
self.fingerprints = set()
self.blacklist = set(
[
"E1n",
"sns",
"1&n",
"s1s",
"1n1",
"1o1",
"1os",
"sn1",
"sonc",
"so1",
"n&n",
"son",
"nov",
"n&s",
"E1s",
"nos",
"nkn&n",
"1sn",
"n&nkn",
"s1n",
"n&nEn",
"s&sn",
"1os1o",
"sU",
"nU",
"n,(n)",
"n&n&n",
"Enkn",
"nk1;",
"1os1o",
"1n1;",
"s*1s",
"1s1",
"nknEn",
"n&sn",
"so1",
"nkn;",
"n&n;",
"von",
"n&nc",
"sonkn",
"n)o1",
"Enn;",
"nBn",
"Ennc",
"n&En",
"nEnEn",
"Esn",
"n1s",
"n(1)s",
"En1",
"En(1)",
"n(1)n",
"n1v",
"n(1)1",
"n&EUE",
"n&EkU",
"s&EUE",
"s&EkU",
"v&EUE",
"v&EkU",
"n&nTn",
"nA",
"nos;n",
"UEn",
"so1no",
"1)on",
"1k(1)",
"s)on",
"1;TnE",
"s&1s",
"n)c",
"svs",
"1n(1)",
"so1s(",
"son1s",
"nf(1n",
"so1sf",
"son1s",
"nf(n)",
"En1c",
"n)on",
"nok&n",
"n;Tkn",
"nEnc",
"nok&1",
"nok&f",
"nok&s",
"nok&v",
"nk(n)",
"nknc",
"son1n",
"n&nBn",
]
)
self.whitelist = set(["T(vv)", "Tnvos", "Tnv;", "1UEnn", "1;Tvk"])
def aslist(self):
"""
return the fingerprints as a sorted list
"""
return sorted(list(self.fingerprints))
def insert(self, fingerprint):
"""
insert a new fingerprint, with possible variations
"""
if len(fingerprint) > 5:
fingerprint = fingerprint[0:5]
if self.validate(fingerprint):
self.fingerprints.add(fingerprint)
def validate(self, s):
"""
detemines if a fingerprint could be used a SQLi
"""
if len(s) == 0:
return False
if s in self.whitelist:
return True
if s in self.blacklist:
return False
# SQL Types are rarely used
if "t" in s and "f(t" not in s and "At" not in s:
return False
if "Un" in s:
return False
if "1nf" in s:
return False
if "s1o" in s:
return False
if "oo" in s:
return False
if "v,s" in s:
return False
if "s,v" in s:
return False
if "v,v" in s:
return False
if "v,1" in s:
return False
if "v,n" in s:
return False
if "n,v" in s:
return False
if "1,v" in s:
return False
if "Eo(" in s:
return False
if "(o(" in s:
return False
if "(o1" in s:
return False
if "(on" in s:
return False
if "(os" in s:
return False
if "(of" in s:
return False
if "(ov" in s:
return False
if "B(n)" in s:
return False
if "oso" in s:
return False
if "o1o" in s:
return False
if "ono" in s:
return False
# only 1 special case for this
# 1;foo:goto foo
# 1;n:k
# the 'foo' can only be a 'n' type
if ":" in s and not "n:" in s:
return False
if "11" in s:
return False
if "))" in s:
return False
if "((" in s:
return False
if "v1" in s:
return False
if "nv" in s and "T" not in s:
return False
if "nn" in s and "T" not in s:
return False
# select @version foo is legit
# but unlikely anywhere else
if "vn" in s and "Evn" not in s:
return False
if "oE" in s:
return False
if "A1" in s:
return False
if "An" in s:
return False
if "A(1" in s:
return False
if "vov" in s:
return False
if "vo1" in s:
return False
if "von" in s:
return False
if "ns" in s:
if "U" in s:
return True
if "T" in s:
return True
return False
if "sn" in s:
# that is... Tsn is ok
if s.find("T") != -1 and s.find("T") < s.find("sn"):
return True
return False
# select foo (as) bar is only nn type i know
if "nn" in s and "Enn" not in s and "T" not in s:
return False
if ",o" in s:
return False
if "kk" in s and "Tkk" not in s:
return False
if "ss" in s:
return False
if "ff" in s:
return False
if "1no" in s:
return False
if "kno" in s:
return False
if "nEk" in s:
return False
if "n(n" in s:
return False
if "1so" in s:
return False
if "1s1" in s:
return False
if "noo" in s:
return False
if "ooo" in s:
return False
if "vvv" in s:
return False
if "1vn" in s:
return False
if "1n1" in s:
return False
if "&1n" in s:
return False
if "&1v" in s:
return False
if "&1s" in s:
return False
if "nnk" in s:
return False
if "n1f" in s:
return False
# folded away
if s.startswith("("):
return False
if "&o" in s:
return False
if "1,1" in s:
return False
if "1,s" in s:
return False
if "1,n" in s:
return False
if "s,1" in s:
return False
if "s,s" in s:
return False
if "s,n" in s:
return False
if "n,1" in s:
return False
if "n,s" in s:
return False
if "n,n" in s:
return False
if "1o1" in s:
return False
if "1on" in s:
return False
if "no1" in s:
return False
if "non" in s:
return False
if "1(v" in s:
return False
if "1(n" in s:
return False
if "1(s" in s:
return False
if "1(1" in s:
return False
if "s(s" in s:
return False
if "s(n" in s:
return False
if "s(1" in s:
return False
if "s(v" in s:
return False
if "v(s" in s:
return False
if "v(n" in s:
return False
if "v(1" in s and "Tv(1" not in s:
return False
if "v(v" in s:
return False
if "TTT" in s:
return False
if s.startswith("n("):
return False
if s.startswith("vs"):
return False
if s.startswith("o"):
return False
if ")(" in s:
return False
# need to investigate T(vv) to see
# if it's correct
if "vv" in s and s != "T(vv)":
return False
# unlikely to be sqli but case FP
if s in ("so1n)", "sonoE"):
return False
return True
def permute(self, fp):
"""
generate alternative (possiblely invalid) fingerprints
"""
self.insert(fp)
# do this for safety
if len(fp) > 1 and len(fp) < 5 and fp[-1] != ";" and fp[-1] != "c":
self.insert(fp + ";")
self.insert(fp + ";c")
# do this for safety
if len(fp) > 1 and len(fp) < 5 and fp[-1] != "c":
self.insert(fp + "c")
for i in range(len(fp)):
if fp[i] == "1":
self.insert(fp[0:i] + "n" + fp[i + 1 :])
self.insert(fp[0:i] + "v" + fp[i + 1 :])
self.insert(fp[0:i] + "s" + fp[i + 1 :])
self.insert(fp[0:i] + "f(1)" + fp[i + 1 :])
self.insert(fp[0:i] + "f()" + fp[i + 1 :])
self.insert(fp[0:i] + "1os" + fp[i + 1 :])
self.insert(fp[0:i] + "1ov" + fp[i + 1 :])
self.insert(fp[0:i] + "1on" + fp[i + 1 :])
self.insert(fp[0:i] + "(1)" + fp[i + 1 :])
elif fp[i] == "s":
self.insert(fp[0:i] + "v" + fp[i + 1 :])
self.insert(fp[0:i] + "1" + fp[i + 1 :])
self.insert(fp[0:i] + "f(1)" + fp[i + 1 :])
self.insert(fp[0:i] + "f()" + fp[i + 1 :])
self.insert(fp[0:i] + "so1" + fp[i + 1 :])
self.insert(fp[0:i] + "sov" + fp[i + 1 :])
self.insert(fp[0:i] + "son" + fp[i + 1 :])
self.insert(fp[0:i] + "(s)" + fp[i + 1 :])
elif fp[i] == "v":
self.insert(fp[0:i] + "s" + fp[i + 1 :])
self.insert(fp[0:i] + "1" + fp[i + 1 :])
self.insert(fp[0:i] + "f(1)" + fp[i + 1 :])
self.insert(fp[0:i] + "f()" + fp[i + 1 :])
self.insert(fp[0:i] + "vo1" + fp[i + 1 :])
self.insert(fp[0:i] + "vos" + fp[i + 1 :])
self.insert(fp[0:i] + "von" + fp[i + 1 :])
self.insert(fp[0:i] + "(v)" + fp[i + 1 :])
elif fp[i] == "E":
# Select top, select distinct, case when
self.insert(fp[0:i] + "Ek" + fp[i + 1 :])
elif fp[i] == ")":
self.insert(fp[0:i] + "))" + fp[i + 1 :])
self.insert(fp[0:i] + ")))" + fp[i + 1 :])
self.insert(fp[0:i] + "))))" + fp[i + 1 :])
if ";E" in fp:
self.insert(fp.replace(";E", ";T"))
if fp.startswith("T"):
self.insert("1;" + fp)
self.insert("1);" + fp)
if "At" in fp:
self.insert(fp.replace("At", "As"))
if "(" in fp:
done = False
parts = []
for char in fp:
if char == "(" and done is False:
parts.append(char)
done = True
parts.append(char)
newline = "".join(parts)
self.insert(newline)
done = False
parts = []
for char in fp:
if char == "(":
if done is True:
parts.append(char)
else:
done = True
parts.append(char)
newline = "".join(parts)
self.insert(newline)
done = False
parts = []
for char in fp:
if char == "(":
parts.append(char)
parts.append(char)
newline = "".join(parts)
self.insert(newline)
def main():
"""main entrance"""
mutator = PermuteFingerprints()
for line in sys.stdin:
mutator.permute(line.strip())
for fingerprint in mutator.aslist():
print(fingerprint)
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
sqli_fingerprints = set(["1234"])

View file

@ -1,50 +0,0 @@
"""
libinjection module for python
Copyright 2012, 2013, 2014 Nick Galbreath
nickg@client9.com
BSD License -- see COPYING.txt for details
"""
try:
from setuptools import setup, Extension
except ImportError:
from distutils.core import setup, Extension
MODULE = Extension(
"_libinjection",
[
"libinjection/libinjection_wrap.c",
"libinjection/libinjection_sqli.c",
"libinjection/libinjection_html5.c",
"libinjection/libinjection_xss.c",
],
swig_opts=["-Wextra", "-builtin"],
define_macros=[],
include_dirs=[],
libraries=[],
library_dirs=[],
)
setup(
name="libinjection",
version="3.9.1",
description="Wrapper around libinjection c-code to detect sqli",
author="Nick Galbreath",
author_email="nickg@client9.com",
url="https://libinjection.client9.com/",
ext_modules=[MODULE],
packages=["libinjection"],
long_description="""
wrapper around libinjection
""",
classifiers=[
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Topic :: Database",
"Topic :: Security",
"Operating System :: OS Independent",
"Development Status :: 3 - Alpha",
"Topic :: Internet :: Log Analysis",
"Topic :: Internet :: WWW/HTTP",
],
)

View file

@ -1,60 +0,0 @@
#!/usr/bin/env python3
"""
Small script to convert fingerprints back to SQL or SQLi
"""
import subprocess
RMAP = {
"1": "1",
"f": "convert",
"&": "and",
"v": "@version",
"n": "aname",
"s": '"1"',
"(": "(",
")": ")",
"o": "*",
"E": "select",
"U": "union",
"k": "JOIN",
"t": "binary",
",": ",",
";": ";",
"c": " -- comment",
"T": "DROP",
":": ":",
"A": "COLLATE",
"B": "group by",
"X": "/* /* nested comment */ */",
}
def fingerprint_to_sqli():
"""
main code, expects to be run in main libinjection/src directory
and hardwires "fingerprints.txt" as input file
"""
mode = "print"
fingerprints = []
with open("fingerprints.txt", "r") as openfile:
for line in openfile:
fingerprints.append(line.strip())
for fingerprint in fingerprints:
sql = []
for char in fingerprint:
sql.append(RMAP[char])
sqlstr = " ".join(sql)
if mode == "print":
print(fingerprint, " ".join(sql))
else:
args = ["./fptool", "-0", sqlstr]
actualfp = subprocess.check_output(args).strip()
if fingerprint != actualfp:
print(fingerprint, actualfp, " ".join(sql))
if __name__ == "__main__":
fingerprint_to_sqli()

View file

@ -1,491 +0,0 @@
#!/usr/bin/env python3
# pylint: disable=C0103,R0911,R0912,R0915
# disable short-variable-names, too many branches, returns, statements
"""
fingerprint fuzzer and generator
Given a fingerprint, this generates other similar fingerprints
that are functionally equivalent for SQLi detection
"""
import sys
class PermuteFingerprints(object):
"""class to mutate / fuzz fingerprints to find new SQLi"""
def __init__(self):
"""initialization"""
self.fingerprints = set()
self.blacklist = set(
[
"E1n",
"sns",
"1&n",
"s1s",
"1n1",
"1o1",
"1os",
"sn1",
"sonc",
"so1",
"n&n",
"son",
"nov",
"n&s",
"E1s",
"nos",
"nkn&n",
"1sn",
"n&nkn",
"s1n",
"n&nEn",
"s&sn",
"1os1o",
"sU",
"nU",
"n,(n)",
"n&n&n",
"Enkn",
"nk1;",
"1os1o",
"1n1;",
"s*1s",
"1s1",
"nknEn",
"n&sn",
"so1",
"nkn;",
"n&n;",
"von",
"n&nc",
"sonkn",
"n)o1",
"Enn;",
"nBn",
"Ennc",
"n&En",
"nEnEn",
"Esn",
"n1s",
"n(1)s",
"En1",
"En(1)",
"n(1)n",
"n1v",
"n(1)1",
"n&EUE",
"n&EkU",
"s&EUE",
"s&EkU",
"v&EUE",
"v&EkU",
"n&nTn",
"nA",
"nos;n",
"UEn",
"so1no",
"1)on",
"1k(1)",
"s)on",
"1;TnE",
"s&1s",
"n)c",
"svs",
"1n(1)",
"so1s(",
"son1s",
"nf(1n",
"so1sf",
"son1s",
"nf(n)",
"En1c",
"n)on",
"nok&n",
"n;Tkn",
"nEnc",
"nok&1",
"nok&f",
"nok&s",
"nok&v",
"nk(n)",
"nknc",
"son1n",
"n&nBn",
]
)
self.whitelist = set(["T(vv)", "Tnvos", "Tnv;", "1UEnn", "1;Tvk"])
def aslist(self):
"""
return the fingerprints as a sorted list
"""
return sorted(list(self.fingerprints))
def insert(self, fingerprint):
"""
insert a new fingerprint, with possible variations
"""
if len(fingerprint) > 5:
fingerprint = fingerprint[0:5]
if self.validate(fingerprint):
self.fingerprints.add(fingerprint)
def validate(self, s):
"""
detemines if a fingerprint could be used a SQLi
"""
if len(s) == 0:
return False
if s in self.whitelist:
return True
if s in self.blacklist:
return False
# SQL Types are rarely used
if "t" in s and "f(t" not in s and "At" not in s:
return False
if "Un" in s:
return False
if "1nf" in s:
return False
if "s1o" in s:
return False
if "oo" in s:
return False
if "v,s" in s:
return False
if "s,v" in s:
return False
if "v,v" in s:
return False
if "v,1" in s:
return False
if "v,n" in s:
return False
if "n,v" in s:
return False
if "1,v" in s:
return False
if "Eo(" in s:
return False
if "(o(" in s:
return False
if "(o1" in s:
return False
if "(on" in s:
return False
if "(os" in s:
return False
if "(of" in s:
return False
if "(ov" in s:
return False
if "B(n)" in s:
return False
if "oso" in s:
return False
if "o1o" in s:
return False
if "ono" in s:
return False
# only 1 special case for this
# 1;foo:goto foo
# 1;n:k
# the 'foo' can only be a 'n' type
if ":" in s and not "n:" in s:
return False
if "11" in s:
return False
if "))" in s:
return False
if "((" in s:
return False
if "v1" in s:
return False
if "nv" in s and "T" not in s:
return False
if "nn" in s and "T" not in s:
return False
# select @version foo is legit
# but unlikely anywhere else
if "vn" in s and "Evn" not in s:
return False
if "oE" in s:
return False
if "A1" in s:
return False
if "An" in s:
return False
if "A(1" in s:
return False
if "vov" in s:
return False
if "vo1" in s:
return False
if "von" in s:
return False
if "ns" in s:
if "U" in s:
return True
if "T" in s:
return True
return False
if "sn" in s:
# that is... Tsn is ok
if s.find("T") != -1 and s.find("T") < s.find("sn"):
return True
return False
# select foo (as) bar is only nn type i know
if "nn" in s and "Enn" not in s and "T" not in s:
return False
if ",o" in s:
return False
if "kk" in s and "Tkk" not in s:
return False
if "ss" in s:
return False
if "ff" in s:
return False
if "1no" in s:
return False
if "kno" in s:
return False
if "nEk" in s:
return False
if "n(n" in s:
return False
if "1so" in s:
return False
if "1s1" in s:
return False
if "noo" in s:
return False
if "ooo" in s:
return False
if "vvv" in s:
return False
if "1vn" in s:
return False
if "1n1" in s:
return False
if "&1n" in s:
return False
if "&1v" in s:
return False
if "&1s" in s:
return False
if "nnk" in s:
return False
if "n1f" in s:
return False
# folded away
if s.startswith("("):
return False
if "&o" in s:
return False
if "1,1" in s:
return False
if "1,s" in s:
return False
if "1,n" in s:
return False
if "s,1" in s:
return False
if "s,s" in s:
return False
if "s,n" in s:
return False
if "n,1" in s:
return False
if "n,s" in s:
return False
if "n,n" in s:
return False
if "1o1" in s:
return False
if "1on" in s:
return False
if "no1" in s:
return False
if "non" in s:
return False
if "1(v" in s:
return False
if "1(n" in s:
return False
if "1(s" in s:
return False
if "1(1" in s:
return False
if "s(s" in s:
return False
if "s(n" in s:
return False
if "s(1" in s:
return False
if "s(v" in s:
return False
if "v(s" in s:
return False
if "v(n" in s:
return False
if "v(1" in s and "Tv(1" not in s:
return False
if "v(v" in s:
return False
if "TTT" in s:
return False
if s.startswith("n("):
return False
if s.startswith("vs"):
return False
if s.startswith("o"):
return False
if ")(" in s:
return False
# need to investigate T(vv) to see
# if it's correct
if "vv" in s and s != "T(vv)":
return False
# unlikely to be sqli but case FP
if s in ("so1n)", "sonoE"):
return False
return True
def permute(self, fp):
"""
generate alternative (possiblely invalid) fingerprints
"""
self.insert(fp)
# do this for safety
if len(fp) > 1 and len(fp) < 5 and fp[-1] != ";" and fp[-1] != "c":
self.insert(fp + ";")
self.insert(fp + ";c")
# do this for safety
if len(fp) > 1 and len(fp) < 5 and fp[-1] != "c":
self.insert(fp + "c")
for i in range(len(fp)):
if fp[i] == "1":
self.insert(fp[0:i] + "n" + fp[i + 1 :])
self.insert(fp[0:i] + "v" + fp[i + 1 :])
self.insert(fp[0:i] + "s" + fp[i + 1 :])
self.insert(fp[0:i] + "f(1)" + fp[i + 1 :])
self.insert(fp[0:i] + "f()" + fp[i + 1 :])
self.insert(fp[0:i] + "1os" + fp[i + 1 :])
self.insert(fp[0:i] + "1ov" + fp[i + 1 :])
self.insert(fp[0:i] + "1on" + fp[i + 1 :])
self.insert(fp[0:i] + "(1)" + fp[i + 1 :])
elif fp[i] == "s":
self.insert(fp[0:i] + "v" + fp[i + 1 :])
self.insert(fp[0:i] + "1" + fp[i + 1 :])
self.insert(fp[0:i] + "f(1)" + fp[i + 1 :])
self.insert(fp[0:i] + "f()" + fp[i + 1 :])
self.insert(fp[0:i] + "so1" + fp[i + 1 :])
self.insert(fp[0:i] + "sov" + fp[i + 1 :])
self.insert(fp[0:i] + "son" + fp[i + 1 :])
self.insert(fp[0:i] + "(s)" + fp[i + 1 :])
elif fp[i] == "v":
self.insert(fp[0:i] + "s" + fp[i + 1 :])
self.insert(fp[0:i] + "1" + fp[i + 1 :])
self.insert(fp[0:i] + "f(1)" + fp[i + 1 :])
self.insert(fp[0:i] + "f()" + fp[i + 1 :])
self.insert(fp[0:i] + "vo1" + fp[i + 1 :])
self.insert(fp[0:i] + "vos" + fp[i + 1 :])
self.insert(fp[0:i] + "von" + fp[i + 1 :])
self.insert(fp[0:i] + "(v)" + fp[i + 1 :])
elif fp[i] == "E":
# Select top, select distinct, case when
self.insert(fp[0:i] + "Ek" + fp[i + 1 :])
elif fp[i] == ")":
self.insert(fp[0:i] + "))" + fp[i + 1 :])
self.insert(fp[0:i] + ")))" + fp[i + 1 :])
self.insert(fp[0:i] + "))))" + fp[i + 1 :])
if ";E" in fp:
self.insert(fp.replace(";E", ";T"))
if fp.startswith("T"):
self.insert("1;" + fp)
self.insert("1);" + fp)
if "At" in fp:
self.insert(fp.replace("At", "As"))
if "(" in fp:
done = False
parts = []
for char in fp:
if char == "(" and done is False:
parts.append(char)
done = True
parts.append(char)
newline = "".join(parts)
self.insert(newline)
done = False
parts = []
for char in fp:
if char == "(":
if done is True:
parts.append(char)
else:
done = True
parts.append(char)
newline = "".join(parts)
self.insert(newline)
done = False
parts = []
for char in fp:
if char == "(":
parts.append(char)
parts.append(char)
newline = "".join(parts)
self.insert(newline)
def main():
"""main entrance"""
mutator = PermuteFingerprints()
for line in sys.stdin:
mutator.permute(line.strip())
for fingerprint in mutator.aslist():
print(fingerprint)
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load diff

View file

@ -1,5 +0,0 @@
#!/bin/sh
echo Content-type: text/plain
echo
env

View file

@ -1,5 +0,0 @@
#!/bin/bash
/opt/bunkerweb/cli/main.py "$@"
exit $?

View file

@ -1,56 +0,0 @@
#!/bin/bash
. /opt/bunkerweb/helpers/utils.sh
log "SCHEDULER" "" "Doing a restart ..."
# Kill the running scheduler
retry=0
if [ -f "/opt/bunkerweb/tmp/scheduler.pid" ] ; then
kill -s TERM "$(cat /opt/bunkerweb/tmp/scheduler.pid)"
ret=$?
if [ $? -ne 0 ] ; then
log "SCHEDULER" "❌" "Error while sending signal to running scheduler (exit status = $ret)"
exit 1
fi
while [ -f "/opt/bunkerweb/tmp/scheduler.pid" ] && [ $retry -lt 3 ] ; do
echo log "SCHEDULER" "" "Waiting for scheduler to stop ..."
sleep 5
retry=$((retry + 1))
done
if [ $retry -eq 3 ] ; then
log "SCHEDULER" "❌" "Timeout while waiting while waiting for scheduler to stop"
exit 1
fi
fi
if [ "$SWARM_MODE" != "yes" ] && [ "$KUBERNETES_MODE" != "yes" ] && [ "$AUTOCONF_MODE" != "yes" ] ; then
VARIABLES_PATH="/etc/nginx/variables.env"
fi
# Run jobs once in foreground
log "SCHEDULER" "" "Executing jobs ..."
if [ -v VARIABLES_PATH ] ; then
/opt/bunkerweb/scheduler/main.py --variables $VARIABLES_PATH --run
else
/opt/bunkerweb/scheduler/main.py --run
fi
ret=$?
if [ $? -ne 0 ] ; then
log "SCHEDULER" "❌" "Error while running jobs (exit status = $ret)"
exit 1
fi
# Run jobs scheduler in background
if [ -v VARIABLES_PATH ] ; then
/opt/bunkerweb/scheduler/main.py --variables $VARIABLES_PATH &
else
/opt/bunkerweb/scheduler/main.py &
fi
ret=$?
if [ $? -ne 0 ] ; then
log "SCHEDULER" "❌" "Error while running jobs (exit status = $ret)"
exit 1
fi
exit 0

View file

@ -1,6 +0,0 @@
local geoip = require "geoip.mmdb"
return {
country_db = geoip.load_database("/opt/bunkerweb/cache/country.mmdb"),
asn_db = geoip.load_database("/opt/bunkerweb/cache/asn.mmdb")
}

View file

@ -580,7 +580,7 @@ spec:
livenessProbe:
exec:
command:
- /opt/bunkerweb/helpers/healthcheck.sh
- /usr/share/bunkerweb/helpers/healthcheck.sh
initialDelaySeconds: 30
periodSeconds: 5
timeoutSeconds: 1
@ -588,7 +588,7 @@ spec:
readinessProbe:
exec:
command:
- /opt/bunkerweb/helpers/healthcheck.sh
- /usr/share/bunkerweb/helpers/healthcheck.sh
initialDelaySeconds: 30
periodSeconds: 1
timeoutSeconds: 1
@ -803,9 +803,9 @@ Repositories of Linux packages for BunkerWeb are available on [PackageCloud](htt
The first step is to install NGINX 1.20.2 using the repository of your choice or by [compiling it from source](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/#compiling-and-installing-from-source).
The target installation folder of BunkerWeb is located at `/opt/bunkerweb`, let's create it :
The target installation folder of BunkerWeb is located at `/usr/share/bunkerweb`, let's create it :
```shell
mkdir /opt/bunkerweb
mkdir /usr/share/bunkerweb
```
You can now clone the BunkerWeb project to the `/tmp` folder :
@ -813,40 +813,44 @@ Repositories of Linux packages for BunkerWeb are available on [PackageCloud](htt
https://github.com/bunkerity/bunkerweb.git /tmp/bunkerweb
```
BunkerWeb needs some dependencies to be compiled and installed to `/opt/bunkerweb/deps`, the easiest way to do it is by executing the [install.sh helper script](https://github.com/bunkerity/bunkerweb/blob/master/deps/install.sh) (please note that you will need to install additional packages which is not covered in this procedure and depends on your own system) :
BunkerWeb needs some dependencies to be compiled and installed to `/usr/share/bunkerweb/deps`, the easiest way to do it is by executing the [install.sh helper script](https://github.com/bunkerity/bunkerweb/blob/master/deps/install.sh) (please note that you will need to install additional packages which is not covered in this procedure and depends on your own system) :
```
mkdir /opt/bunkerweb/deps && \
mkdir /usr/share/bunkerweb/deps && \
/tmp/bunkerweb/deps/install.sh
```
Additional Python dependencies needs to be installed into the `/opt/bunkerweb/deps/python` folder :
Additional Python dependencies needs to be installed into the `/usr/share/bunkerweb/deps/python` folder :
```shell
mkdir /opt/bunkerweb/deps/python && \
pip install --no-cache-dir --require-hashes --target /opt/bunkerweb/deps/python -r /tmp/bunkerweb/deps/requirements.txt && \
pip install --no-cache-dir --target /opt/bunkerweb/deps/python -r /tmp/bunkerweb/ui/requirements.txt
mkdir /usr/share/bunkerweb/deps/python && \
pip install --no-cache-dir --require-hashes --target /usr/share/bunkerweb/deps/python -r /tmp/bunkerweb/deps/requirements.txt && \
pip install --no-cache-dir --target /usr/share/bunkerweb/deps/python -r /tmp/bunkerweb/ui/requirements.txt && \
pip install --no-cache-dir gunicorn
```
Once dependencies are installed, you will be able to copy the BunkerWeb sources to the target `/opt/bunkerweb` folder :
Once dependencies are installed, you will be able to copy the BunkerWeb sources to the target `/usr/share/bunkerweb` folder :
```shell
for src in api cli confs core gen helpers job lua misc utils ui settings.json VERSION linux/variables.env linux/ui.env linux/scripts ; do
cp -r /tmp/bunkerweb/${src} /opt/bunkerweb
cp -r /tmp/bunkerweb/${src} /usr/share/bunkerweb
done
cp /opt/bunkerweb/helpers/bwcli /usr/local/bin
cp /usr/share/bunkerweb/helpers/bwcli /usr/bin
```
Additional folders also need to be created :
```shell
mkdir /opt/bunkerweb/{configs,cache,plugins,tmp}
mkdir -p /etc/bunkerweb/configs && \
mkdir -p /var/cache/bunkerweb && \
mkdir -p /etc/bunkerweb/plugins && \
mkdir -p /var/tmp/bunkerweb
```
Permissions needs to be fixed :
```shell
find /opt/bunkerweb -path /opt/bunkerweb/deps -prune -o -type f -exec chmod 0740 {} \; && \
find /opt/bunkerweb -path /opt/bunkerweb/deps -prune -o -type d -exec chmod 0750 {} \; && \
find /opt/bunkerweb/core/*/jobs/* -type f -exec chmod 750 {} \; && \
chmod 770 /opt/bunkerweb/cache /opt/bunkerweb/tmp && \
chmod 750 /opt/bunkerweb/gen/main.py /opt/bunkerweb/job/main.py /opt/bunkerweb/cli/main.py /opt/bunkerweb/helpers/*.sh /opt/bunkerweb/scripts/*.sh /usr/local/bin/bwcli /opt/bunkerweb/ui/main.py && \
chown -R root:nginx /opt/bunkerweb
find /usr/share/bunkerweb -path /usr/share/bunkerweb/deps -prune -o -type f -exec chmod 0740 {} \; && \
find /usr/share/bunkerweb -path /usr/share/bunkerweb/deps -prune -o -type d -exec chmod 0750 {} \; && \
find /usr/share/bunkerweb/core/*/jobs/* -type f -exec chmod 750 {} \; && \
chmod 770 /var/cache/bunkerweb /var/tmp/bunkerweb && \
chmod 750 /usr/share/bunkerweb/gen/main.py /usr/share/bunkerweb/scheduler/main.py /usr/share/bunkerweb/cli/main.py /usr/share/bunkerweb/helpers/*.sh /usr/share/bunkerweb/scripts/*.sh /usr/bin/bwcli /usr/share/bunkerweb/ui/main.py && \
chown -R root:nginx /usr/share/bunkerweb
```
Last but not least, you will need to set up systemd unit files :
@ -859,7 +863,7 @@ Repositories of Linux packages for BunkerWeb are available on [PackageCloud](htt
systemctl enable bunkerweb-ui
```
The configuration of BunkerWeb is done by editing the `/opt/bunkerweb/variables.env` file :
The configuration of BunkerWeb is done by editing the `/etc/bunkerweb/variables.env` file :
```conf
MY_SETTING_1=value1
@ -923,16 +927,16 @@ ansible-playbook -i inventory.yml playbook.yml
Configuration of BunkerWeb is done by using specific role variables :
| Name | Type | Description | Default value |
|:-----:|:-----:|--------------|----------------|
| `bunkerweb_version` | string | Version of BunkerWeb to install. | `1.4.3` |
| `nginx_version` | string | Version of NGINX to install. | `1.20.2` |
| `freeze_versions` | boolean | Prevent upgrade of BunkerWeb and NGINX when performing packages upgrades. | `true` |
| `variables_env` | string | Path of the variables.env file to configure BunkerWeb. | `files/variables.env` |
| `enable_ui` | boolean | Activate the web UI. | `false` |
| `custom_ui` | string | Path of the ui.env file to configure the web UI. | `files/ui.env` |
| `custom_configs_path` | Dictionary | Each entry is a path of the folder containing custom configurations. Keys are the type of custom configs : `http`, `server-http`, `modsec`, `modsec-crs` and `default-server-http` | empty values |
| `custom_www` | string | Path of the www directory to upload. | empty value |
| `custom_plugins` | string | Path of the plugins directory to upload. | empty value |
| `custom_www_owner` | string | Default owner for www files and folders. | `nginx` |
| `custom_www_group` | string | Default group for www files and folders. | `nginx` |
| Name | Type | Description | Default value |
| :-------------------: | :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
| `bunkerweb_version` | string | Version of BunkerWeb to install. | `1.4.3` |
| `nginx_version` | string | Version of NGINX to install. | `1.20.2` |
| `freeze_versions` | boolean | Prevent upgrade of BunkerWeb and NGINX when performing packages upgrades. | `true` |
| `variables_env` | string | Path of the variables.env file to configure BunkerWeb. | `files/variables.env` |
| `enable_ui` | boolean | Activate the web UI. | `false` |
| `custom_ui` | string | Path of the ui.env file to configure the web UI. | `files/ui.env` |
| `custom_configs_path` | Dictionary | Each entry is a path of the folder containing custom configurations. Keys are the type of custom configs : `http`, `server-http`, `modsec`, `modsec-crs` and `default-server-http` | empty values |
| `custom_www` | string | Path of the www directory to upload. | empty value |
| `custom_plugins` | string | Path of the plugins directory to upload. | empty value |
| `custom_www_owner` | string | Default owner for www files and folders. | `nginx` |
| `custom_www_group` | string | Default group for www files and folders. | `nginx` |

View file

@ -41,13 +41,13 @@ print(
# Print global settings
print("## Global settings\n")
with open("settings.json", "r") as f:
with open("src/common/settings.json", "r") as f:
print_md_table(loads(f.read()))
# Print core settings
print("## Core settings\n")
core_settings = {}
for core in glob("./core/*/plugin.json"):
for core in glob("src/common/core/*/plugin.json"):
with open(core, "r") as f:
core_plugin = loads(f.read())
if len(core_plugin["settings"]) > 0:

View file

@ -8,6 +8,6 @@ fi
if [ "$1" == "dev" ] ; then
mike deploy --push --update-aliases dev
else
mike deploy --push --update-aliases "$(cat VERSION | sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1\.\2/')" latest
mike deploy --push --update-aliases "$(cat src/VERSION | sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1\.\2/')" latest
mike set-default --push latest
fi

View file

@ -113,7 +113,7 @@ The first step is to install the plugin by putting the plugin files inside the c
=== "Linux"
When using the [Linux integration](/1.4/integrations/#linux), plugins must be written to the `/opt/bunkerweb/plugins` folder :
When using the [Linux integration](/1.4/integrations/#linux), plugins must be written to the `/etc/bunkerweb/plugins` folder :
```shell
git clone https://github.com/bunkerity/bunkerweb-plugins && \
cp -rp ./bunkerweb-plugins/* /data/plugins

View file

@ -247,7 +247,7 @@ You will find more settings about reverse proxy in the [settings section](/1.4/s
python3 -m http.server -b 127.0.0.1
```
Configuration of BunkerWeb is done by editing the `/opt/bunkerweb/variables.env` file :
Configuration of BunkerWeb is done by editing the `/etc/bunkerweb/variables.env` file :
```conf
SERVER_NAME=www.example.com
HTTP_PORT=80
@ -852,7 +852,7 @@ You will find more settings about reverse proxy in the [settings section](/1.4/s
python3 -m http.server -b 127.0.0.1 8003
```
Configuration of BunkerWeb is done by editing the `/opt/bunkerweb/variables.env` file :
Configuration of BunkerWeb is done by editing the `/etc/bunkerweb/variables.env` file :
```conf
SERVER_NAME=app1.example.com app2.example.com app3.example.com
HTTP_PORT=80
@ -1076,7 +1076,7 @@ REAL_IP_HEADER=X-Forwarded-For
=== "Linux"
You will need to add the settings to the `/opt/bunkerweb/variables.env` file :
You will need to add the settings to the `/etc/bunkerweb/variables.env` file :
```conf
...
USE_REAL_IP=yes
@ -1248,7 +1248,7 @@ REAL_IP_HEADER=proxy_protocol
=== "Linux"
You will need to add the settings to the `/opt/bunkerweb/variables.env` file :
You will need to add the settings to the `/etc/bunkerweb/variables.env` file :
```conf
...
USE_REAL_IP=yes
@ -1502,7 +1502,7 @@ Some integrations offer a more convenient way of applying configurations such as
=== "Linux"
When using the [Linux integration](/1.4/integrations/#linux), custom configurations must be written to the /opt/bunkerweb/configs folder.
When using the [Linux integration](/1.4/integrations/#linux), custom configurations must be written to the /etc/bunkerweb/configs folder.
Here is an example for server-http/hello-world.conf :
```conf
@ -1516,8 +1516,8 @@ Some integrations offer a more convenient way of applying configurations such as
Because BunkerWeb runs as an unprivileged user (nginx:nginx), you will need to edit the permissions :
```shell
chown -R root:nginx /opt/bunkerweb/configs && \
chmod -R 770 /opt/bunkerweb/configs
chown -R root:nginx /etc/bunkerweb/configs && \
chmod -R 770 /etc/bunkerweb/configs
```
Don't forget to restart the BunkerWeb service once it's done.
@ -1793,9 +1793,9 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
We will assume that you already have the [Linux integration](/1.4/integrations/#linux) stack running on your machine.
By default, BunkerWeb will search for web files inside the `/opt/bunkerweb/www` folder. You can use it to store your PHP application. Please note that you will need to configure your PHP-FPM service to get or set the user/group of the running processes and the UNIX socket file used to communicate with BunkerWeb.
By default, BunkerWeb will search for web files inside the `/var/www/html` folder. You can use it to store your PHP application. Please note that you will need to configure your PHP-FPM service to get or set the user/group of the running processes and the UNIX socket file used to communicate with BunkerWeb.
First of all, you will need to make sure that your PHP-FPM instance can access the files inside the `/opt/bunkerweb/www` folder and also that BunkerWeb can access the UNIX socket file in order to communicate with PHP-FPM. We recommend to set a different user like `www-data` for the PHP-FPM service and to give the nginx group access to the UNIX socket file. Here is corresponding PHP-FPM configuration :
First of all, you will need to make sure that your PHP-FPM instance can access the files inside the `/var/www/html` folder and also that BunkerWeb can access the UNIX socket file in order to communicate with PHP-FPM. We recommend to set a different user like `www-data` for the PHP-FPM service and to give the nginx group access to the UNIX socket file. Here is corresponding PHP-FPM configuration :
```ini
...
[www]
@ -1813,14 +1813,14 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
systemctl restart php-fpm
```
Once your application is copied to the `/opt/bunkerweb/www` folder, you will need to fix the permissions so BunkerWeb (user/group nginx) can at least read files and list folders and PHP-FPM (user/group www-data) is the owner of the files and folders :
Once your application is copied to the `/var/www/html` folder, you will need to fix the permissions so BunkerWeb (user/group nginx) can at least read files and list folders and PHP-FPM (user/group www-data) is the owner of the files and folders :
```shell
chown -R www-data:nginx /opt/bunkerweb/www && \
find /opt/bunkerweb/www -type f -exec chmod 0640 {} \; && \
find /opt/bunkerweb/www -type d -exec chmod 0750 {} \;
chown -R www-data:nginx /var/www/html && \
find /var/www/html -type f -exec chmod 0640 {} \; && \
find /var/www/html -type d -exec chmod 0750 {} \;
```
You can now edit the `/opt/bunkerweb/variable.env` file :
You can now edit the `/etc/bunkerweb/variable.env` file :
```env
HTTP_PORT=80
HTTPS_PORT=443
@ -1828,7 +1828,7 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
SERVER_NAME=www.example.com
AUTO_LETS_ENCRYPT=yes
LOCAL_PHP=/run/php/php-fpm.sock
LOCAL_PHP_PATH=/opt/bunkerweb/www/
LOCAL_PHP_PATH=/var/www/html/
```
Let's check the status of BunkerWeb :
@ -1847,9 +1847,9 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
=== "Ansible"
By default, BunkerWeb will search for web files inside the `/opt/bunkerweb/www` folder. You can use it to store your PHP application. Please note that you will need to configure your PHP-FPM service to get or set the user/group of the running processes and the UNIX socket file used to communicate with BunkerWeb.
By default, BunkerWeb will search for web files inside the `/var/www/html` folder. You can use it to store your PHP application. Please note that you will need to configure your PHP-FPM service to get or set the user/group of the running processes and the UNIX socket file used to communicate with BunkerWeb.
First of all, you will need to make sure that your PHP-FPM instance can access the files inside the `/opt/bunkerweb/www` folder and also that BunkerWeb can access the UNIX socket file in order to communicate with PHP-FPM. We recommend to set a different user like `www-data` for the PHP-FPM service and to give the nginx group access to the UNIX socket file. Here is corresponding PHP-FPM configuration :
First of all, you will need to make sure that your PHP-FPM instance can access the files inside the `/var/www/html` folder and also that BunkerWeb can access the UNIX socket file in order to communicate with PHP-FPM. We recommend to set a different user like `www-data` for the PHP-FPM service and to give the nginx group access to the UNIX socket file. Here is corresponding PHP-FPM configuration :
```ini
...
[www]
@ -1873,10 +1873,10 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
SERVER_NAME=www.example.com
AUTO_LETS_ENCRYPT=yes
LOCAL_PHP=/run/php/php-fpm.sock
LOCAL_PHP_PATH=/opt/bunkerweb/www/
LOCAL_PHP_PATH=/var/www/html/
```
The `custom_site` variable can be used to specify a directory containing your application files (e.g : `my_app`) that will be copied to `/opt/bunkerweb/www` and the `custom_www_owner` variable contains the owner that should be set for the files and folders. Here is an example using the Ansible inventory :
The `custom_site` variable can be used to specify a directory containing your application files (e.g : `my_app`) that will be copied to `/var/www/html` and the `custom_www_owner` variable contains the owner that should be set for the files and folders. Here is an example using the Ansible inventory :
```ini
[mybunkers]
192.168.0.42 variables_env="{{ playbook_dir }}/my_variables.env" custom_www="{{ playbook_dir }}/my_app" custom_www_owner="www-data"
@ -2298,9 +2298,9 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
We will assume that you already have the [Linux integration](/1.4/integrations/#linux) stack running on your machine.
By default, BunkerWeb will search for web files inside the `/opt/bunkerweb/www` folder. You can use it to store your PHP applications : each application will be in its own subfolder named the same as the primary server name. Please note that you will need to configure your PHP-FPM service to get or set the user/group of the running processes and the UNIX socket file used to communicate with BunkerWeb.
By default, BunkerWeb will search for web files inside the `/var/www/html` folder. You can use it to store your PHP applications : each application will be in its own subfolder named the same as the primary server name. Please note that you will need to configure your PHP-FPM service to get or set the user/group of the running processes and the UNIX socket file used to communicate with BunkerWeb.
First of all, you will need to make sure that your PHP-FPM instance can access the files inside the `/opt/bunkerweb/www` folder and also that BunkerWeb can access the UNIX socket file in order to communicate with PHP-FPM. We recommend to set a different user like `www-data` for the PHP-FPM service and to give the nginx group access to the UNIX socket file. Here is corresponding PHP-FPM configuration :
First of all, you will need to make sure that your PHP-FPM instance can access the files inside the `/var/www/html` folder and also that BunkerWeb can access the UNIX socket file in order to communicate with PHP-FPM. We recommend to set a different user like `www-data` for the PHP-FPM service and to give the nginx group access to the UNIX socket file. Here is corresponding PHP-FPM configuration :
```ini
...
[www]
@ -2318,14 +2318,14 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
systemctl restart php-fpm
```
Once your application is copied to the `/opt/bunkerweb/www` folder, you will need to fix the permissions so BunkerWeb (user/group nginx) can at least read files and list folders and PHP-FPM (user/group www-data) is the owner of the files and folders :
Once your application is copied to the `/var/www/html` folder, you will need to fix the permissions so BunkerWeb (user/group nginx) can at least read files and list folders and PHP-FPM (user/group www-data) is the owner of the files and folders :
```shell
chown -R www-data:nginx /opt/bunkerweb/www && \
find /opt/bunkerweb/www -type f -exec chmod 0640 {} \; && \
find /opt/bunkerweb/www -type d -exec chmod 0750 {} \;
chown -R www-data:nginx /var/www/html && \
find /var/www/html -type f -exec chmod 0640 {} \; && \
find /var/www/html -type d -exec chmod 0750 {} \;
```
You can now edit the `/opt/bunkerweb/variable.env` file :
You can now edit the `/etc/bunkerweb/variable.env` file :
```env
HTTP_PORT=80
HTTPS_PORT=443
@ -2334,11 +2334,11 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
MULTISITE=yes
AUTO_LETS_ENCRYPT=yes
app1.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app1.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app1.example.com
app1.example.com_LOCAL_PHP_PATH=/var/www/html/app1.example.com
app2.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app2.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app2.example.com
app2.example.com_LOCAL_PHP_PATH=/var/www/html/app2.example.com
app3.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app3.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app3.example.com
app3.example.com_LOCAL_PHP_PATH=/var/www/html/app3.example.com
```
Let's check the status of BunkerWeb :
@ -2357,9 +2357,9 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
=== "Ansible"
By default, BunkerWeb will search for web files inside the `/opt/bunkerweb/www` folder. You can use it to store your PHP application : each application will be in its own subfolder named the same as the primary server name. Please note that you will need to configure your PHP-FPM service to get or set the user/group of the running processes and the UNIX socket file used to communicate with BunkerWeb.
By default, BunkerWeb will search for web files inside the `/var/www/html` folder. You can use it to store your PHP application : each application will be in its own subfolder named the same as the primary server name. Please note that you will need to configure your PHP-FPM service to get or set the user/group of the running processes and the UNIX socket file used to communicate with BunkerWeb.
First of all, you will need to make sure that your PHP-FPM instance can access the files inside the `/opt/bunkerweb/www` folder and also that BunkerWeb can access the UNIX socket file in order to communicate with PHP-FPM. We recommend to set a different user like `www-data` for the PHP-FPM service and to give the nginx group access to the UNIX socket file. Here is corresponding PHP-FPM configuration :
First of all, you will need to make sure that your PHP-FPM instance can access the files inside the `/var/www/html` folder and also that BunkerWeb can access the UNIX socket file in order to communicate with PHP-FPM. We recommend to set a different user like `www-data` for the PHP-FPM service and to give the nginx group access to the UNIX socket file. Here is corresponding PHP-FPM configuration :
```ini
...
[www]
@ -2384,14 +2384,14 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
MULTISITE=yes
AUTO_LETS_ENCRYPT=yes
app1.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app1.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app1.example.com
app1.example.com_LOCAL_PHP_PATH=/var/www/html/app1.example.com
app2.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app2.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app2.example.com
app2.example.com_LOCAL_PHP_PATH=/var/www/html/app2.example.com
app3.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app3.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app3.example.com
app3.example.com_LOCAL_PHP_PATH=/var/www/html/app3.example.com
```
The `custom_site` variable can be used to specify a directory containing your application files (e.g : `my_app`) that will be copied to `/opt/bunkerweb/www` and the `custom_www_owner` variable contains the owner that should be set for the files and folders. Here is an example using the Ansible inventory :
The `custom_site` variable can be used to specify a directory containing your application files (e.g : `my_app`) that will be copied to `/var/www/html` and the `custom_www_owner` variable contains the owner that should be set for the files and folders. Here is an example using the Ansible inventory :
```ini
[mybunkers]
192.168.0.42 variables_env="{{ playbook_dir }}/my_variables.env" custom_www="{{ playbook_dir }}/my_app" custom_www_owner="www-data"

View file

@ -1,5 +1,5 @@
mkdocs==1.4.2
mkdocs-material==8.5.7
mkdocs-material==8.5.9
pytablewriter==0.64.2
mike==1.1.2
jinja2<3.1.0

View file

@ -14,7 +14,7 @@ When settings are considered as "multiple", it means that you can have multiple
| Setting | Default | Context |Multiple| Description |
|-----------------------|------------------------------------------------------------------------------------------------------------------------|---------|--------|--------------------------------------------------|
|`TEMP_NGINX` |`no` |global |no |internal-use |
|`IS_LOADING` |`no` |global |no |Internal use : set to yes when BW is loading. |
|`NGINX_PREFIX` |`/etc/nginx/` |global |no |Where nginx will search for configurations. |
|`HTTP_PORT` |`8080` |global |no |HTTP port number which bunkerweb binds to. |
|`HTTPS_PORT` |`8443` |global |no |HTTPS port number which bunkerweb binds to. |
@ -73,20 +73,30 @@ When settings are considered as "multiple", it means that you can have multiple
### Blacklist
| Setting | Default | Context |Multiple| Description |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------|---------|--------|------------------------------------------------------------------------------|
|`USE_BLACKLIST` |`yes` |multisite|no |Activate blacklist feature. |
|`BLACKLIST_IP_URLS` |`https://www.dan.me.uk/torlist/?exit` |global |no |List of URLs, separated with spaces, containing bad IP/network to block. |
|`BLACKLIST_IP` | |multisite|no |List of IP/network, separated with spaces, to block. |
|`BLACKLIST_RDNS` |`.shodan.io .censys.io` |multisite|no |List of reverse DNS suffixes, separated with spaces, to block. |
|`BLACKLIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to block.|
|`BLACKLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS blacklist checks on global IP addresses. |
|`BLACKLIST_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to block. |
|`BLACKLIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to block. |
|`BLACKLIST_USER_AGENT` | |multisite|no |List of User-Agent, separated with spaces, to block. |
|`BLACKLIST_USER_AGENT_URLS`|`https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list`|global |no |List of URLs, separated with spaces, containing bad User-Agent to block. |
|`BLACKLIST_URI` | |multisite|no |List of URI, separated with spaces, to block. |
|`BLACKLIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to block. |
| Setting | Default | Context |Multiple| Description |
|----------------------------------|------------------------------------------------------------------------------------------------------------------------------|---------|--------|------------------------------------------------------------------------------------------------|
|`USE_BLACKLIST` |`yes` |multisite|no |Activate blacklist feature. |
|`BLACKLIST_IP_URLS` |`https://www.dan.me.uk/torlist/?exit` |global |no |List of URLs, separated with spaces, containing bad IP/network to block. |
|`BLACKLIST_IP` | |multisite|no |List of IP/network, separated with spaces, to block. |
|`BLACKLIST_RDNS` |`.shodan.io .censys.io` |multisite|no |List of reverse DNS suffixes, separated with spaces, to block. |
|`BLACKLIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to block. |
|`BLACKLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS blacklist checks on global IP addresses. |
|`BLACKLIST_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to block. |
|`BLACKLIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to block. |
|`BLACKLIST_USER_AGENT` | |multisite|no |List of User-Agent, separated with spaces, to block. |
|`BLACKLIST_USER_AGENT_URLS` |`https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list`|global |no |List of URLs, separated with spaces, containing bad User-Agent to block. |
|`BLACKLIST_URI` | |multisite|no |List of URI, separated with spaces, to block. |
|`BLACKLIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to block. |
|`BLACKLIST_IGNORE_IP_URLS` | |global |no |List of URLs, separated with spaces, containing IP/network to ignore in the blacklist. |
|`BLACKLIST_IGNORE_IP` | |multisite|no |List of IP/network, separated with spaces, to ignore in the blacklist. |
|`BLACKLIST_IGNORE_RDNS` | |multisite|no |List of reverse DNS suffixes, separated with spaces, to ignore in the blacklist. |
|`BLACKLIST_IGNORE_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to ignore in the blacklist.|
|`BLACKLIST_IGNORE_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to ignore in the blacklist. |
|`BLACKLIST_IGNORE_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to ignore in the blacklist. |
|`BLACKLIST_IGNORE_USER_AGENT` | |multisite|no |List of User-Agent, separated with spaces, to ignore in the blacklist. |
|`BLACKLIST_IGNORE_USER_AGENT_URLS`| |global |no |List of URLs, separated with spaces, containing User-Agent to ignore in the blacklist. |
|`BLACKLIST_IGNORE_URI` | |multisite|no |List of URI, separated with spaces, to ignore in the blacklist. |
|`BLACKLIST_IGNORE_URI_URLS` | |global |no |List of URLs, separated with spaces, containing URI to ignore in the blacklist. |
### Brotli
@ -140,6 +150,12 @@ When settings are considered as "multiple", it means that you can have multiple
|`CUSTOM_HTTPS_CERT`| |multisite|no |Full path of the certificate or bundle file.|
|`CUSTOM_HTTPS_KEY` | |multisite|no |Full path of the key file. |
### DB
| Setting | Default |Context|Multiple| Description |
|--------------|----------------------------|-------|--------|--------------------------------------------------|
|`DATABASE_URI`|`sqlite:////data/db.sqlite3`|global |no |The database URI, following the sqlalchemy format.|
### DNSBL
| Setting | Default | Context |Multiple| Description |
@ -153,6 +169,23 @@ When settings are considered as "multiple", it means that you can have multiple
|--------|-------|---------|--------|-------------------------------------------------------------------------------------------------|
|`ERRORS`| |multisite|no |List of HTTP error code and corresponding error pages (404=/my404.html 403=/errors/403.html ...).|
### Greylist
| Setting |Default| Context |Multiple| Description |
|--------------------------|-------|---------|--------|----------------------------------------------------------------------------------------------|
|`USE_GREYLIST` |`no` |multisite|no |Activate greylist feature. |
|`GREYLIST_IP_URLS` | |global |no |List of URLs, separated with spaces, containing good IP/network to put into the greylist. |
|`GREYLIST_IP` | |multisite|no |List of IP/network, separated with spaces, to put into the greylist. |
|`GREYLIST_RDNS` | |multisite|no |List of reverse DNS suffixes, separated with spaces, to put into the greylist. |
|`GREYLIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to put into the greylist.|
|`GREYLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS greylist checks on global IP addresses. |
|`GREYLIST_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to put into the greylist. |
|`GREYLIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to put into the greylist. |
|`GREYLIST_USER_AGENT` | |multisite|no |List of User-Agent, separated with spaces, to put into the greylist. |
|`GREYLIST_USER_AGENT_URLS`| |global |no |List of URLs, separated with spaces, containing good User-Agent to put into the greylist. |
|`GREYLIST_URI` | |multisite|no |List of URI, separated with spaces, to put into the greylist. |
|`GREYLIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to put into the greylist. |
### Gzip
| Setting | Default | Context |Multiple| Description |
@ -214,7 +247,7 @@ When settings are considered as "multiple", it means that you can have multiple
|`ALLOWED_METHODS` |`GET\|POST\|HEAD` |multisite|no |Allowed HTTP methods to be sent by clients. |
|`MAX_CLIENT_SIZE` |`10m` |multisite|no |Maximum body size (0 for infinite). |
|`SERVE_FILES` |`yes` |multisite|no |Serve files from the local folder. |
|`ROOT_FOLDER` | |multisite|no |Root folder containing files to serve (/opt/bunkerweb/www/{server_name} if unset). |
|`ROOT_FOLDER` | |multisite|no |Root folder containing files to serve (/var/www/html/{server_name} if unset). |
|`HTTPS_PROTOCOLS` |`TLSv1.2 TLSv1.3` |multisite|no |The supported version of TLS. We recommend the default value TLSv1.2 TLSv1.3 for compatibility reasons. |
|`HTTP2` |`yes` |multisite|no |Support HTTP2 protocol when HTTPS is enabled. |
|`LISTEN_HTTP` |`yes` |multisite|no |Respond to (insecure) HTTP requests. |
@ -228,11 +261,13 @@ When settings are considered as "multiple", it means that you can have multiple
### ModSecurity
| Setting | Default | Context |Multiple| Description |
|-----------------------------------|----------------|---------|--------|--------------------------------------------------|
| `USE_MODSECURITY` | `yes` |multisite|no | Enable ModSecurity WAF. |
| `USE_MODSECURITY_CRS` | `yes` |multisite|no | Enable OWASP Core Rule Set. |
| `MODSECURITY_SEC_AUDIT_ENGINE` | `RelevantOnly` |multisite|no | SecAuditEngine directive of ModSecurity. |
| Setting | Default | Context |Multiple| Description |
|---------------------------------|--------------|---------|--------|------------------------------------------|
|`USE_MODSECURITY` |`yes` |multisite|no |Enable ModSecurity WAF. |
|`USE_MODSECURITY_CRS` |`yes` |multisite|no |Enable OWASP Core Rule Set. |
|`MODSECURITY_SEC_AUDIT_ENGINE` |`RelevantOnly`|multisite|no |SecAuditEngine directive of ModSecurity. |
|`MODSECURITY_SEC_RULE_ENGINE` |`On` |multisite|no |SecRuleEngine directive of ModSecurity. |
|`MODSECURITY_SEC_AUDIT_LOG_PARTS`|`ABCFHZ` |multisite|no |SecAuditLogParts directive of ModSecurity.|
### PHP

View file

@ -115,7 +115,7 @@ Let's take the following logs as an example of ModSecurity detection using defau
```log
2022/04/26 12:01:10 [warn] 85#85: *11 ModSecurity: Warning. Matched "Operator `PmFromFile' with parameter `lfi-os-files.data' against variable `ARGS:id' (Value: `/etc/passwd' )
[file "/opt/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"]
[file "/usr/share/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"]
[line "78"]
[id "930120"]
[rev ""]
@ -139,7 +139,7 @@ Let's take the following logs as an example of ModSecurity detection using defau
[ref "o1,10v9,11t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,t:lowercase"],
client: 172.17.0.1, server: localhost, request: "GET /?id=/etc/passwd HTTP/1.1", host: "localhost"
2022/04/26 12:01:10 [warn] 85#85: *11 ModSecurity: Warning. Matched "Operator `PmFromFile' with parameter `unix-shell.data' against variable `ARGS:id' (Value: `/etc/passwd' )
[file "/opt/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf"]
[file "/usr/share/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf"]
[line "480"]
[id "932160"]
[rev ""]
@ -163,7 +163,7 @@ Let's take the following logs as an example of ModSecurity detection using defau
[ref "o1,10v9,11t:urlDecodeUni,t:cmdLine,t:normalizePath,t:lowercase"],
client: 172.17.0.1, server: localhost, request: "GET /?id=/etc/passwd HTTP/1.1", host: "localhost"
2022/04/26 12:01:10 [error] 85#85: *11 [client 172.17.0.1] ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `10' )
[file "/opt/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf"]
[file "/usr/share/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf"]
[line "80"]
[id "949110"]
[rev ""]

View file

@ -196,7 +196,7 @@ Because the web UI is a web application, the recommended installation procedure
The installation of the web UI using the [Linux integration](/1.4/integrations/#linux) is pretty straightforward because it is installed with BunkerWeb.
The first thing to do is to edit the BunkerWeb configuration located at **/opt/bunkerweb/variables.env** to add settings related to the web UI :
The first thing to do is to edit the BunkerWeb configuration located at **/etc/bunkerweb/variables.env** to add settings related to the web UI :
```conf
HTTP_PORT=80
HTTPS_PORT=443
@ -225,7 +225,7 @@ Because the web UI is a web application, the recommended installation procedure
systemctl restart bunkerweb
```
You can edit the **/opt/bunkerweb/ui.env** file containing the settings of the web UI :
You can edit the **/etc/bunkerweb/ui.env** file containing the settings of the web UI :
```conf
ADMIN_USERNAME=admin
ADMIN_PASSWORD=changeme
@ -234,7 +234,7 @@ Because the web UI is a web application, the recommended installation procedure
Important things to note :
* `http(s)://bwadmin.example.com/changeme/` is the full base URL of the web UI (must match the sub(domain) and /changeme URL used in **/opt/bunkerweb/variables.env**)
* `http(s)://bwadmin.example.com/changeme/` is the full base URL of the web UI (must match the sub(domain) and /changeme URL used in **/etc/bunkerweb/variables.env**)
* replace the username `admin` and password `changeme` with strong ones
Restart the BunkerWeb UI service and you are now ready to access it :

View file

@ -21,4 +21,4 @@ systemctl stop bunkerweb
systemctl stop haproxy
systemctl start haproxy
echo "hello" > /opt/bunkerweb/www/index.html
echo "hello" > /var/www/html/index.html

View file

@ -13,7 +13,7 @@ else
echo "❌ No PHP user found"
exit 1
fi
cp -r ./bw-data/www/* /opt/bunkerweb/www
chown -R $user:nginx /opt/bunkerweb/www
find /opt/bunkerweb/www -type f -exec chmod 0640 {} \;
find /opt/bunkerweb/www -type d -exec chmod 0750 {} \;
cp -r ./bw-data/www/* /var/www/html
chown -R $user:nginx /var/www/html
find /var/www/html -type f -exec chmod 0640 {} \;
find /var/www/html -type d -exec chmod 0750 {} \;

View file

@ -12,8 +12,8 @@ app1.example.com_USE_CORS=yes
app1.example.com_CORS_ALLOW_ORIGIN=https://app2.example.com
app1.example.com_ALLOWED_METHODS=GET|POST|HEAD|OPTIONS
app1.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app1.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app1.example.com
app1.example.com_LOCAL_PHP_PATH=/var/www/html/app1.example.com
app2.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app2.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app2.example.com
app2.example.com_LOCAL_PHP_PATH=/var/www/html/app2.example.com
app3.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app3.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app3.example.com
app3.example.com_LOCAL_PHP_PATH=/var/www/html/app3.example.com

View file

@ -17,10 +17,10 @@ curl https://www.drupal.org/download-latest/tar.gz -Lo /tmp/drupal.tar.gz
tar -xzf /tmp/drupal.tar.gz -C /tmp
current_dir="$(pwd)"
cd /tmp/drupal-*
cp -r * /opt/bunkerweb/www
chown -R $user:nginx /opt/bunkerweb/www
find /opt/bunkerweb/www -type f -exec chmod 0640 {} \;
find /opt/bunkerweb/www -type d -exec chmod 0750 {} \;
cp -r * /var/www/html
chown -R $user:nginx /var/www/html
find /var/www/html -type f -exec chmod 0640 {} \;
find /var/www/html -type d -exec chmod 0750 {} \;
cd "$current_dir"
cp -r ./bw-data/configs/* /opt/bunkerweb/configs
chown -R nginx:nginx /opt/bunkerweb/configs
cp -r ./bw-data/configs/* /etc/bunkerweb/configs
chown -R nginx:nginx /etc/bunkerweb/configs

View file

@ -10,4 +10,4 @@ USE_GZIP=yes
LIMIT_REQ_URL_1=/core/install.php
LIMIT_REQ_RATE_1=5r/s
LOCAL_PHP=/run/php/php-fpm.sock
LOCAL_PHP_PATH=/opt/bunkerweb/www
LOCAL_PHP_PATH=/var/www/html

View file

@ -14,7 +14,7 @@ services:
# folders that need write access
tmpfs:
- /tmp:mode=0770,uid=0,gid=101
- /opt/bunkerweb/tmp:mode=0770,uid=0,gid=101
- /var/tmp/bunkerweb:mode=0770,uid=0,gid=101
- /etc/nginx:mode=0770,uid=0,gid=101
ports:
- 80:8080

View file

@ -14,7 +14,7 @@ else
exit 1
fi
curl https://downloads.joomla.org/fr/cms/joomla4/4-1-5/Joomla_4-1-5-Stable-Full_Package.zip?format=zip -Lo /tmp/joomla.zip
unzip -qq /tmp/joomla.zip -d /opt/bunkerweb/www
chown -R $user:nginx /opt/bunkerweb/www
find /opt/bunkerweb/www -type f -exec chmod 0640 {} \;
find /opt/bunkerweb/www -type d -exec chmod 0750 {} \;
unzip -qq /tmp/joomla.zip -d /var/www/html
chown -R $user:nginx /var/www/html
find /var/www/html -type f -exec chmod 0640 {} \;
find /var/www/html -type d -exec chmod 0750 {} \;

View file

@ -12,4 +12,4 @@ LIMIT_REQ_RATE_1=8r/s
LIMIT_REQ_URL_2=/installation/index.php
LIMIT_REQ_RATE_2=8r/s
LOCAL_PHP=/run/php/php-fpm.sock
LOCAL_PHP_PATH=/opt/bunkerweb/www
LOCAL_PHP_PATH=/var/www/html

View file

@ -15,7 +15,7 @@ else
fi
curl https://download.moodle.org/download.php/direct/stable400/moodle-4.0.2.tgz -Lo /tmp/moodle.tgz
tar -xzf /tmp/moodle.tgz -C /tmp
cp -r /tmp/moodle/* /opt/bunkerweb/www
chown -R $user:nginx /opt/bunkerweb/www
find /opt/bunkerweb/www -type f -exec chmod 0640 {} \;
find /opt/bunkerweb/www -type d -exec chmod 0750 {} \;
cp -r /tmp/moodle/* /var/www/html
chown -R $user:nginx /var/www/html
find /var/www/html -type f -exec chmod 0640 {} \;
find /var/www/html -type d -exec chmod 0750 {} \;

View file

@ -9,4 +9,4 @@ USE_CLIENT_CACHE=yes
USE_GZIP=yes
MAX_CLIENT_SIZE=50m
LOCAL_PHP=/run/php/php-fpm.sock
LOCAL_PHP_PATH=/opt/bunkerweb/www
LOCAL_PHP_PATH=/var/www/html

View file

@ -15,8 +15,8 @@ else
fi
curl https://download.nextcloud.com/server/releases/latest.zip -Lo /tmp/nextcloud.zip
unzip -qq /tmp/nextcloud.zip -d /tmp
cp -r /tmp/nextcloud/* /opt/bunkerweb/www
chown -R $user:nginx /opt/bunkerweb/www
find /opt/bunkerweb/www -type f -exec chmod 0640 {} \;
find /opt/bunkerweb/www -type d -exec chmod 0750 {} \;
cp -r bw-data/configs/* /opt/bunkerweb/configs
cp -r /tmp/nextcloud/* /var/www/html
chown -R $user:nginx /var/www/html
find /var/www/html -type f -exec chmod 0640 {} \;
find /var/www/html -type d -exec chmod 0750 {} \;
cp -r bw-data/configs/* /etc/bunkerweb/configs

View file

@ -13,7 +13,7 @@ else
echo "❌ No PHP user found"
exit 1
fi
cp -r ./bw-data/www/* /opt/bunkerweb/www
chown -R $user:nginx /opt/bunkerweb/www
find /opt/bunkerweb/www -type f -exec chmod 0640 {} \;
find /opt/bunkerweb/www -type d -exec chmod 0750 {} \;
cp -r ./bw-data/www/* /var/www/html
chown -R $user:nginx /var/www/html
find /var/www/html -type f -exec chmod 0640 {} \;
find /var/www/html -type d -exec chmod 0750 {} \;

View file

@ -9,6 +9,6 @@ AUTO_LETS_ENCRYPT=yes
USE_CLIENT_CACHE=yes
USE_GZIP=yes
app1.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app1.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app1.example.com
app1.example.com_LOCAL_PHP_PATH=/var/www/html/app1.example.com
app2.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app2.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app2.example.com
app2.example.com_LOCAL_PHP_PATH=/var/www/html/app2.example.com

View file

@ -13,7 +13,7 @@ else
echo "❌ No PHP user found"
exit 1
fi
cp -r ./bw-data/www/* /opt/bunkerweb/www
chown -R $user:nginx /opt/bunkerweb/www
find /opt/bunkerweb/www -type f -exec chmod 0640 {} \;
find /opt/bunkerweb/www -type d -exec chmod 0750 {} \;
cp -r ./bw-data/www/* /var/www/html
chown -R $user:nginx /var/www/html
find /var/www/html -type f -exec chmod 0640 {} \;
find /var/www/html -type d -exec chmod 0750 {} \;

View file

@ -8,4 +8,4 @@ AUTO_LETS_ENCRYPT=yes
USE_CLIENT_CACHE=yes
USE_GZIP=yes
LOCAL_PHP=/run/php/php-fpm.sock
LOCAL_PHP_PATH=/opt/bunkerweb/www
LOCAL_PHP_PATH=/var/www/html

View file

@ -22,4 +22,4 @@ systemctl stop bunkerweb
systemctl stop haproxy
systemctl start haproxy
echo "hello" > /opt/bunkerweb/www/index.html
echo "hello" > /var/www/html/index.html

View file

@ -5,6 +5,6 @@ if [ $(id -u) -ne 0 ] ; then
exit 1
fi
mkdir /opt/bunkerweb/www/{app1.example.com,app2.example.com}
echo "hello" > /opt/bunkerweb/www/app1.example.com/index.html
echo "hello" > /opt/bunkerweb/www/app2.example.com/index.html
mkdir /var/www/html/{app1.example.com,app2.example.com}
echo "hello" > /var/www/html/app1.example.com/index.html
echo "hello" > /var/www/html/app2.example.com/index.html

View file

@ -9,6 +9,6 @@ AUTO_LETS_ENCRYPT=yes
USE_CLIENT_CACHE=yes
USE_GZIP=yes
app1.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app1.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app1.example.com
app1.example.com_LOCAL_PHP_PATH=/var/www/html/app1.example.com
app2.example.com_LOCAL_PHP=/run/php/php-fpm.sock
app2.example.com_LOCAL_PHP_PATH=/opt/bunkerweb/www/app2.example.com
app2.example.com_LOCAL_PHP_PATH=/var/www/html/app2.example.com

View file

@ -5,8 +5,8 @@ if [ $(id -u) -ne 0 ] ; then
exit 1
fi
mkdir /opt/bunkerweb/www/{app1,app2}
echo "hello" > /opt/bunkerweb/www/app1/index.html
echo "hello" > /opt/bunkerweb/www/app2/index.html
cp -r bw-data/configs/* /opt/bunkerweb/configs
chown -R nginx:nginx /opt/bunkerweb/configs
mkdir /var/www/html/{app1,app2}
echo "hello" > /var/www/html/app1/index.html
echo "hello" > /var/www/html/app2/index.html
cp -r bw-data/configs/* /etc/bunkerweb/configs
chown -R nginx:nginx /etc/bunkerweb/configs

View file

@ -8,4 +8,4 @@ AUTO_LETS_ENCRYPT=yes
USE_CLIENT_CACHE=yes
USE_GZIP=yes
LOCAL_PHP=/run/php/php-fpm.sock
LOCAL_PHP_PATH=/opt/bunkerweb/www
LOCAL_PHP_PATH=/var/www/html

View file

@ -15,11 +15,11 @@ else
fi
curl https://wordpress.org/latest.zip -Lo /tmp/wordpress.zip
unzip -qq /tmp/wordpress.zip -d /tmp
cp -r /tmp/wordpress/* /opt/bunkerweb/www
chown -R $user:nginx /opt/bunkerweb/www
find /opt/bunkerweb/www -type f -exec chmod 0640 {} \;
find /opt/bunkerweb/www -type d -exec chmod 0750 {} \;
cp -r ./bw-data/configs/* /opt/bunkerweb/configs
chown -R nginx:nginx /opt/bunkerweb/configs
find /opt/bunkerweb/configs -type f -exec chmod 0644 {} \;
find /opt/bunkerweb/configs -type d -exec chmod 0755 {} \;
cp -r /tmp/wordpress/* /var/www/html
chown -R $user:nginx /var/www/html
find /var/www/html -type f -exec chmod 0640 {} \;
find /var/www/html -type d -exec chmod 0750 {} \;
cp -r ./bw-data/configs/* /etc/bunkerweb/configs
chown -R nginx:nginx /etc/bunkerweb/configs
find /etc/bunkerweb/configs -type f -exec chmod 0644 {} \;
find /etc/bunkerweb/configs -type d -exec chmod 0755 {} \;

View file

@ -8,5 +8,5 @@ AUTO_LETS_ENCRYPT=yes
USE_CLIENT_CACHE=yes
USE_GZIP=yes
LOCAL_PHP=/run/php/php-fpm.sock
LOCAL_PHP_PATH=/opt/bunkerweb/www
LOCAL_PHP_PATH=/var/www/html
MAX_CLIENT_SIZE=50m

View file

@ -1,40 +0,0 @@
version: "3"
services:
mybunker:
image: bunkerity/bunkerweb:1.4.3
ports:
- 80:8080
- 443:8443
environment:
- MULTISITE=yes
- SERVER_NAME=
- API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24
- AUTOCONF_MODE=yes
- AUTO_LETS_ENCRYPT=yes # will be applied to all the services
labels:
- "bunkerweb.INSTANCE"
networks:
- bw-autoconf
- bw-services
myautoconf:
image: bunkerity/bunkerweb-autoconf:1.4.3
volumes:
- ./bw-data:/data
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- bw-autoconf
volumes:
bw-data:
networks:
bw-autoconf:
ipam:
driver: default
config:
- subnet: 10.20.30.0/24
bw-services:
name: bw-services

View file

@ -1,12 +0,0 @@
#!/bin/bash
if [ $(id -u) -ne 0 ] ; then
echo "❌ Run me as root"
exit 1
fi
if [ -d bw-data ] ; then
mkdir bw-data
fi
chown -R root:101 bw-data
chmod -R 770 bw-data

View file

@ -1,120 +0,0 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: bunkerweb
spec:
selector:
matchLabels:
app: bunkerweb
template:
metadata:
labels:
app: bunkerweb
# mandatory annotation
annotations:
bunkerweb.io/INSTANCE: "yes"
spec:
containers:
- name: bunkerweb
image: bunkerity/bunkerweb:1.4.3
imagePullPolicy: Always
securityContext:
runAsUser: 101
runAsGroup: 101
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
ports:
- containerPort: 8080
hostPort: 80
- containerPort: 8443
hostPort: 443
env:
- name: KUBERNETES_MODE
value: "yes"
# replace with your DNS resolvers
# e.g. : kube-dns.kube-system.svc.cluster.local
- name: DNS_RESOLVERS
value: "coredns.kube-system.svc.cluster.local"
- name: USE_API
value: "yes"
# 10.0.0.0/8 is the cluster internal subnet
- name: API_WHITELIST_IP
value: "127.0.0.0/8 10.0.0.0/8"
- name: SERVER_NAME
value: ""
- name: MULTISITE
value: "yes"
livenessProbe:
exec:
command:
- /opt/bunkerweb/helpers/healthcheck.sh
initialDelaySeconds: 30
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 3
readinessProbe:
exec:
command:
- /opt/bunkerweb/helpers/healthcheck.sh
initialDelaySeconds: 30
periodSeconds: 1
timeoutSeconds: 1
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: svc-bunkerweb
spec:
clusterIP: None
selector:
app: bunkerweb
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-bunkerweb
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: ""
volumeName: pv-bunkerweb
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: bunkerweb-controller
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: bunkerweb-controller
template:
metadata:
labels:
app: bunkerweb-controller
spec:
serviceAccountName: sa-bunkerweb
volumes:
- name: vol-bunkerweb
persistentVolumeClaim:
claimName: pvc-bunkerweb
containers:
- name: bunkerweb-controller
image: bunkerity/bunkerweb-autoconf:1.4.3
imagePullPolicy: Always
env:
- name: KUBERNETES_MODE
value: "yes"
volumeMounts:
- name: vol-bunkerweb
mountPath: /data
nodeSelector:
kubernetes.io/hostname: srv1

View file

@ -1,30 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cr-bunkerweb
rules:
- apiGroups: [""]
resources: ["services", "pods", "configmaps"]
verbs: ["get", "watch", "list"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "watch", "list"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-bunkerweb
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: crb-bunkerweb
subjects:
- kind: ServiceAccount
name: sa-bunkerweb
namespace: default
apiGroup: ""
roleRef:
kind: ClusterRole
name: cr-bunkerweb
apiGroup: rbac.authorization.k8s.io

View file

@ -1,61 +0,0 @@
version: "3.5"
services:
mybunker:
image: bunkerity/bunkerweb:1.4.3
ports:
- published: 80
target: 8080
mode: host
protocol: tcp
- published: 443
target: 8443
mode: host
protocol: tcp
environment:
- SWARM_MODE=yes
- SERVER_NAME=
- MULTISITE=yes
- API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24
- AUTO_LETS_ENCRYPT=yes # will be applied to all the services
networks:
- bw-autoconf
- bw-services
deploy:
mode: global
# placement:
# constraints:
# - "node.role==worker"
labels:
- "bunkerweb.INSTANCE"
myautoconf:
image: bunkerity/bunkerweb-autoconf:1.4.3
environment:
- SWARM_MODE=yes
volumes:
- bw-data:/data
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- bw-autoconf
deploy:
replicas: 1
placement:
constraints:
- "node.role==manager"
networks:
bw-autoconf:
driver: overlay
attachable: true
name: bw-autoconf
ipam:
config:
- subnet: 10.20.30.0/24
bw-services:
driver: overlay
attachable: true
name: bw-services
volumes:
bw-data:

View file

@ -1,7 +0,0 @@
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

View file

@ -1,31 +0,0 @@
#!/bin/bash
#
# A shell option that causes the shell to exit immediately if a command exits with a non-zero status.
set -e
#
# function to stop bunkerweb
function stopBunker()
{
echo "Stopping Bunkerweb service ..."
# Stop bunkerweb service
systemctl stop bunkerweb
}
function stopUI()
{
echo "Stopping bunkerweb-ui service ..."
# Stop flask server
systemctl stop bunkerweb-ui
echo "Done !"
}
#
# Check if bunkerweb service is running
if systemctl is-active --quiet bunkerweb; then
# Stop bunkerweb service
stopBunker
fi
# Check if bunkerweb-ui service is running
if systemctl is-active --quiet bunkerweb-ui; then
# Stop ui service
stopUI
fi

View file

@ -1,3 +0,0 @@
ADMIN_USERNAME=admin
ADMIN_PASSWORD=changeme
ABSOLUTE_URI=http://localhost:5000

View file

@ -1,3 +0,0 @@
HTTP_PORT=80
HTTPS_PORT=443
DNS_RESOLVERS=8.8.8.8 8.8.4.4

View file

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -1,57 +0,0 @@
FROM python:3.11-alpine
# Copy python requirements
COPY bw/deps/requirements.txt /opt/bunkerweb/deps/requirements.txt
# Install python requirements
RUN apk add --no-cache --virtual build py3-pip g++ gcc python3-dev musl-dev libffi-dev openssl-dev cargo && \
pip install --no-cache-dir --upgrade pip && \
pip install wheel && \
mkdir /opt/bunkerweb/deps/python && \
pip install --no-cache-dir --require-hashes --target /opt/bunkerweb/deps/python -r /opt/bunkerweb/deps/requirements.txt && \
apk del build
# Copy files
# can't exclude specific files/dir from . so we are copying everything by hand
COPY scheduler /opt/bunkerweb/scheduler
COPY bw/api /opt/bunkerweb/api
COPY bw/confs /opt/bunkerweb/confs
COPY bw/core /opt/bunkerweb/core
COPY bw/gen /opt/bunkerweb/gen
COPY bw/helpers /opt/bunkerweb/helpers
COPY bw/settings.json /opt/bunkerweb/settings.json
COPY db /opt/bunkerweb/db
COPY utils /opt/bunkerweb/utils
COPY VERSION /opt/bunkerweb/VERSION
# Add scheduler user, install runtime dependencies, create data folders and set permissions
RUN apk add --no-cache bash libgcc libstdc++ openssl git && \
ln -s /usr/local/bin/python3 /usr/bin/python3 && \
addgroup -g 101 scheduler && \
adduser -h /var/cache/nginx -g scheduler -s /bin/sh -G scheduler -D -H -u 101 scheduler && \
echo "Docker" > /opt/bunkerweb/INTEGRATION && \
for dir in $(echo "cache configs configs/http configs/stream configs/server-http configs/server-stream configs/default-server-http configs/default-server-stream configs/modsec configs/modsec-crs cache/letsencrypt plugins www") ; do mkdir -p "/data/${dir}" && ln -s "/data/${dir}" "/opt/bunkerweb/${dir}" ; done && \
chown -R scheduler:scheduler /data && \
chmod -R 770 /data && \
mkdir /opt/bunkerweb/tmp && \
chown -R scheduler:scheduler /opt/bunkerweb && \
find /opt/bunkerweb -type f -exec chmod 0740 {} \; && \
find /opt/bunkerweb -type d -exec chmod 0750 {} \; && \
chmod 770 /opt/bunkerweb/tmp && \
chmod 750 /opt/bunkerweb/gen/*.py /opt/bunkerweb/scheduler/main.py /opt/bunkerweb/scheduler/entrypoint.sh /opt/bunkerweb/helpers/*.sh /opt/bunkerweb/deps/python/bin/* && \
find /opt/bunkerweb/core/*/jobs/* -type f -exec chmod 750 {} \; && \
mkdir /etc/nginx && \
chown -R scheduler:scheduler /etc/nginx && \
chmod -R 770 /etc/nginx && \
chmod 660 /opt/bunkerweb/INTEGRATION
# Fix CVEs
RUN apk add "libssl1.1>=1.1.1q-r0" "libcrypto1.1>=1.1.1q-r0" "git>=2.32.3-r0" "ncurses-libs>=6.2_p20210612-r1" "ncurses-terminfo-base>=6.2_p20210612-r1" "libtirpc>=1.3.2-r1" "libtirpc-conf>=1.3.2-r1" "zlib>=1.2.12-r2" "libxml2>=2.9.14-r1"
VOLUME /data /etc/nginx
WORKDIR /opt/bunkerweb/scheduler
USER root:scheduler
ENTRYPOINT ["/opt/bunkerweb/scheduler/entrypoint.sh"]

View file

@ -1,55 +0,0 @@
#!/bin/bash
. /opt/bunkerweb/helpers/utils.sh
if [ -f /opt/bunkerweb/tmp/scheduler.pid ] ; then
rm -f /opt/bunkerweb/tmp/scheduler.pid
fi
# setup and check /data folder
/opt/bunkerweb/helpers/data.sh "ENTRYPOINT"
# trap SIGTERM and SIGINT
function trap_exit() {
log "ENTRYPOINT" " " "Catched stop operation"
if [ -f "/opt/bunkerweb/tmp/scheduler.pid" ] ; then
log "ENTRYPOINT" " " "Stopping job scheduler ..."
kill -s TERM "$(cat /opt/bunkerweb/tmp/scheduler.pid)"
fi
}
trap "trap_exit" TERM INT QUIT
# trap SIGHUP
function trap_reload() {
log "ENTRYPOINT" " " "Catched reload operation"
/opt/bunkerweb/helpers/scheduler-restart.sh
if [ $? -ne 0 ] ; then
log "ENTRYPOINT" " " "Error while restarting scheduler"
fi
}
trap "trap_reload" HUP
if [ "$SWARM_MODE" == "yes" ] ; then
echo "Swarm" > /opt/bunkerweb/INTEGRATION
elif [ "$KUBERNETES_MODE" == "yes" ] ; then
echo "Kubernetes" > /opt/bunkerweb/INTEGRATION
elif [ "$AUTOCONF_MODE" == "yes" ] ; then
echo "Autoconf" > /opt/bunkerweb/INTEGRATION
fi
if ! grep -q "Docker" /opt/bunkerweb/INTEGRATION ; then
# Init database
get_env > "/tmp/variables.env"
/opt/bunkerweb/gen/save_config.py --variables /tmp/variables.env --init
if [ "$?" -ne 0 ] ; then
log "ENTRYPOINT" "❌" "Scheduler generator failed"
exit 1
fi
fi
# execute jobs
log "ENTRYPOINT" " " "Executing scheduler ..."
/opt/bunkerweb/scheduler/main.py
log "ENTRYPOINT" " " "Scheduler stopped"
exit 0

1
src/VERSION Normal file
View file

@ -0,0 +1 @@
1.4.4

45
src/autoconf/Dockerfile Normal file
View file

@ -0,0 +1,45 @@
FROM python:3.11-alpine
# Copy python requirements
COPY src/common/deps/requirements.txt /usr/share/bunkerweb/deps/requirements.txt
# Install dependencies
RUN apk add --no-cache --virtual build g++ gcc python3-dev musl-dev libffi-dev openssl-dev cargo && \
pip install --no-cache-dir --upgrade pip && \
pip install wheel && \
mkdir /usr/share/bunkerweb/deps/python && \
pip install --no-cache-dir --require-hashes --target /usr/share/bunkerweb/deps/python -r /usr/share/bunkerweb/deps/requirements.txt && \
apk del build
# Copy files
# can't exclude specific files/dir from . so we are copying everything by hand
COPY src/autoconf /usr/share/bunkerweb/autoconf
COPY src/common/api /usr/share/bunkerweb/api
COPY src/common/cli /usr/share/bunkerweb/cli
COPY src/common/core /usr/share/bunkerweb/core
COPY src/common/db /usr/share/bunkerweb/db
COPY src/common/helpers /usr/share/bunkerweb/helpers
COPY src/common/settings.json /usr/share/bunkerweb/settings.json
COPY src/common/utils /usr/share/bunkerweb/utils
# Add nginx user, drop bwcli, setup data folders, permissions and logging
RUN apk add --no-cache bash && \
addgroup -g 101 nginx && \
adduser -h /var/cache/nginx -g nginx -s /bin/sh -G nginx -D -H -u 101 nginx && \
cp /usr/share/bunkerweb/helpers/bwcli /usr/bin/ && \
chown -R nginx:nginx /usr/share/bunkerweb && \
find /usr/share/bunkerweb -type f -exec chmod 0740 {} \; && \
find /usr/share/bunkerweb -type d -exec chmod 0750 {} \; && \
chmod 750 /usr/share/bunkerweb/cli/main.py /usr/share/bunkerweb/helpers/*.sh /usr/bin/bwcli /usr/share/bunkerweb/autoconf/main.py /usr/share/bunkerweb/deps/python/bin/* && \
chown root:nginx /usr/bin/bwcli
# Fix CVEs
RUN apk add "libssl1.1>=1.1.1q-r0" "libcrypto1.1>=1.1.1q-r0" "git>=2.32.3-r0" "ncurses-libs>=6.2_p20210612-r1" "ncurses-terminfo-base>=6.2_p20210612-r1" "libtirpc>=1.3.2-r1" "libtirpc-conf>=1.3.2-r1" "zlib>=1.2.12-r2" "libxml2>=2.9.14-r1"
VOLUME /data /etc/nginx
WORKDIR /usr/share/bunkerweb/autoconf
USER root:nginx
CMD ["python3", "/usr/share/bunkerweb/autoconf/main.py"]

View file

@ -5,10 +5,10 @@ from signal import SIGINT, SIGTERM, signal
from sys import exit as sys_exit, path as sys_path
from traceback import format_exc
sys_path.append("/opt/bunkerweb/deps/python")
sys_path.append("/opt/bunkerweb/utils")
sys_path.append("/opt/bunkerweb/api")
sys_path.append("/opt/bunkerweb/db")
sys_path.append("/usr/share/bunkerweb/deps/python")
sys_path.append("/usr/share/bunkerweb/utils")
sys_path.append("/usr/share/bunkerweb/api")
sys_path.append("/usr/share/bunkerweb/db")
from logger import setup_logger
from SwarmController import SwarmController

88
src/bw/Dockerfile Normal file
View file

@ -0,0 +1,88 @@
FROM nginx:1.20.2-alpine AS builder
# Copy dependencies sources folder
COPY src/common/deps /tmp/bunkerweb/deps
# Compile and install dependencies
RUN apk add --no-cache --virtual build bash build autoconf libtool automake geoip-dev g++ gcc curl-dev libxml2-dev pcre-dev make linux-headers musl-dev gd-dev gnupg brotli-dev openssl-dev patch readline-dev && \
mkdir -p /usr/share/bunkerweb/deps && \
chmod +x /tmp/bunkerweb/deps/install.sh && \
bash /tmp/bunkerweb/deps/install.sh && \
apk del build
# Copy python requirements
COPY src/common/deps/requirements.txt /usr/share/bunkerweb/deps/requirements.txt
# Install python requirements
RUN apk add --no-cache --virtual build py3-pip g++ gcc python3-dev musl-dev libffi-dev openssl-dev cargo && \
pip install --no-cache-dir --upgrade pip && \
pip install wheel && \
mkdir /usr/share/bunkerweb/deps/python && \
pip install --no-cache-dir --require-hashes --target /usr/share/bunkerweb/deps/python -r /usr/share/bunkerweb/deps/requirements.txt && \
apk del build
FROM nginx:1.20.2-alpine
# Copy dependencies
COPY --from=builder /usr/share/bunkerweb /usr/share/bunkerweb
# Copy files
# can't exclude deps from . so we are copying everything by hand
COPY src/bw/loading /usr/share/bunkerweb/loading
COPY src/bw/lua /usr/share/bunkerweb/lua
COPY src/bw/misc /usr/share/bunkerweb/misc
COPY src/common/api /usr/share/bunkerweb/api
COPY src/common/cli /usr/share/bunkerweb/cli
COPY src/common/confs /usr/share/bunkerweb/confs
COPY src/common/core /usr/share/bunkerweb/core
COPY src/common/db /usr/share/bunkerweb/db
COPY src/common/gen /usr/share/bunkerweb/gen
COPY src/common/helpers /usr/share/bunkerweb/helpers
COPY src/common/settings.json /usr/share/bunkerweb/settings.json
COPY src/common/utils /usr/share/bunkerweb/utils
COPY src/VERSION /usr/share/bunkerweb/VERSION
# Install runtime dependencies, pypi packages, move bwcli, create data folders and set permissions
RUN apk add --no-cache bash python3 && \
cp /usr/share/bunkerweb/helpers/bwcli /usr/bin/ && \
echo "Docker" > /usr/share/bunkerweb/INTEGRATION && \
mkdir -p /var/tmp/bunkerweb && \
mkdir -p /var/www && \
mkdir -p /etc/bunkerweb && \
mkdir -p /data/cache && ln -s /data/cache /var/cache/bunkerweb && \
mkdir -p /data/cache/letsencrypt && ln -s /data/cache/letsencrypt /etc/letsencrypt && \
mkdir -p /data/www && ln -s /data/www /var/www/html && \
for dir in $(echo "configs plugins") ; do mkdir -p "/data/${dir}" && ln -s "/data/${dir}" "/etc/bunkerweb/${dir}" ; done && \
for dir in $(echo "configs/http configs/stream configs/server-http configs/server-stream configs/default-server-http configs/default-server-stream configs/modsec configs/modsec-crs") ; do mkdir "/data/${dir}" ; done && \
chown -R root:nginx /data && \
chmod -R 770 /data && \
chown -R root:nginx /usr/share/bunkerweb /var/cache/bunkerweb /etc/bunkerweb /var/tmp/bunkerweb /usr/bin/bwcli && \
for dir in $(echo "/usr/share/bunkerweb /etc/bunkerweb") ; do find ${dir} -type f -exec chmod 0740 {} \; ; done && \
for dir in $(echo "/usr/share/bunkerweb /etc/bunkerweb") ; do find ${dir} -type d -exec chmod 0750 {} \; ; done && \
chmod 770 /var/cache/bunkerweb /var/tmp/bunkerweb && \
chmod 750 /usr/share/bunkerweb/cli/main.py /usr/share/bunkerweb/gen/main.py /usr/share/bunkerweb/helpers/*.sh /usr/bin/bwcli /usr/share/bunkerweb/deps/python/bin/* && \
chown -R root:nginx /etc/nginx && \
chmod -R 770 /etc/nginx && \
rm -f /var/log/nginx/* && \
mkdir /var/log/letsencrypt /var/lib/letsencrypt && \
chown root:nginx /var/log/letsencrypt /var/lib/letsencrypt && \
chmod 770 /var/log/letsencrypt /var/lib/letsencrypt && \
ln -s /proc/1/fd/2 /var/log/nginx/error.log && \
ln -s /proc/1/fd/2 /var/log/nginx/modsec_audit.log && \
ln -s /proc/1/fd/1 /var/log/nginx/access.log && \
ln -s /proc/1/fd/1 /var/log/nginx/jobs.log && \
ln -s /proc/1/fd/1 /var/log/letsencrypt/letsencrypt.log && \
chmod 660 /usr/share/bunkerweb/INTEGRATION
# Fix CVEs
RUN apk add "freetype>=2.10.4-r3" "curl>=7.79.1-r2" "libcurl>=7.79.1-r2" "openssl>=1.1.1q-r0" "libssl1.1>=1.1.1q-r0" "libcrypto1.1>=1.1.1q-r0" "git>=2.32.3-r0" "ncurses-libs>=6.2_p20210612-r1" "ncurses-terminfo-base>=6.2_p20210612-r1" "zlib>=1.2.12-r2" "libxml2>=2.9.14-r1"
VOLUME /data /etc/nginx
EXPOSE 8080/tcp 8443/tcp
USER nginx:nginx
HEALTHCHECK --interval=10s --timeout=10s --start-period=10s --retries=6 CMD /usr/share/bunkerweb/helpers/healthcheck.sh
ENTRYPOINT ["/usr/share/bunkerweb/helpers/entrypoint.sh"]

View file

@ -18,33 +18,6 @@ api.global.GET["^/ping$"] = function(api)
return api:response(ngx.HTTP_OK, "success", "pong")
end
api.global.POST["^/jobs$"] = function(api)
-- ngx.req.read_body()
-- local data = ngx.req.get_body_data()
-- if not data then
-- local data_file = ngx.req.get_body_file()
-- if data_file then
-- local file = io.open(data_file)
-- data = file:read("*a")
-- file:close()
-- end
-- end
-- local ok, env = pcall(cjson.decode, data)
-- if not ok then
-- return api:response(ngx.HTTP_INTERNAL_SERVER_ERROR, "error", "can't decode JSON : " .. env)
-- end
-- local file = io.open("/opt/bunkerweb/tmp/jobs.env", "w+")
-- for k, v in pairs(env) do
-- file:write(k .. "=" .. v .. "\n")
-- end
-- file:close()
local status = os.execute("/opt/bunkerweb/helpers/scheduler-restart.sh")
if status == 0 then
return api:response(ngx.HTTP_OK, "success", "jobs executed and scheduler started")
end
return api:response(ngx.HTTP_INTERNAL_SERVER_ERROR, "error", "exit status = " .. tostring(status))
end
api.global.POST["^/reload$"] = function(api)
local status = os.execute("/usr/sbin/nginx -s reload")
if status == 0 then
@ -62,8 +35,8 @@ api.global.POST["^/stop$"] = function(api)
end
api.global.POST["^/confs$"] = function(api)
local tmp = "/opt/bunkerweb/tmp/api_" .. ngx.var.uri:sub(2) .. ".tar.gz"
local destination = "/opt/bunkerweb/" .. ngx.var.uri:sub(2)
local tmp = "/var/tmp/bunkerweb/api_" .. ngx.var.uri:sub(2) .. ".tar.gz"
local destination = "/usr/share/bunkerweb/" .. ngx.var.uri:sub(2)
if ngx.var.uri == "/confs" then
destination = "/etc/nginx"
elseif ngx.var.uri == "/data" then

6
src/bw/lua/mmdb.lua Normal file
View file

@ -0,0 +1,6 @@
local geoip = require "geoip.mmdb"
return {
country_db = geoip.load_database("/var/cache/bunkerweb/country.mmdb"),
asn_db = geoip.load_database("/var/cache/bunkerweb/asn.mmdb")
}

View file

@ -1,9 +1,9 @@
local datastore = require "datastore"
local ipmatcher = require "resty.ipmatcher"
local cjson = require "cjson"
local resolver = require "resty.dns.resolver"
local mmdb = require "mmdb"
local logger = require "logger"
local datastore = require "datastore"
local ipmatcher = require "resty.ipmatcher"
local cjson = require "cjson"
local resolver = require "resty.dns.resolver"
local mmdb = require "mmdb"
local logger = require "logger"
local utils = {}
@ -26,7 +26,7 @@ utils.set_values = function()
"240.0.0.0/4",
"255.255.255.255/32"
}
local ok, err = datastore:set("misc_reserved_ips", cjson.encode({data = reserved_ips}))
local ok, err = datastore:set("misc_reserved_ips", cjson.encode({ data = reserved_ips }))
if not ok then
return false, err
end
@ -223,7 +223,7 @@ utils.get_version = function()
if version then
return version
end
local f, err = io.open("/opt/bunkerweb/VERSION", "r")
local f, err = io.open("/usr/share/bunkerweb/VERSION", "r")
if not f then
logger.log(ngx.ERR, "UTILS", "Can't read VERSION file : " .. err)
return "unknown"
@ -260,7 +260,7 @@ utils.get_rdns = function(ip)
return false, err
end
local resolvers = cjson.decode(str_resolvers)
local rdns, err = resolver:new{
local rdns, err = resolver:new {
nameservers = resolvers,
retrans = 1,
timeout = 1000
@ -289,7 +289,7 @@ utils.get_ips = function(fqdn, resolvers)
return false, err
end
local resolvers = cjson.decode(str_resolvers)
local rdns, err = resolver:new{
local rdns, err = resolver:new {
nameservers = resolvers,
retrans = 1,
timeout = 1000
@ -343,8 +343,8 @@ end
utils.rand = function(nb)
local charset = {}
for i = 48, 57 do table.insert(charset, string.char(i)) end
for i = 65, 90 do table.insert(charset, string.char(i)) end
for i = 48, 57 do table.insert(charset, string.char(i)) end
for i = 65, 90 do table.insert(charset, string.char(i)) end
for i = 97, 122 do table.insert(charset, string.char(i)) end
local result = ""
for i = 1, nb do
@ -353,7 +353,7 @@ utils.rand = function(nb)
return result
end
utils.get_deny_status = function ()
utils.get_deny_status = function()
local status, err = datastore:get("variable_DENY_HTTP_STATUS")
if not status then
logger.log(ngx.ERR, "UTILS", "Can't get DENY_HTTP_STATUS variable " .. err)
@ -362,4 +362,4 @@ utils.get_deny_status = function ()
return tonumber(status)
end
return utils
return utils

View file

@ -5,10 +5,10 @@ from os import _exit
from sys import exit as sys_exit, path
from traceback import format_exc
path.append("/opt/bunkerweb/deps/python")
path.append("/opt/bunkerweb/cli")
path.append("/opt/bunkerweb/utils")
path.append("/opt/bunkerweb/api")
path.append("/usr/share/bunkerweb/deps/python")
path.append("/usr/share/bunkerweb/cli")
path.append("/usr/share/bunkerweb/utils")
path.append("/usr/share/bunkerweb/api")
from logger import setup_logger
from CLI import CLI

View file

@ -12,7 +12,7 @@ server {
{% if IS_LOADING == "yes" +%}
root /opt/bunkerweb/loading;
root /usr/share/bunkerweb/loading;
index index.html;
{% endif %}
@ -20,7 +20,7 @@ server {
include /etc/nginx/default-server-http/*.conf;
# include custom default-server configurations
include /opt/bunkerweb/configs/default-server-http/*.conf;
include /etc/bunkerweb/configs/default-server-http/*.conf;
log_by_lua_block {

View file

@ -18,11 +18,11 @@ log_format logf '{{ LOG_FORMAT }}';
access_log /var/log/nginx/access.log logf;
# temp paths
proxy_temp_path /opt/bunkerweb/tmp/proxy_temp;
client_body_temp_path /opt/bunkerweb/tmp/client_temp;
fastcgi_temp_path /opt/bunkerweb/tmp/fastcgi_temp;
uwsgi_temp_path /opt/bunkerweb/tmp/uwsgi_temp;
scgi_temp_path /opt/bunkerweb/tmp/scgi_temp;
proxy_temp_path /var/tmp/bunkerweb/proxy_temp;
client_body_temp_path /var/tmp/bunkerweb/client_temp;
fastcgi_temp_path /var/tmp/bunkerweb/fastcgi_temp;
uwsgi_temp_path /var/tmp/bunkerweb/uwsgi_temp;
scgi_temp_path /var/tmp/bunkerweb/scgi_temp;
# close connections in FIN_WAIT1 state
reset_timedout_connection on;
@ -40,9 +40,9 @@ resolver {{ DNS_RESOLVERS }} ipv6=off;
port_in_redirect off;
# lua path and dicts
lua_package_path "/opt/bunkerweb/lua/?.lua;/opt/bunkerweb/core/?.lua;/opt/bunkerweb/plugins/?.lua;/opt/bunkerweb/deps/lib/lua/?.lua;;";
lua_package_cpath "/opt/bunkerweb/deps/lib/?.so;/opt/bunkerweb/deps/lib/lua/?.so;;";
lua_ssl_trusted_certificate "/opt/bunkerweb/misc/root-ca.pem";
lua_package_path "/usr/share/bunkerweb/lua/?.lua;/usr/share/bunkerweb/core/?.lua;/etc/bunkerweb/plugins/?.lua;/usr/share/bunkerweb/deps/lib/lua/?.lua;;";
lua_package_cpath "/usr/share/bunkerweb/deps/lib/?.so;/usr/share/bunkerweb/deps/lib/lua/?.so;;";
lua_ssl_trusted_certificate "/usr/share/bunkerweb/misc/root-ca.pem";
lua_ssl_verify_depth 2;
lua_shared_dict datastore {{ DATASTORE_MEMORY_SIZE }};

View file

@ -71,7 +71,7 @@ if value == "yes" then
end
-- Load plugins into the datastore
local plugin_paths = {"/opt/bunkerweb/core", "/opt/bunkerweb/plugins"}
local plugin_paths = {"/usr/share/bunkerweb/core", "/etc/bunkerweb/plugins"}
for i, plugin_path in ipairs(plugin_paths) do
local paths = io.popen("find -L " .. plugin_path .. " -maxdepth 1 -type d ! -path " .. plugin_path)
for path in paths:lines() do

View file

@ -1,18 +1,18 @@
# /etc/nginx/nginx.conf
# load dynamic modules
load_module /opt/bunkerweb/modules/ngx_http_cookie_flag_filter_module.so;
#load_module /opt/bunkerweb/modules/ngx_http_geoip2_module.so;
load_module /opt/bunkerweb/modules/ngx_http_headers_more_filter_module.so;
load_module /opt/bunkerweb/modules/ngx_http_lua_module.so;
load_module /opt/bunkerweb/modules/ngx_http_modsecurity_module.so;
load_module /opt/bunkerweb/modules/ngx_http_brotli_filter_module.so;
load_module /opt/bunkerweb/modules/ngx_http_brotli_static_module.so;
#load_module /opt/bunkerweb/modules/ngx_stream_geoip2_module.so;
#load_module /opt/bunkerweb/modules/ngx_stream_lua_module.so;
load_module /usr/share/bunkerweb/modules/ngx_http_cookie_flag_filter_module.so;
#load_module /usr/share/bunkerweb/modules/ngx_http_geoip2_module.so;
load_module /usr/share/bunkerweb/modules/ngx_http_headers_more_filter_module.so;
load_module /usr/share/bunkerweb/modules/ngx_http_lua_module.so;
load_module /usr/share/bunkerweb/modules/ngx_http_modsecurity_module.so;
load_module /usr/share/bunkerweb/modules/ngx_http_brotli_filter_module.so;
load_module /usr/share/bunkerweb/modules/ngx_http_brotli_static_module.so;
#load_module /usr/share/bunkerweb/modules/ngx_stream_geoip2_module.so;
#load_module /usr/share/bunkerweb/modules/ngx_stream_lua_module.so;
# PID file
pid /opt/bunkerweb/tmp/nginx.pid;
pid /var/tmp/bunkerweb/nginx.pid;
# worker number (default = auto)
worker_processes {{ WORKER_PROCESSES }};
@ -45,7 +45,7 @@ http {
include /etc/nginx/http/*.conf;
# include custom http configurations
include /opt/bunkerweb/configs/http/*.conf;
include /etc/bunkerweb/configs/http/*.conf;
}
#stream {
@ -56,5 +56,5 @@ http {
# include /etc/nginx/stream/*.conf;
# include custom stream configurations
# include /opt/bunkerweb/configs/stream/*.conf;
# include /etc/bunkerweb/configs/stream/*.conf;
#}

Some files were not shown because too many files have changed in this diff Show more