前言近期在部署IIS应用需要记录IIS的详细访问日志发现ModSecurity能满足需求便尝试使用ModSecurity有一些小坑记录一下本文不涉及ModSecurity的waf功能。一 安装ModSecurity1.1 下载前往ModSecurity Release下载ModSecurityIIS_2.9.7-64b-64.msi1.2 安装默认安装即可1.3 启用默认安装的路径C:\Program Files\ModSecurity IIS修改需要启用ModSecurity网站的web.config修改配置如下?xml version1.0 encodingUTF-8? configuration !-- others config ...-- system.webServer ModSecurity enabledtrue configFileC:\Program Files\ModSecurity IIS\modsecurity_iis.conf / /system.webServer /configuration修改C:\Program Files\ModSecurity IIS\modsecurity.conf具体配置情况不做说明需要自行百度SecRuleEngine DetectionOnly SecAuditLogType Concurrent SecAuditLog d:\modsecurity\logs\modsec_audit.log SecAuditLogStorageDir d:\modsecurity\logs\ SecAuditLogFormat JSON SecRule REQUEST_HEADERS:Host ^localhost$ id:1000001,phase:1,pass,nolog,ctl:auditEngineOff,msg:Disable audit logging for localhost requests修改完配置之后需要重启IIS生效具体测试ModSecurity是否生效的方法可以参考CSDN另外一位老哥的方法二 安装Logstash2.1 下载Logstash在es官网下载logstash-9.4.1-windows-x86_64.zip2.2 安装Logstash解压到D盘下2.3 安装mysql插件cd D:\logstash-9.4.1 ./bin/logstash-plugin install logstash-output-jdbc下载数据库的驱动文件mysql-connector-java-8.0.13.jar把该文件存放到logstash目录下2.4 创建数据库本次数据库采用mysql使用另外一台centos7 docker安装有看到使用es数据库的应该会更方便一点下次采用ELK测试一下新建modsecurity数据库创建modlog表具体如下DROP TABLE IF EXISTS modlog; CREATE TABLE modlog ( id int(11) NOT NULL AUTO_INCREMENT, client_ip varchar(255) DEFAULT NULL, time_stamp varchar(255) DEFAULT NULL, date datetime DEFAULT NULL, server_id varchar(255) DEFAULT NULL, client_port int(11) DEFAULT NULL, host_ip varchar(255) DEFAULT NULL, host_port int(11) DEFAULT NULL, uri varchar(255) DEFAULT NULL, unique_id varchar(255) DEFAULT NULL, request mediumtext, response mediumtext, producer mediumtext, messages mediumtext, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT40 DEFAULT CHARSETutf8;三 配置创建mslogtomysql.conf内容如下具体目录和数据库需要按照实际情况填写input { file { path [D:/modsecurity/logs/*/*/*/*] start_position beginning codec json close_older 120 ignore_older 3600 stat_interval 10 } } filter { # 解析 JSON 消息 json { source message remove_field [message] } # 提取时间戳组件 mutate { add_field { [time_parts] %{[transaction][time][0]} timezone %{[transaction][time][1]} } } # 使用 date 插件解析时间戳替代原来的复杂月份转换 date { match [[time_parts], dd/MMM/yyyy:HH:mm:ss.SSSSSS] target timestamp timezone Asia/Shanghai } # 提取日期和时间组件用于数据库 ruby { code event.set(year, event.get(timestamp).year) event.set(month, event.get(timestamp).month) event.set(day, event.get(timestamp).day) event.set(time_stamp, event.get(timestamp).strftime(%Y-%m-%d %H:%M:%S)) } # 清理临时字段 mutate { remove_field [time_parts, timezone, date, month, day, time, year] } } output { stdout { codec json } jdbc { driver_jar_path D:/logstash-9.4.1/mysql-connector-java-8.0.13.jar driver_class com.mysql.cj.jdbc.Driver connection_string jdbc:mysql://192.168.192.100:3306/modsecurity?userrootpasswordpassworduseUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai statement [ INSERT INTO modlog (client_ip, time_stamp, client_port, host_ip, host_port, uri, request, response, producer, messages) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?), %{[transaction][remote_address]}, %{time_stamp}, %{[transaction][remote_port]}, %{[transaction][local_address]}, %{[transaction][local_port]}, %{[request][request_line]}, %{[request]}, %{[response]}, %{[audit_data][producer]}, %{[audit_data][messages]} ] } }执行命令将数据写入到mysql中可先使用-t参数对配置文件进行检测以下是配置通过示例PS D:\logstash-9.4.1 .\bin\logstash.bat -f .\mslogtomysql.conf -t Using bundled JDK: D:\logstash-9.4.1\jdk\bin\java.exe Sending Logstash logs to D:/logstash-9.4.1/logs which is now configured via log4j2.properties [2026-05-26T16:01:25,250][INFO ][logstash.runner ] Log4j configuration path used is: D:\logstash-9.4.1\config\log4j2.properties [2026-05-26T16:01:25,281][WARN ][deprecation.logstash.runner] The use of JAVA_HOME has been deprecated. Logstash 8.0 and later ignores JAVA_HOME and uses the bundled JDK. Running Logstash with the bundled JDK is recommended. The bundled JDK has been verified to work with each specific version of Logstash, and generally provides best performance and reliability. If you have compelling reasons for using your own JDK (organizational-specific compliance requirements, forexample), you can configure LS_JAVA_HOME to use that version instead. [2026-05-26T16:01:25,281][INFO ][logstash.runner ] Starting Logstash {logstash.version 9.4.1, jruby.version jruby 10.0.5.0 (3.4.5) 2026-04-06 5db1ba72f3 OpenJDK 64-Bit Server VM 21.0.1110-LTS on 21.0.1110-LTS indy jit [x86_64-mswin32]} [2026-05-26T16:01:25,281][INFO ][logstash.runner ] JVM bootstrap flags: [-Xms1g, -Xmx1g, -Djava.awt.headlesstrue, -Dfile.encodingUTF-8, -XX:HeapDumpOnOutOfMemoryError, -Djava.security.egdfile:/dev/urandom, -Djruby.regexp.interruptibletrue, -Djruby.compile.invokedynamictrue, -Djdk.io.File.enableADStrue, -Dlog4j2.isThreadContextMapInheritabletrue, --add-exportsjdk.compiler/com.sun.tools.javac.apiALL-UNNAMED, --add-exportsjdk.compiler/com.sun.tools.javac.fileALL-UNNAMED, --add-exportsjdk.compiler/com.sun.tools.javac.parserALL-UNNAMED, --add-exportsjdk.compiler/com.sun.tools.javac.treeALL-UNNAMED, --add-exportsjdk.compiler/com.sun.tools.javac.utilALL-UNNAMED, --add-opensjava.base/java.securityALL-UNNAMED, --add-opensjava.base/java.ioALL-UNNAMED, --add-opensjava.base/java.nio.channelsALL-UNNAMED, --add-opensjava.base/sun.nio.chALL-UNNAMED, --add-opensjava.management/sun.managementALL-UNNAMED, -Dio.netty.allocator.maxOrder11] [2026-05-26T16:01:25,422][INFO ][org.logstash.jackson.StreamReadConstraintsUtil] Jackson default value override logstash.jackson.stream-read-constraints.max-string-length configured to 200000000 (logstash default) [2026-05-26T16:01:25,437][INFO ][org.logstash.jackson.StreamReadConstraintsUtil] Jackson default value override logstash.jackson.stream-read-constraints.max-number-length configured to 10000 (logstash default) [2026-05-26T16:01:25,437][INFO ][org.logstash.jackson.StreamReadConstraintsUtil] Jackson default value override logstash.jackson.stream-read-constraints.max-nesting-depth configured to 1000 (logstash default) [2026-05-26T16:01:25,562][WARN ][logstash.config.source.multilocal] Ignoring the pipelines.yml file because command line options are specified [2026-05-26T16:01:29,352][INFO ][logstash.codecs.json ] ECS compatibility is enabled but target option was not specified. This may cause fields to be set at the top-level of the event where they are likely to clash with the Elastic Common Schema. It is recommended to set the target option to avoid potential schema conflicts (if your data is ECS compliant or non-conflicting, feel free to ignore this message) [2026-05-26T16:01:30,832][INFO ][logstash.codecs.json ] ECS compatibility is enabled but target option was not specified. This may cause fields to be set at the top-level of the event where they are likely to clash with the Elastic Common Schema. It is recommended to set the target option to avoid potential schema conflicts (if your data is ECS compliant or non-conflicting, feel free to ignore this message) [2026-05-26T16:01:31,065][WARN ][org.logstash.instrument.metrics.UserMetric][main] UserMetric type mismatch for %s (expected: %s, received: %s); a null implementation will be substituted [2026-05-26T16:01:31,065][WARN ][org.logstash.instrument.metrics.UserMetric][main] UserMetric type mismatch for %s (expected: %s, received: %s); a null implementation will be substituted [2026-05-26T16:01:31,112][INFO ][logstash.javapipeline ][main] Pipeline main is configured with pipeline.ecs_compatibility: v8 setting. All plugins in this pipeline will default to ecs_compatibility v8 unless explicitly confgured otherwise.Configuration OK [2026-05-26T16:01:31,112][INFO ][logstash.runner ] Using config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash成功之后直接执行.\bin\logstash.bat -f .\mslogtomysql.conf即可小坑1 Fixnum错误JDBC - Exception. Not retrying {exception: #NameError: uninitialized constant LogStash::Outputs::Jdbc::Fixnum解决办法手动修改jdbc.rb文件找到文件D:\logstash-9.4.1\vendor\bundle\jruby\3.4.0\gems\logstash-output-jdbc-5.4.0\lib\logstash\outputs\jdbc.rb修改296行代码删除“Fixnum,”找到 296 when Fixnum, Integer 297 if value 2147483647 or value -2147483648 298 statement.setLong(idx 1, value) 299 else 300 statement.setInt(idx 1, value) 301 end 修改为 296 when Integer 297 if value 2147483647 or value -2147483648 298 statement.setLong(idx 1, value) 299 else 300 statement.setInt(idx 1, value) 301 end2 [FATAL][logstash.runner ] The given configuration is invalid. Reason: Expected one of [ \t\r\n], #, input, filter, output at line 1, column 1 (byte 1)直接从win server 2016上创建txt文件在运行时会报错PS D:\logstash-9.4.1 .\bin\logstash.bat -f .\mslogtomysql.conf -t Using bundled JDK: D:\logstash-9.4.1\jdk\bin\java.exe Sending Logstash logs to D:/logstash-9.4.1/logs which is now configured via log4j2.properties [2026-05-26T15:56:06,631][INFO ][logstash.runner ] Log4j configuration path used is: D:\logstash-9.4.1\config\log4j2.properties [2026-05-26T15:56:06,663][WARN ][deprecation.logstash.runner] The use of JAVA_HOME has been deprecated. Logstash 8.0 and later ignores JAVA_HOME and uses the bundled JDK. Running Logstash with the bundled JDK is recommended. The bundled JDK has been verified to work with each specific version of Logstash, and generally provides best performance and reliability. If you have compelling reasons for using your own JDK (organizational-specific compliance requirements, forexample), you can configure LS_JAVA_HOME to use that version instead. [2026-05-26T15:56:06,663][INFO ][logstash.runner ] Starting Logstash {logstash.version 9.4.1, jruby.version jruby 10.0.5.0 (3.4.5) 2026-04-06 5db1ba72f3 OpenJDK 64-Bit Server VM 21.0.1110-LTS on 21.0.1110-LTS indy jit [x86_64-mswin32]} [2026-05-26T15:56:06,663][INFO ][logstash.runner ] JVM bootstrap flags: [-Xms1g, -Xmx1g, -Djava.awt.headlesstrue, -Dfile.encodingUTF-8, -XX:HeapDumpOnOutOfMemoryError, -Djava.security.egdfile:/dev/urandom, -Djruby.regexp.interruptibletrue, -Djruby.compile.invokedynamictrue, -Djdk.io.File.enableADStrue, -Dlog4j2.isThreadContextMapInheritabletrue, --add-exportsjdk.compiler/com.sun.tools.javac.apiALL-UNNAMED, --add-exportsjdk.compiler/com.sun.tools.javac.fileALL-UNNAMED, --add-exportsjdk.compiler/com.sun.tools.javac.parserALL-UNNAMED, --add-exportsjdk.compiler/com.sun.tools.javac.treeALL-UNNAMED, --add-exportsjdk.compiler/com.sun.tools.javac.utilALL-UNNAMED, --add-opensjava.base/java.securityALL-UNNAMED, --add-opensjava.base/java.ioALL-UNNAMED, --add-opensjava.base/java.nio.channelsALL-UNNAMED, --add-opensjava.base/sun.nio.chALL-UNNAMED, --add-opensjava.management/sun.managementALL-UNNAMED, -Dio.netty.allocator.maxOrder11] [2026-05-26T15:56:06,820][INFO ][org.logstash.jackson.StreamReadConstraintsUtil] Jackson default value override logstash.jackson.stream-read-constraints.max-string-length configured to 200000000 (logstash default) [2026-05-26T15:56:06,820][INFO ][org.logstash.jackson.StreamReadConstraintsUtil] Jackson default value override logstash.jackson.stream-read-constraints.max-number-length configured to 10000 (logstash default) [2026-05-26T15:56:06,835][INFO ][org.logstash.jackson.StreamReadConstraintsUtil] Jackson default value override logstash.jackson.stream-read-constraints.max-nesting-depth configured to 1000 (logstash default) [2026-05-26T15:56:06,959][WARN ][logstash.config.source.multilocal] Ignoring the pipelines.yml file because command line options are specified [2026-05-26T15:56:07,101][FATAL][logstash.runner ] The given configuration is invalid. Reason: Expected one of [ \t\r\n], #, input, filter, output at line 1, column 1 (byte 1) [2026-05-26T15:56:07,132][FATAL][org.logstash.Logstash ] Logstash stopped processing because of an error: (SystemExit) exit org.jruby.exceptions.SystemExit: (SystemExit) exit at org.jruby.RubyKernel.exit(org/jruby/RubyKernel.java:976) at org.jruby.RubyKernel.exit(org/jruby/RubyKernel.java:935) at D_3a_.logstash_minus_9_dot_4_dot_1.lib.bootstrap.environment.main(D:\logstash-9.4.1\lib\bootstrap\environment.rb:90)解决办法从mac上保存为ASCII编码再拷贝到windows上便没有问题