logo
Apache Lounge
Webmasters

 

About Forum Index Downloads Search Register Log in RSS X


Keep Server Online

If you find the Apache Lounge, the downloads and overall help useful, please express your satisfaction with a donation.

or

Bitcoin

A donation makes a contribution towards the costs, the time and effort that's going in this site and building.

Thank You! Steffen

Your donations will help to keep this site alive and well, and continuing building binaries. Apache Lounge is not sponsored.
Post new topic   Forum Index -> How-to's & Documentation & Tips View previous topic :: View next topic
Reply to topic   Topic: HOWTO: Building ModSecurity using MSVC toolset
Author
tangent
Moderator


Joined: 16 Aug 2020
Posts: 400
Location: UK

PostPosted: Mon 03 Nov '25 18:13    Post subject: HOWTO: Building ModSecurity using MSVC toolset Reply with quote

This post is supplemental to, and dependent on, the related HOWTO "Building Apache and dependencies using CMake" https://www.apachelounge.com/viewtopic.php?t=8609
Specifically, it assumes the same build platform and toolset.

The intention is to track the mod_security build listed under the Apache Lounge download section, but allowing the user to customise build options if so desired. To that end, this build script is based around the 2.x (rather than the later 3.x) series of ModSecurity.

Additional configuration options are currently edited into the default apache2\Makefile.win file, including options for WITH_PCRE2, WITH_APU_CRYPTO and HTACCESS_CONFIG.

Note, this post does not cover configuring ModSecurity within Apache.

Change log :
03 Nov 2025 : 1.0 - Initial release.

Sequence
  1. Prerequisites
    Complete the Apache build process detailed in HOWTO "Building Apache and dependencies using CMake" - https://www.apachelounge.com/viewtopic.php?t=8609

  2. Preparation
    Add the following source folders based on the appropriate version of the following packages. This list matches the latest package versions at the time of writing.

    Code:
    C:\Development
       └ Apache24
          ├ src
          │   ├ modsecurity-2.9.12
          │   ├ yajl-2.1.0
          │
          └ build

  3. Source Packages
    Download and extract the above packages (*.tar.gz or *.zip format) into the corresponding source folders shown above. These packages can be download from GitHub, currently here:

    https://github.com/owasp-modsecurity/ModSecurity/tags
    https://github.com/lloyd/yajl/tags

  4. Build Batch File
    Download the build batch file code from the post below in this thread, and save it in the above 'build' folder as build_mod_security.bat

    a) Edit the build batch file to set BUILD_BASE as required, if using a different build path to that above.
    b) Update the target PREFIX, if the default location of C:\Apache24 isn't correct.
    c) Choose 32 or 64 bit builds by setting the PLATFORM variable in the build batch file to x86 or x64 as required, matching your Apache build.
    d) Similarly, set the variable BUILD_TYPE to Release or Debug.
    e) Update the path to the vcvarsall.bat file if need be, to match your Visual Studio toolset.
    f) Edit the package version details to match your downloads as appropriate.

  5. Build
    Open a command or Powershell window with administrative rights, change to the above build folder, and run the build_mod_security.bat batch file. Ideally, redirect the build process output to a log file so you can check for errors. If using Powershell, you can use the tee command, viz:

    Code:
    C:\Development\Apache24\build> .\build_mod_security.bat 2>&1 | tee build_mod_security.log

    N.B. A Windows native binary of tee can be found still at https://gnuwin32.sourceforge.net/packages/coreutils.htm

  6. Checks
    When finished search the log file output for fatal errors (hopefully none).

    Confirm the ModSecurity files have been created below PREFIX as expected, e.g.
    Code:
    C:\Development\apache24\build>dir C:\Apache24\modules\mod_security2.so
     Volume in drive C has no label.
     Volume Serial Number is 6874-FF76

     Directory of c:\Apache24\modules

    03/11/2025  15:52           743,936 mod_security2.so
                   1 File(s)        743,936 bytes
                   0 Dir(s)  65,599,393,792 bytes free

    C:\Development\apache24\build>dir c:\Apache24\conf\modsecurity*
     Volume in drive C has no label.
     Volume Serial Number is 6874-FF76

     Directory of c:\Apache24\conf

    05/08/2025  19:13             9,047 modsecurity.conf-recommended
                   1 File(s)          9,047 bytes
                   0 Dir(s)  65,599,393,792 bytes free

    Prepare and test your ModSecurity configuration within Apache as required.

    I hope people find this HOWTO useful.


