NTP 的 ACL 控制

跟 ntp 权限访问相关的都在 restrict 这个声明里面。

默认情况下,如果 ntp.conf 里面没有任何的 restrict 字段,表示默认全部放行。比如下面这个配置:
# cat /etc/ntp.conf
server x.x.x.x prefer
server y.y.y.y
server z.z.z.z

这意味着什么了?如果服务器开了公网 IP,没有防火墙的,再加上 ntp 无法监听指定的端口,这会导致互联网上任何一台主机都能够操作这台 ntp,比如:
ntpq> peers
     remote           refid      st t when poll reach   delay   offset  jitter
     ==============================================================================
     *192.168.40.92     202.112.31.197   3 u 1010 1024  377    0.202    0.000 0.398
     +192.168.50.44      202.112.31.197   3 u  364 1024  377    0.314    1.415 0.875
     +192.168.30.8      202.112.31.197   3 u  424 1024  377    0.280    1.759 0.952
     +dns2.synet.edu. 137.189.4.10     2 u  395 1024  377   11.255    0.830 0.647
      LOCAL(0)        .LOCL.          10 l  24d   64    0    0.000    0.000 0.000

还能看到 NTP, OS 的相关信息:
ntpq> rl
associd=0 status=0615 leap_none, sync_ntp, 1 event, clock_sync,
version="ntpd [email protected] Tue Jun  5 20:12:08 UTC 2012 (1)",
processor="x86_64", system="Linux/3.2.0-40-generic", leap=00, stratum=4,
precision=-23, rootdelay=12.562, rootdisp=73.370, refid=192.168.40.92,
reftime=d59b67c9.85575f94  Thu, Jul 15 2013 17:00:57.520,
clock=d59b700e.367fac37  Thu, Jul 15 2013 17:36:14.212, peer=59253,
tc=10, mintc=3, offset=0.000, frequency=5.968, sys_jitter=0.398,
clk_jitter=0.242, clk_wander=0.036

下面参照官方文档学习下 ntp 在 acl 方面做的一些工作。
默认先阻挡掉一切的连接:
restrict default ignore

下面的语句实现跟上面类似的效果:
restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery

如果仅仅有上面这条,这意味着会 block 所有的主机,包括本机。这个明显不是我们想要的,可以开放指定的机器,包括 localhost。下面这个仅仅对 192.168.40.0 以及 localhost 开放查询权限:
restrict -4 default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
restrict 192.168.40.0 mask 255.255.255.0

注意: restrict 需要使用 IP 而非域名的形式。

从上面可以看到,ntp 配置的不好会对系统的安全造成非常严重的隐患。另外,老生常谈的事,绝对不要在线上环境执行不熟悉的命令,修改不熟悉的配置,很多工程师都是修改完了重启发现没问题就仍在那儿不管了,以为自己做的很好,其实留下了很严重的安全隐患。

保护好你的远程卡

远程卡的好处不要多说,已经成为众多厂商的标配了,但是很多公司不乏很多上规模(比如这个)的公司,忽略了远程卡的安全,然后,然后就被搞了。
我们在很早期的时候也遇到过类似的情况。两年前我们上的某批机器,当时为了途方便(那时候我还没有部署 vpn ),远程卡都是放的是公网 IP,再加上当时的自动化做得不是很好,有一台疏忽了修改其默认的用户名密码,导致了这台机器被一个小 cracker 搞了一把。回顾下当时的情景,大致是这样的:
那天晚上正准备睡觉,突然收到短信说服务器被重启了,后续连续收到几条类似的报警。立马登陆到远程卡上 launch console,发现需要发送共享的请求。当时除了我有权限登陆到远程卡之外,没有人可以登陆,当时只是觉得很奇怪,但是没有意识到已经被入侵了。再请求了几次之后竟然可以 launch 了,打开控制界面发现服务器又在重启。后来反应过来,遭入侵了。通过控制卡的回放功能,确认果真被入侵了。那个小哥尽管进了远程卡,但是没有办法登陆,只能通过重启的办法,重置了我们的 root 密码。刚重置完发现发现了,然后,然后就跑了。
接着就是吸取教训写 post-mortem,快速的加固系统,远程卡出问题,当然是从远程卡入手。最容易入手的包括如下的几点:
1. 远程卡全部隐藏到内网里,回收所有不需要公网机器的 IP
2. 修改其用户名密码,登陆端口
当时机器的数量还在两位数,再加上当时对自动化方面没有太大的需求,尤其是这类不涉及系统层面的自动化,花了一天不到的时间,一台台人肉修改完了所有的机器(想象当年多无知)。后来所有新上架的机器都按照这个标准继续执行,当然不再是人肉执行了。

