Chebis26/network-security-sg-nsg-nacl

GitHub: Chebis26/network-security-sg-nsg-nacl

面向 AWS 和 Azure 的生产级网络安全分层防护项目,通过 Terraform 自动化实现 Security Groups、NACL 与 NSG 的纵深防御架构及合规规则集。

Stars: 0 | Forks: 0

# 网络安全 — SG、NSG 与 NACL 深度解析 [![AWS](https://img.shields.io/badge/AWS-SG_NACL-FF9900?logo=amazon-aws)](https://aws.amazon.com/) [![Azure](https://img.shields.io/badge/Azure-NSG-0078D4?logo=microsoft-azure)](https://azure.microsoft.com/) [![Terraform](https://img.shields.io/badge/Terraform-1.7+-623CE4?logo=terraform)](https://www.terraform.io/) 生产级安全层实现:AWS Security Groups(有状态,实例级别)、NACLs(无状态,子网级别)以及 Azure NSGs — 包含分层防御纵深架构、Terraform 自动化以及合规对齐的规则集。 ## 防御纵深架构 ``` INBOUND TRAFFIC FLOW (internet → application): Internet │ ▼ [Layer 1: AWS WAF / Azure WAF on App Gateway] SQL Injection, XSS, OWASP Top 10, IP reputation │ ▼ [Layer 2: Network ACL (AWS) / Azure NSG on subnet] Stateless, explicit deny rules: • Block source IPs in threat intel list • Deny management ports (22, 3389) from internet • Allow ALB ephemeral ports (1024-65535) inbound │ ▼ [Layer 3: Security Group / Azure NSG on NIC] Stateful, allow-list only: • ALB SG → App SG (port 8080 only) • App SG → DB SG (port 5432 only) • No rules = implicitly denied │ ▼ [Layer 4: Application] mTLS, JWT validation, application-level authz RESULT: 4 independent layers must all allow traffic. Compromise of one layer does not grant access. ``` ## AWS Security Groups — 生产级规则集 ### 分层 Security Group 模式 ``` # terraform/aws/security-groups/main.tf # 第 1 层:ALB Security Group (internet-facing) resource "aws_security_group" "alb" { name = "sg-alb-public" description = "ALB — HTTPS from internet only; outbound to app SG" vpc_id = var.vpc_id ingress { description = "HTTPS from internet" from_port = 443; to_port = 443; protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { description = "HTTP from internet (redirect to HTTPS)" from_port = 80; to_port = 80; protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { description = "To app tier only" from_port = 8080; to_port = 8080; protocol = "tcp" security_groups = [aws_security_group.app.id] } tags = merge(var.tags, { Name = "sg-alb" }) } # 第 2 层:App Security Group resource "aws_security_group" "app" { name = "sg-app-private" description = "App — from ALB SG only; to DB SG and VPC endpoints" vpc_id = var.vpc_id ingress { description = "From ALB SG" from_port = 8080; to_port = 8080; protocol = "tcp" security_groups = [aws_security_group.alb.id] } egress { description = "To DB" from_port = 5432; to_port = 5432; protocol = "tcp" security_groups = [aws_security_group.db.id] } egress { description = "HTTPS to AWS services (VPC endpoints)" from_port = 443; to_port = 443; protocol = "tcp" cidr_blocks = [var.vpc_cidr] } tags = merge(var.tags, { Name = "sg-app" }) } # 第 3 层:Database Security Group resource "aws_security_group" "db" { name = "sg-db-isolated" description = "DB — from app SG only; NO outbound" vpc_id = var.vpc_id ingress { description = "PostgreSQL from app SG only" from_port = 5432; to_port = 5432; protocol = "tcp" security_groups = [aws_security_group.app.id] } # No egress rules = all outbound blocked tags = merge(var.tags, { Name = "sg-db" }) } # VPC Endpoint Security Group(shared-services VPC 中的共享 endpoints) resource "aws_security_group" "vpc_endpoints" { name = "sg-vpc-endpoints" description = "VPC Endpoints — HTTPS from VPC CIDR only" vpc_id = var.vpc_id ingress { description = "HTTPS from entire VPC" from_port = 443; to_port = 443; protocol = "tcp" cidr_blocks = [var.vpc_cidr] } tags = merge(var.tags, { Name = "sg-vpc-endpoints" }) } ``` ## AWS NACLs — 无状态子网控制 ``` # terraform/aws/nacls/main.tf # NACLs 是 STATELESS 的 — 必须显式允许返回流量 # Public Subnet NACL(仅限 ALB 和 NAT GW) resource "aws_network_acl" "public" { vpc_id = var.vpc_id subnet_ids = var.public_subnet_ids # Inbound ingress { rule_no = 100; action = "allow"; protocol = "tcp"; from_port = 443; to_port = 443; cidr_block = "0.0.0.0/0" } ingress { rule_no = 110; action = "allow"; protocol = "tcp"; from_port = 80; to_port = 80; cidr_block = "0.0.0.0/0" } # Ephemeral ports — required for return traffic (TCP responses) ingress { rule_no = 900; action = "allow"; protocol = "tcp"; from_port = 1024; to_port = 65535; cidr_block = "0.0.0.0/0" } # Deny all else ingress { rule_no = 32766; action = "deny"; protocol = "-1"; from_port = 0; to_port = 0; cidr_block = "0.0.0.0/0" } # Outbound egress { rule_no = 100; action = "allow"; protocol = "-1"; from_port = 0; to_port = 0; cidr_block = "0.0.0.0/0" } tags = merge(var.tags, { Name = "nacl-public" }) } # Private Subnet NACL(Application 层) resource "aws_network_acl" "private" { vpc_id = var.vpc_id subnet_ids = var.private_subnet_ids # Inbound: only from VPC CIDR + ephemeral ports ingress { rule_no = 100; action = "allow"; protocol = "tcp"; from_port = 8080; to_port = 8080; cidr_block = var.vpc_cidr } ingress { rule_no = 110; action = "allow"; protocol = "tcp"; from_port = 443; to_port = 443; cidr_block = var.vpc_cidr } ingress { rule_no = 900; action = "allow"; protocol = "tcp"; from_port = 1024; to_port = 65535; cidr_block = "0.0.0.0/0" } # Explicit deny: block SSH from internet ingress { rule_no = 50; action = "deny"; protocol = "tcp"; from_port = 22; to_port = 22; cidr_block = "0.0.0.0/0" } ingress { rule_no = 32766; action = "deny"; protocol = "-1"; from_port = 0; to_port = 0; cidr_block = "0.0.0.0/0" } # Outbound egress { rule_no = 100; action = "allow"; protocol = "tcp"; from_port = 5432; to_port = 5432; cidr_block = var.data_subnet_cidr } egress { rule_no = 110; action = "allow"; protocol = "tcp"; from_port = 443; to_port = 443; cidr_block = "0.0.0.0/0" } egress { rule_no = 900; action = "allow"; protocol = "tcp"; from_port = 1024; to_port = 65535; cidr_block = "0.0.0.0/0" } tags = merge(var.tags, { Name = "nacl-private" }) } # Data Subnet NACL(Database 层 — 限制最严格) resource "aws_network_acl" "data" { vpc_id = var.vpc_id subnet_ids = var.data_subnet_ids # Only PostgreSQL from private subnet CIDR ingress { rule_no = 100; action = "allow"; protocol = "tcp"; from_port = 5432; to_port = 5432; cidr_block = var.private_subnet_cidr } ingress { rule_no = 32766; action = "deny"; protocol = "-1"; from_port = 0; to_port = 0; cidr_block = "0.0.0.0/0" } # Return traffic only to private subnet egress { rule_no = 100; action = "allow"; protocol = "tcp"; from_port = 1024; to_port = 65535; cidr_block = var.private_subnet_cidr } egress { rule_no = 32766; action = "deny"; protocol = "-1"; from_port = 0; to_port = 0; cidr_block = "0.0.0.0/0" } tags = merge(var.tags, { Name = "nacl-data" }) } ``` ## Azure NSGs — 生产级规则集 ``` # terraform/azure/nsg/main.tf resource "azurerm_network_security_group" "app" { name = "nsg-app-subnet" resource_group_name = var.resource_group location = var.location # INBOUND RULES (lower priority number = evaluated first) security_rule { name = "Allow-HTTPS-from-AppGW" priority = 100 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "8080" source_address_prefix = var.appgw_subnet_cidr destination_address_prefix = "*" } security_rule { name = "Allow-AppGW-Management" priority = 110 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_ranges = ["65200-65535"] # Required for AppGW health probes source_address_prefix = "GatewayManager" # Azure service tag destination_address_prefix = "*" } security_rule { name = "Allow-AzureLoadBalancer" priority = 120 direction = "Inbound" access = "Allow" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = "AzureLoadBalancer" destination_address_prefix = "*" } security_rule { name = "Deny-All-Inbound" priority = 4000 direction = "Inbound" access = "Deny" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = "*" destination_address_prefix = "*" } # OUTBOUND RULES security_rule { name = "Allow-DB-Outbound" priority = 100 direction = "Outbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "5432" source_address_prefix = "*" destination_address_prefix = var.data_subnet_cidr } security_rule { name = "Allow-KeyVault-Outbound" priority = 110 direction = "Outbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "443" source_address_prefix = "*" destination_address_prefix = "AzureKeyVault" # Service tag } security_rule { name = "Deny-All-Outbound" priority = 4000 direction = "Outbound" access = "Deny" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = "*" destination_address_prefix = "*" } tags = var.tags } ``` ## 验证与测试 ``` # AWS:获取 ENI 的有效 security rules aws ec2 describe-network-interface-attribute \ --network-interface-id $ENI_ID \ --attribute groupSet # AWS:检查 subnet 上的有效 NACL rules aws ec2 describe-network-acls \ --filters Name=association.subnet-id,Values=$SUBNET_ID \ --query 'NetworkAcls[0].{Inbound:Entries[?!Egress],Outbound:Entries[?Egress]}' \ --output json # Azure:查看 NIC 的有效 security rules az network nic list-effective-nsg \ --name nic-app-vm \ --resource-group rg-prod \ --query 'effectiveSecurityRules[*].{Name:name,Priority:priority,Access:access,Direction:direction,Port:destinationPortRange}' \ --output table # Azure:使用 Network Watcher 测试连通性 az network watcher test-ip-flow \ --vm vm-app \ --direction Inbound \ --protocol TCP \ --local 10.1.1.10:8080 \ --remote 10.0.1.4:1234 # App GW private IP # 预期:Allow az network watcher test-ip-flow \ --vm vm-app \ --direction Inbound \ --protocol TCP \ --local 10.1.1.10:22 \ --remote 0.0.0.0:12345 # Internet source # 预期:Deny ``` ## 许可证 MIT License
标签:AWS, Azure, DevSecOps, DPI, ECS, Terraform, 上游代理, 合规与审计, 基础架构即代码, 漏洞利用检测, 网络安全, 隐私保护