Last edited by tangent on Mon 03 Nov '25 19:06; edited 3 times in total
Back to top
tangent
Moderator


Joined: 16 Aug 2020
Posts: 400
Location: UK

PostPosted: Mon 03 Nov '25 18:14    Post subject: Reply with quote

Change log :
03 Nov 2025 : 1.0 - Initial release.

Code:
@echo off

rem @(#)build_mod_security.bat 1.0 - 2025-11-03 tangent
rem
rem 1.0 - Initial release. 2025-11-03

rem These instructions build ModSecurity and YAJL, assuming you've already built Apache
rem HTTPD following the HOWTO details at https://www.apachelounge.com/viewtopic.php?t=8609
rem
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION

rem Set required build base folder and target prefix.
rem
set BUILD_BASE=C:\Development\Apache24\build
set PREFIX=C:\Apache24

rem Set required build platform to x86 or x64.
rem
rem set PLATFORM=x86
set PLATFORM=x64

rem Set required build type to Release or Debug.
rem
rem set BUILD_TYPE=Debug
set BUILD_TYPE=Release

rem Request PDB files - ON or OFF.
rem
set INSTALL_PDB=OFF

rem Define build packages with their version. This is also the recommended build order.
rem PCRE2 is supported with ModSecurity 2.9.8 onwards, as is LUA 5.4 series.
rem YAJL is an optional package for ModSecurity.
rem
set YAJL=yajl-2.1.0
set MOD_SECURITY=modsecurity-2.9.12

rem ------------------------------------------------------------------------------
rem
rem Define path to MS Visual Studio build environment script.

set VCVARSALL=C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat

if exist "%VCVARSALL%" (
  call "%VCVARSALL%" %PLATFORM%
) else (
  echo Could not find "%VCVARSALL%"
  exit /b
)

rem ------------------------------------------------------------------------------
rem
rem YAJL (for ModSecurity)

rem Check for package and switch to source folder.
rem
call :check_package_source %YAJL%

if !STATUS! == 0 (
  rem Patch relevant CMakeLists.txt file to adjust install locations.
  rem
  perl -pi.bak -e ^" ^
    s~(RUNTIME DESTINATION^) lib~${1} bin~; ^
    s~(DESTINATION^) share(/pkgconfig^)~${1} lib${2}~; ^
    ^" src\CMakeLists.txt

  set YAJL_CMAKE_OPTS=-DCMAKE_INSTALL_PREFIX=%PREFIX% -DCMAKE_BUILD_TYPE=%BUILD_TYPE%
  call :build_package %YAJL% "!YAJL_CMAKE_OPTS!" & if not !STATUS! == 0 exit /b !STATUS!
)

rem ------------------------------------------------------------------------------
rem
rem ModSecurity

rem Check for package and switch to source folder.
rem
call :check_package_source %MOD_SECURITY%

if !STATUS! == 0 (
  echo. & echo Building %MOD_SECURITY%

  rem Build from Makefile.win in apache2 sub-folder.
  rem
  pushd apache2

  rem Patch Makefile.win to revise various library and include paths.
  rem Notably, revise the LUA lua5.1.lib reference to lib54.lib.
  rem Add required build macros, and correct libinjection path.
  rem
  perl -pi.bak -e ^" ^
    s~(PCRE\^)\\^)(pcre^)(.lib \\^)\n~${1}lib\\${2}2-8${3}\n~; ^
    s~(CURL\^)\\^)(libcurl^)(.lib^)~${1}lib\\${2}_imp${3}~; ^
    s~(LIBXML2\^)\\^).+\\(libxml2^)(.lib^)~${1}lib\\${2}${3}~; ^
    s~(LIBXML2\^)\\include^) ~${1}\\libxml2~; ^
    s~(LIBS = .+^)\$\((LUA^)(.+^)~${1}\$\(LUA^)\\lib\\lua54.lib~; ^
    s~(APR_INLINE.+VERSION\^)$^)~${1} -DWITH_PCRE2 -DWITH_PCRE_JIT -DWITH_PCRE_STUDY -DWITH_APU_CRYPTO -DHTACCESS_CONFIG -D_CRT_SECURE_NO_WARNINGS~; ^
    s~(libinjection^)/~${1}\\~; ^
    ^" Makefile.win

  rem Set configure options.
  rem
  set MOD_SECURITY_CONFIGURE_OPTS=APACHE=%PREFIX% PCRE=%PREFIX% LIBXML2=%PREFIX% LUA=%PREFIX% CURL=%PREFIX% YAJL=%PREFIX%

  nmake /f Makefile.win !MOD_SECURITY_CONFIGURE_OPTS! clean
  nmake /f Makefile.win !MOD_SECURITY_CONFIGURE_OPTS! & call :get_status
  if !STATUS! == 0 (
    nmake /f Makefile.win !MOD_SECURITY_CONFIGURE_OPTS! install & call :get_status
    if not !STATUS! == 0 (
      echo nmake install for %MOD_SECURITY% failed with status !STATUS!
    ) else (
      rem Some additional manual installation is required.
      rem
      rem Define extra files as src_dir#src_file#dst_dir#dst_file
      rem If dst_file is missing, then use src_file as destination filename
      rem
      set EXTRAS=.#mod_security2.exp#%PREFIX%\lib ^
             .#mod_security2.lib#%PREFIX%\lib ^
                 ..#modsecurity.conf-recommended#%PREFIX%\conf ^
       ..#unicode.mapping#%PREFIX%\conf

      for %%a in (!EXTRAS!) do (
        for /f "tokens=1,2,3,4 delims=#" %%c in ("%%a") do (
          if "%%f" == "" (set DST=%%d) else (set DST=%%f)
          echo -- Installing: "%%e\!DST!
          copy /b /y "%%c\%%d" "%%e\!DST!"
        )
      )
    )
  ) else (
    echo nmake for %MOD_SECURITY% failed with status !STATUS!
  )
  popd

  rem Build from Makefile.win in mlogc sub-folder.
  rem
  pushd mlogc

  rem Patch Makefile.win to revise various paths and required build macros.
  rem
  perl -pi.bak -e ^" ^
    s~(\^)\\^)(pcre^)(.lib \\^)\n~${1}lib\\${2}2-8${3}\n~; ^
    s~(\^)\\^)(libcurl^)(.lib^)~${1}lib\\${2}_imp${3}~; ^
    s~(APR_INLINE.+VERSION\^)$^)~${1} -DWITH_PCRE2 -D_CRT_SECURE_NO_WARNINGS~; ^
    ^" Makefile.win

  rem Set configure options.
  rem
  set MOD_SECURITY_CONFIGURE_OPTS=APACHE=%PREFIX% PCRE=%PREFIX% CURL=%PREFIX%

  nmake /f Makefile.win !MOD_SECURITY_CONFIGURE_OPTS! clean
  nmake /f Makefile.win !MOD_SECURITY_CONFIGURE_OPTS! & call :get_status
  if !STATUS! == 0 (
    nmake /f Makefile.win !MOD_SECURITY_CONFIGURE_OPTS! install & call :get_status
    if not !STATUS! == 0 (
      echo nmake install for %MOD_SECURITY% failed with status !STATUS!
    ) else (
      rem Install additional files.
      rem
      rem Define extra files as src_dir#src_file#dst_dir#dst_file
      rem If dst_file is missing, then use src_file as destination filename
      rem
      set EXTRAS=.#mlogc-default.conf#%PREFIX%\conf ^
             .#mlogc-batch-load.pl.in#%PREFIX%\bin#mlogc-batch-load.pl

      for %%a in (!EXTRAS!) do (
        for /f "tokens=1,2,3,4 delims=#" %%c in ("%%a") do (
          if "%%f" == "" (set DST=%%d) else (set DST=%%f)
          echo -- Installing: "%%e\!DST!
          copy /b /y "%%c\%%d" "%%e\!DST!"
        )
      )
    )
  ) else (
    echo nmake for %MOD_SECURITY% failed with status !STATUS!
    exit /b !STATUS!
  )
  popd
)
exit /b !STATUS!

