Secure and Isolate Access To Azure Resources by Using Network Security Groups and Service Endpoints
Secure and Isolate Access To Azure Resources by Using Network Security Groups and Service Endpoints
network access
8 minutes
As part of the project to move your ERP system to Azure, you must ensure that servers
have proper isolation, so that only allowed systems can make network connections. For
example, you have database servers that store data for your ERP app. You want to block
prohibited systems from communicating with the servers over the network, while
allowing app servers to communicate with the database servers.
Network security groups are assigned to a network interface or a subnet. When you
assign a network security group to a subnet, the rules apply to all network interfaces in
that subnet. You can restrict traffic further by associating a network security group to
the network interface of a VM.
When you apply network security groups to both a subnet and a network interface, each
network security group is evaluated independently. Inbound traffic is first evaluated by
the network security group applied to the subnet, and then by the network security
group applied to the network interface. Conversely, outbound traffic from a VM is first
evaluated by the network security group applied to the network interface, and then by
the network security group applied to the subnet.
In this manufacturing company scenario, network security groups can help you secure
the network. You can control which computers can connect to your app servers. You
configure the network security group so that only a specific range of IP addresses can
connect to the servers. You can lock this down even more by only allowing access to or
from specific ports, or from individual IP addresses. These rules can be applied to
devices that are connecting remotely from on-premises networks, or between resources
within Azure.
Security rules
A network security group contains one or more security rules. Configure security rules to
either allow or deny traffic.
SEC
Property Explanation
Name A unique name within the network security group.
Priority A number between 100 and 4096.
Source or Any, or an individual IP address, classless inter-domain routing (CIDR) block (10.0.0.0/24, f
destination tag, or app security group.
Protocol TCP, UDP, or Any.
Direction Whether the rule applies to inbound, or outbound traffic.
Port range An individual port or range of ports.
Action Allow or deny the traffic.
Network security group security rules are evaluated by priority, using the 5-tuple
information (source, source port, destination, destination port, and protocol) to allow or
deny the traffic. When the conditions for a rule match the device configuration, rule
processing stops.
For example, suppose your company has created a security rule to allow inbound traffic
on port 3389 (RDP) to your web servers, with a priority of 200. Next, suppose that
another admin has created a rule to deny inbound traffic on port 3389, with a priority of
150. The deny rule takes precedence, because it's processed first. The rule with priority
150 is processed before the rule with priority 200.
With network security groups, the connections are stateful. Return traffic is
automatically allowed for the same TCP/UDP session. For example, an inbound rule
allowing traffic on port 80 also allows the VM to respond to the request (typically on an
ephemeral port). You don't need a corresponding outbound rule.
With regard to the ERP system, the web servers for the ERP app connect to database
servers that are in their own subnets. You can apply security rules to state that the only
allowed communication from the web servers to the database servers is port 1433 for
SQL Server database communications. All other traffic to the database servers will be
denied.
When you create a network security group, Azure creates several default rules. These
default rules can't be changed, but can be overridden with your own rules. These default
rules allow connectivity within a virtual network and from Azure load balancers. They
also allow outbound communication to the internet, and deny inbound traffic from the
internet.
DEFAULT SEC
Priority Rule name Description
65000 AllowVnetInbound Allow inbound coming from any VM to any VM within the su
65001 AllowAzureLoadBalancerInbound Allow traffic from the default load balancer to any VM within
65500 DenyAllInBound Deny traffic from any external source to any of the VMs.
DEFAULT SEC
Priority Rule name Description
65000 AllowVnetOutbound Allow outbound going from any VM to any VM within the subnet.
65001 AllowInternetOutbound Allow outbound traffic going to the internet from any VM.
65500 DenyAllOutBound Deny traffic from any internal VM to a system outside the virtual netwo
Multiple IP addresses
Multiple ports
Service tags
App security groups
Suppose your company wants to restrict access to resources in your datacenter, spread
across several network address ranges. With augmented rules, you can add all these
ranges into a single rule, reducing the administrative overhead and complexity in your
network security groups.
Service tags
You use service tags to simplify network security group security even further. You can
allow or deny traffic to a specific Azure service, either globally or per region.
Service tags simplify security for VMs and Azure virtual networks, by allowing you to
restrict access by resources or services. Service tags represent a group of IP addresses,
and help simplify the configuration of your security rules. For resources that you can
specify by using a tag, you don't need to know the IP address or port details.
You can restrict access to many services. Microsoft manages the service tags (you can't
create your own). Some examples of the tags are:
Use app security groups within a network security group to apply a security rule to a
group of resources. It's easier to deploy and scale up specific app workloads. You just
add a new VM deployment to one or more app security groups, and that VM
automatically picks up your security rules for that workload.
An app security group enables you to group network interfaces together. You can then
use that app security group as a source or destination rule within a network security
group.
For example, your company has a number of front-end servers in a virtual network. The
web servers must be accessible over ports 80 and 8080. Database servers must be
accessible over port 1433. You assign the network interfaces for the web servers to one
app security group, and the network interfaces for the database servers to another app
security group. You then create two inbound rules in your network security group. One
rule allows HTTP traffic to all servers in the web server app security group. The other rule
allows SQL traffic to all servers in the database server app security group.
Without app security groups, you'd need to create a separate rule for each VM.
The key benefit of app security groups is that it makes administration easier. You can
easily add and remove network interfaces to an app security group as you deploy or
redeploy app servers. You can also dynamically apply new rules to an app security
group, which are then automatically applied to all the VMs in that app security group.
When to use network security groups
As a best practice, you should always use network security groups to help protect your
networked assets against unwanted traffic. Network security groups give you granular
control access over the network layer, without the potential complexity of setting
security rules for every VM or virtual network.
As the solution architect for the manufacturing company, you now want to start moving
the ERP app and database servers to Azure. As a first step, you're going to test out your
network security plan, using two of your servers.
In this unit, you'll configure a network security group and security rules to restrict
network traffic to specific servers. You want your app server to be able to connect to
your database server over HTTP. You don't want the database server to be able to use
HTTP to connect to the app server.
Important
You need your own Azure subscription to run this exercise, and you might incur
charges. If you don't already have an Azure subscription, create a free account before
you begin.
Azure CLICopy
az account list-locations -o table
3. Next, create the resource group.
Azure CLICopy
rg=<resource group name>
Azure CLICopy
az network vnet create \
--resource-group $rg \
--name ERP-servers \
--address-prefix 10.0.0.0/16 \
--subnet-name Applications \
--subnet-prefix 10.0.0.0/24
Azure CLICopy
az network vnet subnet create \
--resource-group $rg \
--vnet-name ERP-servers \
--address-prefix 10.0.1.0/24 \
--name Databases
Azure CLICopy
az network nsg create \
--resource-group $rg \
--name ERP-SERVERS-NSG
Azure CLICopy
wget -N https://raw.githubusercontent.com/MicrosoftDocs/mslearn-secure-
and-isolate-with-nsg-and-service-endpoints/master/cloud-init.yml && \
az vm create \
--resource-group $rg \
--name AppServer \
--vnet-name ERP-servers \
--subnet Applications \
--nsg ERP-SERVERS-NSG \
--image UbuntuLTS \
--size Standard_DS1_v2 \
--admin-username azureuser \
--custom-data cloud-init.yml \
--no-wait \
--admin-password <password>
Azure CLICopy
az vm create \
--resource-group $rg \
--name DataServer \
--vnet-name ERP-servers \
--subnet Databases \
--nsg ERP-SERVERS-NSG \
--size Standard_DS1_v2 \
--image UbuntuLTS \
--admin-username azureuser \
--custom-data cloud-init.yml \
--admin-password <password>
3. It can take several minutes for the VMs to be in a running state. To confirm
that the VMs are running, in the Cloud Shell, run the following command.
Azure CLICopy
az vm list \
--resource-group $rg \
--show-details \
--query "[*].{Name:name, Provisioned:provisioningState,
Power:powerState}" \
--output table
When your VM creation is complete, you should see the following output.
OutputCopy
Name Provisioned Power
---------- ------------- ----------
AppServer Succeeded VM running
DataServer Succeeded VM running
1. To connect to your VMs, use SSH directly from Cloud Shell. To do this, you
need the public IP addresses that have been assigned to your VMs. To list
the IP addresses that you'll use to connect to the VMs, in the Cloud Shell,
run the following command.
Azure CLICopy
az vm list \
--resource-group $rg \
--show-details \
--query "[*].{Name:name, PrivateIP:privateIps, PublicIP:publicIps}" \
--output table
2. To make it easier to connect to your VMs during the rest of this exercise,
assign the public IP addresses to variables. To save the public IP address
of AppServer and DataServer to a variable, in the Cloud Shell, run the
following command.
BashCopy
APPSERVERIP="$(az vm list-ip-addresses \
--resource-group $rg \
--name AppServer \
--query
"[].virtualMachine.network.publicIpAddresses[*].ipAddress" \
--output tsv)"
DATASERVERIP="$(az vm list-ip-addresses \
--resource-group $rg \
--name DataServer \
--query
"[].virtualMachine.network.publicIpAddresses[*].ipAddress" \
--output tsv)"
BashCopy
ssh azureuser@$APPSERVERIP -o ConnectTimeout=5
BashCopy
ssh azureuser@$DATASERVERIP -o ConnectTimeout=5
Remember that the default rules deny all inbound traffic into a virtual network, unless
this traffic is coming from the same virtual network. The Deny All Inbound rule blocked
the inbound SSH connections you just attempted.
Inbound
CHECK DEFAULT C
Name Priority Source IP Destination IP
Allow VNet Inbound 65000 VIRTUAL_NETWORK VIRTUAL_NETWORK
CHECK DEFAULT C
Name Priority Source IP Destination IP
Deny All Inbound 65500 * *
1. To create a new inbound security rule to enable SSH access, in the Cloud
Shell, run the following command.
Azure CLICopy
az network nsg rule create \
--resource-group $rg \
--nsg-name ERP-SERVERS-NSG \
--name AllowSSHRule \
--direction Inbound \
--priority 100 \
--source-address-prefixes '*' \
--source-port-ranges '*' \
--destination-address-prefixes '*' \
--destination-port-ranges 22 \
--access Allow \
--protocol Tcp \
--description "Allow inbound SSH"
BashCopy
ssh azureuser@$APPSERVERIP -o ConnectTimeout=5
The network security group rule might take a minute or two to take effect. If
you receive a connection failure message, try again.
3. You should now be able to connect. After the Are you sure you want to
continue connecting (yes/no)? message, enter yes.
4. Enter the password you used when you created the VM.
5. Close the AppServer session, enter exit.
6. To check whether you can now connect to your DataServer VM, in the
Cloud Shell, run the following command.
BashCopy
ssh azureuser@$DATASERVERIP -o ConnectTimeout=5
7. You should now be able to connect. After the Are you sure you want to
continue connecting (yes/no)? message, enter yes.
8. Enter the password you used when you created the VM.
9. To close the DataServer session, enter exit.
1. To create a new inbound security rule to deny HTTP access over port 80, in
the Cloud Shell, run the following command.
Azure CLICopy
az network nsg rule create \
--resource-group $rg \
--nsg-name ERP-SERVERS-NSG \
--name httpRule \
--direction Inbound \
--priority 150 \
--source-address-prefixes 10.0.1.4 \
--source-port-ranges '*' \
--destination-address-prefixes 10.0.0.4 \
--destination-port-ranges 80 \
--access Deny \
--protocol Tcp \
--description "Deny from DataServer to AppServer on port 80"
Test HTTP connectivity between virtual machines
Here, you'll check if your new rule works. AppServer should be able to communicate
with DataServer over HTTP. DataServer shouldn't be able to communicate
with AppServer over HTTP.
BashCopy
ssh -t azureuser@$APPSERVERIP 'wget http://10.0.1.4; exit; bash'
2. Enter the password you used when you created the VM.
3. The response should include a 200 OK message.
4. To connect to your DataServer VM, in the Cloud Shell, run the following
command. Check if DataServer can communicate with AppServer over
HTTP.
BashCopy
ssh -t azureuser@$DATASERVERIP 'wget http://10.0.0.4; exit; bash'
5. Enter the password you used when you created the VM.
6. This shouldn't succeed, because you've blocked access over port 80. After
several minutes, you should get a Connection timed out message. To stop
the command before the timeout, press Ctrl+C.
Azure CLICopy
az network asg create \
--resource-group $rg \
--name ERP-DB-SERVERS-ASG
Azure CLICopy
az network nic ip-config update \
--resource-group $rg \
--application-security-groups ERP-DB-SERVERS-ASG \
--name ipconfigDataServer \
--nic-name DataServerVMNic \
--vnet-name ERP-servers \
--subnet Databases
Azure CLICopy
az network nsg rule update \
--resource-group $rg \
--nsg-name ERP-SERVERS-NSG \
--name httpRule \
--direction Inbound \
--priority 150 \
--source-address-prefixes "" \
--source-port-ranges '*' \
--source-asgs ERP-DB-SERVERS-ASG \
--destination-address-prefixes 10.0.0.4 \
--destination-port-ranges 80 \
--access Deny \
--protocol Tcp \
--description "Deny from DataServer to AppServer on port 80 using
application security group"
BashCopy
ssh -t azureuser@$APPSERVERIP 'wget http://10.0.1.4; exit; bash'
2. Enter the password you used when you created the VM.
3. As before, the response should include a 200 OK message. The app security
group settings can take a minute or two to take effect. If you don't initially
receive the 200 OK message, wait a minute and try again.
4. To connect to your DataServer in the Cloud Shell (at the top-right in Azure;
the box with the >_) , run the following command. Check if DataServer can
communicate with AppServer over HTTP.
BashCopy
ssh -t azureuser@$DATASERVERIP 'wget http://10.0.0.4; exit; bash'
5. Enter the password you used when you created the VM.
6. As before, this shouldn't succeed, because you've blocked access over port
80. After several minutes, you should get a Connection timed out message.
To stop the command before the timeout, press Ctrl+C.
You've now confirmed that your network security group rule works using an app
security group, in the same way as when you used a source IP address. If we were to add
additional data servers, you can easily ensure they have the proper network security by
adding the new servers to the ERP-DB-SERVERS-ASG.
You've migrated your existing app and database servers for your ERP system to Azure as
VMs. Now, to reduce your costs and administrative requirements, you're considering
using some Azure platform as a service (PaaS) services. Storage services will hold certain
large file assets, such as engineering diagrams. These engineering diagrams have
proprietary information in them, and must remain secure from unauthorized access.
These files must only be accessible from specific systems.
In this unit, you'll look at how to use virtual network service endpoints for securing
supported Azure services.
By default, Azure services are all designed for direct internet access. All Azure resources
have public IP addresses, including PaaS services, such as Azure SQL Database and
Azure Storage. Because these services are exposed to the internet, anyone can
potentially access your Azure services.
Service endpoints can connect certain PaaS services directly to your private address
space in Azure, so they act like they’re on the same virtual network. Use your private
address space to access the PaaS services directly. Adding service endpoints doesn't
remove the public endpoint. It simply provides a redirection of traffic.
Azure service endpoints are available for many services, such as:
Azure Storage
Azure SQL Database
Azure Cosmos DB
Azure Key Vault
Azure Service Bus
Azure Data Lake
For a service like SQL Database, which can't be accessed until you add IP addresses to its
firewall, service endpoints should still be considered. Using a service endpoint for SQL
Database restricts access to specific virtual networks, providing greater isolation and
reducing the attack surface.
How service endpoints work
To enable a service endpoint, you must do the following two things:
When you enable a service endpoint, you restrict the flow of traffic, and enable your
Azure VMs to access the service directly from your private address space. Devices
cannot access the service from a public network. On a deployed VM vNIC, if you look
at Effective routes, you'll notice the service endpoint as the Next Hop Type.
And here's an example route table after you've added two service endpoints to the
virtual network:
The following diagram shows how you can use a service endpoint and firewall
configuration to enable on-premises devices to access Azure Storage resources.
As the solution architect, you're planning to move sensitive engineering diagram files
into Azure Storage. The files must only be accessible from computers inside the
corporate network. You want to create a virtual network service endpoint for Azure
Storage to secure the connectivity to your storage accounts.
In this unit, you'll create a service endpoint, and use network rules to restrict access to
Azure Storage. You'll create a virtual network service endpoint for Azure Storage on
the Databases subnet. You'll then verify that your DataServer VM can access Azure
Storage. Lastly, you'll check that the AppServer VM, which is on a different subnet, can't
access storage.
Azure CLICopy
az network nsg rule create \
--resource-group $rg \
--nsg-name ERP-SERVERS-NSG \
--name Allow_Storage \
--priority 190 \
--direction Outbound \
--source-address-prefixes "VirtualNetwork" \
--source-port-ranges '*' \
--destination-address-prefixes "Storage" \
--destination-port-ranges '*' \
--access Allow \
--protocol '*' \
--description "Allow access to Azure Storage"
2. To create an outbound rule to deny all internet access, in the Cloud Shell,
run the following command.
Azure CLICopy
az network nsg rule create \
--resource-group $rg \
--nsg-name ERP-SERVERS-NSG \
--name Deny_Internet \
--priority 200 \
--direction Outbound \
--source-address-prefixes "VirtualNetwork" \
--source-port-ranges '*' \
--destination-address-prefixes "Internet" \
--destination-port-ranges '*' \
--access Deny \
--protocol '*' \
--description "Deny access to Internet."
BashCopy
STORAGEACCT=$(az storage account create \
--resource-group $rg \
--name engineeringdocs$RANDOM \
--sku Standard_LRS \
--query "name" | tr -d '"')
2. To store the primary key for your storage in a variable, in the Cloud Shell,
run the following command.
BashCopy
STORAGEKEY=$(az storage account keys list \
--resource-group $rg \
--account-name $STORAGEACCT \
--query "[0].value" | tr -d '"')
Azure CLICopy
az storage share create \
--account-name $STORAGEACCT \
--account-key $STORAGEKEY \
--name "erp-data-share"
Enable the service endpoint
You now need to configure the storage account to be accessible only from database
servers, by assigning the storage endpoint to the Databases subnet. You then add a
security rule to the storage account.
Azure CLICopy
az network vnet subnet update \
--vnet-name ERP-servers \
--resource-group $rg \
--name Databases \
--service-endpoints Microsoft.Storage
2. To deny all access to change the default action to Deny, in the Cloud Shell,
run the following command. After network access is denied, the storage
account is not accessible from any network.
Azure CLICopy
az storage account update \
--resource-group $rg \
--name $STORAGEACCT \
--default-action Deny
3. To restrict access to the storage account, in the Cloud Shell, run the
following command. By default, storage accounts are open to accept all
traffic. You want only traffic from the Databases subnet to be able to access
the storage.
Azure CLICopy
az storage account network-rule add \
--resource-group $rg \
--account-name $STORAGEACCT \
--vnet ERP-servers \
--subnet Databases
BashCopy
APPSERVERIP="$(az vm list-ip-addresses \
--resource-group $rg \
--name AppServer \
--query
"[].virtualMachine.network.publicIpAddresses[*].ipAddress" \
--output tsv)"
DATASERVERIP="$(az vm list-ip-addresses \
--resource-group $rg \
--name DataServer \
--query
"[].virtualMachine.network.publicIpAddresses[*].ipAddress" \
--output tsv)"
BashCopy
ssh -t azureuser@$APPSERVERIP \
"mkdir azureshare; \
sudo mount -t cifs //$STORAGEACCT.file.core.windows.net/erp-data-
share azureshare \
-o
vers=3.0,username=$STORAGEACCT,password=$STORAGEKEY,dir_mode=0777,file_mo
de=0777,sec=ntlmssp; findmnt \
-t cifs; exit; bash"
3. Enter the password you used when you created the VM.
4. The response should include a mount error message. This connection isn't
allowed, because there is no service endpoint for the storage account on
the Applications subnet.
5. To connect to your DataServer VM, and attempt to mount the Azure file
share, in the Cloud Shell, run the following command.
BashCopy
ssh -t azureuser@$DATASERVERIP \
"mkdir azureshare; \
sudo mount -t cifs //$STORAGEACCT.file.core.windows.net/erp-data-
share azureshare \
-o
vers=3.0,username=$STORAGEACCT,password=$STORAGEKEY,dir_mode=0777,file_mo
de=0777,sec=ntlmssp;findmnt \
-t cifs; exit; bash"
6. Enter the password you used when you created the VM.
7. The mount should be successful, and the response should include details of
the mount point. This is allowed because you created the service endpoint
for the storage account on the Databases subnet.
Summary
2 minutes
You've learned about isolating and securing network resources in Azure. You now know
how to use network security groups to secure virtual networks and VMs by creating
rules to control network traffic. You've also learned how to use network service
endpoints to control traffic to services, such as Azure Storage and Azure SQL Database.
You can now use network security groups and service endpoints to ensure that network
access to your Azure VMs and services is properly secured.
Learn more
For more information about network security groups, see the security groups overview.
For more information about virtual network service endpoints, see the virtual network
service endpoint overview.