Optimize your Microsoft Teams traffic with QoS on a UniFi USG

At times like these, when everybody is working from home and the whole family uses the internet as well, the traffic requirements can be tough on your internet connection. When you are using real-time collaboration tools, such as Microsoft Teams, that rely on a good and stable internet connection for voice, video and screen sharing, parallel Netflix/Disney+/Hulu/Amazon Prime traffic can make the experience subpar for everybody involved.

Thankfully it’s possible to optimize your outgoing traffic based on what services are used.

In this example I show you how to setup traffic shaping on a UniFi USG or EdgeRouter using DSCP to optimize your Microsoft Teams meetings. This setup is only an example and you can easily adapt it to your router if it supports DSCP. If it does not, the Ubiquiti EdgeRouter X is about 50 bucks.

Continue reading

Certificate management with Azure Automation and Let’s Encrypt

The Let’s Encrypt project has had a lasting impact on the Internet landscape. Free SSL certificates for everyone can be created automatically and signed by Let’s Encrypt. Due to the broad acceptance by browser manufacturers and cross-signing, the certificates are valid almost everywhere.
However, an automated solution is absolutely necessary due to the short validity period of 90 days. Using PowerShell in Azure Automation, a workflow can be created that takes care of certificate renewal and secure central storage. This workflow is the optimal basis for distributing the certificates to the actual service.

The basis for such an automation solution is provided by AzAutomation-PoshACME

Continue reading

Is this ip address part of the Office 365 IP address range?

The analysis of firewall logs in Office 365 projects repeatedly raises the question: Is this blocked IP address part of the Office 365 address range?

Thanks to PowerShell and the information published by Microsoft, the answer is only a few lines of code away.

My script “Test-IsO365IpAddress.ps1” simply needs the IP address in question and optionally the TCP/UDP port. It retrieves the current list of address ranges from Microsoft and checks if the IP address is part of one of the IP networks. If this is the case, the script outputs all services that use this network.

If a port was also specified as part of the command the output will be filtered.

In addition to the service name (e.g. “Exchange Online”), the category (Optimize, Allow or Default), the required ports, the subnet and the somewhat obsolete “Required” category are also displayed.

Equipped with this data, the visit to the firewall team should be successful.

Many thanks also to Luben Kirov who allowed my to use his network functions to analysis the IP networks fast and reliable and Siva Padisetty whose function checkSubnet I used as inspiration for my own implementation.

SCHANNEL settings in Azure Windows Marketplace image changed

A couple of weeks ago I recognized new registry keys the SCHANNEL settings of the Windows 2016 Azure Marketplace image. Those setting are different from a manually deployed and updated Windows machine!

The newly created registry keys disable the following ciphers and protocols

  • Ciphers
    • RC4 128/128
    • RC4 40/128
    • RC4 56/128
  • Protocols
    • SSL 2.0 Client
    • SSL 3.0 Client/Server

First of all: The settings changed are regarding old ciphers and protocols that should be disabled in any secure environment after all! Some of them are even disabled without any registry keys starting Windows 2016 already.

Microsoft has published an article “TLS (Schannel SSP) changes in Windows 10 and Windows Server 2016” which describes the changes made in those OS version for release. This includes the deactivation of NULL, MD5, DES, and export ciphers.

Also it states that SSL 2.0 has been removed completely, and SSL 3.0 client and server is disabled by default. This makes the registry changes obsolete and only configures the defaults in place.Maybe Microsoft did this to help some poorly configured audit tool to show successful results or to better show the default config to the administrator.

In 2013 Microsoft published the “Security Advisory 2868725” which states the mentioned RC4 ciphers should be disabled. So after about 5 – 6 years later Microsoft has implemented this best practice for all newly deployed Azure VMs. Sadly it did not document the change anywhere.

Please be aware that if you deploy a Windows 2016 server from ISO and install the latest updates RC4 will still be active with the exception when using SCH_USE_STRONG_CRYPTO, as you can read here. You should disable

Query the Log Analytics Workspace for all Azure VM

Sometimes you just need to know to which Log Analytics Workspace (OMS for the old folks out there) a VM send it’s data to. Or even all of you Azure VMs an once.

With the following script this task is easy as pie. And thanks to RamblingCookieMonster and his PSExcel modul you can send the result straight to everybody who is fond of Excel.

AzureRM.Network 0.9 breaks Azure Automation Runbooks

If you are using Azure Automation and use the AzureRM.Network module in one of the versions from 0.9.0 to min. 0.10.0, you may experience problems running Azure Automation Runbooks.

If the runbooks used are more complex overall, this version may result in a high memory load. If more than 400 MB RAM are used, the runbook ends after three attempts in the status “Suspended”.

The runbook job was attempted 3 times, but it failed each time. Common reasons that runbook jobs fail can be found here:

A downgrade to version 6.8.0 is required. The easiest way, of course, is with PowerShell.

$ModuleName = "AzureRM.Network"
$MaxVersion = "6.8.0"

# Gather information
$AffectedAutomationAccounts = Get-AzureRmAutomationAccount | Get-AzureRmAutomationModule -Name AzureRM.Network | Where-Object {$_.Version -gt $MaxVersion }

# Review
$AffectedAutomationAccounts | Select-Object ResourceGroupName, AutomationAccountName, Name, Version

#region Redeploy
Write-Verbose "Generate RootTemplate.json in `"DevOpsgallerystorage.blob.core.windows.net`""
$uri = "https://www.PowerShellgallery.com/packages/$ModuleName/$MaxVersion/DeployItemToAzureAutomation?itemType=PSModule&requireLicenseAcceptance=False"
# This only generates the RootTemplate.json for the specified version. It simulates the Button "Deploy to Azure Automation" on the Gallery
Invoke-WebRequest $uri | Out-Null

# Download JSON 
$uri = "https://DevOpsgallerystorage.blob.core.windows.net/armtemplates/$ModuleName/$MaxVersion/RootTemplate.json"
$templateFileName = ".\RootTemplate.$ModuleName.$ModuleVersion.json"
Invoke-WebRequest -Uri $uri -OutFile $templateFileName | Out-Null

$AffectedAutomationAccounts | ForEach-Object {
    $AutomationAccountLocation = Get-AzureRmAutomationAccount -ResourceGroupName $_.ResourceGroupName -Name $_.AutomationAccountName | Select-Object -ExpandProperty Location
    $parameters = @{
        "Automation Account Name"            = $_.AutomationAccountName
        "Automation Account Location"        = "$AutomationAccountLocation"
        "New or existing Automation account" = "Existing"
    $params = @{
        "ResourceGroupName"       = $_.ResourceGroupName
        "TemplateFile"            = $templateFileName 
        "TemplateParameterObject" = $parameters
        "Mode"                    = 'Incremental'
    New-AzureRmResourceGroupDeployment @params