Keeping your NSG updated

If you are working from different places over time, keeping the Network Security Group (NSG) updated will be a task that you quickly want to automate. I have an inbound rule on my NSGs that I always call “allow-all-from-temp-ip” that controls access to my resources which I constantly change when I’m out travelling.

In this post, I will show you how to write a small powershell script to update the NSG rule. In the github sources you will also find a bash script that does the same on Mac/Linux.

Network Security Groups

If you don’t know what an NSG is in Azure, you can think of it as a list of Allow/Deny rules of what network traffic can flow inbound and outbound. You can think of it as a firewall protecting the resources you can put in an Azure Virtual Network.

An NSG can be applied to a subnet in an Azure Virtual Network or directly onto a VMs NIC (network interface card). If you have them on both, the network traffic must be allowed by both NSGs.

A normal configuration of mine when working with an Azure VM is like below. I have two Inbound security rules, where the first is called “allow-all-from-home” and the second “allow-all-from-temp-ip”. Both rules allow all inbound traffic from one single ip address, which means I don’t have to think about ports being blocked when I test stuff.

Public ip address

Whenever I come to a new location, I modify the “allow-all-from-temp-ip” rule to reflect the current public ip address I’m using. Going to webpage http://ipinfo.io you can find your ip address. If you want to manually update your NSG rules, grab the ip address from ipinfo and use the Azure portal to update your inbound rule(s).

But if you want to automate, ipinfo.io supports REST API calls which means you can call the API and get the result back as a JSON structure. In powershell, this might look like this:

$acct = Get-AzureRmContext
$user = $acct.Account.Id

$resp = Invoke-RestMethod "http://ipinfo.io"
Write-Host "Current ip addr $($resp.ip) via provider $($resp.org)"

$sourceAddrPrefix = "$($resp.ip)/32"
$description = "allow all inbound from temp ip $($resp.ip), provider $($resp.org). Set by $user at $(Get-Date -format 's')"

The NSG rules work with something known as CIDR notation when it comes to specifying ip addresses. The /32 means 32 bits of the ip address are the mask bits and for an IPv4 address this means all the bits so using /32 basically means 1 ip address. You can play with CIDR online calculaters, like http://www.subnet-calculator.com/cidr.php, where you can see that 10.4.3.0/24 gives you 10.4.3.0 – 10.4.3.255 since 24 mask bits means 255.255.255.0, etc.

The call to Get-AzureRmAccount is there just so I can add it to the description which user I was running as when I made the change.

Updating the NSG

Updating the NSG is quite simple. It is just a matter of retrieving the NSG, finding the specific NSG inbound rule and updating it. If the rule isn’t already defined we need to add it with the next available priority.

$rule = ($nsg | Get-AzureRmNetworkSecurityRuleConfig -Name $SecurityRuleName -ErrorAction SilentlyContinue)
if ($rule -eq $null) {
 $prio = [int]($nsg.SecurityRules[$nsg.SecurityRules.Count-1].Priority)
 $prio += 10
 Write-Host "Adding $SecurityRuleName rule to allow $sourceAddrPrefix with priority $prio"
 $ret = ($nsg | Add-AzureRmNetworkSecurityRuleConfig -Name $SecurityRuleName `
                -SourceAddressPrefix $sourceAddrPrefix  -SourcePortRange "*" `
                -DestinationAddressPrefix "*" -DestinationPortRange "*" `
                -Protocol "*" -Direction "Inbound" -Access "Allow" `
                -Priority $prio -Description $description)
} else {
 Write-Host "Updating $SecurityRuleName rule to allow $sourceAddrPrefix"
 $ret = ($nsg | Set-AzureRmNetworkSecurityRuleConfig -Name $SecurityRuleName `
                -SourceAddressPrefix $sourceAddrPrefix  -SourcePortRange "*" `
                -DestinationAddressPrefix "*" -DestinationPortRange "*" `
                -Protocol "*" -Direction "Inbound" -Access "Allow" `
                -Priority $rule.Priority -Description $description)
}
Write-Host "Saving to Azure..."
$ret = ($nsg | Set-AzureRmNetworkSecurityGroup)

Running the script

So whenever I enter a new location, I just run the script to update the NSG rule of whatever work I was doing. It is especially usefull if I know I’m going to be showing something on a projector to a group of people, because troubleshooting network ports being blocked is a sure thing to loose time and interrest of the people around you.

A word of warning

My script opens ALL ports for TCP/UDP from a single ip address, which is basically disabling the firewall for it. I do it just during dev/test so I can work productively. In a real world case, where you do hybrid cloud networking, you should of course specify a list of known ports and source addresses instead of making it wide open.

Sources

The powershell script can be found on github
https://github.com/cljung/azps/blob/master/change-nsg-ipaddr.ps1

Bash script that does the same
https://github.com/cljung/azps/blob/master/change-nsg-ipaddr.sh