Building libModSecurity v3 from source

libModSecurity is a C++17 library. On Unix-like systems it is built with autotools; Windows builds use CMake and Conan and are described in the Windows build README. The library does nothing on its own: after installing it, add a connector for your web server, see libModSecurity v3 with NGINX and libModSecurity v3 with Apache.

If you only need a working installation, your distribution most likely packages the library and the NGINX connector already; see Distribution packages for libModSecurity v3. Build from source when you need the current release before your distribution ships it, a build option the package does not enable (LMDB, Lua, ssdeep), or the development branch.

Dependencies

LibraryStatusWhat it enables
C++17 compiler, GNU autotools, pkg-configrequiredthe build itself
YAJL 2.xrequiredJSON request bodies, JSON audit log, the test suite
PCRE2 (libpcre2-8)required, default@rx and every other regular-expression user. Legacy PCRE 8.x is used instead only with --with-pcre
libxml2 >= 2.6.29optional, auto-detectedXML request body processor, XML variable, @validateDTD, @validateSchema
libcurl >= 7.15.1optional, auto-detectedSecRemoteRules, remote @pmFromFile/@ipMatchFromFile files, the Status Engine
Lua 5.1 to 5.5 or LuaJIToptional, auto-detectedSecRuleScript, exec and @inspectFile with Lua scripts
libmaxminddboptional, auto-detected@geoLookup with GeoLite2/GeoIP2 databases
libfuzzy (ssdeep)optional, auto-detected@fuzzyHash
LMDBoptional, opt-inon-disk persistent collections (SecDataDir); without it collections live in process memory
Flex and Bisononly with --enable-parser-generationregenerating the SecLang parser; the release tarball and the git tree ship a generated parser

When an optional library is missing, the corresponding operator or directive is compiled out and a configuration using it fails to load. LMDB is special: even when the library is installed, it is not used unless you pass --with-lmdb explicitly.

Warning

The legacy MaxMind GeoIP C API (libGeoIP, --with-geoip) is still accepted but deprecated and no longer maintained upstream. Use libmaxminddb with a GeoLite2 or GeoIP2 database instead.

The git tree also carries submodules under others/: libinjection (@detectSQLi, @detectXSS) and mbedtls (hashing and base64 helpers). Both are required for a source build and must be initialized after cloning; the release tarball bundles them.

Package names for the development headers, for the two most common families:

# Debian and Ubuntu
sudo apt install build-essential automake libtool pkg-config libyajl-dev libpcre2-dev libxml2-dev \
    libcurl4-openssl-dev liblua5.4-dev libmaxminddb-dev libfuzzy-dev liblmdb-dev
# Fedora, RHEL and EPEL
sudo dnf install gcc-c++ automake libtool pkgconf yajl-devel pcre2-devel libxml2-devel \
    libcurl-devel lua-devel libmaxminddb-devel ssdeep-devel lmdb-devel

Get the source

Stable release (recommended). The current release is v3.0.17. The release tarball already bundles the git submodules and is signed:

wget https://github.com/owasp-modsecurity/ModSecurity/releases/download/v3.0.17/modsecurity-v3.0.17.tar.gz
wget https://github.com/owasp-modsecurity/ModSecurity/releases/download/v3.0.17/modsecurity-v3.0.17.tar.gz.sha256
wget https://github.com/owasp-modsecurity/ModSecurity/releases/download/v3.0.17/modsecurity-v3.0.17.tar.gz.asc
sha256sum -c modsecurity-v3.0.17.tar.gz.sha256
gpg --verify modsecurity-v3.0.17.tar.gz.asc modsecurity-v3.0.17.tar.gz
tar xzf modsecurity-v3.0.17.tar.gz
cd modsecurity-v3.0.17

Development branch. For the latest code, clone v3/master and initialize the submodules:

git clone --branch v3/master https://github.com/owasp-modsecurity/ModSecurity
cd ModSecurity
git submodule update --init --recursive

Verify that every submodule shows a commit hash in git submodule status; a leading - means it was not initialized and the build will fail.

Build

./build.sh        # git checkout only: generates the configure script
./configure
make
sudo make install

The library is installed under /usr/local/modsecurity by default (--prefix changes that). Because it is a dynamic library, that location must be known to the dynamic linker: add /usr/local/modsecurity/lib to /etc/ld.so.conf.d/ and run ldconfig, or set LD_LIBRARY_PATH. The modsecurity.pc file installed under lib/pkgconfig lets other software find the library through pkg-config.

Run the unit and regression tests after building:

make check

Configure options

Every optional library has a --with-NAME=PATH option that points at an installation prefix, and a --without-NAME form that disables the feature even when the library is present:

OptionDefaultEffect
--with-pcre2=PATHauto-detectedPCRE2, the regular-expression engine used by default
--with-pcre=PATHoffbuild against legacy PCRE 8.x instead of PCRE2
--with-yajl=PATHauto-detected, requiredYAJL location
--with-libxml=PATHauto-detectedlibxml2
--with-curl=PATHauto-detectedlibcurl; versions from 7.34.0 enable TLS 1.2 for remote rule downloads
--with-lua=PATHauto-detectedLua (5.1 to 5.5 or LuaJIT)
--with-maxmind=PATHauto-detectedlibmaxminddb for @geoLookup
--with-geoip=PATHauto-detectedlegacy libGeoIP for @geoLookup (deprecated)
--with-ssdeep=PATHauto-detectedlibfuzzy for @fuzzyHash
--with-lmdb[=PATH]offLMDB-backed persistent collections

Feature switches:

OptionDefaultEffect
--enable-parser-generationoffregenerate the SecLang parser with Flex and Bison instead of using the shipped one. Needed only when you change src/parser/*.yy or *.ll
--disable-examplesexamples builtskip the example programs in examples/
--disable-debug-logsdebug logs builtcompile SecDebugLog support out (NO_LOGS) for a slightly faster library; the regression tests cannot run without it
--enable-assertionsoffkeep assert() checks (undefines NDEBUG)
--enable-mutex-on-pmoffserialize @pm and @pmFromFile evaluation with a mutex; only for debugging suspected races in multi-threaded connectors
--enable-afl-fuzzoffbuild the AFL fuzzing utilities
--enable-valgrindoffrun the unit tests under Valgrind (--disable-valgrind-memcheck and friends select the tools)
--enable-doxygen-* / --disable-doxygen-*HTML onlywhich Doxygen outputs make doxygen-doc produces
Note

The output of ./configure --help is misleading for the library options: because of how they are generated, only --with-yajl is listed, but all of the --with-* options above are accepted. The summary that configure prints at the end shows which libraries were found.