vWAN P2S VPN - unable to limit network traffic with Azure firewall

Audun Solemdal 6 Reputation points
2022-07-21T07:29:19.57+00:00

Original Issue: https://github.com/MicrosoftDocs/azure-docs/issues/95864

So I've followed the article and deployed a P2S VPN in vWAN with an existing vWan, hub and spoke vnets.
I deployed a P2S gateway to an existing virtual hub. The vWAN is connected to multiple vnets associated to the default route table, with propagation to the noneRouteTable. I have set custom DNS server to azure firewall, which in turn points to two VM's running custom dns servers in our network.

The default route table has a next hop to the central Azure firewall. The P2S VPN config is associated with the firewall for private traffic in the Firewall manager GUI

Although I don't really understand why this part is necessary to ensure traffic flows through the firewall Verify that you created rules in the Create Rules section. If these steps are missed, the rules you created won't actually be associated to the hub and the route table and packet flow won't use Azure Firewall. I have created a network fw rule to allow access from the client IP addresses to the IP addresses of AKS API servers located in three different VNets.

What happens is that I am able to connect to the network without issues, but the traffic seems to bypass azure firewall. Log analytics logs shows nothing on my port 80 or 443 requests which succeed, but do show ICMP traffic on port 8 being blocked, with the SourceIP being the address assigned by the VPN client.

Protocol: OpenVPN
I am using the Azure VPN client on Windows 10, client certificate and Azure AD give the same result.

It seems to me as the next hop for the firewall is bypassed for port 80 and 443. Log entries for ICMP type=8 (tracert) are showing in the logs as denied (expected)

Azure Virtual WAN
Azure Virtual WAN
An Azure virtual networking service that provides optimized and automated branch-to-branch connectivity.
186 questions
Azure VPN Gateway
Azure VPN Gateway
An Azure service that enables the connection of on-premises networks to Azure through site-to-site virtual private networks.
1,368 questions
Azure Virtual Network
Azure Virtual Network
An Azure networking service that is used to provision private networks and optionally to connect to on-premises datacenters.
2,131 questions
{count} vote

3 answers

