![回答](https://linux22.com/image/695410/%E5%9B%9E%E7%AD%94.png)
我已经盯着屏幕看了大约 2 个小时,试图弄清楚为什么这不起作用。我正在构建具有私有和公共子网的典型 VPC,并尝试尽可能地锁定它。我有几个安全组,但我知道问题出在 NACL 中,因为如果我放宽规则,一切都会正常。
我遇到的问题是,我无法从公有子网或私有子网中的任何 EC2 实例内部访问互联网(端口 80 和 443)。我知道“问题规则”是入站编号 1000,它允许来自 的所有临时端口10.0.0.0/16
。如果我将此规则更改为应用于所有源(0.0.0.0/0
),我可以从两个子网中的所有 ec2 实例访问互联网(我正在通过运行不同的应用程序来测试这一点;主要是 curl 和 yum。
我只是很难理解这种行为,因为入站规则应该允许任何 ec2 实例打开临时端口并与路由器通信,然后路由器可以与任何主机的端口 80 和 443 通信。我感觉我在这里忽略了简单但关键的一点 :)。
编辑
在 ASCII 艺术中,这是我对规则的理解
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)
编辑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:
从那里你可以看到 curl 打开了端口 40174 并且 google(prg03s06-in-f4.1e100.net)从端口 80 进行回复(日志中的 http)。
回答
感谢 Tim 和 Michael-sqlbot。答案有点埋在评论中。但问题是对入站规则的工作方式存在误解。端口范围在入境规则请参阅目的端口,而不是源端口。来自 AWS 文档
以下是网络 ACL 规则的组成部分:
- 规则编号。规则从编号最低的规则开始评估。只要某条规则与流量匹配,就会应用该规则,而不管是否有编号更高的规则与之相抵触。
- 协议。您可以指定任何具有标准协议号的协议。有关更多信息,请参阅协议号。如果指定 ICMP 作为协议,则可以指定任何或所有 ICMP 类型和代码。
- [仅限入站规则]流量来源(CIDR 范围)和目标(侦听)端口或端口范围。
- [仅限出站规则] 流量的目标(CIDR 范围)和目标端口或端口范围。
- 对于指定的流量,选择允许或拒绝。
答案1
当你在端口 80 上建立连接(或与任何端口上的任何守护进程建立连接)时,该连接将移交给高端端口,以保持端口 80 可以自由接受新连接。这些被称为临时端口。
您需要允许传入流量到这些高范围端口,根据 Wikipedia,这些端口是 32768 到 61000。如果您正在提供 Web 服务器,您可能还需要允许它们传出 - 您将其作为规则 100。
更新/扩展 NACL 是无状态的,这意味着您需要允许数据需要流动的每个方向的端口。当您连接到端口 80 上的 Web 服务器时,他们的 Web 服务器会说“连接已接受,继续在端口(例如)50000 上进行此交换”。这就是为什么您需要允许高范围端口传入以允许传出流量的原因。
还有另一种解释这里。
答案2
如果我没看错的话,当你将入站规则 1000 更改为 0.0.0.0/0 而不是 10.0.0.0/16 时,从 EC2 实例到互联网的连接就可以正常工作。我认为这对我来说有点道理。
当流量进入入站并经过 NACL(与您的实例所在的子网相关联)时,源不是 10.0.0.0/16 子网,而是您连接到的 Web 服务上的任何 IP 地址。这就是为什么 0.0.0.0/0 有效而 10.0.0.0/16 无效的原因