How-to guide

Close open ports and public endpoints on Azure

Find every public IP, open NSG rule and exposed platform service on Azure, close the ones you do not need, and verify the result from outside.

By the Cloudverg engineering team · · 7 min read

Why this matters

A resource on Azure becomes reachable from the internet in one of two ways. It has a public IP address of its own, or it sits behind something that gives it one, such as a Standard Load Balancer frontend, an Application Gateway, or a platform service endpoint with public network access switched on. Unless a rule blocks the traffic first, that endpoint answers strangers.

Network Security Groups are where most of the mess lives. Every NSG ships with default rules that allow traffic inside the virtual network and from the Azure load balancer probe. People then add rules for a demo, a vendor or a late debugging session, and those rules do not expire. A port opened to 0.0.0.0/0 in a hurry is still open a year later, and nobody can tell you why it is there.

The quieter exposure sits in platform services. A storage account, Key Vault, SQL server, Cosmos DB account or container registry created from the portal often starts with public network access on and the firewall set to all networks. The overview page says nothing about it. Closing these is the same job as closing ports, done with different settings in a different place.

Before you start

You need read access to every subscription you plan to review and write access to change anything. The Reader role is enough for inventory, and Azure Resource Graph lets you query across subscriptions at once from the portal or with az graph query. Export that list before you touch a single rule. You will need it later to show what changed.

Decide what stays public on purpose. Customer web apps, API gateways, VPN gateways and anything behind Azure Front Door or Application Gateway with WAF have a real reason to face the internet. Write those down with an owner and a reason. Everything else is a candidate for closing.

Next, find what depends on the current shape. Ask each application team which hostnames and connection strings it uses. Check the DNS records you control. Hosted build agents and third-party webhooks connect from addresses you do not own, so allowlists built for them tend to break the moment the provider rotates a range.

Pick a change window and a rollback. For platform services the slow part is private DNS, not the endpoint itself. Test name resolution from inside the virtual network before you turn public access off.

How to do it

Start with inventory, not with rules. Editing an NSG before you know what the subnet carries is how outages happen. Build a complete list of public IP addresses and resources with public network access enabled, then work through it item by item and mark each one as keep, close or investigate.

Order the work so risk drops early. Remove what nothing uses, then move platform services onto private endpoints, then lock down management access, then add policy so the next person cannot quietly reopen it. Each stage is small enough to test on its own.

Keep a change log. Record the resource, the rule or setting you changed, the reason and who asked for it. In six months that log is the only thing that explains why one particular port is still open. Tag anything temporary with an expiry date and put the date in the tag value.

  1. Inventory public IP addresses. Run az network public-ip list --query "[].{name:name,address:ipAddress,attached:ipConfiguration.id}" -o table, or query Azure Resource Graph for resources of type microsoft.network/publicipaddresses. Flag every address that is unattached or points at something nobody recognizes.
  2. Find NSG rules that allow the internet. List inbound rules whose source is 0.0.0.0/0, Internet or Any on the NSGs attached to your subnets and network interfaces. Check the effective security rules on each virtual machine, because the subnet and interface rules combine.
  3. Remove unused addresses and frontends. Delete public IPs attached to nothing and retire test load balancer or Application Gateway frontends that serve no traffic. If a virtual machine has a public IP but you reach it through Bastion or a VPN, disassociate the address.
  4. Move platform services to private endpoints. Create a private endpoint in the right subnet for each storage account, Key Vault, SQL server, Cosmos DB account and container registry. Link the matching private DNS zone, such as privatelink.blob.core.windows.net or privatelink.vaultcore.azure.net, so clients resolve the private address.
  5. Turn off public network access. Set the public network access setting to Disabled on each of those services and remove broad exceptions such as the allow Azure services switch unless a first-party service genuinely needs it. Do this only after name resolution works from inside the network.
  6. Close management ports. Remove internet rules for RDP 3389, SSH 22, WinRM and database ports. Use Azure Bastion for browser-based sessions, or just-in-time access in Defender for Cloud, which opens a port for a set window to one source address.
  7. Restrict web app entry points. Replace wide IP allowlists on App Service and Functions with access restrictions, or move to private endpoints with public access off. Check the SCM site rules separately, since Kudu has its own exposure settings.
  8. Put a filter in front of anything still public. Terminate inbound web traffic at Application Gateway with WAF or Azure Front Door and send it to a private backend. Keep the backend address out of the public range so the filter cannot be bypassed.
  9. Add policy guardrails. Assign built-in policies that deny public IP creation outside approved resource groups and audit resources with public network access enabled. Use Deny for new resources and Audit for existing ones so the fix list stays visible.

