总览

Web 服务器的部署地点


图 5.1( a)和路由器直接相连
- 服务器直接部署在公司网络上,并且可以从互联网直接访问
- 问题
- IP 地址不足
- 安全问题
从互联网传来的网络包会无节制地进入服务器, 这意味着服务器在攻击者看来处于“裸奔” 状态
图 5.1( b)通过防火墙进行隔离
- 它只允许发往指定服务器的指定应用程序的网络包通过, 从而屏蔽其他不允许通过的包
图 5.1( c)部署在服务商数据中心
- 服务器部署在这里可以获得很高的访问速度,当服务器访问量很大时这是非常有效。
- 数据中心不但提供安放服务器的场地, 还提供各种附加服务, 如服务器工作状态监控、 防火墙的配置和运营、 非法入侵监控等, 从这一点来看, 其安全性也更高
- 运行
如果 Web 服务器部署在数据中心里, 那么网络包会从互联网核心部分直接进入数据中心, 然后到达服务器。 如果数据中心有防火墙, 则网络包会先接受防火墙的检查, 放行之后再到达服务器。
防火墙的结构和原理
主流的包过滤方式
- 人们设计了多种方式 A, 其中任何一种方式都可以实现防火墙的目的, 但出于性能、价格、 易用性等因素, 现在最为普及的是包过滤方式
规则

