• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 虚拟主机匹配的深入讨论

    本文档试图确切解释Apache HTTP Server在确定服务于哪个虚拟主机的请求时的功能。

    大多数用户应该阅读有关与基于IP的虚拟主机为基础的名称来决定他们想要使用哪种类型,然后阅读更多关于基于名称或基于IP virtualhosts,然后看一些例子。

    如果您想了解所有详细信息,则可以返回此页面。

    配置文件

    有一个主服务器,其中包含出现在<VirtualHost>各节之外的所有定义。

    有称为vhost的虚拟服务器,由<VirtualHost>部分定义。

    每个VirtualHost指令包括一个或多个地址和可选端口。

    可以使用主机名代替虚拟主机定义中的IP地址,但是在启动时会解析它们,如果任何名称解析失败,这些虚拟主机定义将被忽略。因此,不建议这样做。

    可以将地址指定为*,如果没有其他虚拟主机具有在其上接收到请求的显式地址,则该地址将与请求匹配。

    VirtualHost指令中显示的地址可以具有可选端口。如果未指定端口,则将其视为通配符端口,也可以使用来明确指出*。通配符端口与任何端口匹配。

    VirtualHost指令中指定的端口号不会影响Apache侦听的端口号,它们仅控制VirtualHost将选择处理请求的端口号。使用Listen指令控制服务器侦听的地址和端口。)

    整个地址集(包括来自DNS查找的多个结果)统称为虚拟主机的地址集

    Host只要在多个虚拟主机中列出了IP地址和端口组合的最具体匹配项,Apache 就会根据客户端提供的HTTP 标头自动进行区分。

    ServerName指令可以出现在服务器定义内的任何位置。但是,每个外观都会覆盖先前的外观(在该服务器内)。如果未ServerName指定,则服务器将尝试从服务器的IP地址推断出它。

    给定IP:端口对的配置文件中第一个基于名称的虚拟主机很重要,因为它用于该地址和端口上接收到的所有请求,而该IP:端口对没有其他虚拟主机具有匹配的ServerName或ServerAlias。如果服务器不支持服务器名称指示,则还用于所有SSL连接。

    VirtualHost伪指令中名称的完整列表被视为(非通配符)ServerAlias(但不会被任何ServerAlias语句覆盖)。

    为每个虚拟主机设置各种默认值。尤其是:

    1. 如果虚拟主机没有ServerAdminTimeoutKeepAliveTimeoutKeepAliveMaxKeepAliveRequestsReceiveBufferSize,或SendBufferSize指令那么相应的值被从主服务器继承。(也就是说,继承自主服务器中该值的最终设置。)
    2. 定义虚拟主机默认目录权限的“查找默认值”与主服务器的目录权限合并。这包括任何模块的任何按目录的配置信息。
    3. 主服务器中每个模块的每服务器配置都合并到vhost服务器中。

    本质上,主服务器被视为构建每个虚拟主机的“默认值”或“基础”。但是,这些主服务器定义在config文件中的位置基本上无关紧要-当最终合并发生时,已经解析了主服务器的整个配置。因此,即使主服务器定义出现在虚拟主机定义之后,它也可能会影响虚拟主机定义。

    如果主服务器此时没有ServerName,则httpd使用正在运行的计算机的主机名。我们将调用主服务器地址集,即由ServerName主服务器上的DNS查找返回的IP地址。

    对于任何未定义的ServerName字段,基于名称的虚拟主机默认为在VirtualHost定义虚拟主机的语句中首先给出的地址。

    任何包含魔术_default_通配符的虚拟主机都将与ServerName主服务器相同。

    虚拟主机匹配

    服务器确定要用于请求的虚拟主机,如下所示:

    IP地址查询

    当首次在某个地址和端口上接收到连接时,服务器将查找VirtualHost具有相同IP地址和端口的所有定义。

    如果地址和端口不完全匹配,则*考虑通配符()。

    如果未找到匹配项,则该请求由主服务器处理。

    如果有VirtualHostIP地址的定义,则下一步是确定我们是否必须处理基于IP的虚拟主机或基于名称的虚拟主机。

    基于IP的虚拟主机

    如果恰好有一个VirtualHost指令列出了确定为最匹配的IP地址和端口组合,则不会执行进一步的操作,并且会从匹配的虚拟主机提供请求。

    基于名称的虚拟主机

    如果有多个VirtualHost指令列出了确定为最匹配的IP地址和端口组合,则其余步骤中的“列表”是指匹配的虚拟主机的列表,按照它们在配置文件中的顺序排列。

    如果连接使用SSL,则服务器支持Server Name Indication,并且SSL客户端握手包括带有请求的主机名的TLS扩展,然后在下面使用该主机名,就像在Host:非SSL连接上使用标头一样。否则,地址匹配的第一个基于名称的虚拟主机将用于SSL连接。这很重要,因为虚拟主机确定服务器将使用哪个证书进行连接。

    如果请求包含Host:标头字段,则在列表中搜索具有ServerName或的第一个虚拟主机ServerAlias,并从该虚拟主机提供请求。甲Host:头域可以包含一个端口号,但是Apache总是忽略它和针对该客户端发送请求的实端口相匹配。

    配置文件中具有指定IP地址的第一个虚拟主机具有最高优先级,并捕获对未知服务器名称的任何请求,或者捕获没有Host:标头字段的请求(例如HTTP / 1.0请求)。

    持久连接

    查找IP上述只是做一次,而对于特定的TCP / IP会话名称查找是在做每一个保活/持久连接期间请求。换句话说,客户端可以在单个持久连接期间从不同的基于名称的虚拟主机请求页面。

    绝对URI

    如果来自请求的URI是绝对URI,和它的主机名和端口匹配主服务器或配置的虚拟主机之一相匹配,客户端发送的请求,则该计划/主机名/端口前缀是地址和端口剥离后,其余的相对URI由相应的主服务器或虚拟主机提供。如果不匹配,则URI保持不变,并且该请求被视为代理请求。

    观察结果

    • 基于名称的虚拟主机是在服务器选择最匹配的基于IP的虚拟主机之后应用的过程。
    • 如果您不关心客户端连接到的IP地址,请使用“*”作为每个虚拟主机的地址,并且基于名称的虚拟主机将应用于所有已配置的虚拟主机。
    • ServerName并且ServerAlias永远不会对基于IP的虚拟主机执行检查。
    • 仅特定地址集的基于名称的虚拟主机的顺序很重要。在配置文件中排在首位的基于名称的虚拟主机具有最高的优先级为其对应的地址集。
    • Host:标头字段中的任何端口都不会在匹配过程中使用。Apache始终使用客户端向其发送请求的实际端口。
    • 如果两个虚拟主机具有一个公共地址,则这些公共地址将隐式充当基于名称的虚拟主机。从2.3.11开始,这是新行为。
    • 如果客户端连接的IP地址和端口号与任何虚拟主机(包括*虚拟主机)都不匹配,则仅使用主服务器来服务请求。换句话说,主服务器仅捕获对未指定地址/端口组合的请求(除非存在_default_与该端口匹配的虚拟主机)。
    • 您永远不要在VirtualHost指令中指定DNS名称,因为它将迫使您的服务器依赖DNS进行引导。此外,如果您不控制列出的所有域的DNS,则会构成安全威胁。有关此主题以及接下来的两个主题,有更多信息可用。
    • ServerName应该始终为每个虚拟主机设置。否则,每个虚拟主机都需要进行DNS查找。

    提示

    除了“ DNS问题”页面上的提示之外,这里还有一些其他提示:

    • 将所有主服务器定义放在任何VirtualHost定义之前。(这是为了帮助提高配置的可读性-配置后合并过程使得不清楚虚拟主机周围混合的定义可能会影响所有虚拟主机。)