根据这个问题的标题,我如何记录客户端浏览器在Nginx中发送的所有标题?我还想记录响应头.请注意,我使用nginx作为反向代理.
浏览完文档后,我了解到我可以记录一个特定的标题,但我想记录所有的标题.
我会接受hacky解决方案!
pet*_*etr 40
还有两个选项可以在 nginx 中记录标头。
njs 可以从包存储库安装,并预安装在官方 nginx docker 镜像中。njs 至少从 nginx 1.9.15 版本(相当旧)开始可用,但最好使用更新的版本。
安装后在 nginx 配置中启用 njs http 模块:
load_module modules/ngx_http_js_module.so;
Run Code Online (Sandbox Code Playgroud)
标头可能会记录到错误或访问日志中。
HTTP 请求对象具有键值格式的headersIn、headersOut字段,重复的标头将合并在此字段中,而rawHeadersIn、rawHeadersOut是原始标头数组的数组。
创建js模块,使用json序列化header:
// /etc/nginx/headers.js
function headers_json(r) {
return JSON.stringify(r.headersIn)
}
export default {headers_json};
Run Code Online (Sandbox Code Playgroud)
导入js模块,声明变量并将其添加到log_format:
http {
js_import headers.js;
js_set $headers_json headers.headers_json;
# Using custom log format here
log_format main '$remote_addr'
'\t$remote_user'
'\t$time_local'
'\t$request'
'\t$status'
'\t$headers_json';
Run Code Online (Sandbox Code Playgroud)
默认情况下,访问日志中的字符串会被转义,因此您将得到如下内容:
# curl -H 'H: First' -H 'H: Second' localhost:8899
172.17.0.1 - 16/Apr/2021:08:46:43 +0000 GET / HTTP/1.1 200 {\x22Host\x22:\x22localhost:8899\x22,\x22User-Agent\x22:\x22curl/7.64.1\x22,\x22Accept\x22:\x22*/*\x22,\x22H\x22:\x22First,Second\x22}
Run Code Online (Sandbox Code Playgroud)
您可以在log_format指令中使用 escape 参数来更改转义的应用方式。
escape=json 输出示例:
log_format main escape=json ...
{\"Host\":\"localhost:8899\",\"User-Agent\":\"curl/7.64.1\",\"Accept\":\"*/*\",\"H\":\"First,Second\"}
Run Code Online (Sandbox Code Playgroud)
另一种选择是在 javascript 函数中以 Base64 编码包装 json:
function headers_json_base64(r) {
return JSON.stringify(r.headersIn).toString('base64')
}
Run Code Online (Sandbox Code Playgroud)
使用 njs,您可以在 javascript 函数中使用ngx.logor r.log(对于旧版本的 njs ngx 对象不可用)来记录标头。应该显式调用 js 函数才能使其与js_header_filter指令一起工作
。
js模块:
function headers_json_log(r) {
return ngx.log(ngx.WARN, JSON.stringify(r.headersIn))
}
export default {headers_json_log};
Run Code Online (Sandbox Code Playgroud)
启用登录位置:
location /log/ {
js_header_filter headers.headers_json_log;
return 200;
}
Run Code Online (Sandbox Code Playgroud)
对于错误日志,不应用转义,因此您将获得原始 json:
2021/04/16 12:22:53 [warn] 24#24: *1 js: {"Host":"localhost:8899","User-Agent":"curl/7.64.1","Accept":"*/*","H":"First,Second"}
Run Code Online (Sandbox Code Playgroud)
如果您不想弄乱访问日志或者只需要记录特定位置的标头(对于特定位置也可以使用 access_log 指令和单独的 log_format ),则记录到错误日志可能会很有用
镜像指令可用于将请求镜像到不同的位置。它可能比 tcpdump 更方便,尤其是当上游流量被加密时,并且比使用 njs 更简单。
镜像只能用于捕获请求标头,因为响应标头是独立返回的。
镜像指令可以在 http 和服务器上下文或位置上下文中在服务器范围内使用。
# using mirror in server context
mirror /mirror;
mirror_request_body off;
location /mirror {
# Use internal so that location is not available for direct requests
internal;
# Use small timeout not to wait for replies (this is not necessary)
proxy_read_timeout 1;
# Pass headers to logging server
proxy_pass http://127.0.0.1:6677;
# send original request uri in special header
proxy_set_header X-Original-URI $request_uri;
}
Run Code Online (Sandbox Code Playgroud)
要记录标头,可以使用简单的 http 服务器或 netcat oneliner:
nc -kl 6677 > /path/to/headers.log
Run Code Online (Sandbox Code Playgroud)
由于netcat不回复nginx,nginx会用超时错误填充错误日志,此错误不会影响客户端。
Toz*_*art 23
仅对于请求标头,它可以在 nginx/1.18.0 上开箱即用。
/etc/nginx/nginx.conf行error_log /var/log/nginx/error.log;. 将其移到 http/server 范围之外,使其看起来像:error_log /var/log/nginx/error.log debug;
http {
...
Run Code Online (Sandbox Code Playgroud)
注意这个debug部分!
tail -f /var/log/nginx/error.log | grep "http header"输出示例:
2022/04/06 11:53:55 [debug] 3930380#3930380: *5 http header: "Host: example.org"
2022/04/06 11:53:55 [debug] 3930380#3930380: *5 http header: "Connection: Keep-Alive"
2022/04/06 11:53:55 [debug] 3930380#3930380: *5 http header: "X-Forwarded-For: 127.0.0.1"
2022/04/06 11:53:55 [debug] 3930380#3930380: *5 http header: "X-Forwarded-Proto: https"
2022/04/06 11:53:55 [debug] 3930380#3930380: *5 http header: "user-agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:98.0) Gecko/20100101 Firefox/98.0"
2022/04/06 11:53:55 [debug] 3930380#3930380: *5 http header: "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"
...
Run Code Online (Sandbox Code Playgroud)
gau*_*nix 15
经过大量研究,我可以得出结论,开箱即用是不可能的.
更新 - 您可以使用Lua附带的openresty.使用Lua可以做很酷的事情,包括记录所有标题,Redis或其他服务器
use*_*602 13
正如@gauravphoenix所说,你需要Lua附带的opnresty.请参阅https://github.com/openresty/lua-nginx-module/进行安装.一旦它运行,然后添加nginx
header_filter_by_lua_block {
local h = ngx.req.get_headers()
for k, v in pairs(h) do
ngx.log(ngx.ERR, "Got header "..k..": "..v..";")
end
}
Run Code Online (Sandbox Code Playgroud)
检查您的错误日志.
Ama*_*Bah 11
基于@user1778602 的响应,set_by_lua_block可用于将所有标头设置为稍后在 log_format 中使用的变量(请参阅此答案中的更多详细信息)。
set_by_lua_block $request_headers{
local h = ngx.req.get_headers()
local request_headers_all = ""
for k, v in pairs(h) do
local rowtext = ""
rowtext = string.format("[%s %s]\n", k, v)
request_headers_all = request_headers_all .. rowtext
end
return request_headers_all
}
Run Code Online (Sandbox Code Playgroud)
更新您的log_format(请务必在 eg 中使用新格式access_log):
log_format myformat escape=none "$request_headers"
Run Code Online (Sandbox Code Playgroud)
PS:注意记录 PII 数据可能违反 GDPR :)
| 归档时间: |
|
| 查看次数: |
36828 次 |
| 最近记录: |