How to check it worked

Scan from outside Azure. A scan from a machine inside the same virtual network proves nothing about the internet path. Run a full port scan against each public IP you kept, for example with nmap and the -Pn flag, or use Test-NetConnection from a laptop for individual ports. Do this after every change window, not once a year.

Confirm the live setting rather than trusting your notes. Resource Graph is good for inventory, but not every property is indexed there, so check the portal blade or the service CLI. For storage, az storage account show --query publicNetworkAccess returns the current value. For NSGs, use the effective security rules view on the virtual machine, which shows the combined result of the subnet and network interface rules.

Read the logs. Virtual network flow logs through Network Watcher, Azure Firewall logs and Application Gateway access logs all show denied and allowed traffic. After a change, denied counts on the ports you closed tell you who was still calling. That is a faster way to find a forgotten integration than waiting for a support ticket.

Finally, re-run your Defender for Cloud recommendations and look at the items covering management ports and public network access. Anything still listed is either a genuine exception to document or a resource you missed.

Mistakes to avoid

The most common one is an IP allowlist full of Azure datacenter ranges because a pipeline runs on hosted build agents. Those ranges are large and they change. Move the pipeline onto a self-hosted agent inside the virtual network, or authenticate with a service principal and skip the IP rule entirely.

People also assume one NSG wins. It does not. Traffic must be allowed by both the subnet NSG and the network interface NSG, and the default AllowVnetInbound rule lets anything inside the virtual network reach the resource. Read the effective rules before you conclude a port is closed.

Turning off public network access before the private DNS zone is linked breaks name resolution for every client that used the public name from inside the network. Delete a public IP without checking DNS and users land on a dead hostname. Put a WAF in front but leave the origin reachable on its own address and the WAF becomes optional for anyone who finds the origin.

If you want an outside read before you start cutting, options range from an internal review to a paid assessment. The Cloud security review from Cloudverg is one of them: a fixed price $6,500 read-only review across up to five subscriptions, with public exposure, network and encryption checks and a prioritized fix list. It takes two to three weeks and starts within ten business days.

Frequently asked questions

Does an NSG close ports on an Azure storage account or SQL server?

No. Network Security Groups attach to subnets and network interfaces, so they only filter traffic to virtual machines and other resources with a NIC. Platform services are filtered by their own firewall settings and by the public network access switch, which you change on the service itself.

What is the difference between a service endpoint and a private endpoint?

A service endpoint keeps traffic to the service on the Azure backbone, but the service still has a public address and public network access. A private endpoint gives the service a private IP inside your subnet and lets you disable public access completely. Private endpoints carry an hourly and data charge, so they cost more than service endpoints.

Can I close RDP and SSH without a VPN?

Yes. Azure Bastion gives you browser-based RDP and SSH through a dedicated subnet named AzureBastionSubnet, with no public IP on the machines themselves. Just-in-time access in Defender for Cloud is the lighter option: the port stays closed until someone requests access for a set period.

Fixed price

Want help with this? Cloud security review

$6,500 fixed price

2 to 3 weeks · Starts within 10 business days

A read-only review of identity, network exposure, encryption and logging across your cloud accounts, with a prioritized fix list.

What is included

Related guides

More cloud security guides   Security and compliance

Smallest way to start

Get a senior architect on your problem this week

Ninety minutes on the cloud, AI or security question that is blocking you, a pre-read of your material and a written summary within two business days.

$450 one-time