对于这台被入侵的机器,本来是打算直接重装的,经过再三的权衡,再加这是台 db server,上面有很重要的数据,最终并没有选择重装,把能检查的地方都检查了一遍,后续的几天密切的关注这台机器的所有进出口的流量、涉及的进程等等。
后来经过对入侵机器以及几台相关机器的追踪观察,确认没有造成更大的损失,事件到此为止。

接下来的几天,还做了以下的几件事:
1. 所有的机器实行 ssh 的公私钥登陆,取消默认的密码登陆
2. 对服务器的访问权限所了一个比较粗的控制,尤其是开放了公网机器的,基本就是 iptables + tcpwrappers

针对这次远程卡入侵做的事情基本就是这样,后面还陆陆续续的做了些其他的事情,不过我觉得,也只能防住八成的小黑客,或许连八成都没有,即使有专职的安全工程师,这个比例也不会高到哪儿去。有点需要注意的是,绝对不可能做到 100%,只要不是 100%,就有乘虚而入的机会。
老板不重视安全是一回事,被搞了以后重视安全是另外一回事,在平时就很注重安全的更是粉毛麟角了。很不幸的是大部分的老板都属于前两者。为此带来的结果就是安全工程师在公司的地位相对比较低,见过不少公司都是把安全工程师划分到 IT support 部门,而非主流的运维、基础架构甚至单独成立一个安全部门,这个在非互联网公司更明显。尽管我个人很尊敬做安全,并且我也很清楚做安全的其实很有技术含量,但是大陆的整体环境就那样,这个近期好像无解。

two-factor 认证的问题

研究了下 google 出的 google-authenticator,准备用在 ssh 的登陆上,安装配置确实很简单,参照这个文档一步步往下就可以。
很不幸的是,如果要在 ssh 的登陆过程中使用,就没那么理想了。
目前我们所有的服务器都是通过公私钥验证,理论上说,只要私钥不被窃取,是不可能登陆到我们服务器的。但是试用了 two-factor 之后,则必须要开启密码验证的方式,然后再输入那个随机生成的一串字符。根据这两个(1, 2)文档所示,目前没有好的方式可以让公钥认证跟密码登陆共存,这也就意味着,我们是不可能同时使用 two-factor 结合公私钥来登陆服务器的。除非不使用标准的 openssh。
这样看来,two-factor 并不是一个很好的选择。看到有不少公司把它拿来做跳板机,有钱的当然直接买 RSA 了,这或许是一个比较好的选择,不过这样意味着需要一些集中的用户管理方案。
很早之前,我无意发现有同事把自己电脑的整个 ~ 给同步到 github.com 上去了,这个目录里面包含要进入我们的内网环境的 VPN 证书文件,登陆服务器的私钥文件。不幸的是,这个项目还有不少的 fork,虽然事后做了大量的工作,不过现在看来,是不是上个 two-factor 能够最大程度的减小这类悲剧发生之后的影响。

TCP Wrappers 的注意事项

通常情况下,可以在 hosts.deny 里面建立一条 ALL:ALL 的规则,再到 hosts.allow 里面定义允许放行的服务。该做法理论可行,但实际操作中会遇到不少问题:任何一个有权限的人都可以通过 hosts.allow 添加权限,或者干脆将 hosts.deny 删除,因此比较好的方式是在 hosts.allow 的最后追加:
ALL:ALL:DENY

