原始答案
安全组是有状态的,这意味着从实例发起到另一个源的流量将允许与该出站请求(即临时端口)相关的所有返回流量。这实际上是 VPC 中的 NACL,您必须实际允许临时流量,因为它不是有状态的,并且不像安全组那样理解返回流量。
也就是说,对于 ALB -> 实例流量,您不需要在 sec 组中打开这些端口,因为 sec 组将允许从 ALB(到实例)内部发起的流量以及相关的临时端口流量返回到ALB。
您的实例只需要正在检查的任何端口(端口 80/8080/等),因为它是来自外部的流量。但是,它不需要任何东西来允许流量出站到 ALB 临时端口,因为这些是从实例内部启动的,并且附加到允许流量的传入端口。
编辑:
在使用 EC2 实例进行大量工作以尝试解释这一点后,我在原始解释中发现了一些错误。我将在此处保留原始解释,因为我认为知道错误发生很重要。
无论如何,让我们在这里寻求更深入的答案。
NACL(网络访问控制列表)
这些是无状态防火墙。基本上,它不知道传出的临时端口流量与传入的 HTTP 流量有关。它也是一个优先类型系统。基本上,您按照您希望它们评估的顺序对您的规则进行编号,从最低到最高。当它遇到与流量匹配的规则时,它就会应用它。您也可以明确拒绝流量。
这里的主要缺点是 NACL 仅允许单向 20 条规则(总共 40 条规则),而安全组允许您单向 50 条规则(总共 100 条规则)。也就是说,如果您出于某种原因开始用完安全组规则,则始终可以采用通用流量规则并将它们应用于 NACL。在高合规性环境中,NACL 也是需要考虑的因素,在这种环境中,您绝对必须阻止某些流量,因为明确的拒绝规则是可能的,而安全组是完全允许的规则。
安全组
与 NACL 不同,安全组只能具有许可效应规则。 DENY 只是缺少一个宽容的角色。但是,在下面解释的某些情况下,安全组会跟踪流量并自动添加一条规则以允许其他方向的流量。
默认情况下,安全组具有允许所有出站流量的规则。这里的想法是,如果它是从您的实例启动的,那么大多数用例都可以。现在,如果黑客理论上可以通过服务漏洞访问系统,那么他们现在几乎可以在任何他们想要的地方拥有出站流量。
您可以在此处删除安全组中的出站流量规则。在这种情况下,您将拥有以下内容:
- 来自实例的流量将被拒绝
- 如果接受传入规则,则无论是否缺少出站规则,都将允许出站流量
- 如果添加了出站规则(例如端口 80),则允许从实例调用端口 80 上的外部服务器。与该端口相关的传入流量也将被允许。
安全组还跟踪连接(这就是它们被称为有状态的原因)以允许来自其他方向的流量自动相关。 但是只有在流量被拒绝时才会跟踪。
例如,如果您没有删除允许所有访问的出站规则,则安全组不需要有状态,因为不需要添加规则。然而,当流量不允许时,它确实需要是有状态的。我找不到真正可靠的文档来说明它是如何做到的,但我推测它是围绕三向 TCP 握手。重要的是,当 SYN 进入或离开允许的端口时,它开始允许另一个方向的流量。然后它完全跟踪其余的握手(SYN+ACK -> ACK)何时完成。当连接关闭相关的数据包到来时,它可能会删除跟踪。
考虑到这一点,在处理高容量前端服务时,如果可能的话,最好对传出流量更加宽容,因为我可以想象跟踪开始将事情放慢到明显的速度。
建议
- 取消 NACL 规则,只允许所有流量进出。让有状态的安全组为您处理事情。
- 将实例放在 ALB 后面的私有子网中。这将阻止外部交通,因为没有路线。
- 但是,您需要一个 NAT Gateway,它可以让您的私有实例连接到 Internet 以获取重要信息,例如从发行版服务器获取软件包更新。
- 后端实例的安全组:允许 ELB 期望入站流量的任何端口。允许所有出站流量。
- ALB 的安全组:允许任何端口(我假设为 80 或 443)的入站流量并允许所有出站流量。
- 创建所谓的堡垒实例。它只是一个仅允许 SSH(或 Windows 实例的 RDP)的 EC2 实例。您将其用作登录私有子网实例的网关。这应该允许安全组中的所有出站流量,并允许 SSH 流量向内只允许访问您的 IP。这非常重要,因为如果您不限制 IP,随机机器人会扫描亚马逊公共 IP 空间(通常来自拥有巨大 IP 空间的中国或俄罗斯)并随机尝试连接到 22 端口。您只是不想处理尤其是因为远程登录漏洞的可能性总是大于 0%。