网络是怎么连接的-防火墙|负载均衡|缓存服务器|代理

630 阅读14分钟

防火墙

让我们先来探索一下包是如何通过防火墙的。

即只允许发往特定服务器中的特定应用程序的包通过,然后屏蔽其他的包。

1624111376927.jpg

网络上有很多包,防火墙是如何分辨哪些包可以通过的。人们设计了多种方式,其中任何一种方式都可以实现防火墙的目的,但出于性能、价格、易用性等因素,现在最为普及的是包过滤方式。

网络包的头部包含了用于控制通信操作的控制信息,只要检查这些信息,就可以获得很多有用的内容。

因为公司内网访问互联网需要做地址转换,所以互联网并不能直接访问公司内网。

包通过防火墙的时候,如果判断结果为阻止,那么这个包会被丢弃并被记录下来。

这是因为这些被丢弃的包中通常含有非法入侵的痕迹,通过分析这些包能够搞清楚入侵者使用的手法,从而帮助我们更好地防范非法入侵。

实际上,在防火墙允许包通过之后,就没有什么特别的机制了,因此包过滤并不是防火墙专用的一种特殊机制,而是应该看作在路由器的包转发功能基础上附加的一种功能。

只不过当判断规则比较复杂时,通过路由器的命令难以维护这些规则,而且对阻止的包进行记录对于路由器来说负担也比较大,因此才出现了专用的硬件和软件。如果规则不复杂,也不需要记录日志,那么用内置包过滤功能的普通路由器来充当防火墙也是可以的。

防火墙并不是万能的,当接收包的内容有问题的时候,防火墙就无能为力了。

要应对这种情况有两种方法。这个问题的根源在于Web服务器程序的Bug,因此修复Bug防止宕机就是其中一种方法。这类Bug中,危险性较高的会作为安全漏洞公布出来,开发者会很快发布修复了Bug的新版本,因此持续关注安全漏洞信息并更新软件的版本是非常重要的。

另一种方法就是在防火墙之外部署用来检查包的内容并阻止有害包的设备或软件。当然,即便是采用这种方法也并不是完美无缺的,因为包的内容是否有风险,是由Web服务器有没有Bug决定的,因此当服务器程序中有潜在的Bug并且尚未被发现时,我们也无法判断包中的风险,也无法阻止这样的包。

也就是说,我们无法抵御未知的风险。

负载均衡

当服务器的访问量上升时,增加服务器线路的带宽是有效的,但并不是网络变快了就可以解决所有的问题。高速线路会传输大量的网络包,这会导致服务器的性能跟不上。尤其是通过CGI等应用程序动态生成数据的情况下,对服务器CPU的负担更重,服务器性能的问题也会表现得越明显。

在这种情况下,使用多台服务器来分担负载的方法更有效。这种架构统称为分布式架构,其中对于负载的分担有几种方法,最简单的一种方法就是采用多台Web服务器,减少每台服务器的访问量。

要采用这样的方法,必须有一个机制将客户端发送的请求分配到每台服务器上。具体的做法有很多种,最简单的一种是通过DNS服务器来分配。

当访问服务器时,客户端需要先向DNS服务器查询服务器的IP地址,如果在DNS服务器中填写多个名称相同的记录,则每次查询时DNS服务器都会按顺序返回不同的IP地址。

1624111376926.jpg

但这种方式是有缺点的。假如多台Web服务器中有一台出现了故障,这时我们希望在返回IP地址时能够跳过故障的Web服务器,然而普通的DNS服务器并不能确认Web服务器是否正常工作,因此即便Web服务器宕机了,它依然可能会返回这台服务器的IP地址。

在通过CGI等方式动态生成网页的情况下,有些操作是要跨多个页面的,如果这期间访问的服务器发生了变化,这个操作就可能无法继续。例如在购物网站中,可能会在第一个页面中输入地址和姓名,在第二个页面中输入信用卡号,这就属于刚才说的那种情况。

为了避免出现前面的问题,可以使用一种叫作负载均衡器的设备。

如果操作没有跨多个页面,则可以根据Web服务器的负载状况来进行判断。

当操作跨多个页面时,则不考虑Web服务器的负载,而是必须将请求发送到同一台Web服务器上。