或者再追加一条:

ALL:DENY
这样即使 hosts.deny 被删除,对系统也没有影响。

另外在使用:
service : ALL : allow
service : ALL : deny
这两条规则时要注意,一旦匹配到该行,接下来的所有规则将被忽略,因此,上面这两条规则需要放在所有规则的最后,如果按下面的写法则无效:
sshd : ALL : allow
sshd : bad.host : deny
sshd : 88.4.2. : deny

正确的写法如下:
sshd : bad.host : deny
sshd : 8.8.4.2. : deny
sshd : ALL : allow

Continue reading

如何设置邮箱以及密码

下面这个是写给对安全有比较高要求的同学,如果你是个 shitizen,每天仅仅是用用百毒扣扣看看猫扑,完全可以忽略下面的文字。

这年头不光密码要做的足够的复杂,连邮箱都需要有一定级别的强度,不然遇到 #MircoSHIT 这种二货,只能等死了。

对于邮箱来说,比如一个叫王人人的同学,使用下面这些组成的邮箱去注册人人网是很容易被人『猜』出来的:
[email protected]
[email protected]
[email protected]
[email protected]

[email protected]

如果他恰巧用了上面的某些邮箱,然后又注册了 Skype,他的账户就裸奔了。
而像 『[email protected]』这类的及其变形则比较适合做注册之用,如果对安全特别高,可以 Google『Disposable Temporary E-Mail』,或者像中情局的那位大大跟她情人一样,共用一个邮箱草稿。

另外一点重要的是,务必一个网站一个邮箱,对应一套独特的密码。
对于密码的选择,最初是生成一套相对有规律的密码,然后做 sha1sum,不过依然不够强悍,还有很可能被 crack 掉,后来干脆直接随机生成,大小写、数字、特殊字符必须包含,这会涉及到管理问题,纯用脑子记明显是不可能,需要第三方的工具帮你来记忆,具体的操作,很多文档都说的很好,比如这几个(1, 2, 3),不再叙述。

很多人都是出了问题再事后补救,第一次可以,第二次再出现类似的问题就不好了。

Successful su for nobody by root 问题

/var/log/auth.log* 文件中出现了如下的条目:
Jul 30 06:52:59 jaseywang-pc su[3973]: Successful su for nobody by root
Jul 30 06:52:59 jaseywang-pc su[3973]: + ??? root:nobody
Jul 30 06:52:59 jaseywang-pc su[3973]: pam_unix(su:session): session opened for user nobody by (uid=0)
Jul 30 06:52:59 jaseywang-pc su[3973]: pam_unix(su:session): session closed for user nobody
Jul 30 06:52:59 jaseywang-pc su[3988]: Successful su for nobody by root
Jul 30 06:52:59 jaseywang-pc su[3988]: + ??? root:nobody
Jul 30 06:52:59 jaseywang-pc su[3988]: pam_unix(su:session): session opened for user nobody by (uid=0)
Jul 30 06:52:59 jaseywang-pc su[3988]: pam_unix(su:session): session closed for user nobody
Jul 30 06:52:59 jaseywang-pc su[4016]: Successful su for nobody by root
Jul 30 06:52:59 jaseywang-pc su[4016]: + ??? root:nobody
Jul 30 06:52:59 jaseywang-pc su[4016]: pam_unix(su:session): session opened for user nobody by (uid=0)
Jul 30 06:53:04 jaseywang-pc su[4016]: pam_unix(su:session): session closed for user nobody
Jul 30 06:53:05 jaseywang-pc CRON[27528]: pam_unix(cron:session): session closed for user root

并且是差不多每天这个时段出现,最开始以为是被 hack 了,后来排查发现其实是 cron 跑的 log 输出:
$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts –report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts –report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts –report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts –report /etc/cron.monthly )

看来不要遇到不正常的情况就以为被 hack 了,SA 要镇静。

ref:
http://serverfault.com/questions/226110/entries-in-auth-log-are-i-am-not-sure-what-it-means