用代理连接 OpenVPN 的问题

很多人在公司、学校都是通过代理服务器上的网,需要设置代理。我们有位客户在公司用代理上 OpenVPN 时遇到一个问题,他在我们的 VPS 上安装和配置好了 OpenVPN 服务,客户端也设置了代理 http-proxy 192.168.0.1 3128,可是就是连不上去。OpenVPN 客户端报错如下:

2010-05-16 15:46:48 Attempting to establish TCP connection with 192.168.0.1:3128 [nonblock]
2010-05-16 15:46:48
2010-05-16 15:46:49 TCP connection established with 192.168.0.1:3128
2010-05-16 15:46:49 Send to HTTP proxy: ‘CONNECT 206.221.200.200:1194 HTTP/1.0’
2010-05-16 15:47:40 recv_line: TCP port read timeout expired: Operation now in progress (errno=36)
2010-05-16 15:47:40 TCP/UDP: Closing socket
2010-05-16 15:47:40 process exiting

这是因为大部分代理服务器都封掉了非标准端口,并且很多管理员因为安全因素都封掉了非标准端口的 HTTP CONNECT,所以像 OpenVPN 的默认 1194 端口而且需要CONNECT 方法支持就不行。既然不能去要求公司管理员把 1194 端口打开,我们就只能在自己 VPS 上想办法,幸运的是大部分代理服务器都会开 443 端口并且可以 CONNECT,所以我们只需要修改自己 VPS 上 OpenVPN 服务器的监听端口,把它改成 443 就可以了,使用代理的话还必须用 TCP:

# vi /etc/openvpn/server.conf

# Which TCP/UDP port should OpenVPN listen on?
# If you want to run multiple OpenVPN instances
# on the same machine, use a different port
# number for each one.  You will need to
# open up this port on your firewall.
;port 1194
port 443

# TCP or UDP server?
proto tcp
;proto udp

Ping 域名时 DNS 反向解析问题

中文吃饭的时候看到 Godaddy 事件居然上了 CNN,在美国国会听证会上,GoDaddy 的法律顾问说公司将停止在中国提供新的 .cn 域名注册(据说老的域名还可以继续使用)。不过关系不大,好像中国用户在 Godaddy 注册的 .cn 域名不到3万个。

昨天我们一个用户说他 ping godaddy 域名的时候间隔很长,我理解错了,以为是延迟很长,其实是每次 ping 后间隔时间很长,但是 ping 返回来的 time 值是正常的。这是因为 ping 的时候遇到 DNS 反向解析问题,默认情况下,当 ping 一个域名的时候,ping 从域名服务商得到域名的 IP 地址,然后 ping 访问这个 IP 并试图解析成一个名字,因为我们不提供 DNS 服务也没有 DNS 反向解析,所以导致 ping 需要等到 DNS time out 才返回,这样看上去 ping 回应很慢。

ping 是这样工作的:ping 有两个线程在执行,一个用来发包,一个用来收包和打印结果,发包的线程不停的发,没有问题,问题出在收包的线程,这个时候收包线程是被阻塞的(因为这个时候 DNS 反向解析不成功,一直要等到超时),所以收包线程要等到 DNS 超时后才打印出 ping 的结果,而这个时候结果是正确的,因为结果本来就是对的,只不过因为被阻塞而推迟了显示的时间而已,所以造成 ping 域名间隔很长的假象。如果用 ping -n 关闭掉 DNS 解析就不会有这种问题了,比如:

$ ping -n google.com

撤掉 DD-WRT,换上 Tomato

上周发现刚配置的 Linksys WRT54GL 无线路由器很不稳定,时断时续,刚开始没注意以为是信号干扰,后来经常发生,1小时就断好几次,已经不能忍受了。检查了所有路由器的配置,发现有2个路由器配置错误,或者说这2个路由器只刷了固件根本没有配就放上去了(现在大学生做事情真让人不放心)。原因没有细想,大概就是 LAN 网络接口从 DHCP 服务器得不到 IP 地址的时候,无线网络模块就企图从周围无线路由器得到 IP 地址,但是 WLAN 的 MAC 地址没有在 DHCP 服务器注册,所以永远不会得到 IP,并且影响了其他无线路由器。

