Nginx+Logstash+Elasticsearch+Kibana搭建网站日志分析系统笔记

前言

流程,nignx格式化日志成json,通过logstash直接采集到elasticsearch,然后通过kibana gui界面展示分析

要点nignx日志成json格式,避免nignx默认日志是空格,需要正则匹配,导致logstash占过多cpu
elasticsearch机配置防火墙,只让指定的logstash机访问
kibana只监听本地127.0.0.1使用nignx方向代理,nginx中配置Http Basic Auth账号密码登陆

比较粗略的笔记,备忘
安装java
yum install java-1.8.0-openjdk*

nginx配置

为了让nignx机跑logstash采集日志负载最低,建议直接生成json的方式,直接就可以用logstash读取写入到Elasticsearch

http{} 中定义 格式化日志成json

log_format logstash_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"http_x_forwarded_for":"$http_x_forwarded_for",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"request":"$request",'
'"url":"$uri",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"agent":"$http_user_agent",'
'"status":"$status"}';

server内输出日志 access_log可以配置多个同时输出,可以保留你以前的

access_log /data/wwwlogs/www.iamle.log iamle.com;
access_log /data/wwwlogs/www.iamle.com.logstash_json.log logstash_json;

nginx机安装Logstash1.5.x

rpm --import http://packages.elasticsearch.org/GPG-KEY-elasticsearch
cat > /etc/yum.repos.d/logstash.repo <<EOF
[logstash-1.5]
name=logstash repository for 1.5.x packages
baseurl=http://packages.elasticsearch.org/logstash/1.5/centos
gpgcheck=1
gpgkey=http://packages.elasticsearch.org/GPG-KEY-elasticsearch
enabled=1
EOF
yum clean all
yum install logstash

 

在目录 /etc/logstash/conf.d/
建立配置文件 nginx_json.conf

input {
file {
path => "/data/wwwlogs/www.iamle.com.logstash_json.log"
codec => json
}
}
filter {
mutate {
split => [ "upstreamtime", "," ]
}
mutate {
convert => [ "upstreamtime", "float" ]
}
}
output {
elasticsearch {
host => "elk.server.iamle.com"
protocol => "http"
index => "logstash-%{type}-%{+YYYY.MM.dd}"
index_type => "%{type}"
workers => 5
template_overwrite => true
}
}

service logstash start

日志存储机安装Elasticsearch1.7.x提供数据底层支持

rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
cat > /etc/yum.repos.d/elasticsearch.repo <<EOF
[elasticsearch-1.7]
name=Elasticsearch repository for 1.7.x packages
baseurl=http://packages.elastic.co/elasticsearch/1.7/centos
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1
EOF
yum clean all
yum install elasticsearch

配置文件
配置数据保存位置

vim /etc/elasticsearch/elasticsearch.yml
# Can optionally include more than one location, causing data to be striped across
# the locations (a la RAID 0) on a file level, favouring locations with most free
# space on creation. For example:
#
path.data: /data
目录会自动生成,只需要指定一个空目录就可以了

service elasticsearch start

centos7
systemctl start elasticsearch
systemctl status elasticsearch
elasticsearch.service - Elasticsearch
Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; disabled)
Active: active (running) since Fri 2015-09-04 15:37:08 CST; 1s ago
Docs: http://www.elastic.co
Main PID: 19376 (java)
CGroup: /system.slice/elasticsearch.service
└─19376 /bin/java -Xms256m -Xmx1g -Djava.awt.headless=true -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -X...
Sep 04 15:37:08 elk systemd[1]: Starting Elasticsearch...
Sep 04 15:37:08 elk systemd[1]: Started Elasticsearch.
检查是否已经成功开启
ss -ltnp |grep 9200

centos7配置firewalld固定ip可访问elasticsearch
systemctl start firewalld.service
systemctl status firewalld.service

 

只允许nignx机访问elasticsearch机9200 9300端口

firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" \
source address="10.8.8.2" \
port protocol="tcp" port="9200" accept"

firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" \
source address="10.8.8.2" \
port protocol="tcp" port="9300" accept"
firewall-cmd --reload

iptables -L -n |grep 9200
ACCEPT tcp -- 10.8.8.2 0.0.0.0/0 tcp dpt:9200 ctstate NEW

 

安装Kibana4展示Elasticsearch中的数据

 

wget https://download.elastic.co/kibana/kibana/kibana-4.1.1-linux-x64.tar.gz
tar zxvf kibana-4.1.1-linux-x64.tar.gz
cd kibana-4.1.1-linux-x64
修改配置文件
vim /usr/local/kibana-4.1.1-linux-x64/config/kibana.yml
# Kibana is served by a back end server. This controls which port to use.
port: 5601

