今天在配置confluence邮件功能的时候,启动sendmail竟然需要很长时间,网上查了查,有很多人碰到类似问题,但是一般都是关掉sendmail服务或者关掉dns了事,咱们现在要用它,自然不能关掉了事,dns也不能关,关了服务器没法解析域名

毫无疑问,sendmail去做dns lookup,并且无法lookup到域名,在等待解析超时!

resolv里面也指定了nameserver,应该能正常做dns解析了,既然他无法解析域名,自然这是个本地域名,难道是hosts里面的问题,查看了一下hosts文件:

# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1       localhost.localdomain   localhost
192.168.1.28    rdosrv

好像也没发现啥不对的,他在解析啥呢,看看log去,找到/var/log/maillog(也可能在messages),看到如下内容:

Dec 11 14:25:01 rdosrv sendmail[22710]: starting daemon (8.13.8): SMTP+queueing@01:00:00
Dec 11 14:25:01 rdosrv sm-msp-queue[22717]: My unqualified host name (rdosrv) unknown; sleeping <span style="color: #0000ff;">for</span>
 retry
Dec 11 14:28:08 rdosrv sendmail[22803]: My unqualified host name (rdosrv) unknown; sleeping <span style="color: #0000ff;">for</span>
 retry
Dec 11 14:35:23 rdosrv sendmail[22944]: My unqualified host name (rdosrv) unknown; sleeping <span style="color: #0000ff;">for</span>
 retry
Dec 11 14:35:57 rdosrv sendmail[22962]: My unqualified host name (rdosrv) unknown; sleeping <span style="color: #0000ff;">for</span>
 retry
Dec 11 14:36:54 rdosrv sendmail[22979]: My unqualified host name (rdosrv) unknown; sleeping <span style="color: #0000ff;">for</span>
 retry

竟然是无法解析rdosrv,有点意思,直接去ping rdosrv自然是没问题,突然想到好像FQDN里面规定域名必须用”.”结尾,难道是hosts里面少了一个”.”,尝试修改hosts文件:

# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1       localhost.localdomain   localhost
192.168.1.28    rdosrv.     rdosrv

启动sendmail,刷一下就启动了,呵呵

回头想想,问题其实很简单,但是在网上却没找到什么好的方案,说明都挺懒得,能绕都绕过去了.

原来GROUP_CONCAT中,是支持GROUP内排序的,自己好土。。

SELECT student_name,
  GROUP_CONCAT(DISTINCT test_score ORDER BY test_score DESC SEPARATOR ' ')
  FROM student
  GROUP BY student_name;

nagios使用邮件来告警通知是很常见的一种方式。

1. 使用sendEmail来发送邮件

sendEmail工具非常好用。具体内容参见:

如何使用sendEmail发送邮件

2. 创建一个联系人

# vim /usr/local/nagios/etc/objects/contacts.cfg 
define contact{
        contact_name                    mobei
        alias                           mobei
        service_notification_period     24x7
        host_notification_period        24x7
        service_notification_options    w,u,c
        host_notification_options       d,u
        service_notification_commands   notify-service-by-email
        host_notification_commands      notify-host-by-email
        email                           【You email address】
        }

3. 创建一个组

define contactgroup{
        contactgroup_name       ops
        alias                   ops
        members                 mobei
        }

4. 修改发送邮件命令

# vim /usr/local/nagios/etc/objects/commands.cfg
# 'notify-host-by-email' command definition
define command{
        command_name    notify-host-by-email
        command_line  /usr/local/bin/sendEmail -l /tmp/sendEmail.log -f jiank@126.com -t $CONTACTEMAIL$ -s smtp.126.com -u "$HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$" -xu jiank@126.com -xp jiankong -m "Service: $SERVICEDESC$\\nHost: $HOSTALIAS$\\nAddress: $HOSTADDRESS$  State: $SERVICESTATE$\\nDate/Time: $SHORTDATETIME$\\nInfo:$SERVICEOUTPUT$"
        }

# 'notify-service-by-email' command definition
define command{
        command_name    notify-service-by-email
        command_line  /usr/local/bin/sendEmail -l /tmp/sendEmail.log -f jiank@126.com -t $CONTACTEMAIL$ -s smtp.126.com -u "$HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$" -xu jiank@126.com -xp jiankong -m "Service: $SERVICEDESC$\\nHost: $HOSTALIAS$\\nAddress: $HOSTADDRESS$  State: $SERVICESTATE$\\nDate/Time: $SHORTDATETIME$\\nInfo:$SERVICEOUTPUT$"
        }

5. 指定监控项目。如:

define service {
    use                 generic-service
    hostgroup_name          Mongo Servers
    service_description     Mongo Mapped Memory Usage
    check_command           check_mongodb!10.0.0.160!12345!'ttlsa'!'www.ttlsa.com'!memory_mapped!20!28
    contact_groups          ops
}

sendEmail是一个轻量级,命令行的SMTP邮件客户端。如果你需要使用命令行发送邮件,那么sendEmail是非常完美的选择:使用简单并且功能强大.这个被设计用在php、bash
perl和web站点使用。
以上是sendEmail的简单介绍,千万不要和sendmail搞混掉了。用了sendEmail你将不在喜欢sendmail了.

下载安装sendEmail

sendEmail下载地址:http://caspian.dotconf.net/menu/Software/SendEmail/
# wget http://caspian.dotconf.net/menu/Software/SendEmail/sendEmail-v1.56.tar.gz //下载1.56版本
# tar -xzvf sendEmail-v1.56.tar.gz //解压后就可以使用了
# mv sendEmail /usr/local/bin/

发送邮件

#  /usr/local/bin/sendEmail -f ttlsafrom@163.com -t ttlsato@qq.com \
    -s smtp.163.com -u "我是邮件主题" -o message-content-type=html \
    -o message-charset=utf8 -xu ttlsafrom@163.com -xp 123456 -m "我是邮件内容"

命令说明:

/usr/local/bin/sendEmail 命令主程序
-f ttlsafrom@163.com  发件人邮箱
-s smtp.163.com       发件人邮箱的smtp服务器
-u "我是邮件主题"     邮件的标题
-o message-content-type=html   邮件内容的格式,html表示它是html格式
-o message-charset=utf8        邮件内容编码
-xu ttlsafrom@163.com          发件人邮箱的用户名
-xp 123456               发件人邮箱密码
-m "我是邮件内容"        邮件的具体内容

发送成功之后会有如下提示:
Jul 29 15:02:53 e10074 sendEmail[26347]: Email was sent successfully!

sendEmail使用命令帮助

[root@li229-122 scripts]# sendEmail --help

sendEmail-1.56 by Brandon Zehm <caspian@dotconf.net>

Synopsis:  sendEmail -f ADDRESS [options]

Required:
-f ADDRESS                from (sender) email address
* At least one recipient required via -t, -cc, or -bcc
* Message body required via -m, STDIN, or -o message-file=FILE

Common:
-t ADDRESS [ADDR ...]     to email address(es)
-u SUBJECT                message subject
-m MESSAGE                message body
-s SERVER[:PORT]          smtp mail relay, default is localhost:25

Optional:
-a   FILE [FILE ...]      file attachment(s)
-cc  ADDRESS [ADDR ...]   cc  email address(es)
-bcc ADDRESS [ADDR ...]   bcc email address(es)
-xu  USERNAME             username for SMTP authentication
-xp  PASSWORD             password for SMTP authentication

Paranormal:
-b BINDADDR[:PORT]        local host bind address
-l LOGFILE                log to the specified file
-v                        verbosity, use multiple times for greater effect
-q                        be quiet (i.e. no STDOUT output)
-o NAME=VALUE             advanced options, for details try: --help misc
-o message-content-type=<auto|text|html>
-o message-file=FILE         -o message-format=raw
-o message-header=HEADER     -o message-charset=CHARSET
-o reply-to=ADDRESS          -o timeout=SECONDS
-o username=USERNAME         -o password=PASSWORD
-o tls=<auto|yes|no>         -o fqdn=FQDN

