Skip to main content

19.配置日志记录

NGINX中在本地或通过 syslog 在日志文件中捕获有关错误和请求处理的详细信息。本文介绍如何在NGINX中配置错误和已处理请求的日志记录。

设置错误日志(Setting Up the Error Log)

NGINX将有关遇到的不同严重性级别的问题的信息写入错误日志。error_log 指令设置对特定文件的日志记录 stderr或者 syslog指定要记录的消息的最低严重性级别。默认情况下,错误日志位于 logs/error.log (绝对路径取决于操作系统和安装),并记录来自指定级别以上的所有严重性级别的消息。

以下配置将要记录的错误消息的最低严重性级别 error更改为 warn

error_log logs/error.log warn;

在这种情况下,将记录 warn error crit alert emerg级别的消息。

错误日志的默认设置全局有效。若要重写它,请将 error_log 指令放在 main(顶级)配置上下文中。main上下文中的设置始终由其他配置级别 (http,server,location) 继承。还可以在 [http]、[stream]server和[location]级别指定 error_log该指令,并覆盖从更高级别继承的设置。如果发生错误,消息将仅写入一个错误日志,即最接近发生错误的级别的日志。但是,error_log如果在同一级别上指定了多个指令,则消息将写入所有指定的日志。

设置访问日志(Setting Up the Access Log)

NGINX 在处理请求后立即将有关客户端请求的信息写入访问日志中。默认情况下,访问日志位于 logs/access.log ,信息以预定义的组合格式写入日志。若要覆盖默认设置,请使用 log_format 指令更改记录消息的格式,并使用 access_log 指令指定日志的位置及其格式。日志格式是使用变量定义的。

以下示例定义扩展预定义组合格式的日志格式,该值指示响应的 gzip 压缩比率。然后将该格式应用于启用压缩的虚拟服务器。

http {
log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';

server {
gzip on;
access_log /spool/logs/nginx-access.log compression;
...
}
}

日志格式的另一个示例可以跟踪NGINX和upstream服务器之间的不同时间值,如果您的网站速度变慢,这可能有助于诊断问题。您可以使用以下变量来记录指示的时间值:

  • $upstream_connect_time – 与upstream服务器建立连接所花费的时间
  • $upstream_header_time – 从upstream服务器建立连接和接收响应标头的第一个字节之间的时间
  • $upstream_response_time – 从upstream服务器建立连接和接收响应正文的最后一个字节之间的时间
  • $request_time – 处理请求所花费的总时间

所有时间值均以毫秒为单位。

http {
log_format upstream_time '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"'
'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"';

server {
access_log /spool/logs/nginx-access.log upstream_time;
...
}
}

读取生成的时间值时,请记住以下几点:

  • 当通过多个服务器处理请求时,变量包含多个以逗号分隔的值
  • 当从一个upstream组到另一个upstream组的内部重定向时,值用分号分隔
  • 当请求无法到达upstream服务器或无法接收到完整标头时,变量包含 0(零)
  • 如果在连接到upstream或从缓存中获取回复时出现内部错误,则变量包含 -(连字符)

可以通过为日志消息启用缓冲区和名称包含变量的常用日志文件的描述符缓存来优化日志记录。若要启用缓冲,请使用 access_log 指令的 buffer参数指定缓冲区的大小。然后,当下一条日志消息不适合缓冲区时,缓冲的消息将写入日志文件,以及其他一些情况。

若要启用日志文件描述符的缓存,请使用 open_log_file_cache 指令。

error_log指令类似,在特定配置级别上定义的 access_log 指令将覆盖先前级别的设置。完成请求处理后,消息将写入在当前级别上配置的日志,或从先前级别继承的日志。如果一个级别定义了多个访问日志,则消息将写入所有访问日志。

3.启用条件日志记录(Enabling Conditional Logging)

条件日志记录允许从访问日志中排除琐碎或不重要的日志条目。在 NGINX 中,条件日志记录由 access_log 指令的 if参数启用。

此示例排除具有 HTTP 状态代码 2xx(成功)和 3xx(重定向)的请求:

map $status $loggable {
~^[23] 0;
default 1;
}

access_log /path/to/access.log combined if=$loggable;

用例:对 TLS 参数进行采样(Usecase: Sampling TLS Parameters)

许多客户端使用早于 TLS 1.3 的 TLS 版本。尽管许多密码被声明为不安全,但较旧的实现仍然使用它们;ECC 证书提供比 RSA 更高的性能,但并非所有客户端都可以接受 ECC。许多TLS攻击依赖于“中间人”,他拦截密码协商握手,并强制客户端和服务器选择安全性较低的密码。因此,将NGINX Plus配置为不支持弱密码或传统密码非常重要,但这样做可能会排除旧客户端。

