如何使tcp流的nginx打印完整日志

时间:2017-02-07 06:58:57

标签: logging nginx tcp stream

我使用nginx-1.11.8进行以下配置。

stream {

    log_format  basic   '$time_iso8601 $remote_addr '
                        '$protocol $status $bytes_sent $bytes_received '
                        '$session_time $upstream_addr '
                        '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';

    access_log      logs/stream.log  basic buffer=1k flush=5s;

    include *.stream.conf;
}

现在我只能在tcp日志中获取IP和其他不重要的东西。有一些与tcp数据包中的IP相关的重要信息我想知道。我该怎么做才能在tcp日志中获取完整的tcp包?提前谢谢。

2 个答案:

答案 0 :(得分:1)

如评论中所述,NGINX不是设计上的数据包嗅探器。

您可以查看可以在日志中显示的受支持变量:

http://nginx.org/en/docs/varindex.html

答案 1 :(得分:0)

我认为股票nginx不可能做到这一点,尽管有一天openresty可能做到这一点。 ngx_stream_lua_module仍处于起步阶段,可能仍会开发一些功能来支持偷看流内容。他们也可能正在接受功能请求。

关于为什么今天,$request_bodystream上下文中不存在,我认为有以下几个原因:

    与HTTP支持相比,
  • 流支持仍然是新的。
  • Nginx不讲基础协议(当然,您可以通过stream阻止HTTP流量,但是nginx的处理方式与非HTTP流量没有什么不同)
  • 结果,nginx无法明确回答一些问题,例如:
    1. 什么是请求?
    2. 它从哪里开始?
    3. 它在哪里结束?
    4. 它甚至有类似“身体”的东西吗?
    5. 甚至还有“请求”之类的东西吗?
  • http上下文中,nginx已经需要实现对请求的缓冲,以支持在一个失败的server块中使用多条upstream行重试它们。使用任意TCP协议执行此操作并不安全(哎呀,在所有情况下都无法使用HTTP进行安全操作,但这是服务器管理员关心的问题)。 stream上下文中目前不存在这样的功能,因此没有缓冲区可以为变量提供支持。

对于这些问题的详细说明,nginx无法回答,乍一看似乎很愚蠢,请考虑TCP是一种非常通用的协议。建立在TCP之上的最简单的应用层协议定义了一个非常基本的请求-响应模型,其中一端发送纯文本请求,后跟定界符,而另一端等待请求,然后发送纯文本响应,后跟定界符,然后一侧或两侧关闭连接。当然,在这些情况下,捕获并记录请求和响应似乎很简单。

但是,许多更复杂的协议却无法正常工作。有些协议甚至根本不运行在请求-响应模型上,而是异步的,其中任一方都可以随时发送“消息”,例如WebSockets,STOMP或AMQP。流中可能根本没有定界符,或者定界符可能隐藏在压缩和加密层下,并且并非所有网络加密都是SSL / TLS。此外,如果将内容编码为ASN.1,Protobuf,Thrift,Avro或类似的东西怎么办?您可能想要漂亮的漂亮打印形式,但是nginx不能为您做到这一点,并且即使不是不可能可靠地解析,在日志中转储一堆二进制数据也很困难。像SSH一样,也可能存在嵌套的“通道”或“会话”。即使使用请求-响应模型,在连接的整个生命周期中,哪一侧发出请求和哪一侧发送响应也很容易。

说了这么多,我认为有一个论点可以处理常见或至少简单的情况,因此也许有一天它会变成nginx。在此之前,使用socat或其他网络调试工具将中介放置在nginx之前或之后可能是最简单的。