AWS:使用自定义网络 ACL 访问 Internet 时出错

Aug*_*sto 5 networking routing amazon-web-services

我已经盯着屏幕看了大约两个小时,试图找出为什么这不起作用。我正在构建具有私有和公有子网的典型 VPC,并尝试尽可能地锁定它。我有几个安全组,但我知道问题出在 NACL 中,就好像我放宽了规则,一切正常。

我的入站 NACL 是 入站ACL

出站是 在此输入图像描述

我遇到的问题是,我无法从公共子网或私有子网中的任何 EC2 实例内部访问互联网(端口 80 和 443)。我知道“问题规则”是入站 no 1000,它允许来自 的所有临时端口10.0.0.0/16。如果我更改此规则以应用于所有源 ( 0.0.0.0/0),我可以从两个子网中的所有 ec2 实例访问互联网(我通过运行不同的应用程序来测试这一点;主要是curl 和 yum。

我只是很难理解这种行为,因为入站规则应该允许任何 ec2 实例打开临时端口并与路由器通信,然后路由器可以与任何主机的端口 80 和 443 通信。我感觉我错过了简单但关键的一点:)。

编辑

在ascii art中,这是我对规则的理解

EC2 instance does a curl on www.google.com (port 80) 

SYN Packet out to stablish the connection (ephemeral port on VM to port 80)
EC2 vm (somewhere in 10.0.0.0/16:ephemeral)
 -> SG 
 -> NACL in (in rule 1000 - ALLOW source 10.0.0.0/16 on ports 1024-65535) 
 -> NACL out (out rule 200 - ALLOW destination 0.0.0.0/0 on port 80)
 -> IGW 
 -> Google (172.217.23.14:80)

SYN + ACK Packet in to continue the connection handshake
Google (172.217.23.14:80)
  -> IGW 
  -> NACL in (in rule 100 - ALLOW source 0.0.0.0/0 on port 80) 
  -> NACL out (out rule 100 - ALLOW destination 0.0.0.0/0 on port 1024-65535) 
  -> SG 
  -> EC2 vm (somewhere in 10.0.0.0/16:ephemeral)
Run Code Online (Sandbox Code Playgroud)

编辑2

运行 tcpdump ( sudo tcpdump -i eth0 -s 1500 port not 22) 以确保 google 不会从临时端口返回数据。我已经用数据包标志删除了额外的数据,您可以添加-X到标志中以查看每个数据包中的实际数据。

18:28:56.919335 IP ip-10-112-7-114.eu-west-1.compute.internal.40174 > prg03s06-in-f4.1e100.net.http:
18:28:56.949105 IP prg03s06-in-f4.1e100.net.http > ip-10-112-7-114.eu-west-1.compute.internal.40174:
18:28:56.949119 IP ip-10-112-7-114.eu-west-1.compute.internal.40174 > prg03s06-in-f4.1e100.net.http:
18:28:56.949219 IP ip-10-112-7-114.eu-west-1.compute.internal.40174 > prg03s06-in-f4.1e100.net.http:
18:28:56.979089 IP prg03s06-in-f4.1e100.net.http > ip-10-112-7-114.eu-west-1.compute.internal.40174:
18:28:57.010155 IP prg03s06-in-f4.1e100.net.http > ip-10-112-7-114.eu-west-1.compute.internal.40174:
18:28:57.010178 IP ip-10-112-7-114.eu-west-1.compute.internal.40174 > prg03s06-in-f4.1e100.net.http:
18:28:57.010308 IP ip-10-112-7-114.eu-west-1.compute.internal.40174 > prg03s06-in-f4.1e100.net.http:
18:28:57.041100 IP prg03s06-in-f4.1e100.net.http > ip-10-112-7-114.eu-west-1.compute.internal.40174:
18:28:57.041110 IP ip-10-112-7-114.eu-west-1.compute.internal.40174 > prg03s06-in-f4.1e100.net.http:
Run Code Online (Sandbox Code Playgroud)

从那里您可以看到curl打开了端口40174,并且google(prg03s06-in-f4.1e100.net)从端口80(日志中的http)进行了回复。

回答

感谢 Tim 和 Michael-sqlbot。答案有点隐藏在评论中。但问题在于对入站规则如何运作的误解。入站规则中的端口范围是指目的端口,而不是源端口。来自AWS文档

以下是网络 ACL 规则的组成部分:

  • 规则编号。从编号最小的规则开始评估规则。一旦规则与流量匹配,就会应用该规则,无论任何编号较高的规则可能与其相矛盾。
  • 协议。您可以指定任何具有标准协议号的协议。有关详细信息,请参阅协议号。如果指定 ICMP 作为协议,则可以指定任何或所有 ICMP 类型和代码。
  • [仅限入站规则]流量源(CIDR 范围)和目标(侦听)端口或端口范围
  • [仅限出站规则] 流量的目标(CIDR 范围)和目标端口或端口范围。
  • 为指定流量选择“允许”或“拒绝”。

Tim*_*Tim 5

当您在端口 80(或任何端口上的任何守护程序)上建立连接时,连接将被移交给高范围端口,以保持端口 80 空闲以接受新连接。这些称为临时端口

您需要允许传入流量到达这些高范围端口,根据 Wikipedia,这些端口是 32768 到 61000。如果您提供 Web 服务器,您可能还需要允许它们传出 - 您有规则 100。

更新/扩展 NACL 是无状态的,这意味着您需要允许数据需要在每个方向上流动的端口。当您连接到端口 80 上的 Web 服务器时,他们的 Web 服务器会显示“连接已接受,在端口(例如)50000 上继续此交换”。这就是为什么您需要允许高范围端口传入以允许传出流量。

这里还有另一种解释。

  • @Augusto,这里是被忽视的:入站网络 ACL 只对 *源地址* 和 *目标端口* 感兴趣——不是目标地址,不是源端口,所以对于内部启动的连接,您匹配的端口是 *出站方向(出站 NACL)中的远程*端口(80),但是入站响应(入站 NACL)的*本地*端口(临时)。在入站方面,NACL 必须允许从任何地方访问“到”临时端口,因为那是流量的流向。入站 NACL 对数据包*来自*的端口不感兴趣。 (2认同)
  • 是的,我的解释在中间的某个地方有点模糊......有点让我想起[这个](https://youtu.be/6e1hZGDaqIw)。入站网络 ACL 对源端口或目标地址不感兴趣。为了让 google(或任何人)端口 80 响应从我的临时端口之一发起的连接,我的入站网络 ACL 必须允许从源地址 0.0.0.0/0 访问我的临时端口范围。 (2认同)