3. 网络安全组与应用程序安全组

在 Azure 的边界安全体系中,网络安全组(Network Security Group,NSG)是最基础也最常被低估的一层控制。它工作在子网和网卡两级,对进出流量做五元组过滤;而应用程序安全组(Application Security Group,ASG)并不单独放行流量,它解决的是“如何把一组虚拟机当作一个逻辑对象来引用”的问题。理解这两者的分工,是排查绝大多数“明明配了规则却不通”问题的前提。

NSG 规则优先级:数字越小越先命中

每条 NSG 规则都有一个 100~4096 的优先级数值,数值越小优先级越高。入站和出站流量各自独立评估,评估顺序是:先看优先级数字,再看规则是允许还是拒绝,一旦命中就立即停止,不再继续匹配后续规则。这意味着“拒绝所有”这类兜底规则必须放在最后(例如优先级 4096),否则会遮蔽后面的放行规则。

Azure 在每个 NSG 中都内置了三条默认规则,优先级固定为 65000、65001、65002,用户无法删除,只能被更高优先级的自定义规则覆盖:

  • AllowVnetInBound / AllowVnetOutBound(65000):允许虚拟网络内部互通。
  • AllowAzureLoadBalancerInBound(65001):允许 Azure 负载均衡器的健康探测。
  • DenyAllInBound / DenyAllOutBound(65002):拒绝其余所有流量。

一个常见的误区是:只写了“允许 3389 入站”,却忘了默认的 DenyAllInBound 仍然会拦截其他端口——这本身是符合预期的。真正的问题往往出在优先级冲突上。例如同时存在“拒绝 10.0.0.0/24 访问 22 端口(优先级 200)”和“允许 10.0.0.5 访问 22 端口(优先级 300)”,由于 200 先命中,10.0.0.5 也会被拒绝。要放行单个例外,必须把例外规则的优先级设得比拒绝规则更小。

ASG:让规则跟随角色而不是 IP

ASG 是一组网卡的逻辑集合。规则里不再写具体 IP 或子网,而是写“源 ASG → 目标 ASG + 端口”。当虚拟机加入或离开 ASG 时,规则自动生效,无需修改 NSG。典型用法是定义 asg-web、asg-app、asg-db 三个组,然后写一条“允许 asg-web 访问 asg-app 的 8080 端口”,再写一条“允许 asg-app 访问 asg-db 的 1433 端口”。这样横向扩展 Web 层时,新虚拟机只要加入 asg-web,就自动获得访问应用层的权限。

需要注意:ASG 只能作为规则的源或目标,不能单独存在;同一 NSG 规则中,源和目标不能同时使用 ASG 与 IP 前缀混写(部分场景下源可用 ASG、目标用 IP,但可读性差,建议统一)。另外,ASG 必须与使用它的 NSG 位于同一区域。

NSG 规则优先级评估与 ASG 引用关系 入站流量 Internet / VNet 优先级 100 Deny 10.0.0.0/24 → 22 命中即停止 优先级 200 Allow asg-web → asg-app:8080 ASG 动态匹配 目标子网 应用层 VM 默认规则 65000 AllowVnetInBound → 65001 AllowAzureLoadBalancerInBound → 65002 DenyAllInBound 自定义规则未命中时,最终由 DenyAllInBound 兜底拒绝 ASG 逻辑分组 asg-web(Web 层网卡) asg-app(应用层网卡) asg-db(数据库层网卡) NSG 规则引用 ASG 规则 200:Allow asg-web → asg-app:8080 规则 210:Allow asg-app → asg-db:1433 规则 220:Deny asg-web → asg-db:1433 新增 VM 加入 asg-web 后自动获得 8080 出站权限 无需修改任何 NSG 规则

流量日志分析:从“通不通”到“为什么不通”

NSG 流量日志(NSG Flow Log)记录的是每条规则命中情况,而不是简单的连接结果。启用后,日志以 JSON 格式写入存储账户,字段包括 ruleName、direction、action、flowState、srcAddr、dstAddr、srcPort、dstPort、protocol 等。分析时重点关注三类信息:

  • ruleName 为默认规则名:说明自定义规则没有命中,流量被默认规则处理。若 action 为 Deny,通常是缺少放行规则或优先级被覆盖。
  • flowState 为 B(Begin)但无 C(Continue):表示连接发起后没有后续数据,可能是对端未监听或路由问题,而非 NSG 拒绝。
  • 同一五元组出现多条记录:说明流量在多个 NSG(子网级 + 网卡级)中被分别评估,需要逐层检查。

一个实用的排查顺序是:先确认流量是否到达目标 NSG(看 flowState),再看命中的 ruleName 是自定义还是默认,最后核对优先级数字。如果日志中根本没有该五元组记录,问题通常不在 NSG,而在路由、对等互连或 DNS 解析。

常见配置错误与排错方法

现象 常见原因 排查方法
SSH/RDP 无法连接 拒绝规则优先级高于放行规则 用“有效安全规则”查看最终生效规则,确认优先级顺序
同 VNet 内 VM 互 ping 不通 ICMP 未被默认规则放行 默认 AllowVnetInBound 不含 ICMP,需显式添加允许规则
加入 ASG 后仍不通 ASG 与 NSG 不在同一区域,或网卡未加入 ASG 检查 ASG 区域、网卡关联状态,确认规则源/目标引用正确
负载均衡后端探测失败 NSG 拦截了 168.63.129.16 的健康探测 确认 AllowAzureLoadBalancerInBound 未被更高优先级规则覆盖
出站访问公网被拒 自定义 DenyAllOutBound 优先级过高 检查出站规则优先级,确保放行规则数字小于拒绝规则
排错口诀:先看有效规则,再看流量日志,最后核对优先级。有效规则告诉你“最终谁说了算”,流量日志告诉你“实际命中了谁”,优先级告诉你“为什么是它”。
注意:NSG 是有状态的。如果入站连接被允许,返回流量会自动放行,不需要额外配置出站规则。但如果是主动发起的出站连接,则必须显式允许出站方向。很多“单向通、反向不通”的问题,根源就在于误以为 NSG 需要双向放行。

掌握以上四点后,NSG 与 ASG 的配置就不再是“试错式”操作。规则优先级决定命中顺序,ASG 决定规则的可维护性,流量日志决定排错效率,而常见错误清单则帮助你在动手前就避开已知陷阱。实际工程中,建议把 NSG 规则按“角色 + 端口 + 方向”命名,并定期用有效安全规则导出核对,避免规则膨胀后出现难以察觉的优先级冲突。