要实现这一点,关键在于我们必须要判断一个操作是否跨了多个页面。HTTP的基本工作方式是在发送请求消息之前先建立TCP连接,当服务器发送响应消息后断开连接,下次访问Web服务器的时候,再重新建立TCP连接。因此,在Web服务器看来,每一次HTTP访问都是相互独立的,无法判断是否和之前的请求相关。

之所以会这样,是因为Web中使用的HTTP协议原本就是这样设计的。如果要判断请求之间的相关性,就必须在Web服务器一端保存相应的信息,这会增加服务器的负担。此外,Web服务器最早并不是用来运行CGI程序的,而是主要用来提供静态文件的,而静态文件不需要判断请求之间的相关性,因此最早设计HTTP规格的时候,就有意省略了请求之间相关性的判断。

于是,人们想出了一些方案来判断请求之间的相关性。例如,可以在发送表单数据时在里面加上用来表示关联的信息,或者是对HTTP规格进行扩展,在HTTP头部字段中加上用来判断相关性的信息。

1624111376924.jpg

缓存服务器

除了使用多台功能相同的Web服务器分担负载之外,还有另外一种方法,就是将整个系统按功能分成不同的服务器,如Web服务器、数据库服务器。缓存服务器就是一种按功能来分担负载的方法。

缓存服务器是一台通过代理机制对数据进行缓存的服务器。代理介于Web服务器和客户端之间,具有对Web服务器访问进行中转的功能。

当进行中转时,它可以将Web服务器返回的数据保存在磁盘中,并可以代替Web服务器将磁盘中的数据返回给客户端。这种保存的数据称为缓存,缓存服务器指的也就是这样的功能。

如果在缓存了数据之后,Web服务器更新了数据,那么缓存的数据就不能用了,因此缓存并不是永久可用的。

1624111376922.jpg

CGI程序等产生的页面数据每次都不同,这些数据也无法缓存。

在来自客户端的访问中,总有一部分访问可以无需经过Web服务器,而由缓存服务器直接处理。即便只有这一部分操作通过缓存服务器提高了速度,整体性能也可以得到改善。

通过让缓存服务器处理一部分请求,也可以减轻Web服务器的负担,从而缩短Web服务器的处理时间。

缓存服务器和负载均衡器一样,需要代替Web服务器被注册到DNS服务器中。然后客户端会向缓存服务器发送HTTP请求消息。

缓存服务器会检查请求消息的内容,看看请求的数据是否已经保存在缓存中。根据是否存在缓存数据,后面的操作会有所不同。 1624111376921.jpg

如果只有一台Web服务器,那么情况比较简单,只要将Web服务器的域名和IP地址配置在缓存服务器上,让它无条件转发给这台服务器就可以了。

如果一台缓存服务器对应多台Web服务器就没那么简单了,需要根据请求消息的内容来判断应该转发给哪台Web服务器。

其中比较有代表性的是根据请求消息的URI中的目录名来进行判断。当URI为/dir1/这个目录时,转发给www1.lab.glasscom.com ,当URI为/dir2/这个目录时,转发给www2.lab.glasscom.com。

缓存服务器会根据上述规则来转发请求消息,在这个过程中,缓存服务器会以客户端的身份向目标Web服务器发送请求消息。

它会先创建套接字,然后连接到Web服务器的套接字,并发送请求消息。从Web服务器来看,缓存服务器就相当于客户端。于是,缓存服务器会收到来自Web服务器的响应消息,接收消息的过程也是以客户端的身份来完成的。

接下来,缓存服务器会在响应消息中加上Via头部字段,它表示这个消息是经过缓存服务器中转的,然后缓存服务器会以Web服务器的身份向客户端发送响应消息。

同时,缓存服务器会将响应消息保存到缓存中,并记录保存的时间。

这种在客户端和Web服务器之间充当中间人的方式就是代理的基本原理。在中转消息的过程中,缓存服务器还会顺便将页面数据保存下来,随着缓存数据的积累,用户访问的数据命中缓存的几率也会提高。

接下来我们来看一看命中缓存的情况。

接收客户端的请求消息并检查缓存的过程和刚才是一样的。然后,缓存服务器会添加一个If-Modified-Since头部字段并将请求转发给Web服务器,询问Web服务器用户请求的数据是否已经发生变化。

然后,Web服务器会根据If-Modified-Since的值与服务器上的页面数据的最后更新时间进行比较,如果在指定时间内数据没有变化,就会返回一个表示没有变化的响应。

