How to Configure Windows Server 2016 Distributed Firewall

The Distributed Firewall in Windows Server 2016 SDN is a stateful, policy-driven firewall that enforces network access controls at the virtual machine vNIC level, directly within the Hyper-V Virtual Switch on each host. Unlike traditional perimeter firewalls that inspect traffic at a single point, the Distributed Firewall applies policies at the source and destination of every flow, providing east-west micro-segmentation and north-south perimeter security without requiring traffic to hairpin through a centralised appliance. This dramatically improves both security posture and network performance within the datacenter.

This tutorial covers how to create and apply Distributed Firewall policies using Access Control Lists (ACLs) managed by the Windows Server 2016 Network Controller, including stateful rule definitions, VM attachment, and policy verification.

How the Distributed Firewall Works

Access Control Lists (ACLs) in the SDN Distributed Firewall are defined as resources in the Network Controller. Each ACL contains an ordered list of rules that specify allowed or denied traffic based on protocol, source and destination addresses, and port ranges. ACLs can be applied to individual virtual network interfaces, to entire subnets, or to logical network subnets. The Network Controller distributes ACL policies to the SLB Host Agent and the VFP (Virtual Filtering Platform) extension running in the Hyper-V Virtual Switch on each host. Enforcement happens at line rate without traversing any additional network hops.

Prerequisites

You need a running Windows Server 2016 SDN deployment with the Network Controller and at least one configured virtual network. The SDN Host Agent must be installed on each Hyper-V host. Verify the Network Controller is accessible:

$uri = "https://nc.contoso.com"
Invoke-RestMethod -Uri "$uri/networking/v1/discover" -UseDefaultCredentials

Step 1 — Create an ACL with Firewall Rules

Define an Access Control List with rules for a web server VM that allows inbound HTTP and HTTPS while blocking all other inbound traffic:

$headers = @{ "Content-Type" = "application/json" }

$aclBody = @{
  properties = @{
    aclRules = @(
      @{
        resourceId = "Allow-HTTP"
        properties = @{
          priority = 100
          protocol = "TCP"
          sourcePortRange = "0-65535"
          destinationPortRange = "80"
          sourceAddressPrefix = "*"
          destinationAddressPrefix = "*"
          action = "Allow"
          type = "Inbound"
          logging = "Enabled"
        }
      },
      @{
        resourceId = "Allow-HTTPS"
        properties = @{
          priority = 110
          protocol = "TCP"
          sourcePortRange = "0-65535"
          destinationPortRange = "443"
          sourceAddressPrefix = "*"
          destinationAddressPrefix = "*"
          action = "Allow"
          type = "Inbound"
          logging = "Enabled"
        }
      },
      @{
        resourceId = "Allow-Established"
        properties = @{
          priority = 120
          protocol = "All"
          sourcePortRange = "0-65535"
          destinationPortRange = "0-65535"
          sourceAddressPrefix = "*"
          destinationAddressPrefix = "*"
          action = "Allow"
          type = "Outbound"
          logging = "Disabled"
        }
      },
      @{
        resourceId = "Deny-All-Inbound"
        properties = @{
          priority = 65500
          protocol = "All"
          sourcePortRange = "0-65535"
          destinationPortRange = "0-65535"
          sourceAddressPrefix = "*"
          destinationAddressPrefix = "*"
          action = "Deny"
          type = "Inbound"
          logging = "Enabled"
        }
      }
    )
  }
} | ConvertTo-Json -Depth 7

Invoke-RestMethod `
  -Uri "$uri/networking/v1/accessControlLists/WebServer-ACL" `
  -Method Put `
  -Body $aclBody `
  -Headers $headers `
  -UseDefaultCredentials

Step 2 — Apply the ACL to a VM Network Interface

Attach the ACL to a specific VM’s network interface to enforce the firewall rules at that VM’s vNIC:

$nicUpdate = @{
  properties = @{
    macAddress = "00-22-33-44-55-66"
    ipConfigurations = @(@{
      properties = @{
        privateIPAddress = "10.100.1.11"
        privateIPAllocationMethod = "Static"
        subnet = @{ resourceRef = "/virtualNetworks/TenantAVNet/subnets/TenantA-Subnet1" }
        accessControlList = @{ resourceRef = "/accessControlLists/WebServer-ACL" }
      }
    })
  }
} | ConvertTo-Json -Depth 6

Invoke-RestMethod `
  -Uri "$uri/networking/v1/networkInterfaces/TenantA-VM1-NIC" `
  -Method Put `
  -Body $nicUpdate `
  -Headers $headers `
  -UseDefaultCredentials

Step 3 — Apply an ACL to an Entire Subnet

For broader enforcement, apply an ACL at the subnet level to affect all VMs attached to that subnet:

$subnetUpdate = @{
  properties = @{
    addressPrefix = "10.100.1.0/24"
    accessControlList = @{ resourceRef = "/accessControlLists/WebServer-ACL" }
  }
} | ConvertTo-Json -Depth 4

Invoke-RestMethod `
  -Uri "$uri/networking/v1/virtualNetworks/TenantAVNet/subnets/TenantA-Subnet1" `
  -Method Put `
  -Body $subnetUpdate `
  -Headers $headers `
  -UseDefaultCredentials

Step 4 — Verify Policy Distribution

Confirm the ACL has been distributed to the Hyper-V hosts and applied to the virtual switch. On the host running the target VM, check the VFP rules:

vfpctrl /port  /list-rule

The rules should reflect the ACL entries defined in the Network Controller, with the allow and deny actions correctly applied to the appropriate traffic directions.

Step 5 — Test Firewall Enforcement

Test that the firewall rules are working as expected. From an external host, test that port 80 is reachable:

Test-NetConnection -ComputerName 10.100.1.11 -Port 80

Then test a port that should be blocked:

Test-NetConnection -ComputerName 10.100.1.11 -Port 3389

Port 80 should succeed and port 3389 (RDP) should time out or be refused.

Step 6 — Review Firewall Logs

When logging is enabled on ACL rules, events are written to the Event Log. Query the Firewall log on the Network Controller or the host agent logs:

Get-WinEvent -LogName "Microsoft-Windows-SDN*" | Where-Object { $_.LevelDisplayName -eq "Warning" }

Conclusion

The Distributed Firewall in Windows Server 2016 SDN delivers micro-segmentation at the vNIC level, providing fine-grained access control that follows VM workloads regardless of which physical host they run on. Because policies are defined centrally in the Network Controller and enforced at the hypervisor level, the Distributed Firewall eliminates the scalability limitations of traditional perimeter firewalls and reduces the blast radius of any security incident by preventing lateral movement between workloads within the virtual network fabric.