上面是个小问题,重新配置一下就可以了。遇到另外一个问题是,几个 Linksys WRT54GL 刚启动的时候运行稳定,过10分钟左右就出现丢包、连接延迟超长等不正常现象。检查了多遍路由器配置没发现问题,用 sniffer 探包发现路由器运行一段时间后就从 DHCP 服务器那里得不到地址了,然后过段时间又好了。DHCP 服务器应该没什么问题,我们 n 多 PC 都在用,最后怀疑到 DD-WRT 头上。

在 DHCP 服务器上 ping 无线路由器(因为篇幅关系,下面数据是截取的、不完整):

$ ping 192.168.1.96
PING 192.168.1.96 (192.168.1.96): 56 data bytes
64 bytes from 192.168.1.96: icmp_seq=0 ttl=64 time=651.472 ms
64 bytes from 192.168.1.96: icmp_seq=1 ttl=64 time=257.708 ms
64 bytes from 192.168.1.96: icmp_seq=2 ttl=64 time=3.930 ms
64 bytes from 192.168.1.96: icmp_seq=3 ttl=64 time=2.213 ms
64 bytes from 192.168.1.96: icmp_seq=4 ttl=64 time=2.196 ms
64 bytes from 192.168.1.96: icmp_seq=5 ttl=64 time=74.325 ms
64 bytes from 192.168.1.96: icmp_seq=6 ttl=64 time=2.098 ms
Request timeout for icmp_seq 7
64 bytes from 192.168.1.96: icmp_seq=12 ttl=64 time=3391.375 ms
64 bytes from 192.168.1.96: icmp_seq=13 ttl=64 time=2393.664 ms
Request timeout for icmp_seq 14
Request timeout for icmp_seq 15
64 bytes from 192.168.1.96: icmp_seq=26 ttl=64 time=5046.445 ms
64 bytes from 192.168.1.96: icmp_seq=27 ttl=64 time=4046.750 ms
64 bytes from 192.168.1.96: icmp_seq=28 ttl=64 time=2.309 ms
...

换成 Tomato 固件后,再 ping:

$ ping 192.168.1.96
PING 192.168.1.96 (192.168.1.96) 56(84) bytes of data.
64 bytes from 192.168.1.96: icmp_seq=1 ttl=64 time=0.683 ms
64 bytes from 192.168.1.96: icmp_seq=2 ttl=64 time=0.690 ms
64 bytes from 192.168.1.96: icmp_seq=3 ttl=64 time=0.658 ms
64 bytes from 192.168.1.96: icmp_seq=4 ttl=64 time=0.681 ms
64 bytes from 192.168.1.96: icmp_seq=5 ttl=64 time=0.662 ms
64 bytes from 192.168.1.96: icmp_seq=6 ttl=64 time=0.650 ms
64 bytes from 192.168.1.96: icmp_seq=7 ttl=64 time=0.635 ms
64 bytes from 192.168.1.96: icmp_seq=8 ttl=64 time=0.682 ms
64 bytes from 192.168.1.96: icmp_seq=9 ttl=64 time=0.639 ms
...

Tomato 的数据比 DD-WRT 好看的多,事实上也稳定的多,现在已经把所有固件换成 Tomato,这周再继续观察一下。让 VPSee 不解的是 DD-WRT 出来好多年了,n 多的人在使用,界面专业、文档丰富、社区活跃、也有很多人推荐,为什么实际效果这么差强人意呢?本来觉得 DD-WRT vs OpenWrt vs Tomato 这样的讨论和比较 Linux 发行版一样没有意义,现在看来还是要多尝试,多测试,人家的意见只能参考,不能人云亦云。

超轻量级窗口管理器:dwm