1624111376917.jpg

这时,Web服务器只要查询一下数据的最后更新时间就好了,比返回页面数据的负担要小一些。而且返回的响应消息也比较短,能相应地减少负担。

返回消息到达缓存服务器,然后缓存服务器就会知道Web服务器上的数据和本地缓存中的数据是一样的,于是就会将缓存的数据返回给客户端。

当Web服务器上的数据有变化时,后面的过程和没有命中缓存的情况是一样的。Web服务器会返回最新版本的数据,然后缓存服务器加上Via字段发送给客户端,同时将数据保存在缓存中。

还有一种方法是在客户端一侧部署缓存服务器。

代理

缓存服务器使用的代理机制最早就是放在客户端一侧的,这才是代理的原型,称为正向代理。

正向代理刚刚出现的时候,其目的之一就是缓存,这个目的和服务器端的缓存服务器相同。不过,当时的正向代理还有另外一个目的,那就是用来实现防火墙。

1624111376916.jpg

防火墙的目的是防止来自互联网的非法入侵,而要达到这个目的,最可靠的方法就是阻止互联网和公司内网之间的所有包。不过,这样一来,公司员工就无法上外网了,因此还必须想一个办法让必要的包能够通过,这个办法就是利用代理。

它会先接收来自客户端的请求消息,然后再转发到互联网中,这样就可以实现只允许通过必要的网络包了。这时,如果能够利用代理的缓存,那么效果就会更好,因为对于以前访问过的数据,可以直接从位于公司内网的代理服务器获得,这比通过低速线路访问互联网要快很多。

代理出现在ADSL和FTTH之前,因为那个时候没有廉价的高速网络,所以通过这个方式来尽可能的获取更好的体验。

由于代理在转发过程中可以查看请求,的内容,所以可以根据内容判断是否允许访问。也就是说,通过代理可以禁止员工访问危险的网站,或者是与工作内容无关的网站。

在使用正向代理时,一般需要在浏览器的设置窗口中的“代理服务器”一栏中填写正向代理的IP地址,浏览器发送请求消息的过程也会发生相应的变化。

当设置了正向代理时,浏览器会忽略网址栏的内容,直接将所有请求发送给正向代理。请求消息的内容也会有一些不同。

没有正向代理时,浏览器会从网址中提取出Web服务器域名后面的文件名或目录名,然后将其作为请求的URI进行发送;而有正向代理时,浏览器会在请求的URI字段中填写完整的http://...网址。

正向代理转发消息的过程也和服务器端的缓存服务器有一些不同,不同点在于对转发目标Web服务器的判断上。使用正向代理时,URI部分为http://... 这样的完整网址,因此可以根据这个网址来转发,不需要像服务器端的缓存服务器一样实现设置好转发目标Web服务器,而且可以发给任意Web服务器。

1624111376912.jpg

而服务器端的缓存服务器只能向事先设置好的目标进行转发,这就是两者不同的地方。

我们可以通过将请求消息中的URI中的目录名与Web服务器进行关联,使得代理能够转发一般的不包含完整网址的请求消息。我们前面介绍的服务器端的缓存服务器采用的正是这种方式,这种方式称为反向代理。

使用正向代理后,需要设置浏览器这一点除了麻烦、容易发生故障之外,还有其他一些限制。如果我们想把代理放在服务器端,那么服务器不知道谁会来访问,也没办法去设置客户端的浏览器,因此无法采用这种方法来实现。

缓存服务器判断转发目标的方法还有一种,那就是查看请求消息的包头部。因为包的IP头部中包含接收方IP地址,只要知道了这个地址,就知道用户要访问哪台服务器了。这种方法称为透明代理。

如何才能让请求消息到达透明代理。由于透明代理不需要设置在浏览器中,那么浏览器还是照常向Web服务器发送请求消息。

总之,正常情况下,请求消息是从浏览器直接发送到Web服务器,并不会到达透明代理。

我们必须将透明代理放在请求消息从浏览器传输到Web服务器的路径中,当消息经过时进行拦截。可能大家觉得这种方法太粗暴,但只有这样才能让消息到达透明代理,然后再转发给Web服务器。

如果请求消息有多条路径可以到达Web服务器,那么就必须在这些路径上都放置透明代理,因此一般是将网络设计成只有一条路可以走的结构,然后在这一条路径上放置透明代理。