rem ------------------------------------------------------------------------------
rem
rem Get current errorlevel value and assign it to the status variable.

:get_status
call doskey /exename=err err=%%errorlevel%%
for /f "usebackq tokens=2 delims== " %%i in (`doskey /m:err`) do (set STATUS=%%i)
exit /b !STATUS!

rem ------------------------------------------------------------------------------
rem
rem Get package and version from release variable passed as first parameter.

:get_package_details
set RELEASE=%~1
for /f "delims=-" %%i in ('echo(%RELEASE:-=^&echo(%') do call set "PACKAGE=%%RELEASE:-%%i=%%"
for %%i in (%RELEASE:-= %) do set VERSION=%%i
exit /b

rem ------------------------------------------------------------------------------
rem
rem Check package source folder exists, from release variable passed as first parameter.
rem
:check_package_source

set SRC_DIR=%BUILD_BASE%\..\src\%~1
if not exist "!SRC_DIR!" (
  echo Warning for package %~1
  echo Could not find package source folder "!SRC_DIR!"
  set STATUS=1
) else (
  cd /d "!SRC_DIR!"
  set STATUS=0
)
exit /b !STATUS!

rem ------------------------------------------------------------------------------
rem
rem Build subroutine.
rem Parameter one is the package release variable.
rem Parameter two is any required CMake options.
rem Parameter three (optional) is any package sub-folder to the CMakeLists.txt file.