# The host to bind the server to.
#监听本地地址 用nignx反向代理
host: "127.0.0.1"

nohup ./bin/kibana &

检查是否已经成功开启
ss -ltnp |grep 5601

 

使用nignx反向代理kibana
nginx配置Http Basic Auth账号密码登陆
http://trac.edgewall.org/export/10770/trunk/contrib/htpasswd.py (nginx wiki里推荐的)
运行示例
chmod 777 htpasswd.py
./htpasswd.py -c -b htpasswd username password
#-c为生成文件 htpasswd为文件名

server
{
listen 80;
#listen [::]:80;
server_name elk.server.iamle.com;

location / {
auth_basic "Password please";
auth_basic_user_file /usr/local/nginx/conf/htpasswd;
proxy_pass http://127.0.0.1:5601/;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

老版本
https://download.elastic.co/kibana/kibana/kibana-3.1.3.tar.gz
https://www.elastic.co/downloads/past-releases/kibana-3-1-3

参考

http://kibana.logstash.es/
https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-repositories.html

扩展centos7 firewall的使用

 

检查防火墙状态
firewall-cmd --stat

临时开放ftp服务
firewall-cmd --add-service=ftp
永久开放ftp服务
firewall-cmd --add-service=ftp --permanent
关闭ftp服务
firewall-cmd --remove-service=ftp --permanent
配置防火墙在public区域永久开放http服务
firewall-cmd --permanent --zone=public --add-service=http
加入指定开放端口
firewall-cmd --add-port=1324/tcp

为了让之前的设定生效当然要重启服务咯
systemctl restart firewalld
或者使用下面的命令免去重启服务(防火墙策略配置后重新载入)
firewall-cmd --complete-reload
firewall-cmd --reload (这两句功能相同)

检查ftp服务的21端口是否开放
iptables -L -n | grep 21
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:21 ctstate NEW

查询ftp服务启用状态
firewall-cmd --query-service ftp

查看当前规则
firewall-cmd --list-all

仅允许部分IP访问本机服务配置
firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" \
source address="192.168.0.4/24" service name="http" accept"

仅允许部分IP访问本机端口配置
firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" \
source address="192.168.0.4/24" \
port protocol="tcp" port="8080" accept"

 

故障现象

微信服务号发送模版消息失败,生成事件二维码图片也失败

代码没有任何改动,莫名其妙就这样了

# 调试过程
检查后发现如下返回错误

{
“errcode”: 40001,
“errmsg”: “invalid credential, access_token is invalid or not latest”
}
{
“errcode”: 40001,
“errmsg”: “invalid credential, access_token is invalid or not latest”
}
检查微信所有api相关参数是否正确,检查都是对的
重新获取新的access_token测试能通过
一度怀疑是不是缓存有效期是不是出问题了
过期了应该是下图的样子42001,而不是40001呀

{
“errcode”: 42001,
“errmsg”: “access_token expired”
}
 
 
{
“errcode”: 42001,
“errmsg”: “access_token expired”
}
https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=CM2Dt8rXdcMB5k_In4mGRF6M2jT_NYAakU4RyrHyj1uRXNxdmupGDRhWYA_DSgG_LRgcwXRbsJCVrR5IVBl5rx3jNRyo-T_xPTJ4ZhrjCxc
 

找到问题

http://segmentfault.com/q/1010000002998425
最后一句话点醒了我
yi5344 说道 access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
 
突然想起来,在我们的系统当中有两处独立的微信公众号SDK调用,缓存access_token是独立工作的。
对于同一个微信公众号来说 access_token 是一把钥匙。
如果本地access_token多处单独存储和缓存,这样会导致多处都去更新微信api中access_token值,当更新发生的时候这样只有一处是正常的,其他地方本地的access_token就失效了。
 

解决方法

对于同一个微信公众账号的  access_token 只能存储在一个地方。

故障现象

苏州移动网络宽带在使用企业QQ的时候企业QQ群里发送图片失败,即便再次重发也不行,所有人在企业QQ群里面发图都不行

使用电信线路正常,普通QQ也没问题,企业QQ使用代理登陆正常

故障分析

使用网络抓包分析看到底是什么情况

由于使用wireshark无法指定进程抓包,也没法看到是哪个进程的包,虽然可以用没运行其他网络软件的系统来进行抓包分析。

我使用更方便的工具Microsoft Message Analyzer来抓包分析。(

Add Columns增加字段 PID,

找到你要抓包的网络软件相应的PID号,我这里企业QQ当前运行的PID是4100

View Filter 写

*Pid == 4100

还推荐一款可以指定进程抓包的软件SRSniffer

 

通过抓包得知,普通QQ私信和群发送图片和接收都是走的http协议

企业QQ私信发图片和接收图片走的http协议,企业QQ群发送图片和接收图片是走的UDP协议。

当在企业QQ群里发送图片的时候,同时观察抓包情况。

仔细观察分析发现,企业QQ发送图片会开始发送UDP数据包,腾讯的服务器ip无返回数据包。

把无返回数据包的ip进行ping和tracert操作,发现无法ping,也无法tracert,证明到这个ip网络是不通的。

我这里是routeros路由器,多线接入,所以把发现移动线路不通的ip策略路由到电信线路上去,这下企业QQ群图片就发送正常了。

我这里抓到的企业QQ群图片发送腾讯服务器IP地址为(这里肯定是不全的,只采集到部分发现的)

183.60.16.207
183.60.56.92
183.60.48.171
183.60.18.38
183.60.62.185

查了下ip归属,居然都是电信的ip,看来企业QQ这里有问题啊,为什么没解析到对应的线路上去。

还不知道有多少ip不通,我先治标把183.60.0.0/16全路由到电信线路上去了。

解决方案

1、如果自己可以做路由,把不通的ip走其他线路,如果只有一个线路可以用vpn的方式解决,走vpn里面去。治标。

2、立马联系移动的客户经理,联系到他们的网络软调,反馈这些ip不通的问题,做路由调通。治本。

3、在企业QQ上反馈,为什么企业QQ群发送图片,移动带宽线路,为什么也是电信ip的服务器,应该智能分配到移动线路的ip上去,或者说有BGP也行

 

 

后记2015年12月企业QQ群出现群里面接收图片有的能接收有的不能接收

更新最新版企业QQ无效,换了一个网络还是无效
通过抓包分析知道企业QQ群接收图片会先从183.60.62.185 udp 8000 去尝试取图片数据,多次尝试失败后会走http协议到另外的地址下载图片
除了慢以外,而且有时候图片也显示不了
办公网络 ping 183.60.62.185 不通, 用17ce多节点ping也不通
思路,通过dst-nat目标nat修改nat包实现重定向
需要重定向183.60.62.185 tcp 443 udp 80 到 另外一个企业QQ群图片服务器 183.60.18.38 tcp 443 udp 80
路由器使用的是routeros,所以直接改nat包实现重定向即可,命令为

/ip firewall nat
add action=dst-nat chain=dstnat comment=\
    "\C6\F3\D2\B5qq\C8\BA\CD\BC\C6\AC\B7\FE\CE\F1\C6\F7\D6\D8\B6\A8\CF\F2udp" \
    disabled=no dst-address=183.60.62.185 protocol=udp to-addresses=\
    183.60.18.38 to-ports=0-65535
add action=dst-nat chain=dstnat comment=\
    "\C6\F3\D2\B5qq\C8\BA\CD\BC\C6\AC\B7\FE\CE\F1\C6\F7\D6\D8\B6\A8\CF\F2tcp" \
    disabled=no dst-address=183.60.62.185 protocol=tcp to-addresses=\
    183.60.18.38 to-ports=0-65535

故障

vagrant管理的centos虚拟机在做过 yum -y update 后更新了系统以及内核

然后下一次vagrant up的时候共享目录不能挂载到/vagrant目录( /sbin/mount.vboxsf: mounting failed with the error: No such device)

详细信息

Failed to mount folders in Linux guest. This is usually because
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:

mount -t vboxsf -o uid=`id -u vagrant`,gid=`getent group vagrant | cut -d: -f3` vagrant /vagrant
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant` vagrant /vagrant

The error output from the last command was:

/sbin/mount.vboxsf: mounting failed with the error: No such device

搜索资料知道原因是yum update更新了内核,但是没有更新VirtualBox的连接的问题。

需要执行

sudo /etc/init.d/vboxadd setup

修复即可

 

资料

‘vagrant up’ fails to mount linked directory /vagrant

Vagrant up遇到mount no such device的问题

缘由

PHP Multipartform-data远程DOS攻击漏洞,恶意构造的请求会导致服务器的cpu使用率达到100%。
全版本受影响,危害严重。请尽快修复漏洞。

受影响的软件及系统:

PHP 5.0.0 – 5.0.5
PHP 5.1.0 – 5.1.6
PHP 5.2.0 – 5.2.17
PHP 5.3.0 – 5.3.29
PHP 5.4.0 – 5.4.40
PHP 5.5.0 – 5.5.24
PHP 5.6.0 – 5.6.8

未受影响的软件及系统:

PHP 5.4.41
PHP 5.5.25
PHP 5.6.9
以下是百度同学的源码漏洞分析
PHP multipart/form-data 远程DOS漏洞 {:target=”_blank“}

更新到官网最新版本得到修复

http://php.net/ChangeLog-5.php#5.4.41
http://php.net/ChangeLog-5.php#5.5.25
http://php.net/ChangeLog-5.php#5.6.9

官网的漏洞报告和讨论

Sec Bug #69364 PHP Multipart/form-data remote dos Vulnerability{:target=”_blank“}
内容摘抄
鸟哥也在关注这个漏洞哟
[2015-05-15 05:37 UTC] laruence@php.net
does this needs a CVE id?
有人问 php5.3.x系列的修复呢?
[2015-05-19 03:04 UTC] welpher dot yu at gmail dot com
what about 5.3?
官方回答请看php版本支持信息
[2015-05-19 03:47 UTC] stas@php.net
5.3 is EOL since last year: http://php.net/supported-versions.php

php版本支持信息 {:target=”_blank“}中我们看到 php5.3支持已经过期了,也就是就算是有严重bug官方也不会修复php5.3.x系列了.
php5.3.x系列的最终版是php5.3.29

总结

如果你线上使用的是 php5.4.x or php5.5.x or php5.6.x请升级到官网最新版本
如果你使用的是php5.3.29 or php5.3.x 建议升级到 php5.4.41
其中php升级带来的代码兼容问题请结合自己的项目参考官方文档进行升级

如果是php5.3.x系列想停留在现在的版本,的自己修改php源码,修复本漏洞.

php5.3.29的民间补丁

https://coding.net/u/simapple/p/oldphppatch/git

下载里面的补丁到php源码目录,然后执行

php5.3.x

patch p1 < ./php5.3patch

php5.2.x

patch p1 < ./php5.2patch

重新编译即可

 

在线检查工具

紧急安全通告在线检查-绿盟{:target=”_blank“}

前言

当我们使用haproxy 做负载均衡器的时候,负载均衡多个后端服务器,但是有一个问题,负载均衡后端的服务器的是需要占用haproxy机端口的.
tcp的端口一共65535个除去保留端口,基本也就64k可用的样子.

那么f5之类套着硬件皮的负载均衡器是怎么做到的可以负载几十万的连接数的?

其实f5机本身自己使用了多个内网ip地址,一个f5上的内网ip地址拥有连接后端64k连接的能力.

那么haproxy支持这样的功能么,从而负载更高的连接数么?

经过灿哥的分享,我们知道是可以的,只要给haproxy机配置多个lan内网ip,haproxy机可以通过多个lan内网ip去负载均衡后端服务器.

一个内网ip去负载一台后端服务,这样一个haproxy内网ip就有了长64k连接的负载能力了.

配置haproxy 用多个lan内网ip做负载均衡,以突破haproxy机只支持64k连接(突破单ip 65535端口限制)

配置例子
haproxy负载均衡机
外网ip: 8.8.8.8
haproxy内网ip1: 10.8.8.2
haproxy内网ip2: 10.8.8.3
haproxy内网ip3: 10.8.8.4

后端web1内网ip: 10.8.8.10
后端web2内网ip: 10.8.8.11
后端web3内网ip: 10.8.8.12

server web1 10.8.8.10 : 80 check source 10.8.8.2 : 1025 – 65000
server web2 10.8.8.11 : 80 check source 10.8.8.3 : 1025 – 65000
server web3 10.8.8.12 : 80 check source 10.8.8.4 : 1025 – 65000

如果haproxy机只有一个内网ip 10.8.8.2 去反向代理所有后端,总连接数就只有64k,如果这样配置利用了多个ip去链接后端那么一个haproxy就可以64k连接
从而让haproxy机支持甚至几十w的连接数了.

haproxy官方手册相关

haproxy 手册位置

source <addr>[:<pl>[-<ph>]] [usesrc { <addr2>[:<port2>] | client | clientip } ]
source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | hdr_ip(<hdr>[,<occ>]) } ]
source <addr>[:<pl>[-<ph>]] [interface <name>] ...
The "source" parameter sets the source address which will be used when
connecting to the server. It follows the exact same parameters and principle
as the backend "source" keyword, except that it only applies to the server
referencing it. Please consult the "source" keyword for details.

Additionally, the "source" statement on a server line allows one to specify a
source port range by indicating the lower and higher bounds delimited by a
dash ('-'). Some operating systems might require a valid IP address when a
source port range is specified. It is permitted to have the same IP/range for
several servers. Doing so makes it possible to bypass the maximum of 64k
total concurrent connections. The limit will then reach 64k connections per
server.

Supported in default-server: No

Doing so makes it possible to bypass the maximum of 64k total concurrent connections. The limit will then reach 64k connections per server.

这样做可以绕过64 k的最大并发连接。限制将达到64 k每台后端服务器的连接。也就是说我3台web后端每台64k,haproxy机上就是 64k * 3 = 192k