简介
配送应用的公有访问路径已可用,但供应的访问规则允许来自任意 IPv4 来源的 HTTP。你将为应用配置一个独立安全组,仅允许预期的客户端和端口。真实请求将展示来源限制、端口限制和有状态回复如何影响访问。
请先完成“将公有子网连接到互联网”。本全新环境供应自己的网络、公网地址、路由和应用,不复用之前的 VM。CLI 已配置。保留供应的资源和无关的参考网络;只有新建的安全组是需要删除的练习资源。
认证关联
本实验为以下考试主题提供动手练习。
- Cloud Practitioner (CLF-C02) · 任务 3.5:VPC 中的安全组访问控制。
- Solutions Architect – Associate (SAA-C03) · 任务 1.2:针对网络来源、端口和协议的基础应用安全控制。
- CloudOps Engineer – Associate (SOA-C03) · 任务 5.1 和 5.3:基础安全组配置,以及检查其对连接性的影响。
- Security – Specialty (SCS-C03) · 任务 3.3:使用安全组允许和阻止所需流量的基础练习。
关联空的练习安全组
本步骤中,你将检查可用的应用,并用自己的空组替换其宽泛的访问组。
使用 Terminal 执行命令,点击旁边的 AWS View。视图读取与 CLI 相同的资源状态,显示 application-network、其中的公有和私有子网,以及私有地址为 10.20.1.10 的应用。公网地址和互联网网关路由已供应;请保持不变。
cd /home/labex/project
按 Name 标签选择 VPC。--filters 限定服务器结果,--query 选择 ID,$(...) 将结果保存到 shell 变量:
VPC_ID=$(aws ec2 describe-vpcs \
--filters Name=tag:Name,Values=application-network \
--query 'Vpcs[0].VpcId' \
--output text)
选择该 VPC 内供应的应用接口:
ENI_ID=$(aws ec2 describe-network-interfaces \
--filters "Name=vpc-id,Values=$VPC_ID" Name=tag:Name,Values=application-interface \
--query 'NetworkInterfaces[0].NetworkInterfaceId' \
--output text)
安全组在关联资源的网络接口处控制允许的流量。入站规则允许到达应用的流量;出站规则允许应用主动发起的流量。保存唯一供应组的 ID,以便清理时恢复。[0] 选择此单组列表的第一项:
SUPPLIED_GROUP_ID=$(aws ec2 describe-network-interfaces \
--network-interface-ids "$ENI_ID" \
--query 'NetworkInterfaces[0].Groups[0].GroupId' \
--output text)
读取规则,但不要修改:
aws ec2 describe-security-groups \
--group-ids "$SUPPLIED_GROUP_ID" \
--query 'SecurityGroups[].{ID:GroupId,Inbound:IpPermissions,Outbound:IpPermissionsEgress}' \
--output json
供应组允许来自 0.0.0.0/0(任意 IPv4 来源)的入站 TCP 端口 80,并允许全部出站流量。HTTP使用请求和响应;端口标识接收服务。应用在 TCP 端口 80 和 8081 上提供 HTTP,但供应规则仅允许端口 80。
在 AWS View 中,依次点击 Request application · client A 和 Request application · client B。两者均在端口 80 返回 Success 和 Application online。客户端 A 使用 198.51.100.10,客户端 B 使用 198.51.100.20。点击 Request port 8081;这个来自客户端 A 的请求失败,因为该端口尚未获准。
在同一 VPC 中创建独立组。--group-name 设置名称,--description 说明用途,引号中的标签规范作为一个参数添加所有权标签。保存新 ID:
GROUP_ID=$(aws ec2 create-security-group \
--group-name parcel-web \
--description "Parcel HTTP access" \
--vpc-id "$VPC_ID" \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=parcel-web},{Key=Project,Value=parcel}]' \
--query 'GroupId' \
--output text)
新组没有入站授权,并允许全部出站流量。安全组包含允许规则,不包含显式拒绝规则。没有匹配允许规则的流量会被阻断。
--groups 替换接口的组列表。仅关联新组;若同时保留宽泛的供应组,两组权限会合并,两个客户端仍会获准:
aws ec2 modify-network-interface-attribute \
--network-interface-id "$ENI_ID" \
--groups "$GROUP_ID"
修改成功时没有输出。确认接口现在仅关联自己的组:
aws ec2 describe-network-interfaces \
--network-interface-ids "$ENI_ID" \
--query 'NetworkInterfaces[].{ID:NetworkInterfaceId,Groups:Groups}' \
--output json
AWS View 现在显示 parcel-web 和 Inbound · none。从客户端 A 和 B 发送新请求;两者都变为 Connection failed。公网地址和路由仍在,但空组不允许任何入站请求。保持此 Terminal 打开,以保留保存的 ID。
仅允许预期 HTTP 客户端
本步骤中,你将允许客户端 A 访问端口 80,并验证其他来源和端口仍被阻断。
入站规则指定协议、端口范围和来源。--protocol tcp 选择 TCP,--port 80 选择这一个端口,--cidr 198.51.100.10/32 仅选择客户端 A 的 IPv4 地址。/32 包含一个 IPv4 地址,比 0.0.0.0/0 更窄。
将规则添加到自己的组,而不是供应组:
aws ec2 authorize-security-group-ingress \
--group-id "$GROUP_ID" \
--protocol tcp \
--port 80 \
--cidr 198.51.100.10/32
响应表示成功,可能包含新规则 ID。读取全部入站规则:
aws ec2 describe-security-groups \
--group-ids "$GROUP_ID" \
--query 'SecurityGroups[].IpPermissions' \
--output json
现在有一条 TCP 规则,FromPort 和 ToPort 均为 80,来源为 198.51.100.10/32。AWS View 显示相同的入站来源和端口。
点击 Request application · client A。结果为 Success,来源 198.51.100.10,目标端口 80,正文 Application online。这是供应应用返回的真实响应。
再点击 Request application · client B 和 Request port 8081。两者均返回 Connection failed。第一个请求的来源不匹配;第二个来自客户端 A,但端口不匹配。公网地址和路由提供路径,安全组决定哪些流量可以使用该路径。
测试并移除临时端口授权
本步骤中,你将证明另一个监听端口只有存在对应规则时才可达,然后移除临时授权。
供应的应用也在端口 8081 提供 HTTP。保持相同的允许来源,为该端口添加一条临时规则:
aws ec2 authorize-security-group-ingress \
--group-id "$GROUP_ID" \
--protocol tcp \
--port 8081 \
--cidr 198.51.100.10/32
再次读取规则:
aws ec2 describe-security-groups \
--group-ids "$GROUP_ID" \
--query 'SecurityGroups[].IpPermissions' \
--output json
现在有两条 TCP 规则:端口 80 和 8081,均仅允许客户端 A。AWS View 显示两者。点击 Request port 8081。结果变为 Success,目标端口为 8081,正文为 Application online。这确认第二个服务正在运行;之前失败是访问规则的限制。