Help:
--help                    the helpful overview you're reading now
--help addressing         explain addressing and related options
--help message            explain message body input and related options
--help networking         explain -s, -b, etc
--help output             explain logging and other output options
--help misc               explain -o options, TLS, SMTP auth, and more
1 删除0字节文件 find . -type f -size 0 -exec rm -rf {} \;
find . type f -size 0 -delete
2 查看进程,按内存从大到小排列 ps -e -o “%C : %p : %z : %a”|sort -k5 -nr
3 按cpu利用率从大到小排列 ps -e -o “%C : %p : %z : %a”|sort -nr
4 打印说cache里的URL grep -r -a jpg /data/cache/* | strings | grep “http:” | awk -F’http:’ ‘{print “http:”$2;}’
5 查看http的并发请求数及其TCP连接状态 netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
6 sed在这个文里Root的一行,匹配Root一行,将no替换成yes。 sed -i ‘/Root/s/no/yes/’ /etc/ssh/sshd_config
7 如何杀掉mysql进程 ps aux |grep mysql |grep -v grep  |awk ‘{print $2}’ |xargs kill -9
killall -TERM mysqld
kill -9 `cat /usr/local/apache2/logs/httpd.pid`
8 显示运行3级别开启的服务(从中了解到cut的用途,截取数据) ls /etc/rc3.d/S* |cut -c 15-
9 如何在编写SHELL显示多个信息,用EOF cat << EOF
+————————————————————–+
|   === Welcome to Tunoff services ===                         |
+————————————————————–+
EOF
10 for的用法(如给mysql建软链接) cd /usr/local/mysql/bin
for i in *
do ln /usr/local/mysql/bin/$i /usr/bin/$i
done
11 取IP地址 ifconfig eth0 |grep “inet addr:” |awk ‘{print $2}’|cut -c 6-
ifconfig | grep ‘inet addr:’| grep -v ’127.0.0.1′ |cut -d: -f2 | awk ‘{ print $1}’
12 内存的大小 free -m |grep “Mem” | awk ‘{print $2}’
13 查看80端口的连接,并排序 netstat -an -t | grep “:80″ | grep ESTABLISHED | awk ‘{printf “%s %s\n”,$5,$6}’ | sort
14 查看Apache的并发请求数及其TCP连接状态 netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
15 统计一下服务器下面所有的jpg的文件的大小 find / -name *.jpg -exec wc -c {} \;|awk ‘{print $1}’|awk ‘{a+=$1}END{print a}’
16 CPU的数量 cat /proc/cpuinfo |grep -c processor
17 CPU负载 cat /proc/loadavg
18 CPU负载 mpstat 1 1
19 内存空间 free
20 磁盘空间 df -h
21 如发现某个分区空间接近用尽,可以进入该分区的挂载点,用以下命令找出占用空间最多的文件或目录 du -cks * | sort -rn | head -n 10
22 磁盘I/O负载 iostat -x 1 2
23 网络负载 sar -n DEV
24 网络错误 netstat -i
cat /proc/net/dev
25 网络连接数目 netstat -an | grep -E “^(tcp)” | cut -c 68- | sort | uniq -c | sort -n
26 进程总数 ps aux | wc -l
27 查看进程树 ps aufx
28 可运行进程数目 vmwtat 1 5
29 检查DNS Server工作是否正常,这里以61.139.2.69为例 dig www.baidu.com @61.139.2.69
30 检查当前登录的用户个数 who | wc -l
31 日志查看、搜索 cat /var/log/rflogview/*errors
grep -i error /var/log/messages
grep -i fail /var/log/messages
tail -f -n 2000 /var/log/messages
32 内核日志 dmesg
33 时间 date
34 已经打开的句柄数 lsof | wc -l
35 网络抓包,直接输出摘要信息到文件。 tcpdump -c 10000 -i eth0 -n dst port 80 > /root/pkts
36 然后检查IP的重复数 并从小到大排序 注意 “-t\  +0″ 中间是两个空格,less命令的用法。 less pkts | awk {‘printf $3″\n”‘} | cut -d. -f 1-4 | sort | uniq -c | awk {‘printf $1″ “$2″\n”‘} | sort -n -t\  +0
37 kudzu查看网卡型号 kudzu –probe –class=network

期待着复活节长周末,无心恋战~

上周参加一个 workshop 从微软 speaker 那里拿到几张 Microsoft Azure 的 promo 卡片,貌似可以购买200美元的 Azure 服务。到 http://aka.ms/azurecode 输入 promo code 等待24小时等通知,然后看邮件说明就可以用了。登录 Microsoft Azure 后惊讶发现居然挺好用的,至少比 Amazon EC2 要好用得多,Amazon EC2 弄的太复杂,单是那个价格表就让人看晕,第一次试用 Amazon EC2 的时候有点摸不着北~

Microsoft Azure 界面简单清晰,要创建的服务一目了然,命名一看就知道要干什么,非常赞。虚拟机就叫虚拟机(Virtual Machine)嘛,Amazon 管虚拟机叫实例(Instance),Instances 还分什么 On-Demand Instances 和 Reserved Instances,Reserved Instances 里面又分 Light, Medium, Heavy;硬盘就是硬盘(disk)嘛,为啥 Amazon 一定要叫 Elastic Block Store (EBS) 呢,哦,还有,EBS Standard 和 EBS Provisioned 价格是不一样的,云计算一定要云里来雾里去吗?!

Microsoft Azure 平台上可以创建很多服务,网站、虚拟机、云服务、移动服务、存储、SQL 数据库、缓存、CDN 等等,几乎包括了云技术的方方面面,很强大。大家熟悉的优秀的 VPS 服务商 Linode 只相当于 Azure 里面的一个功能~

填好虚拟机的 DNS 名、选择虚拟机的操作系统和配置、记住用户名、输入密码、选择数据中心就可以了:

azure1

创建成功后进入虚拟机的控制面板:

azure2

虚拟机性能监控不能少:

azure3

如果安装了 nginx/apache 之类的服务器,更改了 ssh 端口之类的别忘了在控制面板里把相应的端口打开:

azure4

 

动态规划

基本上就是说:你追一个MM的时候,需要对该MM身边的各闺中密友都好,这样你追MM这个问题就分解为对其MM朋友的问题,只有把这些问题都解决了,最终你才能追到MM。因此,该问题适用于聪明的MM,懂得“看一个人,不是看他如何对你,而是看他如何对他人。”的道理,并且对付这样的MM总能得到最优解。但确定是开销较大,因为每个子问题都要好好对待……

 

贪心法

基本上就是:你追一个MM的时候,从相识到相知,每次都采用最aggressive的方式,进攻进攻再进攻!从不采用迂回战术或是欲擒故纵之法!目标是以最快的速度确立两人的关系。该法优点是代价小,速度快,但缺点是不是每次都能得到最优解……、

回溯算法

基本上就是:追一个MM,但也许你还是情窦初开的新手,不知道如何才能讨得MM的欢心,于 是你只好一条路一条路的试,MM不开心了,你就回溯回去换另一种方式。当然其间你也许会从某些途径得到一些经验,能够判断哪些路径不好,会剪枝(这就是分支估界了)。你也可以随机选择一些路径来实施,说不定能立杆见影(这就是回溯的优化了)但总的来说,你都需要一场持久战……该算法一般也能得到最优解,因为大多数MM会感动滴!!但其缺点是开销大除非你是非要谈一场恋爱不可,否则不推荐使用。特别是你可能还有许多其他的事情要做,比如学习,比如事业……

 

NP完全问题

呵呵,那你为什么那么贱,非要去追呢?记住:“天涯何处无芳草!” . 不过如果你“非如此不可”的话,建议升级你的硬件,好好学习,好好工作,加强实力,人到中年的时候也许你能解开NP难……

 

网络流

追MM的时候总避免不了送礼物,但是你老是直接送礼物就会给MM造成很大的压力,于是你就想到了通过朋友来转送的方法。你希望送给MM尽可能多的礼物,所以就是需要找到一种配送方案,就是最大流了。然而你请别人帮忙并不是不要开销的,你让A同学拿去给B同学可能需要一些花费,自然你不是一个大款,想最小化这个花费,那么就是最小费用最大流了……

 

NP

在你追了若干美女都失败告终后,你发现有一批美女追起来是一样困难的,如果你能追到其中任何一个就能追到其他所有的美女,你把这样的女人叫作NP-Complete。P=NP:这是一个美好的猜想,追美女和恐龙的难度其实一样。APX与Random:NP的美女难追,你无法完全占有她。你只好随机的去靠近她装作若无其事;或者用一种策略,追到她的一个approximation ratio,例如50%。APX-hard:这样的女人,连一个固定的百分比都不给你,还是另谋高就吧。

 

匹配

从初中到高中到大学大家追来追去,就是个二分图匹配的过程….”和谐社会”应该就一个最大匹配…

可是后来有某些MM同时跟>1个人发展,违背了匹配的基本原则…大家都很BS之…然后最近断背山很火,人们惊奇得发现原来还可以是 任意图匹配…

 

深度优先和广度优先:

深度优先就是追一个mm追到底,直到失败然后换个mm继续追……

广度优先就是同时追多个mm,一起发展……

 

遍历

前序遍历就是直接搞定MM,然后搞定她爸妈(左)和你自己爸妈(右)。

中序遍历就是先搞定未来岳父岳父,然后搞定她,最后告诉你爸妈。

后序遍历就是,让未来的岳父岳母和自己爸妈都觉得你们合适之后,才对MM下手,这个时候就没有障碍了啊。

 

STL

某位贝尔实验室的大牛在追了N个MM后,为了造福后来人,总结了自己的经验,出了本《 追MM求爱秘笈大全》,英文名叫Standard courTing Library,(/* court : vt.向…献殷勤, 追求; vi.求爱)缩写为 STL. 广大同学在使用STL后,惊喜地发现追MM变得异常方便,大大缩短了时间和精力…

VPN大家耳熟能详,但是socks用到的人比较少,那什么是socks呢?请看第二段或者百度百科,socks分别有4和5两个版本,现在5为主流。工作中经常用VPN访问国外,但是同时国内的速度又慢了,让人很纠结,实际上这个时候可以考虑使用socks。指定某一个程序使用国外socks即可。这样国内国外速度同时有保证。

SOCKS是什么:防火墙安全会话转换协议 (Socks: Protocol for sessions traversal across firewall securely) SOCKS 协议提供一个框架,为在 TCP 和 UDP 域中的客户机/服务器应用程序能更方便安全地使用网络防火墙所提供的服务。这个协议从概念上来讲是介于应用层和传输层之间的 “中介层(shim-layer)”,因而不提供如传递 ICMP 信息之类的网络层网关服务。

开始我们的socks之旅吧,安装配置一直到最后的测试,请接着往下看。

1. 安装socks 5
1.1 安装依赖开发库

# yum install pam-devel openldap-devel openssl-devel

1.2 安装socks 5

# tar -xzvf ss5-3.8.9-8.tar.gz
# cd ss5-3.8.9
# ./configure
# make
# make install

2. socks 5配置
2.1 修改配置文件

# vim /etc/opt/ss5/ss5.conf
auth 0.0.0.0/0 – -
改为
auth 0.0.0.0/0 – u
permit – 0.0.0.0/0 – 0.0.0.0/0 – – – – -
改成为
permit u 0.0.0.0/0 – 0.0.0.0/0 – – – – -

3. 添加socket 5用户

# cat /etc/opt/ss5/ss5.passwd
 ##用户  密码
ttlsa 123456

4. 启动socket 5

# sh /etc/rc.d/init.d/ss5 start
doneting ss5...

默认情况ss5文件没有执行权限,如果觉得使用sh来启动麻烦,那么按如下方法:

# chmod u+x /etc/rc.d/init.d/ss5
# chkconfig --add ss5 //可选
# chkconfig ss5 on //可选
# service ss5 start

5. 查看是否启动

# netstat -lntp  | grep ss5
tcp        0      0 0.0.0.0:1080   0.0.0.0:*      LISTEN      14262/ss5

默认端口1080

6. 测试socks5
安装Proxifier,默认情况所有请求都走socks5.打开百度,输入IP,可以看到如下结果是我们运维生存时间(ttlsa.com)的ip地址

socks5-test

7. 常见错误
7.1 缺少PAM

configure: error: *** Some of the headers weren't found ***
# yum -y install pam-devel

8. 结束
socks5你安装成功了吗?这会儿我还没关闭socks5,你可以拿本章的账号密码做个测试。喜欢ttlsa的朋友,请继续关注我们,你们的支持是对我们最大的鼓舞。

 

SystemTap

 

应用:

对管理员,SystemTap可用于监控系统性能,找出系统瓶颈,而对于开发者,可以查看他们的程序运行时在linux系统内核内部的运行情况。主要用于查看内核空间事件信息,对用户空间事件的探测,目前正加紧改进。

安装

1、SystemTap的安装及使用需要针对正在使用的内核安装相应的kernel-devel、kernel-debuginfo和kernel-debuginfo-common包,以插入探针。

2、安装SystemTap和SystemTap-runtime包

3、使用如下命令测试一下:

stap -v -e ‘probe vfs.read {printf(“read performed/n”); exit()}’

 

为目标机产生SystemTap instrumentation:

这样就可以在一台机器上为多种内核产生SystemTap instrumentation,而且目标机上只安装SystemTap-runtime即可。

操作如下:

  1.          在目标机上安装systemtap-runtime RPM包;
  2.          使用uname –r查看目标机内核;
  3.          在host system上安装SystemTap;
  4.          在host system上安装目标机内核及相关RPMs
  5.          在host name上运行命令:
stap -r kernel_version script -m module_name

 

  1.          把新产生的模块拷贝到目标机,并运行如下命令:
staprun module_name.ko

 

注意:host system和目标机架构及操作系统版本必须一致。

 

运行SystemTap脚本

运行stap和staprun需要被授以权限,一般用户需要运行SystemTap,则需要被加入到以下用户组的一个:1、stapdev:用stap编译SystemTap脚本成内核模块,并加载进内核;2、stapusr:仅能运行staprun加载/lib/modules/kernel_version/systemtap/目录下模块。

SystemTap Flight Recorder模式

该模式允许长时间运行SystemTap脚本,但仅focus on 最近的输出,有2个变种:in-memory和file模式,两种情况下SystemTap都作为后台进程运行。

In-memory模式:

stap -F iotime.stp

一旦脚本启动后,你可以看到以下输出信息以辅助命令重新连到运行中的脚本:

Disconnecting from systemtap module.

To reconnect, type “staprun -A stap_5dd0073edcb1f13f7565d8c343063e68_19556″

当感兴趣的事件发生时,可以重新连接到运行中的脚本,并在内存Buffer中输出最近的数据并持续输出:

staprun -A stap_5dd0073edcb1f13f7565d8c343063e68_19556

内存Buffer默认1MB,可以使用-S选项,例如-S2指定为2MB

File Flight Recorder

stap -F -o /tmp/pfaults.log -S 1,2  pfaults.stp

命令结果输出到/tmp/pfaults.log.[0-9],每个文件1MB,并且仅保存最近的两个文件,-S指定了第一个参数:每个输出文件大小1MB,第二个参数:仅保留最近的两个文件,systemtap在pfaults.log后面加.[0-9]后缀。

该命令的输出是systemtap脚本进程ID,使用如下命令可以终止systemtap脚本

kill -s SIGTERM 7590

运行ls –sh /tmp/pfaults.log.*

1020K /tmp/pfaults.log.5    44K /tmp/pfaults.log.6

SystemTap如何工作

SystemTap的基本工作原理就是:event/handler,运行systemtap脚本产生的加载模块时刻监控事件的发生,一旦发生,内核就调用相关的handler处理。

 

一运行一个SystemTap脚本就会产生一个SystemTap session:

  1.          SystemTap检查脚本以及所使用的相关tapset库;
  2.          SystemTap将脚本转换成C语言文件,并运行C语言编译器编译之创建一个内核模块;
  3.          SystemTap加载该模块,从而使用所有探针(events和handlers);
  4.          事件发生时,执行相关handlers
  5.          一旦SystemTap session停止,则探针被禁止,该内核模块被卸载。

 

探针:event及其handler,一个SystemTap脚本可以包含多个探针。

SystemTap脚本以.stp为扩展名,其基本格式如下所示:

probe event {statements}

允许一个探针内多个event,以,隔开,任一个event发生时,都会执行statements,各个语句之间不需要特殊的结束符号标记。而且可以在一个statements block中包含其他的statements block。

函数编写:

function function_name(arguments) {statements}

probe event {function_name(arguments)}

SystemTap Event

可大致划分为synchronous和asynchronous。

同步事件:

执行到定位到内核代码中的特定位置时触发event

  1.          syscall.system_call

系统调用入口和exit处:syscall.system_call和syscall.system_call.return,比如对于close系统调用:syscall.close和syscall.close.return

  1.          vfs.file_operation

vfs.file_operation和vfs.file_operation.return

  1.          kernel.function(“function”)

如:kernel.function(“sys_open”)和kernel.function(“sys_open”).return

可使用*来代表wildcards:

probe kernel.function(“*@net/socket.c”) { }

probe kernel.function(“*@net/socket.c”).return { }

代表了net/socket.c中所有函数的入口和exit口。

  1.          kernel.trace(“tracepoint”)

2.6.30及newer为内核中的特定事件定义了instrumentation,入kernel.trace(“kfree_skb”)代表内核中每次网络buffer被释放掉时的event。

  1.          module(“module”).function(“function”)
probe module(“ext3″).function(“*”) { }

probe module(“ext3″).function(“*”).return { }

系统内核模块多存放在/lib/modules/kernel_version

Asynchronous Events

不绑定到内核的特定指令或位置处。包括:

1、  begin:SystemTap session开始时触发,当SystemTap脚本开始运行时触发;

2、  end :SystemTap session终止时触发;

3、  timer事件:

probe timer.s(4)

{

printf(“hello world/n”)

}

  •  timer.ms(milliseconds)
  •  timer.us(microseconds)
  •  timer.ns(nanoseconds)
  •  timer.hz(hertz)
  •  timer.jiffies(jiffies)

可查看man stapprobes来查看其它支持的events

SystemTap Handler/Body

支持的函数:

1、  printf (“format string/n”, arguments),%s:字符串,%d数字,以 , 隔开;

2、  tid():当前线程ID;

3、  uid():当前用户ID;

4、  cpu():当前CPU号;

5、  gettimeofday_s():自从Epoch开始的秒数;

6、  ctime()将从Unix Epoch开始的秒数转换成date;

7、  pp():描述当前被处理的探针点的字符串;

8、  thread_indent():

probe kernel.function(“*@net/socket.c”)

{

printf (“%s -> %s/n”, thread_indent(1), probefunc())

}

probe kernel.function(“*@net/socket.c”).return

{

printf (“%s <- %s/n”, thread_indent(-1), probefunc())

}

 

0 ftp(7223): -> sys_socketcall

1159 ftp(7223):  -> sys_socket

2173 ftp(7223):   -> __sock_create

2286 ftp(7223):    -> sock_alloc_inode

2737 ftp(7223):    <- sock_alloc_inode

3349 ftp(7223):    -> sock_alloc

3389 ftp(7223):    <- sock_alloc

3417 ftp(7223):   <- __sock_create

4117 ftp(7223):   -> sock_create

4160 ftp(7223):   <- sock_create

4301 ftp(7223):   -> sock_map_fd

4644 ftp(7223):    -> sock_map_file

4699 ftp(7223):    <- sock_map_file

4715 ftp(7223):   <- sock_map_fd

4732 ftp(7223):  <- sys_socket

4775 ftp(7223): <- sys_socketcall

函数thread_indent()只有1个参数:代表对线程的”indentation counter”的增减数,即系统调用显示的步数,返回字符串(自从第一次调用thread_indent()以来的描述:进程名(进程ID))

9、  name

标记系统调用的名字,仅用于syscall.system_call中。

 

10、              target()

stap script -x process ID or stap script -c command联合使用,如果想在脚本中获得进程ID或命令可以如此做

probe syscall.* {

if (pid() == target())

printf(“%s/n”, name)

}

 

SystemTap Handler构造

变量

1、  不必事先声明,直接使用即可,由SystemTap自动判断其属于string还是integer,整数则默认为0,默认在probe中声明的是local变量

2、  在各个probe之间共享的变量使用global声明

global count_jiffies, count_ms

probe timer.jiffies(100) { count_jiffies ++ }

probe timer.ms(100) { count_ms ++ }

probe timer.ms(12345)

{

hz=(1000*count_jiffies) / count_ms

printf (“jiffies:ms ratio %d:%d => CONFIG_HZ=%d/n”,

count_jiffies, count_ms, hz)

exit ()

}

Target变量

Probe event可以映射到代码的实际位置,如kernel.function(“function”)、kernel.statement(“statement”),这允许使用target变量来记录代码中指定位置处可视变量的值。

运行如下命令:可以显示指定vfs_read处可视target变量

stap -L ‘kernel.function(“vfs_read”)’

显示

kernel.function(“vfs_read@fs/read_write.c:277″) $file:struct file* $buf:char* $count:size_t

$pos:loff_t*

每个target变量以$开头:变量类型。如果是结构体类型,则SystemTap可以使用->来查看其成员。对基本类型,integer或string,SystemTap有函数可以直接读取address处的值,如:

kernel_char(address)

Obtain the character at address from kernel memory.

kernel_short(address)

Obtain the short at address from kernel memory.

kernel_int(address)

Obtain the int at address from kernel memory.

kernel_long(address)

Obtain the long at address from kernel memory

kernel_string(address)

Obtain the string at address from kernel memory.

kernel_string_n(address, n)

Obtain the string at address from the kernel memory and limits the string to n bytes.

 

打印target变量

$$vars:类似sprintf(“parm1=%x … parmN=%x var1=%x … varN=%x”, parm1, …, parmN, var1, …, varN),目的是打印probe点处的每个变量;

$$locals:$$vars子集,仅打印local变量;

$$parms:$$vars子集,仅包含函数参数;

$$return:仅在return probes存在,类似sprintf(“return=%x”, $return),如果没有返回值,则是空串

例子如下:

stap -e ‘probe kernel.function(“vfs_read”) {printf(“%s/n”, $$parms); exit(); }’

函数vfs_read有4个参数:file、buf、count和pos,输出如下:

file=0xffff8800b40d4c80 buf=0x7fff634403e0 count=0×2004 pos=0xffff8800af96df48

如果你想知道数据结构里面的成员信息,可以在”$$params”后面加一个”$”,如下所示:

stap -e ‘probe kernel.function(“vfs_read”) {printf(“%s/n”, $$parms$); exit(); }’

输出如下:

file={.f_u={…}, .f_path={…}, .f_op=0xffffffffa06e1d80, .f_lock={…}, .f_count={…}, .f_flags=34818, buf=”” count=8196 pos=-131938753921208

仅一个”$”表示,不展开数据结构域成员,如想展开,则需使用”$$”

stap -e ‘probe kernel.function(“vfs_read”) {printf(“%s/n”, $$parms$$); exit(); }’

输出受限于最大字符串大小:

file={.f_u={.fu_list={.next=0xffff8801336ca0e8, .prev=0xffff88012ded0840}, .fu_rcuhead={.next=0xffff8801336ca0e8

强制类型转换

大多数情况下,SystemTap都可以从debuginfo中获得变量类型,但对于代码中void指针则debuginfo中类型信息不可用,同样probe handler里面的类型信息在function里面也不可用,怎么办呢?

 

SystemTap函数参数使用long来代替typed pointer,SystemTap的@cast操作可以指出对象正确类型:

function task_state:long (task:long)

{

return @cast(task, “task_struct”, “kernel<linux/sched.h>”)->state

}

第一个参数是指向对象的指针, 第二个参数是将该对象(参数1)要强制类型转换成的类型,第三个参数指出类型定义的出处,是可选的。

检查Target变量可用性

随着代码运行,变量可能失效,因此需要用@defined来判断该变量是否可用:

probe vm.pagefault = kernel.function(“__handle_mm_fault@mm/memory.c”) ?,

kernel.function(“handle_mm_fault@mm/memory.c”) ?

{

name = “pagefault”

write_access = (@defined($flags)

? $flags & FAULT_FLAG_WRITE : $write_access)

address = $address

}

条件语句

if (condition)

statement1

else

statement2

 

global countread, countnonread

probe kernel.function(“vfs_read”),kernel.function(“vfs_write”)

{

if (probefunc()==”vfs_read”)

countread ++

else

countnonread ++

}

probe timer.s(5) { exit() }

probe end

{

printf(“VFS reads total %d/n VFS writes total %d/n”, countread, countnonread)

}

 

循环语句

while (condition)

statement

 

for (initialization; conditional; increment) statement

比较:

==、>=、<=、!=

命令行参数:

使用$标志着希望输入的是integer类型命令行参数,@:string

probe kernel.function(@1) { }

probe kernel.function(@1).return { }

关联数组

关联数组一般在multiple probes里面处理,所以必须声明为global,不管是在一个还是多个probes里面用,要读取数组成员值,可以:

array_name[index_expression]

如下所示:

foo["tom"] = 23

foo["dick"] = 24

foo["harry"] = 25

一个索引可以包含最多9个索引表达式,用 , 隔开:

device[pid(),execname(),uid(),ppid(),"W"] = devname

 

SystemTap的数组操作

赋值:

array_name[index_expression] = value

例子:索引和值可以使用handler function:

foo[tid()] = gettimeofday_s()

每次触发这个语句,多次后就会构成一个关联数组,如果tid()返回值在foo索引中已有一个,则用新值代替旧值。

读取数组值:

delta = gettimeofday_s() – foo[tid()]

如果无法找到指定”索引”对应的值,则数组读返回0(int)或null/empty值(string)

增加关联数组值

array_name[index_expression] ++

处理数组的多个成员:

global reads

probe vfs.read

{

reads[execname()] ++

}

probe timer.s(3)

{

foreach (count in reads)

printf(“%s : %d /n”, count, reads[count])

}

这个foreach无序打印所有reads数组值,如果想升序/降序,则需要使用升序(+)、降序(-),也可以限制处理的数组数目:

probe timer.s(3)

{

foreach (count in reads- limit 10)

printf(“%s : %d /n”, count, reads[count])

}

Clearing/Deleting数组和数组成员

global reads

probe vfs.read

{

reads[execname()] ++

}

probe timer.s(3)

{

foreach (count in reads)

printf(“%s : %d /n”, count, reads[count])

delete reads

}

使用delete操作来删除数组成员或整个数组。

global reads, totalreads

probe vfs.read

{

reads[execname()] ++

totalreads[execname()] ++

}

probe timer.s(3)

{

printf(“=======/n”)

foreach (count in reads-)

printf(“%s : %d /n”, count, reads[count])

delete reads

}

probe end

{

printf(“TOTALS/n”)

foreach (total in totalreads-)

printf(“%s : %d /n”, total, totalreads[total])

}

在if语句中使用数组:

global reads

probe vfs.read

{

reads[execname()] ++

}

probe timer.s(3)

{

printf(“=======/n”)

foreach (count in reads-)

if (reads[count] >= 1024)

printf(“%s : %dkB /n”, count, reads[count]/1024)

else

printf(“%s : %dB /n”, count, reads[count])

}

检查成员

可以检查是否一个指定健是数组键值:

if([index_expression] in array_name) statement

 

global reads

probe vfs.read

{

reads[execname()] ++

}

probe timer.s(3)

{

printf(“=======/n”)

foreach (count in reads+)

printf(“%s : %d /n”, count, reads[count])

if(["stapio"] in reads) {

printf(“stapio read detected, exiting/n”)

exit()

}

}

计算统计集合

统计集合用于收集数值的统计信息,用于计算新值

global reads

probe vfs.read

{

reads[execname()] <<< count

}

操作符<<<用于将count返回的值存放在read数组中execname()相关的值中,即一个键值关联多个相关值。

为计算统计信息,使用@extractor(variable/array index expression),extractor可以是如下integer extractor:

count:@count(writes[execname()])返回存放在writes数组中某单一键值对应的值数目;

sum:@sum(writes[execname()])返回在writes数组中某单一键值对应的值的和

min:最小值

max:最大值

avg:variable/array作为索引的统计集合中数据的平均值

global reads

probe vfs.read

{

reads[execname(),pid()] <<< 1

}

probe timer.s(3)

{

foreach([var1,var2] in reads)

printf(“%s (%d) : %d /n”, var1, var2, @count(reads[var1,var2]))

}

Tapsets

Tapsets是脚本库,里面预写好了probes和functions可以被SystemTap脚本调用,tapsets也使用.stp作为后缀,默认位于:/usr/share/systemtap/tapset,但无法直接运行。

How to upgrade OpenSSL on Ubuntu?

4月8日爆出的 heartbleed 漏洞要求把 OpenSSL 升级到 1.0.1g 版本。

关于这个漏洞的技术说明,可以看这里: 关于OpenSSL“心脏出血”漏洞的分析 

 Heartbleed test 网站,可以测试自己的网站有没有这个漏洞。

我最担心的,是在升级 OpenSSL 的过程中,远程 SSH 无法连线。

 OSChina  Segmentfault 上询问后,得知这种情况不会发生。

另外,可以采用比较保险的方法:

保险起见,你在现有的ssh连接上输入命令升级openssl,然后重启服务。不要断开SSH连接。然后新开一个SSH会话,确认一切正常后再断开旧的SSH连接。

升级的方法,参照这几篇文章吧,我就懒得写了:

 

互联网上信息传播速度和影响力比以前增长了不啻数倍,甲方在响应漏洞的时候,咱得跟上节奏,否则就可能被曝光了,在大水军的推动下,安全行业已经升华为情报行业了,嗯,通俗的说就是安全和娱乐挂钩,优雅点就是安全要接地气,要深入群众深入平常百姓。只要公司所在的领域竞争足够激烈,一定会有人帮你找漏洞的,也一定会有人帮你打广告,因为对他们来说,这是项目,这是KPI,这是人民币,咱需要,他们也同样需要。

心血漏洞已经被媒体撩hi了,互联网媒体报道了,传统媒体也报道了,当老板过问此事的时候,咱的回答也大概反应了咱的专业程度。

要快速,有效的处理openssl heartbeat这类漏洞,建议考虑下面几点:

0、资源清单

有扫描1-65535吗?

平时端口扫描有识别应用吗?

公开的exp有什么危害?私有的exp大概在啥范围传播?

有了这些信息,接下来的事情的速度就有保障了。

如果万一你还能知道什么ip跑的什么域名运行的什么server什么app的什么版本,负责人是谁,那就更犇了,不过这事在互联网公司知易行难。

1、处理思路

有轻重缓急吗?如果老板问起的时候只处理了下面环节中的部分,也是说的过去的,但得思路清晰,有时间点。

公开的https 默认端口–>公开的smtps pops–>公开的https非默认端口–>公开的smtps pops非默认端口

接着按照上面的优先级处理非公开的的SSL。

2、处理要点

能配置解决就配置解决。例如关闭某些应用的TLS支持。

能把公开的变成非公开的争取时间也行。例如加ACL,至于黑客在内部可以绕过ACL了,那是另外的问题了。

要备份原有的ssl库(因为有可能用了新库可能会导致业务不稳定的,要做好回滚的准备,哪怕只是yum update openssl一下)

3、后话

端口扫描看似简单,我知道的端口扫描这事运营的好的公司真不多,我个人认为端口扫描是安全团队基础安全能力的重要体现,共勉之!

当然了,咱的KPI可能不在这,理解万岁:)

另外如果黑客在内部了,处理起来变化会多很多,不过这是另外一个话题了:咱内部有IDS能发现有人在扫SSL漏洞吗?

质量=效率+效果

流量劫持,这种古老的攻击沉寂了一段时间后,最近又开始闹的沸沸扬扬。众多知名品牌的路由器相继爆出存在安全漏洞,引来国内媒体纷纷报道。只要用户没改默认密码,打开一个网页甚至帖子,路由器配置就会被暗中修改。互联网一夜间变得岌岌可危。

攻击还是那几种攻击,报道仍是那千篇一律的砖家提醒,以至于大家都麻木了。早已见惯运营商的各种劫持,频繁的广告弹窗,大家也无可奈何。这么多年也没出现过什么损失,也就睁只眼闭只眼。

事实上,仅仅被运营商劫持算是比较幸运了。相比隐匿在暗中的神秘黑客,运营商作为公众企业还是得守法的,广告劫持虽无节操但还是有底线的。这不,能让你看见广告了,也算是在提醒你,当前网络存在被劫持的风险,得留点神;相反,一切看似风平浪静毫无异常,或许已有一个天大的间谍潜伏在网络里,随时等你上钩 —— 这可不是弹广告那样简单,而是要谋财盗号了!

我会被劫持吗?

不少人存在一个错误的观点:只有那些安全意识薄弱的才会被入侵。只要装了各种专业的防火墙,系统补丁及时更新,所有的密码都很复杂,劫持肯定是轮不到我了。

的确,安全意识强的自然不容易被入侵,但那只对传统的病毒木马而已。而在流量劫持面前,几乎是人人平等的。网络安全与传统的系统安全不同,网络是各种硬件设备组合的整体,木桶效应尤为明显。即使有神一样的系统,但遇到猪一样的设备,你的安全等级瞬间就被拉低了。现在越来越流行便宜的小路由,它们可是承载着各种网上交易的流量,你能放心使用吗?

即使你相信系统和设备都绝对可靠,就能高枕无忧了吗?事实上有问题的设备并不多,但出问题的事却不少,难道其中还存在什么缺陷?没错,还遗漏了最重要的一点:网络环境。

如果网络环境里有黑客潜伏着,即使有足够专业的技术,是在所难逃了,敌暗我明,稍不留神就会落入圈套。

当然,苍蝇不叮无缝的蛋。有哪些隐患导致你的网络环境出现了裂缝?太多了,从古到今流行过的攻击方式数不胜数。甚至可以根据实际环境,自己创造一种。

现在回忆下尝试过的劫持案例。

上古时代:

  • Hub 嗅探
  • MAC 欺骗
  • MAC 冲刷
  • ARP 攻击
  • DHCP 钓鱼
  • DNS 劫持
  • CDN 入侵

中世纪:

  • 路由器弱口令
  • 路由器 CSRF
  • PPPoE 钓鱼
  • 蜜罐代理

工业时代:

  • WiFi 弱口令
  • WiFi 伪热点
  • WiFi 强制断线
  • WLAN 基站钓鱼

Hub 嗅探

集线器(Hub)这种设备如今早已销声匿迹了,即使在十年前也少有人用。作为早期的网络设备,它唯一的功能就是广播数据包:把一个接口的收到的数据包群发到所有接口上。且不吐槽那小得惊人的带宽,光是这转发规则就是多么的不合理。任何人能收到整个网络环境的数据,隐私安全可想而知。

hub

嗅探器成了那个时代的顶尖利器。只要配置好过滤器,不多久就能捕捉到各种明文数据,用户却没有任何防御对策。

防范措施:还在用的赶紧扔了吧。

这种设备目前唯一可用之处就是旁路嗅探。利用广播的特性,可以非常方便分析其他设备的通信,例如抓取机顶盒的数据包而不影响正常通信。

MAC 欺骗

交换机的出现逐渐淘汰了集线器。交换机会绑定 MAC 地址和接口,数据包最终只发往一个终端。因此只要事先配置好 MAC 对应的接口,理论上非常安全了。

switch

不过,很少有人会那么做,大多为了偷懒,直接使用了设备默认的模式 —— 自动学习。设备根据某个接口发出的包,自动关联该包的源地址到此接口。

然而这种学习并不智能,甚至太过死板,任何一个道听途说都会当作真理。用户发送一个自定义源 MAC 地址的包是非常容易的,因此交换机成了非常容易被忽悠的对象。只要伪造一个源地址,就能将这个地址关联到自己的接口上,以此获得受害者的流量。

a6

不过,受害者接着再发出一个包,绑定关系又恢复原先正常的。因此只要比谁发的频繁,谁就能竞争到这个 MAC 地址的接收权。如果伪造的是网关地址,交换机就误以为网关电缆插到你接口上,网络环境里的出站流量瞬间都到了你这里。

当然,除非你有其他出站渠道,可以将窃取的数据代理出去;否则就别想再转发给被你打垮的真网关了,被劫持的用户也就没法上外网。所以这招危害性不是很大,但破坏性很强,可以瞬间集体断网。

防范措施:机器固定的网络尽量绑定 MAC 和接口吧。貌似大多数网吧都绑定了 MAC 和接口,极大增强了链路层的安全性。同时,独立的子网段尽可能划分 VLAN,避免过大的广播环境。

大学里见过千人以上还不划分 VLAN 的,用一根短路网线就可以毁掉整个网络。

MAC 冲刷

之前说了集线器和交换机的转发区别。如果交换机发现一个暂时还未学习到的 MAC 地址,将会把数据包送往何处呢?为了不丢包,只能是广播到所有接口。

a7

如果能让交换机的学习功能失效,那就退化成一个集线器了。由于交换机的硬件配置有限,显然不可能无限多的记录地址对应条目。我们不停伪造不重复的源地址,交换机里的记录表很快就会填满,甚至覆盖原有的学习记录,用户的数据包无法正常转发,只能广播到所有接口上了。

a8

防范措施:还是 MAC 和接口绑定。一旦绑定,该接口只允许固定的源地址,伪造的自然就失效了。当然,好一点的交换机都有些策略,不会让一个接口关联过多的 MAC 地址。

曾经在家试过一次,捕捉到小区内用户上网的流量。不过伪造包发的太快,~15万包/秒,更致命的是发错目标地址,发到城域网准入服务器上,导致工作人员切断了整个小区半天的网络… 所以必须得选一个 VLAN 内的、并且实际存在的地址做为目标 MAC,以免产生大量的数据风暴。

ARP 攻击

这种攻击大家几乎都听出老茧了,即使不懂电脑的人也知道装个 ARP 防火墙保平安,其危害之大可想而知。

简单的说,ARP 就是广播查询某个 IP 对应的 MAC 地址,在用这个 IP 的人回个声。知道这个 IP 对应的 MAC 地址,就可以链路通信了(链路层只能通过MAC地址通信)。如果有人冒充回复,并抢在正常人之前,伪造的答案也就先入为主。IP 被解析到错误的地址上,之后所有的通信都被劫持了。

a9

事实上,早期的系统还有个更严重的BUG:直接给用户发送一个 ARP 回复包,即使对方从没请求过,系统也会接受这个回复,并提前保存里面的记录。这种基于缓存的投毒,让劫持成功率更上一层楼。

a10

防范措施:由于这种攻击太过泛滥,以至大部分路由器都带了防 ARP 攻击的功能。客户端的 ARP 防火墙也数不胜数,似乎成了安全软件的标配。当然,系统也支持强制绑定 IP 与 MAC 的对应,必要时可以使用。

很多教程都是用 Wireshark 来演示,事实上当年有一款叫 Iris 的软件非常好用,可以修改封包再次发送,用它可以很容易搞明白各种攻击的原理。不过N年没更新了还不支持64位的。

DHCP 钓鱼

现实中,并不是每个人都会配置网络参数,或者出于方便,让网络系统自动配置。出于这个目的,DHCP 服务诞生了。

由于没有配置IP地址、网关、DNS等,在网络上是寸步难行的,因此首先需要从DHCP那获得这些。然而,既然连 IP 地址都没有,那又是如何通信的?显然,只能发到广播地址(255.255.255.255)上,而自己则暂时使用无效的IP地址(0.0.0.0)。(事实上,链路层的通信只要有 MAC 地址就行,IP 地址已属于网络层了,但 DHCP 由于某些特殊需要使用的是 UDP 协议)

因为是发往广播,内网环境里的所有用户都能听到。如果存在多个DHCP服务器,则分别予以回复;用户则选择最先收到的。由于规则是如此简单,以至于用户没有选择的余地。

尚若黑客也在内网里也开启了DHCP服务,用户收到的回复包很可能就是黑客发出的,这时用户的网络配置完全听天由命了,不想被劫持都难了。

防范措施:如果是用网线上网的话,最好还是手动的配置。当然,管理员应该严格控制DHCP回复的权限,只允许交换机特定的接口才有资格发送回复包。

只要是这类提问/抢答模式的,都面临被冒充回答的风险。很多原理都类似。

DNS 劫持

如同 ARP 将 IP 解析成 MAC 地址 一样,DNS 负责将域名解析成 IP 地址。作为网络层的服务,面对的用户更广泛,当然面临的风险也大的多。一旦遭到入侵,所有用户都倒霉了。近些年的重大网络事故无不和 DNS 有关。

DNS 服务一旦被黑客控制,用户发起的各种域名解析,都将被暗中操控。将正常网站解析成黑客服务器的 IP,并事先开启了 HTTP 代理,用户上网时几乎看不出任何破绽;而黑客则获取到所有访问流量,各种网站账号信息都将一览无余。

dns-hijack

由于 DNS 服务器的重要性,现实中通常有着较高的安全防护,想入侵它系统不是件易事。但实际未必如此兴师动众,一些 DNS 程序本身就存在着设计缺陷,导致黑客能控制某些域名的指向。其中最恶名昭彰的当属 DNS 缓存投毒

大家或许已发现,域名->IP->MAC->接口,只要是动态查询的就会多一个环节,风险自然增加。灵活性与安全性始终是不可兼得。

防范措施:手动设置一些权威的 DNS 服务器,例如 8.8.8.8,4.4.4.4 会靠谱的多。

公网上的 DNS 劫持很少发生,但家用路由器的 DNS 劫持已泛滥成灾了。开头报道的路由器漏洞,最终的利用方式也就是修改了 DNS 地址。

CDN 入侵

CDN 能加速大家都知道,但其中原理不少人都不清楚。其实,CDN 本身就是一种 DNS 劫持,只不过是良性的。

不同于黑客强制 DNS 把域名解析到自己的钓鱼 IP 上,CDN 则是让 DNS 主动配合,把域名解析到临近的服务器上。这台服务器同样也开启了 HTTP 代理,让用户感觉不到 CDN 的存在。

不过 CDN 不像黑客那样贪心,劫持用户所有流量,它只『劫持』用户的静态资源访问,对于之前用户访问过的资源,CDN 将直接从本地缓存里反馈给用户,因此速度有了很大的提升。

然而,只要是有缓存的地方,都是大有可为的。一旦 CDN 服务器遭受入侵,硬盘上的缓存文件就岌岌可危了,网页被注入脚本,可执行文件被感染,一大波僵尸即将出现。

cdn-hijack

防范措施:感觉运营商不靠谱的话,换个第三方不带加速的 DNS,或许就不会解析到 CDN 服务器上了。

不少 CDN 黑白通吃,为了省流量不按套路出牌,超过了缓存时间也不更新,甚至还有忽略 URL 问号后面的,导致程序猿们在资源更新的问题上头疼不已。

路由器弱口令

当电脑价格一再下降,到了大家打算买第二台的时候,路由器市场也随之火热起来。

但由于繁琐的配置,差劲的用户体验,至今仍有相当部分的用户不明白如何配置路由器。192.168.1.1 和 admin/admin 几乎成了国内路由器的常量。多少回,用这毫无技术含量的方法进入网吧或图书馆的路由器后台。

如果有人恶搞重启路由,或者给他人限速,你得感谢他的仁慈,这都算不严重。要是把路由器的DNS给改了,那就相当严重了!公网的 DNS 劫持一般不会持续太久,但路由器的 DNS 劫持也许长年累月都不会觉察到。

事实上,不乏一些安全意识强的用户也使用默认密码。理由很简单,目前的路由器有两道门槛:一个 WiFi 连接密码,另一个才是管理密码。很多人设置了复杂的 WiFi 密码就高枕无忧了,心想都连不到我的网络里怎么可能进的了后台?

之前我也有过这观念,但总觉不对劲:万一家里其他电脑或手机中毒了,自动尝试用弱口令爆进路由器后台怎么办。城门都被占领了,城墙再牢固又有何用。

router-weak-pwd

事实上,黑客除了修改 DNS 配置外,还有更恐怖的行为:升级路由器的固件 —— 替换成一个看似完全相同但植入了恶意程序的固件!尽管这目前还尚未普及,然而一旦流行,大批路由器将成为潘多拉魔盒。

防范措施:千万别轻视路由器的密码,其实它比你所有账号都重要。

不改默认密码的用户,神都保佑不了你~

路由器 CSRF

回到本文开始所说的,为什么有那么多路由器会出现这个漏洞呢?也许是路由器的开发人员太高估用户了,认为绝大多数用户都修改了默认密码,因此 CSRF 几乎难以产生。

事实上,国内网民的安全意识远超他们的想象。加上刚才说的,只设置了 WiFi 密码而忽略了管理密码,导致一个恶意程序就能悄悄进入路由器后台。

没想到现在这种病毒还真出现了,而且居然还是 Web 版的!

router-csrf

CSRF漏洞让病毒木马都用不着了。用户直接访问一个网页,甚至是一帖子,浏览器自动向路由器发起修改配置的请求。

由于国产路由器的网页开发是如此的差劲,登录基本都是用既不安全又丑陋的401弹框。这种登录只需在URL里填上『用户名:密码@』即可自动通过,即使登录失败也不会有什么提示

防范措施:绝对要看管好路由器密码,并且定期去检查配置是否被篡改。

看过路由器页面源代码会发现,那简直是惨不忍睹,甚至还是 IE5 时代的风格。路由器芯片都是采购的,内核也有开源的,所谓的『自主研发』就是做了那几个页面?

PPPoE 钓鱼

好了,不吐槽路由器了,下面说说再高级的路由器也无法避免的事。

除了一些大公司或学校,用的是固定的专线接入上网,个人或者小组织很少会使用这种土豪级套餐,只能老老实实的拨号上网 —— 无论是电信,还是网通铁通各种通。

不少人都存在误区,认为拨号是物理信号的建立过程,在没有拨上之前,点对点是不通的。如果真是这样,那么拨号时账号密码是如何传过去的呢?显然不可能。事实上,终端之间时刻都是畅通的,只不过不拨号就无法得到IP、网关、会话等参数,即使强制把包发给网关,人家虽能收到,但没有认证的会话是不予理睬的,你自然没法上网。

PPPoE,大家经常在拨号时看到这词。Point-Point Protocol over Ethernet,故名思议,就是点对点的协议:用户发送账号密码认证给终端(BRAS),并得到上网 IP、网关地址、会话等。而且协议是基于以太网的,哪怕线路不是,也得想办法把数据封装进去。

传统的 ADSL 是通过电话线上网的,于是需要一个『猫』来把以太网数据调制成电话信号,最终通过电信交换机传输。这种设备保障每家每户都是独立的,以免电话信号被窃听。

然而,后来兴起的各种通就不一定了。不少打着的『千兆到楼,百兆到家』的宽带,就是建了N个小区局域网,然后合并到一个大的城域网(MAN)里。所谓的『百兆』,无非就是拖进你家的那根网线插在楼下一个 100Mbps 的交换机上而已。

用过网通的都知道,百兆带宽并没有快到哪里,甚至在一些南方地区网速慢如蜗牛。但在下载的时候,却能轻松飙到数兆每秒。这时局域网的作用就发挥出来了,如果附近有多个人在看同样的视频,P2P 就直接在内网里共享流量了,大幅减轻了节点的压力。

但是,整个小区成了一个局域网,是多么的不安全。有时甚至不合理的 VLAN 划分,导致多个小区成一内网。要是有人开启 DHCP 服务,其他用户插上网线就能上网了,连拨号都不用,难道天上掉馅饼了?如果敢吃,那可能就落入黑客的陷阱了。

当然,现在直接插网线的并不多,基本通过路由器自动拨号了。但他们的协议都是一样的 —— PPPoE,一种极不安全的协议。

类似 DHCP 协议,PPPoE 也是通过广播来探寻有哪些可用的终端,意味着整个小区的内网用户都能收到;同时探寻包一直往上冒泡,直到被城域网的终端们收到,然后开始纷纷回应。

如果小区里有人私自开启一个 PPPoE 终端服务,显然是最先被收到的。真正的回应包还在大街小巷里传递着,用户和黑客已经开始协商认证了。

pppoe-phishing

不过或许你会说,这必须有人拨号才能上钩,现在都用路由器,长年累月不会断开。如果不想耐心等,也有很简单的方法:来一次集体掉线。

刚刚说过,可以用短路的网线,引发一场广播风暴。不过这太过暴力了,甚至会引起流量异常的报警。我们可以使用更简单有效的方法:MAC 欺骗,不停伪造终端服务器的 MAC 地址,就可以将小区用户的数据包统统吸过来了。

PPPoE 使用的是一种隧道方式,将任何数据都封装在其栈下,因此捕捉到用户任意一个包,即可得到PPPoE栈上的会话ID。然后冒充终端,向用户发送一个『断开连接』的指令,用户就乖乖下线了。使用这种方法,分分钟就能让整个小区的用户重新拨一次号,于是可以快速钓鱼了。

还有更糟的是,PPPoE 绝大多数时候都是明文传输用户名和密码的,因此还能额外获得用户发来的认证账号。

前面吐槽了大学寝室楼 1000 多机器还不划 VLAN 的,于是写一个简单的 PPPoE 模拟器,就能轻松抓到整个网络环境里的上网账号。(还支持一键全都拨上,集体下线的恶作剧功能~)

pppoe-phishing-demo

防范措施:由于 PPPoE 的安全严重依赖物理层,所以尽量不要装以太网接入的带宽。当然,管理员们应该严格限制 PPPoE 搜寻回复包,就像 DHCP 那样只允许特定接口出现。事实上小区内部是不可能出现 BRAS 服务器的,因此只允许交换机的 WAN 口出现回复包,那样就不容易被钓鱼了。

PPPoE 还有个更严重 BUG,会话ID只有2字节,最多 65536 种可能。事先构造个『拨号断开』的请求包,接着把会话ID依次遍历一下,就能让某个终端服务器的所有用户下线。如果事先收集好所有终端服务器地址,可以发起一次全城断网- -

这个 BUG 应该早已经修复了,只需绑定 <会话ID,用户MAC,小区VLAN-ID> 关系即可。而且一个小脚本就能断开全城各县市的网络,说明终端部署不能太过集中。

蜜罐代理

由于众所周知的原因,某国对代理的需求居高不下。不管黑的白的,透明的还是高匿的,只要能翻出去就是好的。

VPN 需要用户名密码以及各种认证,中途被劫持几乎是不可能的。黑客抓住了人们的纯真的心里,将目光转到代理上面。的确,加密后的数据中途确实难以劫持,但最终仍要在服务端还原出真实内容吧。如果一时大意,连接了某个免费的 VPN,或许就登上了黑客的贼船了。

相比 HTTP 代理只影响部分功能,VPN 将整个系统的流量都通过穿越过去了。而这一切应用程序并不知晓,仍然将一些重要的数据往外发送,最终被黑客所劫持。

honey-proxy

防范措施:不要贪图小利,用那些打着免费幌子的代理。天下没有免费的午餐。

很多蜜罐代理未必是黑客布下的,而是你懂的。

WiFi 弱口令

当互联网延伸到移动设备时,网线成了最大的累赘,无线网络逐渐进入人们视野。如今,由于无线的廉价和便利,几乎应用到所有的便捷设备。一切都不再受限制,人们可以随时随地上网,这是过去难以想象的;黑客也可以随时随地发起攻击,这是过去梦寐以求的。

但无论上网方式如何变化,以太网始终是网络的核心。如同刚才说的 ADSL,尽管载体是电话线路,但最终解调出来的仍是以太网数据。WiFi 也一样,无论电波怎样传播,最终只有还原出标准的以太网封包才能被路由。

无线网络形同一个看不见的巨大集线器,无需任何物理传播介质,附近所有人都可以收听数据信号,专业设备甚至能在更远处捕获。如果没有一种强有力的加密方式把数据封装起来,那么就毫无隐私可言了。

在经历了各种加密被攻破后,WPA2 如今成为无线网络标准加密算法。如果企图通过传统爆后台那样,一次次的尝试弱口令去连接,那效率将是何其的低下。

和拨号不同,WiFi 用户首先需『关联』热点,以建立起物理通道。类似 PPPoE 那样,WiFi 在认证之前也是可以通信的,并且是明文数据 —— 不过,这仅仅是认证数据包明文而已,真正密码显然不会出现在其中。毕竟它和拨号的目的完全不同:一个是为了加密之后所有的流量,而后者仅仅识别下你有没有上网的权限。

通过传统的嗅探工具,可以方便获取这些握手通信包。尽管找不出密码,但里面保存着密钥初始化相关的数据。通过专业的WPA2破解工具,加上丰富的密码字典,有相当一部分的无线网络,能在可接受的时间里被破解。

wifi-weak-pwd

对于不少人来说,无线密码是他第一道也是唯一一道防线。连上之后,不出意外即可轻易进入路由器后台,然后就可以控制他整个内网的流量了。

防范措施:最简单也是最有效的方法:给密码加些特殊符号。

如果给他的路由器刷一个固件,能自动破解其他的无线网络,破解之后自动进后台,自动给它升级自己的固件。。。排山倒海的路由器木马爆发了。

WiFi 热点钓鱼

上面简单的说了无线密码的破解。但若本来就知道密码的情况下,又如何发起入侵呢?

这种场合很常见,在一些商场、餐厅、旅馆等地方,无线网络即使有密码,大家一般也能在墙上或卡片上找到,处于半公开的状态。或者是破解了邻居的无线密码,但无法进入路由器后台,又该如何继续?

如今越来越智能的无线设备,已能很好的防御诸如 MAC 欺骗以及 ARP 攻击这类原始入侵了,因此需要一个更先进和隐蔽的方式,能绕过网络设备,直接发起点对点的进攻。

在大公司或大商场上过无线网的用户会发现,在室内无论走到哪里网络都存在,即使从一层到五层信号照样满格,而在自己家中信号隔墙就下降不少。难道是开了信号特别强大的热点吗?但在建筑外面却收不到。事实上,不难发现每层楼天花板上,都吸附着不少盘子似的东西。没错,正是这些分布在各处的设备,覆盖了整栋楼的无线网络,让信号死角变得更少。

但是同时存在那么多热点,搜索列表里显示的却没有几个。因为他们都有着同样的热点名(SSID),客户端通常会将同名热点合并成一个。至于连接时,系统会选择信号最好的那个。如果这些热点的认证方式也是相同的,无论连哪个都没问题。

wifi-ds

仔细揣摩这条特征,不难发现其中大有文章可做 —— 这不天生就为我们钓鱼准备的!我们再开一个同名同认证的伪热点,只要在信号上压倒对方,钓上附近的鱼儿那是妥妥的。

wifi-spoofing

目前几乎还没有哪个客户端对此有防御,无论是商场还是咖啡店,甚至是一些大公司里,对此也束手无策。原因很简单,问题既不出在设备、也不是部署上,更不能归咎与用户。这是整个协议栈的弱点。

发起此攻击的唯一材料,就是一个超大功率的热点,以此来压倒正常的,争做用户『最信赖』的信号源。

其实,每个热点都时时刻刻广播着一种叫 Beacon 的数据包,里面带有热点名等相关的信息。用户网卡收集之后进过筛选分析,即可得知附近有哪些热点,各自信号如何。功率大的热点,用户接收时的信号强度(RSSI)自然也会高一些。

当然,过高的信号源可能会引起一些监控的警觉,自己也被置于巨大的辐射之中。如果仅仅是对某个方位片杀,使用定向天线会有更好的效果。

不过,光有发射能力还是不够的。即使能把 Beacon 推送到数十公里外,让全城都能看见你的热点名,但前来连接的设备可没有那么强劲信号。因此没有一个高灵敏的接收系统,再强的信号也只是一厢情愿罢了。

防范措施:因为是底层的缺陷,这种劫持通常很难防护。从理论上说,热点通常是固定着的,因此可以事先记录下每个热点的3D坐标,然后根据 WiFi 定位时刻监控热点位置,如果某个热点信号出现在远离事先的地方,很可能是钓鱼热点发出的假信号。

但在现实中,要同时追踪那么多设备并不容易。除非所有的无线设备,都自带监控附近热点的功能,那样可以节省大量追踪成本。

不过在安全性高的场合,还是使用『接入认证』,连接时要求输入用户名和密码来准入。

WiFi 还有个很危险的废功能:用户成功连上之后,一些系统会尝试请求某个特定的 URL,如果返回的是 HTTP 302,会自动弹出重定向后的网页。目的是为了方便打开网页版的准入,有时连上 CMCC 会自动弹出一个登录网页就是如此。iPhone,iPad,WP 都支持,MacOS 最新版弹出的网页不会执行脚本了。利用这个废功能来弹广告应该很不错~

WiFi 强制断线

不得不说 WiFi 的另一个缺陷 —— 被下线。类似 PPPoE 主动或被动断开拨号时都有一个注销包,WiFi 也一样。

之前提到,遍历 PPPoE 的会话ID,冒充所有用户发出注销请求,可以断开全城的网络。WiFi 也有类似的缺陷,只不过正好反过来:冒充热点,向所有用户广播注销包,于是所有连着该热点的用户都下线了。

wifi-deauth

不过,WiFi 的被下线仅仅是认证被注销,用户和热点仍是关联着的。用户接着重新发起认证,因此又给黑客一个获取握手数据的机会。

如果广播持续不断,用户也就一直没法上网,屏幕上会不停的闪烁着『连接中… / 已断开』。对方可能会尝试重启路由,但发现问题仍在,而且所有设备都是这情况,会认为路由器出问题了,于是尝试恢复出厂设置 —— 这一刻,危险降临了!

照国产路由器的风格,出厂时 WiFi 是没有密码的,而且后台基本是弱口令。因此有个非常短暂的安全缝隙,能钻入这台设备并拿下他的网络!如果事先写好脚本,一旦发现有开放的热点,立即连上并且爆入后台,更是可以直接秒杀!对方刚恢复完路由器,还没回到电脑前就已被劫持了,这是无论如何也想不到的。。。

当然,为了防止他之后进入路由器改密码,你必须立即隐藏 SSID,让 Beacon 不再发出,这样大家都看不见这台设备了,只能通过 BSSID(路由器 MAC 地址)来连接。但是人家会有疑问,刚恢复好的路由器怎么看不见?这时得事先建立一个钓鱼热点,名字和那被隐藏的 SSID 一样,将对方引诱到自己的蜜罐上。

在这个蜜罐里开启一个和路由器页面差不多的站点(可以直接反向代理他路由器的页面),拖住用户,让你有充足的时间来操作那台被隐藏的真设备。甚至可以换掉他固件了!

当然,有些设备不让轻易更新固件,需要输入路由器上的某个号码,或者按一个键才能开始。这时得发挥蜜罐站点的作用了,你可以在页面上画个文本框,提示他输入路由器上的那号码,或者直接让他去按那按钮。由于路由器后台太过专业,很少会有人质疑它的权威性,几乎都是按部就班。

honey-router

事实上,你的蜜罐一直开着,对方肯定会在里面配置 WiFi 密码和管理密码,以及 PPPoE 账号。于是他的一切上网秘密都被掌控!即使不改他路由器也无所谓了,以后可以随时进入。

防范措施:不要轻易恢复路由器的出厂设置。真有必要请务必留神,尽快改掉默认密码。即使周围没有黑客,一些中毒的设备随时可能来连上并爆进后台窜乱。

软硬兼施,这招是不是太阴了?稍微用一点心理学或是社工,原本不怎么严重的漏洞可以扩大很多倍。

WLAN 基站钓鱼

前面说的热点钓鱼,只能在特定的场合下进行。劫持KFC的用户,只能在KFC附近;入侵小区的路由,只能在家完成。这极大的限制了攻击范围,完全没有发挥出无线网络的灵活性。

然而有一种网络,无论走到哪都能收到。打开手机,总能看见 CMCC 这类热点如同幽灵一般存在。如今,WLAN 业务已遍地开花,几乎覆盖了全国各地。它支持更高的频段,并向下兼容 WiFi,设备遍布全城,试图打造一个无线城域网。唯一的遗憾是收费的,而且信号也一般,远不如 3G 实用。

有时我们并没有连接这些热点,系统却自动连上了。原因很简单,之前某个时候手贱,去连过它们。而系统会保存主动连过的热点,再次出现时就自动上了。事实上,去连过这些热点的人不在少数。

不用说,你也想到开热点钓鱼了。并且用户几乎都是用 WiFi 来连接,也就没有必要使用 WLAN 设备。使用之前的大功率热点,取个 CMCC 的名字,放在阳台上对着大街,不一会就连上一堆用户了。要是支持虚 AP 的话,把 CMCC-AUTO,ChinaNet 等等这些名字全部用上,前来光临的就更多了。

上面提到了,不少设备连上 WiFi 后能自动弹网页,利用这个特性,钓鱼就更容易了。大多手机系统为了节省流量,当 WiFi 和 3G 同时可用时,会优先使用 WiFi,于是用户的流量不知不觉流到黑客那里。

wlan-phishing

事实上,我们还可以把整套钓鱼方案集成到安卓里。利用手机创建的热点吸引附近的用户,捕捉到的流量还可以通过自己的 3G 网络代理出去。使用 Linux 内核强大的转发机制,我们可以轻易的控制用户的各种流量。以后可别嘲笑街上低头玩手机的人,人家说不定正在劫持你呢。

不过,在一些地方例如地铁上面,3G信号很差,难以将热点收到的数据转发出去,因此只能钓鱼无法劫持。这种单机模式是否仍能入侵呢?下篇文章将叙述,如何发起离线钓鱼。

防范措施:WiFi 不用就应及时关闭,以免自动连上不安全的热点。对于一些长期不用的连接记录,不如趁早删了吧。

安卓热点默认只支持10个用户,在街上开个叫 CMCC 的热点,会发现瞬间就连满了。所以还是把笔记本藏书包里,配几个好点的无线网卡,既隐蔽效果也好。大功率天线虽然很过瘾,但不能过度使用,说不定哪天就被查水表了~

结尾

就谈到这里吧,这些只是之前尝试有效的案例,事实上还有太多的途径,要是再算上系统内部的方式那就无数了。但不论如何变化,流量劫持的最终利用方式几乎是如出一辙的 —— 利用它能做些什么呢?终极危害能有多大?请听下回分解。

 

本周互联网最大的安全事件莫过于HeartBleed漏洞(CVE-2014-0160)的广泛公开。 如果你还不了解详情,可以参考这个分析。简言之,是由于OpenSSL在响应”心跳”时,对于数据包中的长度域不加检查,导致向另一端泄露了程序中最多可达64kb的内存。这是一个高危漏洞,影响范围很广,原因如下:

-          绝大多数网站安全登录时,使用了OpenSSL,并存在此漏洞。

-          攻击者向服务端发起攻击,可以获得服务端进程内的64kb数据,这些数据可能是任何东西:账号、密码、私钥等等

-          该漏洞以及poc已经被广泛公开,大量脚本小子(script kiddie)参与攻击服务器

根据互联网工程任务组(IETF)的RFC6250 文档可以发现,在握手完成之后,心跳包是可以双向传送的。如果客户端在使用一个存在漏洞的openssl版本,服务端向客户端发送心跳请求,同样存在“心脏流血”的隐患。

根据Google官方声明,HeartBleed仅仅影响到4.1.1版本的Android系统。并且google也已经将补丁方案推送至各大厂商。根据我们的分析,此漏洞确实仅在4.1.1上生效,原因是仅有4.1.1的系统上的/system/lib/libssl.so支持heartbeat扩展。

Heart

图中是4.1.1中导出的存在漏洞的函数

客户端链接服务端,反被服务端攻击,是有可能的。但版本限制得比较严格,通常安卓客户端内存数据利用价值也相对较低,因此这个问题危害较小。我们建议系统版本为4.1.1的安卓手机用户:

-          检查自己的系统更新,如果有更新可用,立即升级。

-          使用360手机卫士保护手机系统,并开启网址拦截功能。 不要访问不可信的网站,避免来自服务端的攻击。

-          仅使用360手机助手等可信的安全应用市场下载app,避免该app访问利用漏洞的服务器

-          不要使用公共场所中不可信的免费WiFi

扩展阅读:

比想象中更恐怖!OpenSSL“心血”漏洞深入分析

http://blog.wangzhan.360.cn/?p=165

Common Vulnerabilities and Exposures

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160

Google Services Updated to Address OpenSSL CVE-2014-0160 (the Heartbleed bug)http://googleonlinesecurity.blogspot.com/2014/04/google-services-updated-to-address.html

CyanogenMod 对于该漏洞的patch

https://github.com/CyanogenMod/android_external_openssl/commit/8eb23b21293400219a64414bf6fab03713ea6299

Heartbleed only an issue for Android 4.1.1

http://androidcommunity.com/heartbleed-only-an-issue-for-android-4-1-1-20140409/

TLS & DTLS  Heartbeat Extension

http://www.rfc-editor.org/rfc/pdfrfc/rfc6520.txt.pdf

The Heartbleed Bug

http://heartbleed.com/