访问日志能记哪些字段,客户端传来的内容怎么写进去才安全
服务器的访问日志可以记录哪些字段,取决于格式指令怎么拼,而不是一份固定的表结构。nginx 的日志模块用 log_format 定义命名格式、用 access_log 引用格式,字段由变量组合而成。要判断安全性,先按「这个值是谁提供的」把字段分成两类:来源地址、请求行、状态码、处理耗时由服务器侧产生,来路与客户端标识完全由请求方控制,后者可以带任意字符,也可以整段伪造。
日志格式是指令拼出来的,不是固定的
log_format 的值是一段带变量的模板,命名之后可以被多个 access_log 引用。同一份日志可以按格式区分用途:排查性能的一套、统计来源的一套、审计的一套,字段不必完全重叠。
有两个细节会影响后续解析。一是变量取不到值时记录的是一个连字符,所以解析规则要接受空值形态;二是转义方式,log_format 的 escape 参数可取 default、json、none,默认是 default——default 会把双引号、反斜杠以及值小于 32 或大于 126 的字符转义,json 则按 JSON 字符串的规则转义,none 关闭转义。
哪些字段来自请求本身,哪些来自服务器
| 字段 | 来源 | 客户端可控 | 建议 |
|---|---|---|---|
| 来源地址 | 连接层 | 否(可被代理改写) | 保留,作为最小可用集 |
| 请求行与方法 | 请求 | 是 | 保留,用于定位异常路径 |
| 状态码 | 服务器响应 | 否 | 保留 |
| 处理耗时 | 服务器 | 否 | 保留,性能排查依据 |
| 来路与客户端标识 | 请求头 | 是 | 保留但依赖转义 |
| 完整请求头 | 请求 | 是 | 谨慎,体积大且可能含身份凭证 |
来源地址、请求、状态码、来路、客户端标识这一组是排查用的最小可用集。要不要把请求头整段写进日志要单独判断:里面可能出现带身份信息的凭证,这类值一旦进日志,文件本身就变成了敏感数据。
客户端可控字段为什么要转义
来路与客户端标识由访问者自己的程序发出,内容不做约束。塞进换行符、引号或控制字符,会造成两类后果:解析时字段错位、一条请求被拆成多条记录,或反过来多条被并成一条;伪造出一行「看起来正常」的记录,事后看不出是谁写的。
更深一层的风险在日志的消费端。日志被后台界面、检索面板或报表读取时,未转义的内容可能在展示侧被执行,属于存储型跨站脚本的常见入口。安企CMS 在站内对 XSS 与 SQL 注入做了防护,但日志从写入到分析往往跨多个工具,链路另一端仍然要依赖转义与格式约束,不能假定下游会处理。
按 default 转义写、需要接 JSON 分析管道时按 json 转义,none 只适合完全可信且不会被二次解析的场景。
日志按整站还是按路径配置
access_log 可以在服务器配置的不同层级出现,覆盖整站、站点与路径三级;而一条请求最终在哪一级被记录,取决于处理结束时所在的上下文——发生过内部跳转的请求,记录位置可能和最初匹配的路径不同。
一台主机上跑多个站点时,这一点直接影响排障能否分清责任:按站点分别指定日志文件,比全站共用一个大文件更容易定位。用 Docker 镜像部署的,还要注意日志是否输出到容器外的卷上,否则重启即丢;用宝塔面板或 aaPanel 部署的,日志路径与切割策略通常在面板与服务器配置两处,改完要确认实际生效的那一处。
该留的字段和该挡的处理
保留最小可用集之外,还有两件事要落实。一是归档与留存:日志按周期切割并纳入备份范围,只留当天文件会让事后追溯断档;备份记录里要写明日志文件是否包含在内。二是采集侧脱敏:把带凭证的请求头排除在格式之外,比事后清洗可靠得多。
常见问题
问:日志里要不要记响应体大小? 答:要。它是判断压缩与缓存是否生效的常用依据,且不涉及客户端可控内容。
问:开了 json 转义是不是更安全? 答:转义解决的是字段错位与控制字符,格式换成 JSON 不改变「内容由请求方提供」这一事实,仍需限制记录哪些请求头。
问:多站点共用一台主机,日志要不要分文件? 答:建议按站点分开。共用文件时,排障要先按域名拆一遍,成本高还容易漏。