如果把 X 窗口管理按照重量来划分的话,GNOME/KDE 是两大重量级桌面系统,XFCE 是中型桌面,FVWM, Fluxbox, Blackbox, IceWM 等可以看作轻量级的桌面/窗口管理器。更轻量级的窗口管理器就要数 dwm, xmonad, awesome, ratpoison 等了,这类管理器也叫做平铺窗口管理器(Tiling window manager),它们的特点是:占用资源很少,可以完全的键盘控制,窗口布局一般不叠加并且能平铺整个屏幕、不浪费屏幕像素尽量增加可视范围等,非常适合服务器或者资源有限的机器使用。VPSee 就在一台古董级 Thinkpad 上使用 DWM,一个工作区可以平铺6个窗口用来监视6个 Linksys WRT54GL 无线路由器的连接状况。

因为大部分的工作和时间都锁定在 terminal, vim, firefox,mutt,没有理由为了这4个工具就安装几百兆臃肿的桌面环境,一个轻量的桌面环境能让我更好的把注意力集中在工作上。dwm 就是一款我需要的平铺窗口管理器,用 C 语言写的,全部代码不到2000行,不需要依赖其他库就可以编译,与其他几款平铺窗口管理器不同的是它没有可配置文件供修改,要修改它的配置只能通过修改它的源代码,也就是说每次都需要通过修改 dwm 的源代码(其实就是一个头文件而已,config.def.h)、编译然后安装来配置 dwm. 也有一些平铺窗口管理器是从 dwm 分出来的,比如 awesome, xmonad 等。LinuxToy 介绍了平铺式窗口管理器:awesome另一个平铺式窗口管理器:ion,感兴趣的话可以比较一下。

使用技巧

启动 terminal:Shift+Alt+Enter
启动 dmenu:Alt+p
移动一个窗口到另一个 tag:Shift+Alt+2
转移到另一个 tag:Alt+2
关闭一个窗口:Shift+Alt+c
移动和重设窗口大小:Alt+mouse button
退出 dwm:Shift+Alt+q

dwm 运行的界面如下:

dwm

把 Linksys WRT54GL 路由器当作交换机用

不知道各种无线信号会不会对人体产生危害,反正我每天都沉浸在大量的无线网络中:(,手机、无线路由器、无线网卡、笔记本、蓝牙、GPS、⋯⋯,都在发送或者接收信号,想逃都逃不了。我们在工作区部署了6个 Linksys WRT54GL 路由器,用来扩展我们的网络,特别是那些网线不能到达的地方,比如有的人有在厕所上网的习惯:),除了普通上网,无线网络还负责接入手机以便使用 VoIP 功能

Linksys WRT54GL 是一款是非常 hacker-friendly 的路由器,Cisco 开放了它的固件源代码,本来 Cisco 是不愿意公开源代码的,被人发现固件使用的是 Linux,Linux 是基于 GPL2 协议,迫于公众的压力 Cisco 才开放全部源代码,这也就带动了开源社区,开发者纷纷开发出针对这款路由器的固件(firmware),比如 OpenWRT, DD-WRT, Tomato 等,这些都是基于 Linux 的 Open Source 固件,可以通过在上面安装软件、修改配置等办法以挖掘出路由器的最大潜能,有的人甚至拿 Linksys WRT54GL 做 Wifi 机器人。Linksys WRT54GL 上的原厂固件功能太少,比如只能过滤20个 MAC 地址、可修改的配置选项太少、不能安装软件等。只需要换固件、简单修改一下配置就可以把 Linksys WRT54GL 路由器变成一个纯无线交换机,如果不用 WAN 的话还可以把 WAN 口改成 LAN 的口,这样就有5个 Swtich LAN 口可以使用,这就是 open source 的好处,可以拿来 “玩”。相对 OpenWRT 和 Tomato 来说,DD-WRT 可供修改的配置更多一些,界面也显得更专业一些,而且后面有一个商业化的公司(DD-WRT Shop)在运营,技术支持、文档更丰富一些,OpenWRT,Tomato 则比较简单,容易上手,更适合家庭用户。

linksys wrt54gl

刷固件

首先到 dd-wrt.com 官方网站下载最新的固件,然户按照说明刷最新的固件,过程非常简单,可 google 相关资料。Linksys WRT54GL 上面有3个 MAC 地址,分别对应:WAN、LAN 和 Wireless LAN.

