着陆后飞机停在离建筑物至少 1 公里的广场中间,所有人被要求等待体温检查,四名身着生化防护服的检疫人员登上飞机,神情紧张地对每一位机上人员检查体温,机组人员也不放过。前后折腾了近一个小时才下飞机,从北美回来的人还真是不受首都人民欢迎呢。

为了不引起恐慌,鄙人自觉在家中隔离一个星期,目前感觉很热,但不是发烧,北京已经 34℃ 了撒。
老年痴呆提前出现
着陆后飞机停在离建筑物至少 1 公里的广场中间,所有人被要求等待体温检查,四名身着生化防护服的检疫人员登上飞机,神情紧张地对每一位机上人员检查体温,机组人员也不放过。前后折腾了近一个小时才下飞机,从北美回来的人还真是不受首都人民欢迎呢。

为了不引起恐慌,鄙人自觉在家中隔离一个星期,目前感觉很热,但不是发烧,北京已经 34℃ 了撒。
不知怎么提起猪流感就会想起麦当劳那个猪堡包的广告。老板已经回北京了,刚才上 MSN 碰见,告诉我那趟飞机着陆后有人上来查体温,三人被带走,所有人都留了联系方式,现已经到办公室上班了,无碍。
现在米国这里根本就没人在乎 H1N1,按说已经是世界病例第一多的地方了,至少该紧张点才对,可人家就不,平时根本不谈论这个,地铁照坐,口罩不带,社交活动一样都没少,是米国人太大条还是俺们中国人自己吓唬自己?在和菜头那里看到一个成都人被关的帖子,还真是草木皆兵啊,过两天我也该回去了,祷告中...
vpnc 是一个开源的 VPN 客户端,可以用来连接 Cisco VPN 网关,在 VPS 上使用 vpnc 连接办公网络,可以实现在一个严格限制端口的办公网络里管理 VPS。我的 VPS 是 vpsvillage 的 32-bit Debian 系统,最近折腾了一通,笔记记录如下。
1. 首先要保证系统装有 tun 模块,不巧的是,我的 VPS 上的 kernel 模块全是 64-bit 的版本,这个应该是操作系统安装脚本的问题,联系客服后得知他们提供有 32-bit 的 kernel module 包,并且有个脚本帮助完成安装。
wget ftp://ftp.grokthis.net/pub/linux/modules/install_modules.sh
mv /lib/modules/`uname -r` /lib/modules/`uname -r`.orig
sh install_modules.sh
depmod -a
modprobe tun
2. 安装 vpnc
apt-get install vpnc
3. 导出 VPN 网关的配置文件
公司机器都是 windows 已经装有 Cisco VPN Client,通常在 C:\Program Files\公司\VPN Client\profiles 里面就能找到配置文件。vpnc 带有一个工具可以将 pcf 配置文件直接转换为 vpnc 的配置文件,工具默认安装在 /usr/share/vpnc/pcf2vpnc,是个 perl 脚本,依赖 LWP::Simple 模块,我的 VPS 上没有这个,perl -MCPAN -e 'install LWP::Simple' 等了很久也没完成,放弃。其实可直接根据 pcf 文件里面的内容,参考 /etc/vpnc/example.conf 写一个配置文件,只要 ——
4. 解码配置文件中的 enc_GroupPwd
vpnc 主页提供了个工具 cisco-decode,直接到那解码即可。
5. 默认情况 vpnc 建立了 vpn 隧道之后会把默认网关和 /etc/resolv.conf 修改掉,如果这时候你在外网 ssh 在鼓捣这个,那 ssh 连接就会断了并且再也连不上,要用到两个配置:Target networks 和 DNSUpdate。完整的 vpnc 配置文件示例:
IPSec gateway 12.34.56.78
IPSec ID CorpVPN
IPSec secret grouppassword
Xauth username myusername
Xauth password mypassword
Target networks 10.0.0.0/8 192.168.0.0/16
DNSUpdate no
6. vpnc 需要 root 权限,即使把它 chmod u+s 也没有用,因为它使用的一个库 libgcrypt 会在 init 的时候放弃 euid root 权限,导致不能对 tun0 设备进行 ioctl。
7. 在严格限制端口的办公网络内部,在 VPS 上放一个 cgi 程序来建立 VPN 隧道即可穿透端口限制,但是通常 web 服务都是普通用户(如 www-data, nobody)运行,要调用 vpnc,需要写个 wrapper:
/* VPNC.c */
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
/* gcry_control from libgcrypt drops root euid privilege in vpnc.c */
setuid(0);
return execve("/usr/sbin/vpnc", argv, NULL);
}
然后
gcc -o VPNC VPNC.c
cp VPNC /usr/sbin/
chown root:www-data /usr/sbin/VPNC
chmod 4710 /usr/sbin/VPNC
在 cgi 程序中调用 VPNC 才能拥有 root 权限。vpnc-disconnect 也是一样。
8. cgi 程序的写法就各显神通了,我的 cgi 程序是 bash 脚本,可以 URL/vpnc/q 查询 IP,URL/vpnc/<key> 建立连接,URL/vpnc/d 断开连接,相关的 lighttpd 配置(适应任何脚本):
$HTTP["url"] =~ "^/cgi-bin/.*" {
cgi.assign = ( "" => "" )
} 这是一个突破公司端口封锁的完美解决方案,比 webtunnel 要好得多。
背景是:公司网络只允许 http 和 https 外出访问,以及 msn 端口(1863)到指定的几个服务器,我在外网有一个具有独立域名和 IP 的 服务器(就是这个 VPS),我有该服务器的 root 权限,从外网我可以用公司安装的 Cisco VPN Client 连接到公司网络。这种情况下,我想当自己在公司内网时能无限制的访问外网的任何资源,比如登陆管理自己的 VPS 或者 Home Server。
思路如下:
这是这趟出差跟美国这边同事聊起来才有的点子,超简单是不是,但是个中曲折,真是一言难尽。今天只说下思路,细节后表,太晚了该洗洗睡了...
公司的防火墙升级,原先开放的端口(漏网之鱼)cvspserver 现在被关,只留了个 msn 端口、www 和 htttps,msn 端口只针对 msn 服务器,其他的就更没指望了(没错,我就是敢在公司内部用 nmap 慢速扫描),为了能在公司的网络登录我的 VPS,把 ssh 端口改成 443 也没有用,哇塞,超级厉害的防火墙!居然是基于协议的,难怪我们上网这么慢呐。
于是,webtunnel 成为(似乎?)唯一的穿墙法门。真是天外有天啊。此物只需要放在 web server 上作为 cgi 程序即可提供穿墙隧道,用来登录 ssh 全无问题,甚至可以 ssh -D 进而作为 socks 代理,遗憾就是响应速度不够理想。不过人家才是 0.0.5,走着瞧吧。用法看它的 README,或者先看这里。
用 TETware 做自动化测试框架,越来越觉得这玩意很差,至少是 ksh API 这部分,用我同事的话说,已经“out”了,在我手上改了不少,仍然不够好用。今天竟然发现一个记 log 的接口里面竟然会死循环,调查下去竟然是个 ksh93 的 bug,要不是这个接口写得这么烂,也许这个 bug 永远都见不到天日了。
废话扯完了,看看是什么 bug。
${parameter%pattern} 用来从 parameter 字符串中去掉 pattern 后缀,${parameter#pattern} 用来从 parameter 字符串中去掉 pattern 前缀,这两个经常用来取路径名中的目录和文件名。但是当 parameter 是个多行字符串并且 pattern 符合 “\n.*(.*).*” 模式时它们不干了:
$ cat ksh93bug
NL=$'\n'
PAT="$1"
A="Hello $NL$PAT"
echo "${A%$NL$PAT}"
A="$PAT$NL world"
echo "${A#$PAT$NL}"
$ ksh ksh93bug '()'
Hello
()
()
world
$ ksh ksh93bug 'a(b)c'
Hello
a(b)c
a(b)c
world
仅仅是 AT&T ksh93,包括最新版本都有这个问题,在 bash 和 public domain ksh 中没有问题:
$ bash ksh93bug '()'
Hello
world
$ bash ksh93bug 'a(b)c'
Hello
world
我们的例子是 out=$(mount) 接着 tet_infoline "$out"它就歇菜了,TETware 的 tetapi.ksh 在 tet_output 函数里面用 %% 在循环里面去处理多行文本,哪里想到后缀永远删除不掉,在我试图加 set -x 调试的时候迅速的将硬盘写满了:P
本想报告这个 bug,在 ksh93 主页 上没找到给谁报,懒得伺候了,先改 TETware 再说了。
获悉 Sun 公司 Kernel Networking 北京开发组全组被裁,当年我在这个组实习,转正后虽然去了别的组,无论工作还是私人关系都比较紧密,虽然知道是迟早的事,心里还是非常不好受。又悉其中三人转移到其他组,技术都很牛的三人,其中两个还是我最为佩服的,稍感欣慰。现下行业不景气,和尚多庙少,被裁的兄弟恐怕不太容易找到满意的工作,祝他们好运。
牛年目标:
忍不住还是把 joyus.net 注册了,过期半年了也没人要,怪可惜的。GoDaddy 还涨价了,还好汇率低。用这个 coupon 码 gdr0110m 可打 9 折,截至日期到这个月 22 号。
Python 里 optparse 是一个很不错的命令行参数处理模块,不过当我想把 -h 用作指定 hostname 时发现默认的 -h 参数非常恼人,模块报告一个冲突,但是文档却没有记录如何解决这种问题。翻了源代码,找到解决办法:
方法一,初始化 OptionParser 的实例时指定 add_help_option=False,再自己添加一个 --help 选项:
parser = optparse.OptionParser(usage=usage, add_help_option=False)
parser.add_option('', '--help', action='help')
这样 -h 就空出来啦。
方法二,初始化 OptionParser 实例时指定 conflict_handler="resolve",然后就不用理会默认的 -h/--help 直接加自己的选项就行了,冲突时会只取用最后指定的选项。
parser = optparse.OptionParser(usage=usage, conflict_handler="resolve")