2013年12月18日星期三

使用 goaccess 分析 nginx access.log


​不需要很强大,只需要够用。
安装,今天刚好赶上一个新版本的发布:
$ yum -y install glib2 glib2-devel ncurses ncurses-devel GeoIP GeoIP-devel
$ wget http://downloads.sourceforge.net/project/goaccess/0.7/goaccess-0.7.tar.gz
$ tar -xzvf goaccess-0.7.tar.gz
$ cd goaccess-0.7/
$ ./configure --enable-geoip --enable-utf8 
$ make
# make install
因为access 的format 不一样,所以需要修改一下, 我这里默认的 NCSA 也对不上,看看我的nginx 的 access log format:

    log_format  main  '$remote_addr $http_host $upstream_addr [$time_local] $request '
                      '"$status" $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" "$request_time"';
眼睛看了老半天,终于按空格对上号了(部分字段由于中间有空格,但是没有引号,所以又被多算了一列), vim ~/.goaccessrc:
date_format %d/%b/%Y
log_format %h %^ %^ %^[%d:%^] %^ %r %^ "%s" %b "%R" "%u" "%^" "%D"

上面这个保存为文件,就不用每次去按照下面的提示按 C 去修改了。(至于每个字段的含义,可以去官方查询,另外发现有些是没有,
也有可能是我没发现,比如 $upstream_addr, $http_x_forwarded_for, 没有暂时用 %^ 啰)

然后就是执行命令
$goaccess -f access.log
可以重定向输出为 csv 格式或者 html 格式,罗列的各种 top 分析比较清晰。

ps: 不足之处,缺少 hourly 的支持,比如我的想要对比相邻几个小时内的访问情况,来分析异常请求,这个在作者 github 上有个 issue,
     希望能够早点实现。
https://github.com/allinurl/goaccess/issues/8



haproxy 之 mysql 权限漏洞



    +-------------+        +-------------+          +------------+
    |   CLIENT    |+------>|  HAPROXY    |          | DB SERVER  |
    |  ANY WHERE  |        |   VIP 10.%  |+-------->|  10.%      |
    +-------------+        +-------------+          +------------+

通过haproxy 后,授权都是走内网。
mysql 之权限漏洞,-h 使用的是代理服务器的ip, haproxy 使用的最简单的配置。仅仅只是代理,未配置任何其它规则。
so,使用代理的 ip 连库,mysql 数据库服务器认为是代理来连接本机。而没有 real source,grant ip 无法去限制外部连接。
这是我从任意一个外部机器上连接看到的效果:
$ mysql -hxxxx -P49711 -uxxxx -pxxxx  
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 308044655
Server version: 5.5.23-log Source distribution

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
思考一下,解决方法三种:

1. 透明代理,配置 haproxy 为透明代理,直接可用 mysql 的 权限控制,但是,需要修改 haproxy 的iptables 
   规则,需要修改 db 服务器的网关。--> 不靠谱,要维护的点多,一出问题就悲剧。iptables 可能影响其它服务。

2. 使用 iptables,accept 固定 ip 列表。 --> 无法使用单个文件控制,iprange 太多,不方便维护。给个例子:
#iptables -A INPUT -p tcp --dport 49711 -m iprange --src-range 10.0.0.0/24 -j ACCEPT
 
#iptables -A INPUT -p tcp --dport 49711:49713 -s 122.226.199.49 -j DROP
3. 使用 haproxy 的 acl 规则,使用 whitelist,只需要修改一下配置,ip 维护单独存放到文件。--> 可行。
    白名单 list 从 /etc/hosts 文件中过滤出来,保留为文件 /etc/haproxy/whitelist
10.0.0.0/8
59.32.213.0/24
61.142.208.0/24
120.31.133.0/24
113.106.26.0/24
113.105.245.0/24
211.151.181.0/24
113.107.234.109
haproxy 配置增加 tcp-request 一行:
listen vdb 180.153.21.159:49711
        tcp-request content reject if !{ src -f /etc/haproxy/whitelist }
        mode tcp
        server vdb 10.11.80.128:49710 check inter 1000 rise 2 fall 3 weight 2
上面那一行也可以写成如下两行:
        tcp-request content accept if { src -f /etc/haproxy/whitelist }
        tcp-request content reject

ps: 要是像http 协议一样带一个 header,可以直接使用 forwardfor 搞定。