Windows Server 2008是最新的Windows Server。Windows Server 2008公平地说还是相当不错的,性能和安全性都没有太大的问题,稳定更不用说。

这篇文章里,我会详细介绍如何在Windows Server 2008下,安装使用和配置IIS 7.0的FTP服务。

环境说明:

  • 操作系统:Windows Server 2008 Standard Edition,英文版(由Microsoft DreamSpark支持)
  • 相关软件:Internet Information Services 7.0

首先假定IIS已经安装好。如果不会安装IIS,请参阅其他文章。

1. 安装FTP服务

[singlepic=18135,640,462]

在Server Manager中右键Roles中Web Server(IIS),添加服务器角色(Add Role Service)

[singlepic=18136,640,481]

添加的是FTP Publishing Service,同时要添加其他两个依赖项。

2. 配置FTP服务

[singlepic=18137,640,514]

很遗憾地是,Windows Server 2008中,FTP服务仍然需要老版本IIS6的管理器来管理。在管理工具中打开(Internet Information Services(IIS)6.0 Manager),可以看到一个FTP站点。

[singlepic=18138]

FTP Site,如端口等如果不希望是TCP 21,那么在这里修改。

[singlepic=18139]

Security Accounts,这是一个很危险的选项,默认打开了匿名访问,一定记得关掉。

[singlepic=18141]

Home Directory,这里设置FTP的根目录和权限,以及FTP的目录的列表方式,为了兼容性,我设成了UNIX。

[singlepic=18145]

Messages,这里可以设置当用户被FTP禁止、连接、离开和达到最大连接数时收到的消息。

[singlepic=18142]

Directory Security,这里可以设置默认的访问方式,默认是允许所有访问,然后除去下列表中的例外。也可以按照计算机IP打开某些访问,而禁止所有其他的连接。

3. 添加FTP用户

[singlepic=18147,640,458]

在Windows FTP中,用户是Windows用户。要想添加一个FTP用户,必须添加一个Windows用户,然后去设权限。在Computer Management中,Local Users and Groups下的Users中添加一个普通Windows用户。

[singlepic=18146,640,458]

也许你会担心添加Windows用户会导致安全问题,比如可以远程桌面连接之类,其实不必。首先,添加的Windows用户是普通用户,这样在权限上低于管理员。其次,一个Windows用户要想远程桌面连接服务器,必须同时是Remote Desktop Users这个组的成员,新建用户默认不是的,所以用户不能连接系统。

[singlepic=18143,640,514]

在IIS6 Manager中,右键FTP Site,选择Permissions,把刚才添加的用户赋予FTP权限。其实就是Add,然后找到刚才的用户,然后添加进列表,赋予相应的权限即可。
到这里,常规的FTP就可以连接了。

4. 高级应用——如何开启Passive Mode

主流的FTP客户端一般首选Passive Mode去连接FTP服务器,而Windows默认是不允许的。这样的后果就是在FTP客户端登陆时,可以看到通过了用户名密码认证,在列目录时卡住,不能进行。但是使用PORT Mode则可以连接。其实是可以解决的。方法如下:

[singlepic=18148,640,451]

首先,在IIS6 Manager中,右键整个计算机节点,选择属性。

[singlepic=18149]

然后打开Enable Direct Metabase Edit,允许在IIS运行中改变其配置。

[singlepic=18136,640,481]

然后安装IIS 6.0的脚本工具,默认是不安装的,不安装,则在C盘inetpub中就找不到AdminScripts这个文件夹,因为我们需要AdminScripts下的adsutil.vbs这个脚本。安装方法同添加FTP服务,只不过这次需要勾选“IIS 6 Scripting Tools”,同样有几个依赖项需要安装。

[singlepic=18150]

打开一个命令行(Command Prompt),注意,如果你不是Administrator帐户登陆Windows Server 2008,需要邮件使用“Run as administrator”打开,否则权限不足,会提示:

[code=’c#’]
Permission denied
Err Number: 70 (0x46)
Error Trying To Get the Object: MSFTPSVC
[/code]

正常打开后,输入这条命令:

[code=’c#’]CSCRIPT.exe C:\Inetpub\AdminScripts\adsutil.vbs set /MSFTPSVC/PassivePortRange “5500-5515″[/code]

这样可以允许FTP服务在5500到5515这16个端口中选择端口,供FTP客户端使用。需要说明的是,FTP Passive Mode合法的端口号是从5100到65535,但是都打开是明显不安全的,这个参数要根据你的服务器的并发连接数适当选择。

[singlepic=18151]

执行成功会显示:

[code=’c#’]
Microsoft (R) Windows Script Host Version 5.7
Copyright (C) Microsoft Corporation. All rights reserved.

PassivePortRange : (STRING) “5500-5515”
[/code]
如果你的防火墙是关闭的,那就结
束了,可以在FTP客户端使用FTP Passive Mode连接了。

5. 高级应用——配置Windows Firewall with Advanced Security

[singlepic=18152,640,477]

Windows Server 2008默认配置并打开了Windows Firewall with Advanced Security这个高级Windows防火墙,很好很强大。我们刚才设置的16个端口,现在还通不过防火墙,必须加以配置。
下面开启5500到5515这16个端口的入站操作,也可以作为目的是打开某个端口的配置Windows Firewall with Advanced Security的一般方法。
Windows Firewall with Advanced Security区分Inbound Rules和Outbound Rules,分别对应入站和出站规则。FTP Passive Mode的实质其实是FTP Server选取一个没人(其他FTP客户)占用的端口,然后返还给你的FTP客户端,然后FTP客户端使用这个端口去连接FTP服务,这样可以提高并发连接数及并发连接性能。FTP Passive Mode对服务器来说是一种入站操作。
首先打开Windows Firewall with Advanced Security,然后在Inbound Rules上右键建立新的规则(New Rule)

[singlepic=18153,720,512]

在New Inbound Rule Wizard向导的Rule Type中选择Port,因为我们要配置TCP端口。

[singlepic=18154,720,512]

第二步Protocol and Ports中选择TCP端口,因为FTP属于TCP。下面选择Specific local ports指定特定端口,不要全部打开,否则防火墙变成李雷雷了。
遗憾地是,Windows Firewall with Advanced Security不能使用类似5500-5515的IP段(IP Address Range)表达式。不知道这是出于什么考虑,作为微软技术支持者,我不理解为低下的用户体验,而善意地理解为为了避免管理员图方便打开不必要的端口。因此你必须手工填入这16个端口,并用英文逗号分割。

[singlepic=18155,720,512]

Action中决定,对于前面选择的目标,Windows Firewall with Advanced Security采取何种操作。因为FTP是普通应用,不带安全选项,这里选择Allow the connection。

[singlepic=18156,720,512]

Profile中,可以指定连接来源类型,这是在其他防火墙中少见的一层,可以按照Domain,Private和Public来选择,Domain只允许当前AD中的连接,Private只允许本地网络的连接,Public则是所有连接。不用说,安全性又提高不少。

[singlepic=18157,720,512]

Name中,给这条规则取个名字和描述。将来管理方便,不至于在列表里找不到。

[singlepic=18159,640,477]

我们刚才做了什么?允许5500-5515这16个端口的入站连接。还是很不安全的,因为如果一个端口被打开,而没有相应的监听程序,属于一个安全漏洞。理想的状态是,给这条规则指定程序,指定到Windows FTP的服务。可惜我试了多次不能找到FTP的程序到底是哪一个(本来以为是C:\Windows\system32\inetsrv\inetinfo.exe,因为服务是启动了这一个。也不能只指定到FTP Publishing Service这个服务,连接不上)。
选择刚才添加规则的属性。

[singlepic=18160]

在Programs and Services中,选择Services Settings。

[singlepic=18161]

理想的情况应该是Apply to this service中选中FTP Publishing Service,这样就完美了。可惜这样其实连不上。无奈我只好选择了Apply to services only,只允许到系统服务。这样,除非另一个恶意程序把自己注册为系统服务来监听5500到5515这16个端口,其他普通程序是不可以的,安全性稍微提高了一些。
如此,一个完整的Windows Server 2008下IIS 7.0的FTP(支持Passive Mode)就建立起来了。

本文图片使用Nocoo.Tools提供的工作窗口截图工具ScreenCapture截取。

今天释出的KB958644号紧急更新,引起了我不小的兴趣,很希望知道到底是什么东西导致微软捅了这么大的篓子呢?无奈,因为出品公司(微软)承认这是一个严重的安全漏洞,提出问题的网站(http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-4250)已经去除了关于此漏洞的详细说明。这条路不通了。
MS08-067(http://support.microsoft.com/?kbid=958644)描述了什么样的系统里具体什么样的文件会出问题。从中可以看到,主要问题出在Netapi32.dll这个DLL。可以看出,自Microsoft Windows 2000 Service Pack 4(不是说之前的就没有,而是只从SP4开始技术支持)开始的5.0.2195.7203版本的Netapi32.dll,直到Windows Vista、Windows Server 2008甚至Windows 7 Pre-Beta的6.1.6801.4106版本Netapi32.dll都逃脱不了噩运。
重要的提示来自Microsoft Security Bulletin MS08-067 – Critical(Vulnerability in Server Service Could Allow Remote Code Execution (958644))一文。文中特别指出,这个漏洞如此广泛,甚至Windows Server 2008的Server Core installation也会受到同样安全威胁等级的威胁。这说明,这个漏洞存在很基础的地方。
Server Core installation是Server功能的极小集,根据Compare Server Core Installation Options一文,Server Core installation可以安装以下功能:

  • Active Directory Domain Services
  • Active Directory Lightweight Directory Services
  • DHCP Server
  • DNS Server
  • File Services
  • Hyper-V
  • Print Services
  • Web Services (IIS) without ASP.NET

鉴于Windows 2000也是受害者,因此不可能是Active Directory Lightweight Directory Services和Hyper-V的问题。
Server Core Functions by DLL一文给出了netapi32.dll的详细功能说明。
我不辞辛苦地把提到的API函数进行Google,存在漏洞的API肯定是存在在Windows 2000以来所有版本Windows中的,例如DsGetDcCloseW这样的API,微软文档声称“Client:Requires Windows Vista or Windows XP,Server:Requires Windows Server 2008 or Windows Server 2003.”,因此不可能是与漏洞有关。
剩下的可疑的Windows API有这些:

  • netapi32.dll DsAddressToSiteNamesA
  • netapi32.dll DsAddressToSiteNamesExA
  • netapi32.dll DsAddressToSiteNamesExW
  • netapi32.dll DsAddressToSiteNamesW
  • netapi32.dll DsDeregisterDnsHostRecordsA
  • netapi32.dll DsDeregisterDnsHostRecordsW
  • netapi32.dll DsEnumerateDomainTrustsA
  • netapi32.dll DsEnumerateDomainTrustsW
  • netapi32.dll DsGetDcNameA
  • netapi32.dll DsGetDcNameW
  • netapi32.dll DsGetDcOpenA
  • netapi32.dll DsGetDcOpenW
  • netapi32.dll DsGetDcSiteCoverageA
  • netapi32.dll DsGetDcSiteCoverageW
  • netapi32.dll DsGetSiteNameA
  • netapi32.dll DsGetSiteNameW
  • netapi32.dll DsMergeForestTrustInformationW
  • netapi32.dll DsRoleFreeMemory
  • netapi32.dll DsRoleGetPrimaryDomainInformation
  • netapi32.dll NetApiBufferAllocate
  • netapi32.dll NetApiBufferFree
  • netapi32.dll NetApiBufferReallocate
  • netapi32.dll NetApiBufferSize
  • netapi32.dll NetConnectionEnum
  • netapi32.dll NetDfsAdd
  • netapi32.dll NetDfsAddFtRoot
  • netapi32.dll NetDfsAddStdRoot
  • netapi32.dll NetDfsAddStdRootForced
  • netapi32.dll NetDfsEnum
  • netapi32.dll NetDfsGetClientInfo
  • netapi32.dll NetDfsGetInfo
  • netapi32.dll NetDfsRemove
  • netapi32.dll NetDfsRemoveFtRoot
  • netapi32.dll NetDfsRemoveStdRoot
  • netapi32.dll NetDfsSetClientInfo
  • netapi32.dll NetDfsSetInfo
  • netapi32.dll NetFileClose
  • netapi32.dll NetFileEnum
  • netapi32.dll NetFileGetInfo
  • netapi32.dll NetGetAnyDCName
  • netapi32.dll NetGetDCName
  • netapi32.dll NetGetDisplayInformationIndex
  • netapi32.dll NetGetJoinableOUs
  • netapi32.dll NetGetJoinInformation
  • netapi32.dll NetGroupAdd
  • netapi32.dll NetGroupAddUser
  • netapi32.dll NetGroupDel
  • netapi32.dll NetGroupDelUser
  • netapi32.dll NetGroupEnum
  • netapi32.dll NetGroupGetInfo
  • netapi32.dll NetGroupGetUsers
  • netapi32.dll NetGroupSetInfo
  • netapi32.dll NetGroupSetUsers
  • netapi32.dll NetLocalGroupAdd
  • netapi32.dll NetLocalGroupAddMembers
  • netapi32.dll NetLocalGroupDel
  • netapi32.dll NetLocalGroupDelMembers
  • netapi32.dll NetLocalGroupEnum
  • netapi32.dll NetLocalGroupGetInfo
  • netapi32.dll NetLocalGroupGetMembers
  • netapi32.dll NetLocalGroupSetInfo
  • netapi32.dll NetLocalGroupSetMembers
  • netapi32.dll NetQueryDisplayInformation
  • netapi32.dll NetRemoteComputerSupports
  • netapi32.dll NetRemoteTOD
  • netapi32.dll NetRenameMachineInDomain
  • netapi32.dll NetScheduleJobAdd
  • netapi32.dll NetScheduleJobDel
  • netapi32.dll NetScheduleJobEnum
  • netapi32.dll NetScheduleJobGetInfo
  • netapi32.dll NetServerComputerNameAdd
  • netapi32.dll NetServerComputerNameDel
  • netapi32.dll NetServerDiskEnum
  • netapi32.dll NetServerEnum
  • netapi32.dll NetServerGetInfo
  • netapi32.dll NetServerSetInfo
  • netapi32.dll NetServerTransportAdd
  • netapi32.dll NetServerTransportAddEx
  • netapi32.dll NetServerTransportDel
  • netapi32.dll NetServerTransportEnum
  • netapi32.dll NetSessionDel
  • netapi32.dll NetSessionEnum
  • netapi32.dll NetSessionGetInfo
  • netapi32.dll NetShareAdd
  • netapi32.dll NetShareCheck
  • netapi32.dll NetShareDel
  • netapi32.dll NetShareEnum
  • netapi32.dll NetShareGetInfo
  • netapi32.dll NetShareSetInfo
  • netapi32.dll NetStatisticsGet
  • netapi32.dll NetUnjoinDomain
  • netapi32.dll NetUseAdd
  • netapi32.dll NetUseDel
  • netapi32.dll NetUseEnum
  • netapi32.dll NetUseGetInfo
  • netapi32.dll NetUserAdd
  • netapi32.dll NetUserChangePassword
  • netapi32.dll NetUserDel
  • netapi32.dll NetUserEnum
  • netapi32.dll NetUserGetGroups
  • netapi32.dll NetUserGetInfo
  • netapi32.dll NetUserGetLocalGroups
  • netapi32.dll NetUserModalsGet
  • netapi32.dll NetUserModalsSet
  • netapi32.dll NetUserSetGroups
  • netapi32.dll NetUserSetInfo
  • netapi32.dll NetValidatePasswordPolicy
  • netapi32.dll NetWkstaGetInfo
  • netapi32.dll NetWkstaSetInfo
  • netapi32.dll NetWkstaTransportAdd
  • netapi32.dll NetWkstaTransportDel
  • netapi32.dll NetWkstaTransportEnum
  • netapi32.dll NetWkstaUserEnum
  • netapi32.dll NetWkstaUserGetInfo
  • netapi32.dll NetWkstaUserSetInfo

接下来只能猜了…
基于以上各点线索,猜测KB958644特大漏洞的原理可能是以下:

  • 文件共享及发现(共享打印机等)
  • Active Directory目录服务

为了我之前的文章完整性,下载了Internet Explorer 8 beta1来测试测试~
刚装上开开我的博客,发现一个问题… 强大的IE8立即挂了,然后开始顽强地恢复这个tab,然后再挂… 我无语了,经过页面分析,发现是以下一行代码绝杀了IE8:(略去后面部分,用于描述新闻分享的样式的部分)

[code=’c#’]

[/code]

这是我的Google阅读器分享啊… 强大的IE8在唯美的Google代码面前,华丽地”stopped working…”

然后,好像每次崩溃之后IE8会自动向Microsoft报告错误?担心隐私。

Internet Explorer 7 vs Firefox 2.0.0.12 vs Safari 3.1

出于对我管辖的网站显示效果的负责,今天算是主流浏览器装全了~

IE7嘛,感觉应该是最适合Windows用户的一个吧,显示效果虽然最差,但是应该算是风格最统一的一个。当然,速度极慢,占用内存极大。

Firefox是我最喜欢也是天天在用的浏览器,忘了从哪个版本开始了,Firefox对中文的渲染明显改善了,现在看起来很舒服,而且Google工具栏也有支持Firefox的版本,于是,从IE7作为XP高优先级推送那天开始,Firefox成了我的不二选择。

Safari,可谓最标准化的浏览器,它的js代码执行效率极高,打开网页速度很快,好久没感觉我的网络快了,今天居然有点开内网网页的感觉…一如既往地,Safari对于中文的渲染,很独特很怪异,让人很不适应呢。Mac下的Safari看起来倒更舒服一些。Safari对英文的渲染很漂亮,估计只要再对中文渲染下点功夫,夺下浏览器市场半壁江山,还是可能的~

进步总是有代价的。在web浏览器方面,用户要承受开发者由于对开发工具的滥用和任何针对用户所使用的浏览器的假定而带来的代价(尤其是假定成了Internet Explorer, IE)。当那个被假定的浏览器发布了新的版本,修正了以前的bug,或者改变的某个特性的渲染方式(或者引进了新的特性)以及改变了某种行为,站点就会因此而崩溃,而我们的客户、经理和用户会感到很失望。

我们可以用几个小时的时间来解释为什么我们的站点崩溃了,但是并不比一开始就避免它崩溃来的好。

一些背景知识

基于带有在CSS支持上有重大改进的Internet Explorer 7发布的冲劲,IE开发组开始着手为IE8制作一个全新的渲染引擎——一个可以尽可能多地遵循CSS 2.1标准的引擎。他们努力工作的一个极致表现是正确地渲染了Acid2测试。对于那些关注者来说,这意味着IE在不久的将来将生成出内容和数据URL,永久地放弃hasLayout,这一点已经得到确认。这一点将会使得它的渲染与同样通过Acid2测试的其他浏览器,如Safari, iCab, Konqueror和Opera,到同一起跑线上。(Firefox 3同样也通过了Acid2,但到撰写此文时并未发布。)

在开发新的渲染引擎过程中,IE开发组对IE 7的反馈很重视。一些标准的狂热者甚至一些微软fans都认为,在IE 7中对bug的修正和对CSS的支持增强方面,开发组做的并不够。但是数量更多的开发者则抱怨,他们原本看起来很好的网站,却在IE 7中不能正确渲染。在他的博客中,标准拥护者Roger Johanssen提出了三个导致错误的原因,鉴于他们对于支持标准的迫切要求,IE开发组发现了第四个原因:DOCTYPE开关,一个开启现代CSS布局核心的技术,因为保证兼容性的缘故,存在着致命地瑕疵。

DOCTYPE开关是坏的

早在1988年,Todd Fahrner就发明了一种能够使浏览器使用两套渲染模式的技巧:一种按照开发者的要求遵循标准,另一种则是为其他人准备的。这个概念非常简洁。当一个客户端遇到一个包含完整遵循了当前HTML标准(例如,HTML 2.0不会省略它)的DOCTYPE声明的文档时,它将假定作者知道她自己在做什么,然后使用遵循标准模式来渲染页面(布局元素使用W3C提倡的盒模型)。但是如果不包含DOCTYPE或者包含了一个不标准的DOCTYPE时,文档将会按照一种“奇异”模式进行渲染,例如,布局元素使用IE 5.x/Windows下的非标准的盒模型进行渲染。

这个概念于两年后首次应用于IE5/MAC平台上,并很快被其它浏览器制造商采用。追随标准的开发者们为了使网页通过标准验证,早已经将一个DOCTYPE包含在他们的网页中,因此浏览器根据这个特性来渲染页面,不会造成多余的代价。那些没有明确的标准化概念的开发者则发现,他们写的页面被浏览器特殊对待,因为他们自己以及他们使用的开发工具,都没能够插入正确的DOCTYPE

不幸的是,两个关键性因素,共同导致了DOCTYPE成为了判断标准的标准:

  1. 由于A List Apart和The Web Standards Project的鼓励,由远见的开发者和开发工具开始在他们编写和生成的标记语言中插入合法、完整的DOCTYPE
  2. IE6的渲染行为已经有五年没有改变,导致很多开发者以为它的渲染行为是正确的,而且不太可能变化。

两个原因合起来共同导致了DOCTYPE被破坏,因为它有一个致命的缺点,它认为当你使用了DOCTYPE的时候,就意味着当它向标准靠拢的时候,你要为你自己的行为负责,因为你知道你自己是在做什么,并且希望渲染效果越精确越好。我们怎么知道渲染会失效?当IE7推出的时候,站点就惨不忍睹了。

当然,如Roger指出的那样,崩溃的站点中是因为它们使用了IE6特定的CSS技巧(hacks)。但是更多的灾难是由于它们的开发者仅仅在IE6中检查网站的效果——或者仅仅想关注一下站点在IE6下看起来是什么样子的,因为他们仅仅在一个具备相同浏览器的环境中部署站点(比如,企业的内部局域网内)。当然,你可以耸耸肩,说既然IE6的渲染错误是已经被很好地整理过的,这些开发者可以更了解这些错误,但是,这样的话,你就忽略了其实很多开发者根本不曾明确地选择“标准模式”这个事实,或者根本就不知道有这么个模式的存在。

Chris Wilson,Internet Explorer的平台架构师,经常提到说,IE开发过程中的一条核心原则是,IE开发组做出的任何一个决定,不能“破坏现有网站”。遗憾的是,IE7恰恰破坏了相当一部分开发者的网站。为了避免同样的错误再次发生,Microsoft向The Web Standards Project(我是其会员之一)和几个其他的追求标准的开发者求助,请他们提供一个更好的方法,能够允许开发者“适应到”符合标准的开发上来。这个目标就是寻求一种方法,能够比DOCTYPE更清楚,并且能够被所有浏览器所实现,而不仅仅是IE。

美好的未来

在去年的SXSW上,我非常有幸地看到New York Public Library’s Carrie Bickner制(她正好是ALA的作者的妻子,Jeffrey Zeldman)作的一个绝好的发光二极管标语,标语写,“保护我们的数字遗产和私人收藏”,探讨的是当图书馆和私人当试图保留电子存档时遇到的问题。大部分的问题是文件格式和应用程序的问题:例如,Microsoft Office 2007,不能可靠地渲染一个Word 1.0文档,而大部分人一开始就认为它应该能够正常显示。这个标语引我深思,网络在创作力的推动下是如何改变的,以及网络在标准推行的过程中,将会如何继续这个变化。

作为一个web标准的支持者,我希望看到浏览器在不停地加进新的特性的同时,能够继续增强对标准的实现,但是同时我认为,浏览器应该保护那些我们已经花了这么多努力——基于表格的布局等,做成的网站。当然,很多从“时间机器”里出来的因为DOCTYPE对它们的良好保护,不会出现错误,但是,如果一个网站是基于IE6所谓的“标准”模型建设的呢?我们已经看到,很多这种情况,IE7是不会正确地渲染它们的。这是不是意味着我们要保留一个IE6,以便当我们不能按照作者意图浏览这些网站的时候用?这恰恰是很多图书馆为了能够浏览老的文件所做的事情。IE8即将诞生,我们面对着同样的潜在问题,就是那些按照IE7渲染引擎编写的文档。如何解决?

原文:Beyond DOCTYPE: Web Standards, Forward Compatibility, and IE8,Aaron Gustafson