修改配置

刷完系统后,登陆进 dd-wrt 的 web 管理界面:http://192.168.1.1,默认用户名/密码:root/admin,接下来按下面的设置修改:

打开 Setup -> Basic Setup 页面:

WAN Connection Type : Disabled(禁止WAN)
Local IP Address : 192.168.1.2(设成这台路由器在 LAN 上的 IP 地址)
Subnet Mask : 255.255.255.0(子网掩码)
Gateway: 192.168.0.1(这台路由器所在网络的主 router)
Local DNS : 10.0.0.2(这台路由器所在网络的主 gateway)
DHCP Type : Disable(路由器自己不提供 DHCP 服务)
Assign WAN Port to Switch : (打开这个选项如果你想把 WAN 那个口用作 Switch 口的话)
Use DNSMasq for DHCP: Enable
DHCP-Authoritative: Enable
Save

打开 Setup -> Advanced Routing 页面:

Operating Mode: Router
Save

打开 Wireless -> Basic Settings 页面:

Wireless Network Name (SSID) : CoE(填写自己的无线网络名)
Save

打开 Wireless -> Wireless Security 页面:

Security Mode : WPA2 Personal
WPA Algorithm : AES
WPA Shared Key: YourSharedKey
Save

打开 Services -> Services 页面:

DNSMasq : Disable(禁止这个选项,可选)
ttraff Daemon : Disable(禁止这个选项,可选)
Save

打开 Security -> Firewall 页面:

SPI firewall: Disable(禁止防火墙,如果你想以后通过 IP 地址访问这个路由器的话)
Save

打开 Administration -> Management 页面:

Info Site Password Protection : Enable(查看路由器信息页面需要密码保护,建议打开这个选项)
Routing: Disable
Save

设置完毕后点击 “Apply Settings”,路由器就会重启,重启后路由器就成了一个无线交换机了。

Troubleshooting

如果上面操作导致错误配置,需要恢复到原配置的话需要做 Hard Reset (30/30/30 reset):

  1. 在通电的情况下按住路由器背面的 reset 按钮30秒;
  2. 继续按住 reset 按钮,把电源线拔掉,再坚持30秒;
  3. 继续按住 reset 按钮,插上电源、最后坚持30秒。

在64位的 CentOS 上只安装64位的软件包

在 64位版本的 CentOS 5.4 上使用 yum 安装软件包的时候如果不小心的话会同时安装 i386 和 x86_64 版本的软件,如下面安装的 httpd-devel 就有 i386 和 x86_64 两个版本:

# yum install httpd-devel
...
Dependencies Resolved

================================================================================
 Package              Arch       Version                      Repository   Size
================================================================================
Installing:
 httpd-devel          i386       2.2.3-31.el5.centos.2        updates     147 k
 httpd-devel          x86_64     2.2.3-31.el5.centos.2        updates     147 k
Installing for dependencies:
...

同时安装32位和64位版本的软件虽然不是什么错,也不会对系统造成什么问题,但是这样会浪费硬盘空间,而且显得系统臃肿、不干净。如果想要保持一个纯的64位系统、在64位 CentOS 上避免安装32位软件包的话很容易,只需要在 yum.conf 加上一行过滤掉 i386, i686 的软件包就可以了:

# vi /etc/yum.conf
[main]
...
exclude=*.i?86

然后删除系统上已经安装的 i386/i686 包:

# yum remove \*.i\?86

Minix 上的 AMD Lance 网卡驱动问题

今天在 Minix on VMware 上发现了一个奇怪的问题,使用静态 IP 地址以后,外部网络无法 ping 通 Minix,必须 Minix 先 ping 外面,然后外面才能 ping 通它。在 Google groups 上发现有人也遇到同样的问题:

I have Minix3 on a VMWare virtual machine … If I try to ping the box itself (192.168.1.134), I don’t get a reply unless I first ping the box back from the minix machine. I am running in bridged mode and I can get to the internet fine from the minix machine, but other machines cannot communicate with the minix machine unless the minix machine first communicates with the caller. Has anyone had similar issues? It is driving me crazy.