AWS View 示例:两条窄范围入站规则均存在,客户端 A 在端口 8081 收到应用响应。你的环境生成的资源 ID 会不同。
本练习仅需要端口 80。撤销规则会移除其允许授权。指定相同的协议、端口和来源,仅移除临时规则:
aws ec2 revoke-security-group-ingress \
--group-id "$GROUP_ID" \
--protocol tcp \
--port 8081 \
--cidr 198.51.100.10/32
响应表示成功。查询最终规则:
aws ec2 describe-security-groups \
--group-ids "$GROUP_ID" \
--query 'SecurityGroups[].IpPermissions' \
--output json
仅剩客户端 A 的端口 80 规则。AWS View 移除 8081 规则后,再次点击 Request port 8081;现在请求失败。客户端 A 的端口 80 仍成功,客户端 B 的端口 80 仍失败。你只改变了一个端口授权,没有替换应用或路由。
观察有状态 HTTP 回复
本步骤中,你将移除自己组的默认出站规则,并确认获准入站 HTTP 的响应仍然可用。
安全组是有状态的:获准入站请求的响应可以离开应用,即使没有出站规则允许新连接。出站规则控制应用主动发起的流量;此 HTTP 响应不需要该规则。
读取当前出站权限:
aws ec2 describe-security-groups \
--group-ids "$GROUP_ID" \
--query 'SecurityGroups[].IpPermissionsEgress' \
--output json
新组具有默认的全部流量目标 0.0.0.0/0。下一条命令的 --ip-permissions 将 JSON 规则规范列表作为一个带引号的参数接收。IpProtocol 的值 -1 表示全部协议,IpRanges 标识出站规则的目标。精确移除该默认规则:
aws ec2 revoke-security-group-egress \
--group-id "$GROUP_ID" \
--ip-permissions '[{"IpProtocol":"-1","IpRanges":[{"CidrIp":"0.0.0.0/0"}]}]'
响应表示成功。读取两个方向的规则:
aws ec2 describe-security-groups \
--group-ids "$GROUP_ID" \
--query 'SecurityGroups[].{Inbound:IpPermissions,Outbound:IpPermissionsEgress}' \
--output json
入站仍仅允许客户端 A 的端口 80;出站为空。AWS View 显示 Outbound · none。再次点击 Request application · client A。仍返回 Success 和 Application online:回复属于已获准的入站连接。
重新检查 Request application · client B 和 Request port 8081。两者仍失败。有状态回复不会允许其他来源或端口的新入站访问。此测试证明响应行为,不测试应用主动发起的新出站连接。

AWS View 示例:入站仅允许客户端 A 的端口 80,出站为空,而真实 HTTP 响应仍成功。你的环境生成的资源 ID 会不同。
恢复供应组并删除自己的组
本步骤中,你将恢复原来的应用关联,并仅删除自己的练习安全组。
关联到网络接口的组无法删除。先用保存的供应组替换自己的组;不要删除或修改供应组:
aws ec2 modify-network-interface-attribute \
--network-interface-id "$ENI_ID" \
--groups "$SUPPLIED_GROUP_ID"
确认关联:
aws ec2 describe-network-interfaces \
--network-interface-ids "$ENI_ID" \
--query 'NetworkInterfaces[].{ID:NetworkInterfaceId,Groups:Groups}' \
--output json
仅关联原来的 supplied-application 组。现在删除已不再使用的组:
aws ec2 delete-security-group --group-id "$GROUP_ID"
删除成功时没有输出。查询完整组清单,以独立于可移除的标签证明资源不存在:
aws ec2 describe-security-groups \
--query 'SecurityGroups[].{ID:GroupId,Name:GroupName,VPC:VpcId}' \
--output table
parcel-web 已不存在。供应组和默认组仍在,VPC、子网、应用接口、公网地址和路由也保留。清单查询失败不能证明已删除。
AWS View 再次显示 supplied-application。点击客户端 A 和 B 的请求按钮;两个端口 80 请求都返回 Success,与初始基线一致。Request port 8081 失败,因为未修改的供应组仅允许端口 80。
运行本步骤的完成检查。
总结
你创建并关联了独立安全组,仅允许客户端 A 的 TCP 端口 80,测试并撤销临时第二端口授权,还确认了没有出站授权时的有状态 HTTP 回复。真实请求区分了获准和被阻断的流量。最后,你恢复供应组,并仅删除自己的练习组。
继续学习“为私有子网提供出站访问”,构建私有应用的出站路径,同时不允许未经请求的外部访问。