可以评估从客户端获取的 SSL 数据,并确定如果删除对较旧的 SSL 协议和密码的支持,则排除的客户端比例。

以下配置示例记录任何连接的 TLS 客户端的 SSL 协议、密码和 User-Agent标头,假设每个客户端选择它支持的最新协议和最安全的密码。

在此示例中,每个客户端都由其唯一的 IP 地址和用户代理组合标识。

  1. 定义自定义日志格式 sslparams,其中包括 SSL 协议的版本 ($ssl_protocol)、连接中使用的密码 ($ssl_cipher)、客户端 IP 地址 ($remote_addr) 和标准 HTTP 请求字段 User Agent的值 ($http_user_agent):

    log_format sslparams '$ssl_protocol $ssl_cipher '
    '$remote_addr "$http_user_agent"';
  2. 定义一个键值存储,用于保存客户端及其用户代理的 IP 地址,例如 clients

    keyval_zone zone=clients:80m timeout=3600s;
  3. $remote_addrUser-Agent标头的每个唯一组合创建一个变量,例如 $seen

    keyval $remote_addr:$http_user_agent $seen zone=clients;

    server {
    listen 443 ssl;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;

    if ($seen = "") {
    set $seen 1;
    set $logme 1;
    }
    access_log /tmp/sslparams.log sslparams if=$logme;

    # ...
    }
  4. 查看使用此配置生成的日志文件:

    TLSv1.2 AES128-SHA 1.1.1.1 "Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
    TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 2.2.2.2 "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"
    TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 3.3.3.3 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
    TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 4.4.4.4 "Mozilla/5.0 (Android 4.4.2; Tablet; rv:65.0) Gecko/65.0 Firefox/65.0"
    TLSv1 AES128-SHA 5.5.5.5 "Mozilla/5.0 (Android 4.4.2; Tablet; rv:65.0) Gecko/65.0 Firefox/65.0"
    TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 6.6.6.6 "Mozilla/5.0 (Linux; U; Android 5.0.2; en-US; XT1068 Build/LXB22.46-28) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.10.2.1164 Mobile Safari/537.36"
  5. 处理日志文件以确定数据的分布:

    cat /tmp/sslparams.log | cut -d ' ' -f 2,2 | sort | uniq -c | sort -rn | perl -ane 'printf "%30s %s\n", $F[1], "="x$F[0];'

    在此输出中,将标识低容量、安全性较低的密码:

    ECDHE-RSA-AES128-GCM-SHA256 =========================
    ECDHE-RSA-AES256-GCM-SHA384 ========
    AES128-SHA ====
    ECDHE-RSA-CHACHA20-POLY1305 ==
    ECDHE-RSA-AES256-SHA384 ==

    然后,您可以检查日志以确定哪些客户端正在使用这些密码,然后决定从NGINX 配置中删除这些密码。

记录到系统日志

syslog该实用程序是计算机消息日志记录的标准,允许从单个系统日志服务器上的不同设备收集日志消息。在 NGINX 中,使用 error_logaccess_log 指令中的 syslog:前缀配置了对 syslog 的日志记录。

系统日志消息可以发送到 server=域名、IP 地址或 UNIX 域套接字路径。可以使用端口指定域名或 IP 地址以覆盖默认端口 514 。可以在前缀 unix:后指定 UNIX 域套接字路径:

error_log  syslog:server=unix:/var/log/nginx.sock debug;
access_log syslog:server=[2001:db8::1]:1234,facility=local7,tag=nginx,severity=info;

在该示例中,NGINX 错误日志消息在日 debug志记录级别写入 UNIX 域套接字,访问日志写入具有 IPv6 地址和 1234端口的系统日志服务器。

facility=该参数指定记录消息的程序的类型。默认值为 local7。其他可能的值为:auth,authpriv,daemon,cron,ftp,lpr,kern,mail,news,syslog,user,uucp,local0 ... local7

tag=该参数将自定义标记应用于系统日志消息(在我们的示例中是 nginx)。

severity=该参数设置访问日志的系统日志消息的严重性级别。按严重性递增顺序排列的可能值为:debug,info,notice,warn,error(默认值)crit,alert,emerg。消息记录在指定的级别和所有更严重的级别。在我们的示例中,严重性 error级别还允许记录 crit,alert,emerg级别。