因为绝大多数人都在 VMware 上安装和运行 Minix,所以 Minix 上的 VMware 的网卡驱动尤其重要,至少重要性要高过其他网卡驱动。这里碰到的问题是由 Minix 上面 VMware 的模拟网卡驱动(AMD Lance NIC)造成的,lance 驱动必须被 load 在头 16MB 内存里,如果系统启动以后再 load 网卡的话会造成 lance 被 load 到 16MB 以外,造成驱动不工作。看到这里,马上就会想到如果事先 load 驱动的话(在 16MB 以内)就会避免上述问题,比如在加载文件系统以前?嗯,这是一个耍无赖的方法,但不是最好的。

在 Minix 3.1.5 上的解决办法是运行下面命令重新启动 lance 驱动:

# service refresh lance

在 Minix 3.1.3 上就比较倒霉了,会导致网卡驱动(lance)彻底不工作,不过这难不到众多使用 Minix 的 hacker 们,按照 comp.os.minix 上的这篇 Fix for Minix 3.1.3a, VMware, and Networking 可以在 Minix 3.1.3 上解决这个难题。

在 pfSense 上安装 DDclient

接着昨天的来,现在我们需要给我们刚建的小组内部网络设个动态域名以便外面可以用 ssh 等访问到内部的服务器,首先需要到 DynDNS.com 注册一个免费二级域名,然后在防火墙上安装动态域名客户端,每隔一段时间自动读取 ADSL 路由器的动态 IP 地址然后更新到 DynDNS.com 的域名服务就可以了。

pfSense 有自带的动态域名客户端,打开 pfSense 管理界面后配置 pfSense 自带的 Dynamic DNS 服务(pfSense->Services->Dynamic DNS),发现这个客户端有问题,只能在 save 的时候更新一次 IP 地址,不能自己自动更新 IP 地址,而且第一次提交的 IP 地址是内部的网络地址而不是我们想要的 ADSL 路由器对外的 IP 地址,google 了一下发现 pfSense 自带的动态域名客户端确实有问题:

Only works if pfSense is the public IP assigned to one of its interfaces. If you have a modem that gets your public IP and pfSense is a private IP, private IP address is registered with the provider.

解决办法是 disable pfSense 自带的 Dynamic DNS,安装第三方动态域名客户端 ddclient:

# pkg_add -r http://files.pfsense.org/packages/dns/ddclient-3.7.0.tbz
# cp /usr/local/etc/ddclient.conf.sample /usr/local/etc/ddclient.conf

# chmod +w /usr/local/etc/ddclient.conf
# vi /usr/local/etc/ddclient.conf
use=web, web=checkip.dyndns.com/, web-skip='IP Address'
server=members.dyndns.org
protocol=dyndns2
login=vpsee
password=your-password
vpsee.dyndns.org

修改完上面的 ddclient 的配置文件后,运行 ddclient 测试一下是否能运行:

# /usr/local/sbin/ddclient -daemon=0 -debug -verbose -noquiet

...
Can't load '/usr/local/lib/perl5/site_perl/5.8.8/mach/auto/Net/SSLeay/SSLeay.so' for module Net::SSLeay: Shared object "libssl.so.4" not found, required by "SSLeay.so" at /usr/local/lib/perl5/5.8.8/mach/DynaLoader.pm line 230.
 at /usr/local/lib/perl5/site_perl/5.8.8/IO/Socket/SSL.pm line 17
Compilation failed in require at /usr/local/lib/perl5/site_perl/5.8.8/IO/Socket/SSL.pm line 17.
BEGIN failed--compilation aborted at /usr/local/lib/perl5/site_perl/5.8.8/IO/Socket/SSL.pm line 17.
Compilation failed in require at /usr/local/sbin/ddclient line 1652.

上面错误显示缺少 libssl 库,这个好办,安装一个就可以了:

# pkg_add -r http://files.pfsense.org/packages/devel/openssl-stable-0.9.7l.tbz
# cp /usr/local/openssl/openssl.cnf.sample /usr/local/openssl/openssl.cnf

再次运行 ddclient 后无错误提示,运行成功:

# /usr/local/sbin/ddclient -daemon=0 -debug -verbose -noquiet

最后允许 ddclient 在后台(daemon)运行:

# vi /etc/rc.conf
ddclient_enable="YES"

登陆后 DynDNS.com 就会发现刚注册的二级域名的 IP 地址自动更新了:

dyndns domain

在 pfSense/FreeBSD 上安装 Squid

今年我们扯了一根自己的 4096 kbps ADSL 线路以便我们小组内部使用,不屏蔽端口,想访问什么就访问什么。为了同时访问工作网络和小组的网络,我们需要在不改变自己工作网络的网线和 IP 地址的情况下就能访问这根新的 ADSL 网络,所以需要在现有的工作网络上加一个 firwall/gateway 把 ADSL 和工作网络连接起来。简单的说我们现在有两套完全独立上网的网络,这样用户拿着笔记本进来插入工作网络网线就可以用工作网络上网,也可以改变代理服务器设置后用刚建的 ADSL 网络上网,或者不用网线,打开 WiFi 后直接进入 ADSL 所在的无线网络上网。下图中,如果 172.16.20.12 这台机器想上网,它可以使用 172.16.20.1 代理服务器通过工作网络上网,也可以通过使用代理服务器 172.16.20.10 通过 小组网络和 ADSL 上网。

小组:电话线 -- ADSL 路由器(10.0.0.1/8)
                 |
                 |
                 --------------  Firewall(10.0.0.2/172.16.20.10)
                                     |
                                     |
工作:Internet -- 路由器 -- 交换机 -- 工作网络(172.16.20.0/23)

为什么两个的网络要连起来呢?因为大家都不喜欢在网络之间切换,改 IP、网络设置、代理服务器等,很多时候大家需要同时在两个网络上,用工作网络(上网速度慢,很多端口被屏蔽,严格限制)访问内部所有的服务器,用新建的 ADSL 上网(网络速度快,没有屏蔽端口)。

要建这个 firewall/proxy/gateway 不需要很强大的硬件防火墙和服务器,所以 VPSee 决定把防火墙和 squid 服务安装在同一台机器上,节省资源。上个月对配置 Squid 服务器的硬件要求做了一些调查,接下来就是要在服务器上安装 Squid 服务。

pfSense 是一个基于 FreeBSD 的防火墙版本,从另一个 FreeBSD 防火墙 M0n0wall 发展而来,具有类似功能的 Linux 防火墙发行版本有 SmoothWall, Endian, IPCop, ClearOS, Untangle 等,试用了 一下 SmoothWall 发现非常简单易用,但是缺少一些我们需要的功能,SmoothWall 为了方便家庭用户使用把一些配置术语刻意简化了,比如配置网络的时候用到 Red/Green/Orange 让我摸不着头,我宁愿看到 nge0, bge0, eth0, 00:02:B3:CA:7B:92 等这些熟悉的术语,至少我能马上明白是什么意思。在测试 SmoothWall 的时候还遇到一些奇怪问题,比如启动了 DHCP 服务以后,客户端却不能及时得到 IP,要过几十秒钟,有时候甚至得不到 IP. pfSense 比 SmoothWall 强大很多,可自定义的模块很多,安装和配置第三方软件也很方便,使用起来特别顺手。

在 pfSense 上安装 Squid

安装 pfSense 过程很简单,这里省略,配置完 pfSense 网络接口后就开始安装 Squid,打开 pfSense 管理界面,在 System->packages 下面找到 squid 和 lightsquid(查看 squid 流量的工具)安装,成功后会在 Services 下看到 Proxy server 菜单,进去后可以配置 Squid 服务;在 Status->Proxy report 配置 Lighttpd 和查看 Squid 流量信息。
pfsense-squid