例子
- 现在我们希望允许从互联网访问 Web 服务器(图 5.2 ①), 但禁止 Web 服务器访问互联网
规则一——利用ip
网络包的头部包含了用于控制通信操作的控制信息, 只要检查这些信息, 就可以获得很多有用的内容。
利用IP
- 通过接收方 IP 地址和发送方 IP 地址, 我们可以判断出包的起点和终点
- 从互联网发送过来的包其起点是不确定的, 但终点是确定的, 即 Web 服务器
- 我们允许起点( 发送方 IP 地址) 为任意,终点( 接收方 IP 地址) 为 Web 服务器 IP 地址的包通过
- Web 服务器需要通过确认应答机制 A 通知发送方数据已经正常收到, 这需要 Web 服务器向互联网发送包。
- 在 Web 服务器发往互联网的包中, 我们可以将起点( 发送方 IP 地址) 为Web 服务器地址的包设置为允许通过( 图 5.2 中表的第 3 行)
规则二——通过端口号限定应用程序
- 按照前面的设置, 相当于允许了互联网和 Web 服务器之间所有的包通过, 这个状态很危险。
- 当我们要限定某个应用程序时, 可以在判断条件中加上 TCP 头部或者UDP 头部中的端口号。
即在该例中
- 当包的接收方 IP 地址为 Web 服务器地址, 且接收方端口号为80时, 允许这些包通过( 图 5.2 中表的第 1 行); 或者当包的发送方 IP 地址为 Web 服务器地址, 且发送方端口号为 80 时, 允许这些包通过( 图 5.2 中的表的第 3 行)。
规则三——通过控制位判断连接方向
- 上述两条规则,还没有办法阻止 Web 服务器访问互联网,但Web 使用的 TCP 协议是双向收发网络包的。光判断包的流向还不够, 我们必须要根据访问的方向来进行判断
- 需要用到 TCP头部中的控制位,TCP三次握手中,第二次服务器发送确认的数据包嗷中,TCP 控制位中 SYN 为 1, 而 ACK 为 0。符合这一条就放行
UDP包
实际上也存在无法将希望允许和阻止的访问完全区分开的情况
- 其中一个代表性的例子就是对 DNS 服务器的访问。 DNS 查询使用的是UDP 协议, 而 UDP 与 TCP 不同, 它没有连接操作, 因此无法像 TCP 一样根据控制位来判断访问方向。 所以, 我们无法设置一个规则, 只允许公司内部访问互联网上的 DNS 服务器, 而阻止从互联网访问公司内部的 DNS服务器。
- 这一性质不仅适用于 DNS, 对于所有使用 UDP 协议的应用程序都是共通的。 在这种情况下, 只能二者择其一——要么冒一定的风险允许该应用程序的所有包通过, 要么牺牲一定的便利性阻止该应用程序的所有包通过
- 如果是使用包过滤之外的其他方式的防火墙,有时候是可以判断 UDP 应用程序的访问方向的
通过防火墙
如前面所述,我们可以在防火墙中设置各种规则, 当包到达防火墙时, 会根据这些规则判断是允许通过还是阻止通过。
流程
- 如果判断结果为阻止, 那么这个包会被丢弃并被记录下来 。 这是因为这些被丢弃的包中通常含有非法入侵的痕迹, 通过分析这些包能够搞清楚入侵者使用的手法, 从而帮助我们更好地防范非法入侵
- 如果包被判断为允许通过, 则该包会被转发出去,如果包被判断为允许通过, 则该包会被转发出去,转发规则和路由器一样
防火墙与路由器
- 防火墙像是在路由器的包转发功能基础上附加的包过滤功能
- 但当判断规则比较复杂时, 通过路由器的命令难以维护这些规则, 而且对阻止的包进行记录对于路由器来说负担也比较大, 因此才出现了专用的硬件和软件
防火墙无法抵御的攻击
防火墙只检测包起点终点方向,有些情况下,只有检查包的内容才能识别这种风险, 因此防火墙对这种情况无能为力。
两种方法
- 问题的根源在于 Web 服务器程序的Bug, 因此修复 Bug 防止宕机就是其中一种方法。
- 另一种方法就是在防火墙之外部署用来检查包的内容并阻止有害包的设备或软件。
这种方法和直接修复 Bug 的方法是基本等效的, 但如果服务器数量较多, 更新软件版本需要花费一定的时间, 或者容易忘记更新软件, 这时对包的内容进行检查就会比较有效
通过将请求平均分配给多台服务器来平衡负载
当服务器的访问量上升时, 增加服务器线路的带宽是有效的,更换一台性能更好的服务器 是有效的,但不能能解决所有的问题。
使用多台服务器来分担负载
这种架构统称为分布式架构, 其中对于负载的分担有几种方法, 最简单的一种方法就是采用多台 Web 服务器, 减少每台服务器的访问量。
轮询分配
- 通过 DNS 服务器来分配。 当访问服务器时, 客户端需要先向 DNS 服务器查询服务器的 IP地址, 如果在 DNS 服务器中填写多个名称相同的记录, 则每次查询时DNS 服务器都会按顺序返回不同的 IP 地址。
缺点
- 假如多台 Web 服务器中有一台出现了故障,这时我们希望在返回 IP 地址时能够跳过故障的 Web 服务器, 然而普通的DNS 服务器并不能确认 Web 服务器是否正常工作, 因此即便 Web 服务器宕机了, 它依然可能会返回这台服务器的 IP 地址 (如果浏览器在访问 DNS 服务器返回的第一个 IP 地址失败时,能够继续尝试第二个 IP 地址,就可以回避这个问题了,最近的浏览器有很多都已经具备了这样的功能)
- 在通过 CGI 等方式动态生成网页的情况下, 有些操作是要跨多个页面的, 如果这期间访问的服务器发生了变化, 这个操作就可能无法继续。 例如在购物网站中, 可能会在第一个页面中输入地址和姓名, 在第二个页面中输入信用卡号, 这就属于刚才说的那种情况

使用负载均衡器分配访问
首先要用负载均衡器的 IP 地址代替 Web 服务器的实际地址注册到 DNS 服务器上。客户端会认为负载均衡器就是一台 Web 服务器, 并向其发送请求, 然后由负载均衡器来判断将请求转发给哪台 Web 服务器

