|
| 1 | +# Hub-Spoke Network with NAT Gateway and Azure Firewall |
| 2 | + |
| 3 | +This template deploys a secure hub-spoke network architecture in Azure with a NAT Gateway for outbound connectivity and Azure Firewall for traffic inspection and filtering. The solution includes Azure Bastion for secure VM access and demonstrates best practices for network segmentation and security. |
| 4 | + |
| 5 | +## Architecture Overview |
| 6 | + |
| 7 | +This template creates: |
| 8 | + |
| 9 | +- **Hub Virtual Network**: Contains Azure Firewall, Azure Bastion, and NAT Gateway |
| 10 | +- **Spoke Virtual Network**: Contains a Linux VM for testing |
| 11 | +- **Network peering**: Connects hub and spoke networks |
| 12 | +- **Route table**: Forces spoke traffic through the firewall |
| 13 | +- **NAT Gateway**: Provides secure outbound internet access |
| 14 | +- **Azure Firewall**: Inspects and filters network traffic |
| 15 | +- **Azure Bastion**: Provides secure RDP/SSH access to VMs |
| 16 | + |
| 17 | +## Terraform resource types |
| 18 | + |
| 19 | +- [random_pet](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) |
| 20 | +- [azurerm_resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) |
| 21 | +- [azurerm_virtual_network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network) |
| 22 | +- [azurerm_route_table](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/route_table) |
| 23 | +- [azurerm_subnet_route_table_association](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet_route_table_association) |
| 24 | +- [azurerm_public_ip](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip) |
| 25 | +- [azurerm_nat_gateway](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/nat_gateway) |
| 26 | +- [azurerm_nat_gateway_public_ip_association](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/nat_gateway_public_ip_association) |
| 27 | +- [azurerm_subnet_nat_gateway_association](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet_nat_gateway_association) |
| 28 | +- [azurerm_bastion_host](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/bastion_host) |
| 29 | +- [azurerm_firewall](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/firewall) |
| 30 | +- [azurerm_firewall_policy](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/firewall_policy) |
| 31 | +- [azurerm_firewall_policy_rule_collection_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/firewall_policy_rule_collection_group) |
| 32 | +- [azurerm_virtual_network_peering](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network_peering) |
| 33 | +- [azurerm_network_security_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_security_group) |
| 34 | +- [azurerm_network_interface](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_interface) |
| 35 | +- [azurerm_network_interface_security_group_association](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_interface_security_group_association) |
| 36 | +- [azurerm_linux_virtual_machine](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_virtual_machine) |
| 37 | + |
| 38 | +## Variables |
| 39 | + |
| 40 | +| Name | Description | Default value | |
| 41 | +|-|-|-| |
| 42 | +| `location` | Location for all resources | "East US" | |
| 43 | +| `admin_username` | Admin username for the virtual machine | "azureuser" | |
| 44 | +| `admin_ssh_key` | SSH public key for the virtual machine | *Required* | |
| 45 | + |
| 46 | +## Outputs |
| 47 | + |
| 48 | +| Name | Description | |
| 49 | +|-|-| |
| 50 | +| `hub_vnet_id` | ID of the hub virtual network | |
| 51 | +| `spoke_vnet_id` | ID of the spoke virtual network | |
| 52 | +| `firewall_private_ip` | Private IP address of the Azure Firewall | |
| 53 | +| `nat_gateway_public_ip` | Public IP address of the NAT Gateway | |
| 54 | +| `vm_private_ip` | Private IP address of the virtual machine | |
| 55 | +| `bastion_fqdn` | FQDN of the Azure Bastion | |
| 56 | +| `resource_group_name` | Name of the resource group | |
| 57 | +| `vm_name` | Name of the virtual machine | |
| 58 | + |
| 59 | +## Prerequisites |
| 60 | + |
| 61 | +Before running this template, ensure you have: |
| 62 | + |
| 63 | +- Azure CLI installed and configured |
| 64 | +- Terraform installed (version 1.0 or later) |
| 65 | +- An SSH public key for VM access |
| 66 | + |
| 67 | +## Usage |
| 68 | + |
| 69 | +1. **Generate an SSH key pair** (if you don't have one): |
| 70 | + |
| 71 | + ```bash |
| 72 | + ssh-keygen -t rsa -b 4096 -f ~/.ssh/azure_vm_key |
| 73 | + ``` |
| 74 | + |
| 75 | +2. **Clone and navigate to the template**: |
| 76 | + |
| 77 | + ```bash |
| 78 | + git clone <repository-url> |
| 79 | + cd quickstart/301-nat-gateway-hub-spoke-firewall |
| 80 | + ``` |
| 81 | + |
| 82 | +3. **Initialize Terraform**: |
| 83 | + |
| 84 | + ```bash |
| 85 | + terraform init |
| 86 | + ``` |
| 87 | + |
| 88 | +4. **Plan the deployment**: |
| 89 | + |
| 90 | + ```bash |
| 91 | + terraform plan \ |
| 92 | + -var 'admin_ssh_key=YOUR_SSH_PUBLIC_KEY_CONTENT' |
| 93 | + ``` |
| 94 | + |
| 95 | +5. **Apply the configuration**: |
| 96 | + |
| 97 | + ```bash |
| 98 | + terraform apply \ |
| 99 | + -var 'admin_ssh_key=YOUR_SSH_PUBLIC_KEY_CONTENT' |
| 100 | + ``` |
| 101 | + |
| 102 | + Or create a `terraform.tfvars` file: |
| 103 | + |
| 104 | + ```hcl |
| 105 | + location = "East US" |
| 106 | + admin_username = "azureuser" |
| 107 | + admin_ssh_key = "ssh-rsa AAAAB3NzaC1yc2E..." |
| 108 | + ``` |
| 109 | + |
| 110 | +## Network Architecture Details |
| 111 | + |
| 112 | +### Address Spaces |
| 113 | + |
| 114 | +- **Hub VNet**: 10.0.0.0/16 |
| 115 | + - Subnet-1: 10.0.0.0/24 |
| 116 | + - AzureFirewallSubnet: 10.0.1.64/26 |
| 117 | + - AzureBastionSubnet: 10.0.1.0/26 |
| 118 | +- **Spoke VNet**: 10.1.0.0/16 |
| 119 | + - subnet-private: 10.1.0.0/24 |
| 120 | + |
| 121 | +### Traffic Flow |
| 122 | + |
| 123 | +1. **Outbound Traffic**: VM → Route Table → Azure Firewall → NAT Gateway → Internet |
| 124 | +2. **Inbound Management**: Internet → Azure Bastion → VM |
| 125 | +3. **Inter-VNet**: Hub ↔ Spoke via VNet peering |
| 126 | + |
| 127 | +### Firewall Rules |
| 128 | + |
| 129 | +- Allows HTTP (80) and HTTPS (443) traffic from spoke network (10.1.0.0/24) to the internet |
| 130 | +- All other traffic is blocked by default |
| 131 | + |
| 132 | +## Testing the Deployment |
| 133 | + |
| 134 | +After deployment, you can test the architecture: |
| 135 | + |
| 136 | +1. **Connect to the VM via Azure Bastion**: |
| 137 | + - Go to the Azure Portal |
| 138 | + - Navigate to the VM resource |
| 139 | + - Click "Connect" → "Bastion" |
| 140 | + - Use the admin username and SSH private key |
| 141 | + |
| 142 | +2. **Test outbound connectivity**: |
| 143 | + |
| 144 | + ```bash |
| 145 | + # Test HTTP/HTTPS (should work) |
| 146 | + curl -I https://www.microsoft.com |
| 147 | + curl -I http://www.microsoft.com |
| 148 | + |
| 149 | + # Test other ports (should be blocked) |
| 150 | + nc -zv 8.8.8.8 53 |
| 151 | + ``` |
| 152 | + |
| 153 | +3. **Verify NAT Gateway usage**: |
| 154 | + |
| 155 | + ```bash |
| 156 | + # Check your public IP (should be the NAT Gateway IP) |
| 157 | + curl ifconfig.me |
| 158 | + ``` |
| 159 | + |
| 160 | +## Security Considerations |
| 161 | + |
| 162 | +- The VM in the spoke network has no public IP address |
| 163 | +- All outbound internet traffic goes through the NAT Gateway |
| 164 | +- Azure Firewall inspects and filters traffic based on configured rules |
| 165 | +- Azure Bastion provides secure access without exposing RDP/SSH ports |
| 166 | +- Network Security Groups provide additional subnet-level protection |
| 167 | + |
| 168 | +## Clean up |
| 169 | + |
| 170 | +To avoid ongoing charges, delete the resources when you're done: |
| 171 | + |
| 172 | +```bash |
| 173 | +terraform destroy \ |
| 174 | + -var 'admin_ssh_key=YOUR_SSH_PUBLIC_KEY_CONTENT' |
| 175 | +``` |
| 176 | + |
| 177 | +## Next Steps |
| 178 | + |
| 179 | +Consider enhancing this template by: |
| 180 | + |
| 181 | +- Adding additional firewall rules for specific applications |
| 182 | +- Implementing Azure Monitor for logging and analytics |
| 183 | +- Adding more spoke networks for multi-tier applications |
| 184 | +- Integrating with Azure Key Vault for secrets management |
| 185 | +- Adding DDoS Protection for enhanced security |
0 commit comments