这里使用ELFK收集之前部署的k8sdemo,作为测试,就收集一个日志即可。
这里选择了cosmall日志,这个程序实质上是一个nginx程序,作为反向代理使用。
收集cosmall的日志
这里采用了写脚本,收集最近1小时的日志,并配置corntab
[root@VM-12-8-centos shell]# cat kube-nginx-log.sh
#!/bin/bash
. /root/.bash_profile
kubectl logs --since=1h mall-987568788-5bpqk >> /data/shell/access.log
[root@VM-12-8-centos shell]#
[root@VM-12-8-centos shell]#
[root@VM-12-8-centos shell]# crontab -l
#每小时收集一次日志
13 */1 * * * sh /data/shell/kube-nginx-log.sh > /dev/null 2>&1
因为之前配置均没有将日志挂载到存储上,所以采用kubectl logs的方式定时收集日志
filebeat配置
直接配置filebat收集access.log即可
[root@VM-12-8-centos filebeat]# egrep -v "#|^$" filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /data/shell/access.log
filebeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false
setup.template.settings:
index.number_of_shards: 3
setup.kibana:
output.logstash:
hosts: ["10.0.20.10:5044"]
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
logstash配置
logstash的fileter除了配置grok分析处理日志,还配置了geoip和useragent,date插件
[root@VM-20-10-centos conf.d]# cat logstash_to_elasticsearch.conf
# Sample Logstash configuration for creating a simple
# Beats -> Logstash -> Elasticsearch pipeline.
input {
beats {
port => 5044
}
}
filter {
grok {
match => { "message" => "%{IP:clientip} - (%{USERNAME:user}|-) \[%{HTTPDATE:timestamp}\] \"(%{WORD:request_verb} %{NOTSPACE:request} HTTP/%{NUMBER:httpversion}\s*|%{GREEDYDATA:request})\" %{NUMBER:status:int} %{NUMBER:body_sent:int} \"%{GREEDYDATA:http_referer}\" \"%{GREEDYDATA:http_user_agent}\" \"(%{IPV4:http_x_forwarded_for}|-)\"" }
remove_field => "message"
}
date {
match => [ "time_local", "dd/MMM/yyyy:HH:mm:ss Z" ]
}
geoip {
source => "clientip"
fields => ["city_name","country_name","ip"]
}
useragent {
source => "http_user_agent"
target => "acesss_useragent"
}
}
output {
elasticsearch {
hosts => ["http://10.0.20.10:9200"]
index => "nginx-accesslog-%{+YYYY.MM.dd}"
document_type => "nginx-accesslog"
template_overwrite => true
#user => "elastic"
#password => "changeme"
}
stdout {
codec =>rubydebug
}
}
elasticsearch配置
[root@VM-20-10-centos elasticsearch]# egrep -v "#" elasticsearch.yml
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
http.port: 9200
kibana配置
[root@VM-20-10-centos kibana]# egrep -v "#|^$" kibana.yml
server.port: 3306
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://10.0.20.10:9200"]
测试检查及数据可视化
启动各个程序后,检查索引情况
因为没有配置副本分区,所以索引状态为yellow,不过不影响我们测试,先忽略这个问题。
在kibana中配置nginx这个索引模式
可以看到,在logstash中配置的geoip,useragent插件分析处理后的相关信息,已在特定字段展示
可以根据这些字段,对访问量,访问方法,访问的url,来访ip所属国家,城市等,进行可视化的展示
收集匹配受攻击日志-grok表达式的进一步完善
在运行一段时间后,会发现有一些nginx日志logstash无法正常解析
10.244.0.0 - - [01/Jan/2023:07:46:19 +0000] "\x05\x01\x00" 400 157 "-" "-" "-"
10.244.0.0 - - [01/Jan/2023:07:53:13 +0000] "\x05\x01\x00" 400 157 "-" "-" "-"
10.244.0.0 - - [01/Jan/2023:09:52:31 +0000] "\x05\x01\x00" 400 157 "-" "-" "-"
10.244.0.0 - - [01/Jan/2023:09:53:49 +0000] "\x05\x01\x00" 400 157 "-" "-" "-"
比如如上的这种日志,没有请求方法,也没有请求url,但ngnix返回了400,一般情况,这种日志表示你的服务器受到了攻击,所以,对于这种情况的日志是一定要解析出来,以便及时发现的服务器的异常情况
所以我们将grok表达式完善如下
%{IP:clientip} - (%{USERNAME:user}|-) \[%{HTTPDATE:timestamp}\] \"(%{WORD:request_verb} %{NOTSPACE:request} HTTP/%{NUMBER:httpversion}\s*|%{GREEDYDATA:request})\" %{NUMBER:status:int} %{NUMBER:body_sent:int} \"%{GREEDYDATA:http_referer}\" \"%{GREEDYDATA:http_user_agent}\" \"(%{IPV4:http_x_forwarded_for}|-)\"
#其中的重点是这一段
(%{WORD:request_verb} %{NOTSPACE:request} HTTP/%{NUMBER:httpversion}\s*|%{GREEDYDATA:request})
对于请求的方法和url及http版本协议号,受攻击时,这一段是不会显示的
我们使用GREEDYDATA来匹配这种情况
修改logstash配置文件后重启,再重新配置kibana,可以看到,对于受攻击情况,已经在dashboard有展示
除了常用的get,post方法,还有其他方法的访问
使用KQL查询时,直接查询request:\x05\x01\x00会查询不出来,需要对”\“进行转义才可以查询
从官方文档可以看到相关说明