判断条件根据操作是否跨多个页面
- 如果操作没有跨多个页面, 则可以根据 Web 服务器的负载状况来进行判断。负载均衡器可以定期采集 Web 服务器的 CPU、 内存使用率, 并根据这些数据判断服务器的负载状况, 也可以向 Web 服务器发送测试包, 根据响应所需的时间来判断负载状况。
- 当操作跨多个页面时, 则不考虑 Web 服务器的负载, 而是必须将请求发送到同一台 Web 服务器上
如何判断一个操作是否跨多个页面
- 例如, 可以在发送表单数据时在里面加上用来表示关联的信息, 或者是对 HTTP 规格进行扩展, 在 HTTP 头部字段中加上用来判断相关性的信息这样(这种信息俗称 Cookie), 负载均衡器就可以通过这些信息来作出判断, 将一系列相关的请求发送到同一台Web 服务器, 对于不相关的请求则发送到负载较低的服务器了
使用缓存服务器分担负载
缓存服务器
- 除了使用多台功能相同的 Web 服务器分担负载之外, 还有另外一种方法, 就是将整个系统按功能分成不同的服务器 , 如 Web 服务器、 数据库服务器。 缓存服务器就是一种按功能来分担负载的方法。
- 缓存服务器是一台通过代理机制对数据进行缓存的服务器。 代理介于Web 服务器和客户端之间, 具有对 Web 服务器访问进行中转的功能。当进行中转时, 它可以将 Web 服务器返回的数据保存在磁盘中, 并可以代替Web 服务器将磁盘中的数据返回给客户端
为什么缓存服务器能提高服务器性能
- Web 服务器需要执行检查网址和访问权限, 以及在页面上填充数据等内部操作过程, 因此将页面数据返回客户端所需的时间较长。 相对地, 缓存服务器只要将保存在磁盘上的数据读取出来发送给客户端就可以了, 因此可以比 Web 服务器更快地返回数据。
- 总有一部分访问可以无需经过 Web 服务器, 而由缓存服务器直接处理。
缓存服务器的工作过程

这种在客户端和 Web 服务器之间充当中间人的方式就是代理的基本原理。 在中转消息的过程中, 缓存服务器还会顺便将页面数据保存下来, 随着缓存数据的积累, 用户访问的数据命中缓存的几率也会提高。
缓冲服务器命中的情况
- 首先缓冲服务器接收客户端的请求消息并检查缓存
- 缓存服务器会添加一个 IfModified-Since 头部字段并将请求转发给 Web 服务器, 询问 Web 服务器用户请求的数据是否已经发生变化( 图 5.5( b) ②)。
- 然后, Web 服务器会根据 If-Modified-Since 的值与服务器上的页面数据的最后更新时间进行比较, 如果在指定时间内数据没有变化, 就会返回一个像图 5.7( b) 一样的表示没有变化的响应消息( 图 5.5( b) ③)。 这时,Web 服务器只要查询一下数据的最后更新时间就好了, 比返回页面数据的负担要小一些。 而且返回的响应消息也比较短, 能相应地减少负担。
- 接下来, 返回消息到达缓存服务器, 然后缓存服务器就会知道 Web 服务器上的数据和本地缓存中的数据是一样的, 于是就会将缓存的数据返回给客户端
正向代理
- 客户端一侧的缓存服务器,出现的情况主要是因为早期互联网线路比较慢,将代理放在公司内获取速度大于从互联网中获取
- 正向代理刚刚出现的时候, 其目的之一就是缓存, 这个目的和服务器端的缓存服务器相同。 不过, 当时的正向代理还有另外一个目的, 那就是用来实现防火墙。
正向代理实现防火墙
- 由于代理在转发过程中可以查看请求的内容, 所以可以根据内容判断是否允许访问。 也就是说, 通过代理可以禁止员工访问危险的网站,或者是与工作内容无关的网站。 包过滤方式的防火墙只能根据 IP 地址和端口号进行判断, 因此无法实现这一目的。
正向代理的不同
- 使用正向代理时, 一般需要在浏览器的设置窗口中的“代理服务器”一栏中填写正向代理的 IP 地址, 浏览器发送请求消息的过程也会发生相应的变化。直接将所有请求发送给正向代理。 正向代理可以发往任意Web服务器,
- 请求消息的内容也会有一些不同没有正向代理时, 浏览器会从网址中提取出 Web 服务器域名后面的文件名或目录名, 然后将其作为请求的URI 进行发送。而有正向代理时, 浏览器会在请求的 URI字段中填写完整的 http://… 网址。

