1. Inbound network traffic filtering with Azure Firewall DNAT rules

    TypeScript

    To set up inbound network traffic filtering using Azure Firewall DNAT (Destination Network Address Translation) rules, we’ll walk through creating the requisite resources using Pulumi in TypeScript. DNAT rules allow you to translate and filter inbound Internet traffic to your virtual networks.

    Before we start with the Pulumi program, make sure you have the Azure provider set up in Pulumi. You can authenticate via az login using the Azure CLI.

    Here’s what we’ll do:

    1. Set up an Azure Resource Group: This acts as a logical container for our resources.
    2. Create a Virtual Network (VNet) and a Subnet: These are necessary to define a network for our firewall.
    3. Deploy an Azure Firewall: This will contain our DNAT rule.
    4. Create a Public IP for the Azure Firewall: Required to access the firewall from outside Azure.
    5. Define Azure Firewall DNAT Rules: This enables specific inbound traffic to be redirected.

    This is a high-level outlook on what we are about to build. Let’s start coding:

    import * as pulumi from "@pulumi/pulumi"; import * as azure from "@pulumi/azure-native"; // Step 1: Create a new resource group const resourceGroupName = "rg-firewall-example"; const resourceGroup = new azure.resources.ResourceGroup(resourceGroupName); // Step 2: Define the network for the firewall const vnetName = "vnet-firewall"; const subnetName = "AzureFirewallSubnet"; // The subnet name must be AzureFirewallSubnet const vnet = new azure.network.VirtualNetwork(vnetName, { resourceGroupName: resourceGroup.name, addressSpace: { addressPrefixes: ["10.0.0.0/16"], }, }); const subnet = new azure.network.Subnet(subnetName, { resourceGroupName: resourceGroup.name, virtualNetworkName: vnet.name, addressPrefix: "10.0.1.0/24", // Must be /24 or larger }); // Step 3: Create a public IP for the firewall const publicIp = new azure.network.PublicIPAddress("firewall-publicIp", { resourceGroupName: resourceGroup.name, publicIPAllocationMethod: azure.network.IPAllocationMethod.Static, sku: { name: azure.network.PublicIPAddressSkuName.Standard, } }); // Step 4: Deploy the firewall with a DNAT rule const firewall = new azure.network.AzureFirewall("firewall", { resourceGroupName: resourceGroup.name, ipConfigurations: [{ name: "firewall-ip-configuration", subnet: { id: subnet.id }, publicIPAddress: { id: publicIp.id } }], natRuleCollections: [{ priority: 100, action: { type: azure.network.AzureFirewallRCActionType.Dnat }, rules: [{ name: "ExampleDNATRule", description: "Example rule to demonstrate DNAT", sourceAddresses: ["*"], // Replace with real source IPs if necessary destinationPorts: ["3389"], // Port for RDP, can be replaced with the port you need translatedPort: "3389", // The port traffic will be redirected to on the internal network destinationAddresses: [publicIp.id.apply(value => value.ipAddress)], // The firewall's public IP protocols: ["TCP"], // Protocol to be matched, TCP or UDP }], }] }); // Outputs export const firewallName = firewall.name; export const publicIpAddress = publicIp.ipAddress;

    Each resource has comments next to it explaining what we are doing and why as follows:

    • Resource Group: This is where all resources are allocated for logical grouping and management.
    • Virtual Network & Subnet: The VNet defines the network space, and the subnet must be named "AzureFirewallSubnet" for the firewall to work correctly. It is within this subnet that we’ll be placing our firewall.
    • Public IP: Azure Firewall requires a static public IP that is assigned to its virtual firewall appliance.
    • Azure Firewall: This resource is the core of our solution, within which we define the DNAT rules. It is essentially acting as our traffic filter.
      • The ipConfigurations attribute defines the IP configuration for the Azure Firewall, linking it to our subnet and assigning the public IP.
      • In natRuleCollections, we set up DNAT to translate and filter incoming traffic. We have one example DNAT rule here that would translate any RDP traffic destined to the firewall's public IP to a private IP inside our network.

    Please note that this is an example of how to define the Azure Firewall and DNAT rule with Pulumi. Depending on your actual requirements, the source and destination addresses, ports, and protocols for the NAT rule will vary. You should replace "*" with the actual source addresses and adjust the destination ports and translated port as per your needs.

    For more detailed implementation guides and Azure resource references, you can refer to the Azure Firewall documentation and for Pulumi's TypeScript programming model you can refer to the Pulumi Programming Model documentation.