Rsyslog经反向隧道转发日志时属性被替换如何保留原始值
Rsyslog反向隧道转发日志属性嵌套/丢失解决方案
问题现象
- 发送端host-A输出的原始JSON格式日志,经SSH反向隧道传输到接收端后,外层元属性被替换为localhost、127.0.0.1等本地回环值
- 完整原始日志被整体嵌套封装到外层日志的
message字段中,无法直接识别原始主机名、程序名等属性 - 发送端原始日志示例:
{"@timestamp":"xxxxxxx","@version":"1","sysloghost":"host-A","severity":"xxxxxxx","facility":"xxxxxxx","programname":"host-A-app","procid":"xxxxxxx","relayhost":"host-A","relayip":"host-A","message": "xxxxxxx"}
- 隧道接收端异常日志示例:
{"@timestamp":"yyyyyyy","@version":"1","sysloghost":"localhost","severity":"notice","facility":"user","programname":"","procid":"-","relayhost":"localhost","relayip":"127.0.0.1","message":{"@timestamp":"xxxxxxx","@version":"1","sysloghost":"host-A","severity":"xxxxxxx","facility":"xxxxxxx","programname":"host-A-app","procid":"xxxxxxx","relayhost":"host-A","relayip":"host-A","message": "xxxxxxx"}}
根因说明
反向隧道本质是将发送端的日志流映射到接收端本地的127.0.0.1回环端口,接收端rsyslog默认对从该端口收到的所有流量做全新syslog报文解析:自动提取TCP/IP层的源地址(127.0.0.1)、源主机名(localhost)生成外层元数据,由于收到的载荷本身是完整JSON格式日志,没有符合标准syslog的报文头,rsyslog就会把整个JSON载荷直接当做普通消息文本写入message字段,最终形成嵌套结构。
可行解决方案
方案1:接收端配置JSON解析规则,直接提取嵌套原始日志属性(推荐,无侵入)
不需要修改发送端配置,在接收端rsyslog加载mmjsonparse模块,匹配从回环端口收到的日志,直接解析message字段内的原始JSON,将原始属性提升为日志顶层属性,覆盖外层错误的本地元数据即可。
配置写入接收端rsyslog配置文件,通常路径为/etc/rsyslog.conf或/etc/rsyslog.d/下的自定义conf文件:
# 加载JSON解析模块 module(load="mmjsonparse") # 定义规则集:专门处理反向隧道端口进来的日志 ruleset(name="process_tunnel_log") { # 解析当前报文的message字段(即嵌套的原始JSON日志) action(type="mmjsonparse") # 校验是否解析成功(即message字段确实是合法JSON) if $parsesuccess == "OK" then { # 把解析出来的原始属性赋值给顶层元数据字段 set $!sysloghost = $!message!sysloghost; set $!programname = $!message!programname; set $!severity = $!message!severity; set $!facility = $!message!facility; set $!relayhost = $!message!relayhost; set $!relayip = $!message!relayip; set $!message = $!message!message; # 后续可接转发、本地存储等动作,此时操作的日志已经是还原后的原始属性 *.* /var/log/tunnel_collect.log stop } # 解析失败的非JSON日志走默认处理逻辑 *.* /var/log/messages } # 绑定监听端口到上述规则集,端口替换为实际反向隧道映射的本地端口,比如10514 input(type="imtcp" port="10514" ruleset="process_tunnel_log" address="127.0.0.1")
配置完成后执行systemctl restart rsyslog即可生效,该方案解析性能远高于正则匹配、文本检索方式。
方案2:发送端配置标准syslog头封装,避免接收端重复解析
如果可以修改发送端配置,在发送端输出JSON日志时,提前加上标准syslog报文头,接收端就不会把整个JSON当做普通消息体封装。发送端转发配置参考:
# 发送端配置转发时使用标准syslog格式封装JSON内容 *.* action(type="omfwd" target="127.0.0.1" port="20514" protocol="tcp" template="RSYSLOG_SyslogProtocol23Format" TCP_Framing="octet-counted")
该方案下接收端不需要做特殊JSON解析,rsyslog会自动识别报文头后的JSON载荷,不会出现localhost属性替换问题,长期稳定性最好,符合syslog标准规范。
方案3:调整隧道转发模式,避免源地址被替换为回环地址
如果使用SSH反向隧道,可在隧道参数中添加-g参数允许远程主机绑定到非回环地址,同时配合rsyslog的preservefqdn参数开启主机名保留,直接读取日志内携带的主机名字段,不做反向解析替换:
# 接收端全局配置添加 global(preservefqdn="on")
注意:该方案需要确保隧道两端网络连通性正常,避免非回环绑定出现端口暴露风险,仅建议测试环境使用。
内容的提问来源于stack exchange,提问作者Orisson
相关产品推荐
相关产品推荐