正向代理的改良版——反向代理
使用正向代理需要在浏览器中进行设置, 这可以说是识别正向代理的一个特征。 但是, 设置浏览器非常麻烦, 如果设置错误还可能导致浏览器无法正常工作。如果我们想把代理放在服务器端, 那么服务器不知道谁会来访问,也没办法去设置客户端的浏览器, 因此无法采用这种方法来实现。
前面讲的服务器端的缓存服务器就是方向代理
透明代理
透明代理集合了正向代理和反向代理的优点,这种方法也可以转发一般的请求消息, 因此不需要像正向代理一样设置浏览器参数, 也不需要在缓存服务器上设置转发目标, 可以将请求转发给任意 Web 服务器
内容分发服务
利用内容分发服务分担负载
缓存服务器应该布置在哪里?

比如, 某网站的运营者觉得最近网站上增加了很多大容量的内容, 因此想要增加缓存服务器的容量。 如果缓存放在服务器端, 那么网站运营者可以自己通过增加磁盘空间等方式来进行扩容,但对于放在客户端的缓存就无能为力了
Web 服务器运营者和网络运营商签约, 将可以自己控制的缓存服务器放在客户端的运营商处。
但是花费和精力是web服务商无法承受的
CDSPB
- 为了解决这个问题, 一些专门从事相关服务的厂商出现了, 他们来部署缓存服务器, 并租借给 Web 服务器运营者。 这种服务称为内容分发服务 。提供这种服务的厂商称为 CDSPB, 他们会与主要的供应商签约, 并部署很多台缓存服务器 C。 另一方面, CDSP 会与 Web 服务器运营者签约, 使得 CDSP 的缓存服务器配合 Web 服务器工作。
如何找到最近的缓存服务器
如何让用户不进行任何设置, 也能够将请求消息发送到缓存服务器?
- 第一个方法是用 DNS 服务器来分配访问。但DNS轮询方式按顺序返回 IP 地址, 完全不考虑客户端与缓存服务器的远近, 因此可能会返回离客户端较远的缓存服务器 IP 地址。
- 如果要让用户访问最近的缓存服务器, 则不应采用轮询方式, 而是应该判断客户端与缓存服务器的距离, 并返回距离客户端最近的缓存服务器IP 地址。
到底该怎样判断客户端与缓存服务器之间的距离呢?
- 服务器端DNS服务器事先收集好各缓存服务器部署地点的路由信息,然后通过查询路由信息,就可得知缓存服务器到客户端DNS服务器的路由信息,通过这个信息即可估算出距离,依次查询所有路由器的路由表之后, 我们就可以通过比较找出哪一台路由器距离客户端 DNS 服务器最近。


另一个让客户端访问最近的缓存服务器的方法——重定向
- 利用HTTP 中的Location 的字段。 当 Web 服务器数据转移到其他服务器时可以使用这个字段, 它的意思是“您要访问的数据在另一台服务器上, 请访问那台服务器吧。”
- 重定向服务器找到了后,就将缓存服务器的地址放到Location字段中返回响应
- 缺点在于增加了 HTTP 消息的交互次数, 相应的开销也比较大。重定向的方法是根据客户端发送来的 HTTP 消息的发送方 IP 地址来估算距离的, 因此精度较高。
- 可以改进距离计算,由重定向服务器返回一个计算时间的脚本,然后客户端运行脚本,通过向不同的缓存服务器放松测试包计算往返时间来判断最近缓存服务器


如何更新缓存
原本的方法在后面的每次访问都需要向原始服务器查询数据有没有发生变化, 如果遇到网络拥塞, 就会使响应时间恶化。
改进
- 让 Web 服务器在原始数据发生更新时,立即通知缓存服务器, 使得缓存服务器上的数据一直保持最新状态, 这样就不需要每次确认原始数据是否有变化了
1092

被折叠的 条评论
为什么被折叠?