Sort by: Most helpful
  1. Audun Solemdal 6 Reputation points
    2022-07-22T11:54:28.42+00:00

    Tested port 22 against VM's in various spokes: can confirm that azure firewall picks up the traffic (and denies it as expected)

    The spoke vnets have the defaultRouteTable associated, and propagates to the noneRouteTable. This is done through
    resource "azurerm_virtual_hub_connection" in terraform. The vm spoke connections have internet_security_enabled = true

    The p2s vpn "spoke" if you can call it that has the same routing rules as spoke vnets. I have tried both with internet_security_enabled=true and false, same results

    Effective routes are the same as we have defined in the hubRouteTables:

       {  
           "type": "Microsoft.Network/virtualHubs/hubRouteTables",  
           "apiVersion": "2021-02-01",  
           "name": "[concat(parameters('vhub_name'), '/noneRouteTable')]",  
           "properties": {  
               "routes": [],  
               "labels": [  
                   "none"  
               ]  
           }  
       },  
       {  
           "type": "Microsoft.Network/virtualHubs/hubRouteTables",  
           "apiVersion": "2021-02-01",  
           "name": "[concat(parameters('vhub_name'), '/defaultRouteTable')]",  
           "properties": {  
               "routes": [  
                   {  
                       "name": "all_traffic",  
                       "destinationType": "CIDR",  
                       "destinations": [  
                           "0.0.0.0/0",  
                           "10.0.0.0/8",  
                           "172.16.0.0/12",  
                           "192.168.0.0/16"  
                       ],  
                       "nextHopType": "ResourceId",  
                       "nextHop": "[resourceId('Microsoft.Network/azureFirewalls', parameters('azfw_name'))]"  
                   }  
               ],  
               "labels": [  
                   "default"  
               ]  
           }  
       }  
    
    
    
       // Azure Firewall log data   
       // Start from this query if you want to parse the logs from network rules, application rules, NAT rules, IDS, threat intelligence and more to understand why certain traffic was allowed or denied. This query will show the last 100 log records but by adding simple filter statements at the end of the query the results can be tweaked.   
       // Parses the azure firewall rule log data.   
       // Includes network rules, application rules, threat intelligence, ips/ids, ...  
       AzureDiagnostics  
       | where Category == "AzureFirewallNetworkRule" or Category == "AzureFirewallApplicationRule"  
       //optionally apply filters to only look at a certain type of log data  
       //| where OperationName == "AzureFirewallNetworkRuleLog"  
       //| where OperationName == "AzureFirewallNatRuleLog"  
       //| where OperationName == "AzureFirewallApplicationRuleLog"  
       //| where OperationName == "AzureFirewallIDSLog"  
       //| where OperationName == "AzureFirewallThreatIntelLog"  
       | extend msg_original = msg_s  
       // normalize data so it's eassier to parse later  
       | extend msg_s = replace(@'. Action: Deny. Reason: SNI TLS extension was missing.', @' to no_data:no_data. Action: Deny. Rule Collection: default behavior. Rule: SNI TLS extension missing', msg_s)  
       | extend msg_s = replace(@'No rule matched. Proceeding with default action', @'Rule Collection: default behavior. Rule: no rule matched', msg_s)  
       // extract web category, then remove it from further parsing  
       | parse msg_s with * " Web Category: " WebCategory  
       | extend msg_s = replace(@'(. Web Category:).*','', msg_s)  
       // extract RuleCollection and Rule information, then remove it from further parsing  
       | parse msg_s with * ". Rule Collection: " RuleCollection ". Rule: " Rule  
       | extend msg_s = replace(@'(. Rule Collection:).*','', msg_s)  
       // extract Rule Collection Group information, then remove it from further parsing  
       | parse msg_s with * ". Rule Collection Group: " RuleCollectionGroup  
       | extend msg_s = replace(@'(. Rule Collection Group:).*','', msg_s)  
       // extract Policy information, then remove it from further parsing  
       | parse msg_s with * ". Policy: " Policy  
       | extend msg_s = replace(@'(. Policy:).*','', msg_s)  
       // extract IDS fields, for now it's always add the end, then remove it from further parsing  
       | parse msg_s with * ". Signature: " IDSSignatureIDInt ". IDS: " IDSSignatureDescription ". Priority: " IDSPriorityInt ". Classification: " IDSClassification  
       | extend msg_s = replace(@'(. Signature:).*','', msg_s)  
       // extra NAT info, then remove it from further parsing  
       | parse msg_s with * " was DNAT'ed to " NatDestination  
       | extend msg_s = replace(@"( was DNAT'ed to ).*",". Action: DNAT", msg_s)  
       // extract Threat Intellingence info, then remove it from further parsing  
       | parse msg_s with * ". ThreatIntel: " ThreatIntel  
       | extend msg_s = replace(@'(. ThreatIntel:).*','', msg_s)  
       // extract URL, then remove it from further parsing  
       | extend URL = extract(@"(Url: )(.*)(\. Action)",2,msg_s)  
       | extend msg_s=replace(@"(Url: .*)(Action)",@"\2",msg_s)  
       // parse remaining "simple" fields  
       | parse msg_s with Protocol " request from " SourceIP " to " Target ". Action: " Action  
       | extend   
           SourceIP = iif(SourceIP contains ":",strcat_array(split(SourceIP,":",0),""),SourceIP),  
           SourcePort = iif(SourceIP contains ":",strcat_array(split(SourceIP,":",1),""),""),  
           Target = iif(Target contains ":",strcat_array(split(Target,":",0),""),Target),  
           TargetPort = iif(SourceIP contains ":",strcat_array(split(Target,":",1),""),""),  
           Action = iif(Action contains ".",strcat_array(split(Action,".",0),""),Action),  
           Policy = case(RuleCollection contains ":", split(RuleCollection, ":")[0] ,Policy),  
           RuleCollectionGroup = case(RuleCollection contains ":", split(RuleCollection, ":")[1], RuleCollectionGroup),  
           RuleCollection = case(RuleCollection contains ":", split(RuleCollection, ":")[2], RuleCollection),  
           IDSSignatureID = tostring(IDSSignatureIDInt),  
           IDSPriority = tostring(IDSPriorityInt)  
       | project Target,msg_original,TimeGenerated,Protocol,SourceIP,SourcePort,TargetPort,URL,Action, NatDestination, OperationName,ThreatIntel,IDSSignatureID,IDSSignatureDescription,IDSPriority,IDSClassification,Policy,RuleCollectionGroup,RuleCollection,Rule,WebCategory  
       | where ipv4_is_in_range(SourceIP, "172.26.254.0/24")  
    

    Change the Ip-range in the last line to match the ip range of your client address pool


  2. Audun Solemdal 6 Reputation points
    2022-08-01T12:05:36.083+00:00

    Adding /32 suffixes did the trick. Please add a disclaimer to the article regarding private endpoints. I did not find this intuitive at all, and I assume I won't be the only person wasting time on this.


  3. GitaraniSharma-MSFT 46,931 Reputation points Microsoft Employee
    2022-08-01T17:41:51.013+00:00

    Hello @Audun Solemdal ,

    I understand that you deployed a P2S VPN in vWAN with hub-spoke model with multiple vnets associated to the default route table and propagation set to the noneRouteTable. The default route table has a next hop Azure firewall and the P2S VPN config in the Firewall manager GUI have been configured to route private traffic via Azure Firewall but the traffic seems to bypass Azure Firewall. Log analytics logs were not showing any traffic on port 80 or 443 requests which succeeded.

    Post discussion, we found that you were testing access to private endpoints from your P2S VPN client.

    To filter traffic from clients either on premises or in Azure destined to services exposed via private endpoints in a Virtual WAN connected virtual network using secured virtual hub with Azure Firewall as the security provider, you need to configure /32 prefix for each private endpoint IP in the "Private traffic prefixes" under Security configuration of your Azure Firewall manager to make sure that the Azure Firewall is not bypassed.

    If these /32 prefixes are not configured, traffic destined to private endpoints will bypass Azure Firewall.
    Refer : https://learn.microsoft.com/en-us/azure/firewall-manager/private-link-inspection-secure-virtual-hub

    Once you added the /32 prefixes, the issue was resolved and you were able to see the logs for HTTP(S) traffic to your private endpoints from your P2S VPN client.

    I will discuss this with the backend team and add a NOTE in the below doc for more visibility and clarity:
    https://learn.microsoft.com/en-us/azure/virtual-wan/manage-secure-access-resources-spoke-p2s

    Kindly let us know if the above helps or you need further assistance on this issue.

    ----------------------------------------------------------------------------------------------------------------

    Please "Accept the answer" if the information helped you. This will help us and others in the community as well.

    0 comments No comments