:build_package

call :get_package_details %~1

rem Check source folder exists, else exit (non-fatal).

call :check_package_source %~1
if not !STATUS! == 0 (
  exit /b
) else (
  if not "%~3" == "" (
    set SRC_DIR=!SRC_DIR!\%~3
  )
)

rem Clean up any previous build.

if exist "%BUILD_BASE%\!PACKAGE!" rmdir /s /q "%BUILD_BASE%\!PACKAGE!" 1>nul 2>&1
mkdir "%BUILD_BASE%\!PACKAGE!" 1>nul 2>&1

rem Build, make and install.

if exist "%BUILD_BASE%\!PACKAGE!" (
  cd /d "%BUILD_BASE%\!PACKAGE!"
  echo. & echo Building %~1

  rem Patch CMakeLists.txt to remove debug suffix from libraries. Messes up various builds.
  rem Tried setting CMAKE_DEBUG_POSTFIX to an empty string on the CMake command line but
  rem this doesn't work with all packages, e.g. PCRE2, EXPAT, LIBXML2, etc.

  perl -pi -e ^" ^
    s~((DEBUG_POSTFIX^|POSTFIX_DEBUG^)\s+^)([\x22]*^)[-_]*(^|s^)d([\x22]*^)~${1}\x22${4}\x22~; ^
    ^" "!SRC_DIR!\CMakeLists.txt"

  rem Run CMake to create an NMake makefile, which we then process.

  cmake -G "NMake Makefiles" %~2 -S "!SRC_DIR!" -B . & call :get_status
  if !STATUS! == 0 (
    nmake & call :get_status
    if !STATUS! == 0 (
      nmake install & call :get_status
      if !STATUS! == 0 (
        exit /b !STATUS!
      ) else (
        echo nmake install for !PACKAGE! failed with exit status !STATUS!
        exit /b !STATUS!
      )
    ) else (
      echo nmake for !PACKAGE! failed with exit status !STATUS!
      exit /b !STATUS!
    )
  ) else (
    echo cmake for !PACKAGE! failed with exit status !STATUS!
    exit /b !STATUS!
  )
) else (
  echo Failed to make folder "%BUILD_BASE%\!PACKAGE!"
  exit /b 1
)
exit /b
Back to top


Reply to topic   Topic: HOWTO: Building ModSecurity using MSVC toolset View previous topic :: View next topic
Post new topic   Forum Index -> How-to's & Documentation & Tips