安装完 squid 后根据需要做一下配置,值得注意的是,默认安装后只有和这台 firewall/squid 服务器在同一个网段的机器才能通过这个 squid 访问 Internet,如果其他网段的电脑也想使用这个代理服务器的话除了在 Firewall: Rules 增加规则外,还需要在 Services->Proxy server: Access control 中增加网段到 Allowed subnets.

安装完 lightsquid 后要做如下配置:
1、配置 squid(Proxy server),enable /var/squid/log 路径;
2、配置 lightsquid(Proxy report)时需要点击 Refresh 按钮去创建 lightsquid reports,否则会得到一个出错页面。

在 FreeBSD 上安装 Squid

如果不用 pfSense,想在 FreeBSD 完整操作系统上安装 Squid:

# cd /usr/ports/www/squid
# make install

根据自己需要修改 squid.conf 配置文件:

# cp /usr/local/etc/squid/squid.conf.default /etc/squid/squid.conf
# vi /etc/squid/squid.conf

初始化 cache:

# /usr/local/sbin/squid -z

测试 squid 是否能正常运行:

# /usr/local/sbin/squid -NCd1

配置 Squid 服务器的硬件要求

去年有台 Squid 主服务器的主板坏了,因为有备份服务器所以不碍事,这台备份服务器是一台很老的 Pentium III 级别的 PC,平时不怎么用,只有主服务器 down 掉的时候才临时应付一下。VPSee 现在要抓紧时间把那台 Squid 主服务器换掉(在备份服务器坏掉之前~~),不考虑买新机器了,去年升级留下了很多老机器,以及一些内存、硬盘等配件,相互搭配一下应该可以配出几台好机器。

Squid 服务器的性能对内存和硬盘的要求比较敏感,硬盘缓存多少数据和需要多大内存之间有某种关系,这是因为每个缓存过的 object 在内存里都保留相应的 metadata,方便 Squid 能迅速查询 cache,这些 metadata 是由 StoreEntry 数据结构来保存的,每个 StoreEntry 占用 56 Bytes,加上每个 StoreEntry 都有1个 16-byte 的 cache key,所以保存在 cache 里面的每个 object 在内存中都对应占用 72 Bytes(metadata),这是在32位机器上的情况,如果是64位机器会占用更多(104 Bytes)。算下来在硬盘上缓存 1,000,000 个 objects 的话相应需要占用 72MB 内存用来做 metadata,而实际情况则比这个要多得多。这篇 Wiki 也解释了为什么 Squid 需要大量内存。如何来决定到底需要多少内存呢?能不能有某个公式可以直接套用呢? Squid: The Definitive Guide 这本书给出了这样一个建议,每缓存 1GB 需要 32MB 内存,这样的话一台 1GB 内存的机器可以在硬盘上缓存 32GB 的数据(object)。

As rule of thumb, you need 32 MB of memory for each GB of disk space.

除了知道以上内存和硬盘的关系以外,我们还需要通过实际需求来决定什么样配置的机器能满足用户需求并且取得最佳性价比。那么如何判断需要用多大的硬盘来缓存用户的记录呢?根据去年一年使用 LightSquid 对用户的日志统计和分析,VPSee 发现绝大部分用户每天消耗都不到 100MB 带宽(平均起来才 50MB 每用户每工作日),这样如果算每人每天平均消耗 50MB,每个月算20个工作日,那么每人每月就是消耗 1GB,算下来100人每月应该消耗 100GB 带宽,也就是要缓存每个月的用户记录的话需要 100GB 硬盘空间,根据上面 1GB/32GB 的公式,一台 4GB 内存的服务器就可以完全满足要求。幸运的是,Squid 服务器对 CPU 要求不高,只需要在老机器上加点内存就可以了。

还需要注意的是,一定要再配一台 Squid 服务器作为备份服务器以应付突发事件,cache 的数据不是很重要,所以不必做 RAID,不必花钱在一些昂贵的存储设备上,但是要保证至少有一台备份 Squid 服务器 stand by,在主服务器不能工作的时候能随时替换。Squid: The Definitive Guide 的作者推荐使用 FreeBSD 作为 Squid 服务器的操作系统。