Troubleshooting Ubiquiti UniFi Access Points when Connecting to a Windows-based Controller

I’m a big fan of Ubiquiti’s UniFi access points. I think it’s generally a good idea to divorce the wireless capabilities from the router because you are more able to adapt when new wireless standards come out, and you don’t end up needing to replace a perfectly good 1Gbps router when that happens.

I love the level of insight and control of Ubiquiti’s devices (and the overall user interface – let’s gloss over the fact that it still relies on a Java plugin to run), but getting them to connect to a controller on Windows can be tricky. Here are some recommendations:

  • Assign your UniFi device a static IP address. Do the same to the machine where you install the controller software, if you can
  • Make sure you can ping your UniFi Access Point. If not, you have a problem with your network configuration
  • If you’re getting a disconnections, try and SSH directly in to the device
    • Windows now offers an optional install of SSH as an add on module to Windows, but I wasn’t able to connect to my UniFi because I received the following message:

      Unable to negotiate with 192.168.xxx.xxx port 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,kexguess2@matt.ucc.asn.au

      This means that the SSH installed via Windows couldn’t be used since it didn’t have one of those three key exchange methods available (note that after upgrading my UniFi firmware, the message changed, as it appears they are using more secure key exchanges now: ssh-rsa,ssh-dss).

    • Since I couldn’t use SSH via Powershell, I downloaded good old PuTTY and connected to my UniFi access point that way
      • Run “info” once connected via PuTTY to look for clues regarding your disconnected controller. The “Status” line shows whether or not the device is currently connected. If you see status Unknown[11] (http://192.168.xxx.xxx), then you know there is an issue connecting to your controller. At least this message tells you whether or not your device is trying to communicate with the IP address where your controller resides
        • Run “set-inform http://192.168.xxx.xxx:8080/inform” if your controller isn’t the IP displayed in the info box
      • If you SSH’d in from a machine other than your controller, run a ping command to your controller to make sure that the access point can communicate with your controller
  • Check your Windows Firewall rules
    • On one controller, the connection to my access point was restored almost immediately as soon as I disabled Windows Firewall. Check that the rules created by the installation of the UniFi Controller software apply to all network types (public, private, domain) that you use to communicate with the outside world
      • In my case, the problem was Java was being blocked from private network connections. Once I added private networks to the “Allow” rules, the connection restored almost immediately
    • Check out this post if you’re having trouble identifying what program is blocking your connection: https://superuser.com/questions/1130078/how-to-tell-which-windows-firewall-rule-is-blocking-traffic

 

How to Fix: Inaccessible Boot Device Error Caused by January/February 2018 Windows Update(s)

“Fix” is a bit of a loose term for this solution because it will restore your computer to a workable state without losing any files or applications, but you have to disable Windows Updates so the affected update doesn’t continue to be downloaded over and over again.

Update: There is now a patch out to fix this: https://support.microsoft.com/en-us/help/4090913/march5-2018kb4090913osbuild16299-251. Note that when I checked for updates using Windows Update, it downloaded the bad patch again, so I uninstalled that and downloaded the patch linked from the article above (Actual link to download the update is http://www.catalog.update.microsoft.com/Search.aspx?q=KB4090913).

If you encounter the blue screen of death with the message “Inaccessible Boot Device” and a frowny face, you’ve probably just updated Windows and the computer attempted to reboot.

I will not take any credit for this fix, as I spent several days looking for ways to resolve this problem when it affected machines in my office. A huge thanks goes to reddit user zosan for providing this excellent, step-by-step guide:

How-To: Fix "INACCESSIBLE_BOOT_DEVICE" caused by Win10 Spectre builds 16299.125 or 16299.192. from pcgaming

Hopefully Microsoft resolves this sometime soon so updates don’t have to be disabled too long.

 

Powershell Script: Removing AutoMapping for Shared or Previously Delegated Office365/Exchange Mailbox

In an earlier post, I wrote about how to setup auto-forwarding for a user’s email if they are on an extended leave from the office. One of the interesting problems that has arisen once that employee returned was that their email folder was still showing up in my list of mailboxes in Outlook 2016, even after the forward was disabled and delegate access was confirmed as being removed/never setup in the first place.

Resolving the issue involves a little bit of Powershell, and while the script code isn’t terribly difficult, I did have to piece it together from a couple of different sources and deal with the fact that I had MFA (multi-factor authentication) enabled on my account.

In the end, I disabled MFA briefly on my account while I executed the script below. I was unsuccessful being able to connect to Exchange Online via Powershell with MFA and gave up because I didn’t think it was worth my time to troubleshoot for something that was fairly insignificant for my use case.

Below is the script I used:

#Must disable MFA in order for this to work. Otherwise, there are supposedly ways to get MFA to work with this script, but I wasn't successful with them
$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session
Remove-MailboxPermission -Identity <MailboxToRemove> -User <UserWhoWantsMailboxRemoved> -AccessRights FullAccess
Add-MailboxPermission -Identity <MailboxToRemove> -User <UserWhoWantsMailboxRemoved> -AccessRights FullAccess -AutoMapping:$false
Remove-PSSession $Session

Resources:

Excel Tip – Finding and Breaking External References in Documents

Every once in a while I come across a problem where I open an Excel document and am notified of external references, even though I’m certain the document doesn’t or shouldn’t contain any external references. A common message is:

This workbook contains links to one or more external sources that could be unsafe

In order to find these references in Excel 2016, click the “Data” tab at the top. Then, under the “Queries and Connections” section, choose “Edit Links.” From there, a dialog will pop up showing any links and allowing you to check the status of the links. If the links are truly broken, checking the status should confirm that.

To break the connection, you can simply choose “break” with the appropriate connection selected. Any cell where a value was dependent on the connection was be converted to the current value, so you shouldn’t lose data by breaking the connection – it will simply no longer update along with the connected data source.

Resources:

 

Useful Gmail and Outlook Filters

Every once in awhile I get the urge to clean up emails and get rid of a bunch of stuff I just don’t need. On one hand, it’s nice to be able to reference old emails, but on the other you risk exposing your personal information to potential evil-doers (hackers or even mining/advertiser information if you’re using a freemail account like Gmail). Do you really need those emails from 8 years ago? Probably not.

Anyway, regardless of the motivation, here are some useful filters that I use:

Gmail

Gmail filters listed below are all performed by typing the unbolded text from the bullets below into your search box. You can combine them in any way you like – just put a space between each filter

  • All unread email: label:unread
  • All emails sent or received prior to a specific date: before:2018/1/1
  • All emails without a label: -has:userlabels
  • All emails not in the inbox, sent, drafts, or chat folders: -in:inbox -in:drafts -in:sent -in:chat
  • All emails with attachments: has:attachment
  • All emails at least as large as a certain size (in bytes – example is about 5MB): size:5242880

Outlook

Outlook is a little bit different as it offers some pretty powerful features such as search folders, but filtering can still be performed by using the search box for most items

  • All unread email (multiple options):
    • Choose the folder you want
      • On the right side of the mail pane, there is a dropdown that defaults to “All.” You can select “Unread” from the dropdown to see only unread
    • Create a search folder
      • On the left pane (of the default view) that shows your email folders, scroll down to the bottom of the Data File/Account where you want to view unread messages
      • Look for a folder called “Search Folders”
        • Right click on “Search Folders” and choose “New Search Folder”
        • Select “Unread Mail” from the list in the popup window that opens and hit OK
    • Drag the new “Unread Mail” search folder into your favorites (Optional)
  • All emails received prior to a specific date: received:<2018/1/1
  • All emails sent prior to a specific date: sent:<2018/1/1
  • All emails with attachments: hasattachment:yes (or has:attachment)
  • All emails with an attachment matching a specific file extension: ext:jpg
  • All emails at least as large as a certain size (in bytes – example is about 5MB): messagesize:>=5 MB

Resources:

Converting Large Integers Stored as Floats to NVarChars in SQL (without Scientific Notation)

Converting SQL data types can be a bit finicky, and, at least for this guy, converting a stored, large integer value to a string is not intuitive at all.

I mostly run into this when I import values from some data source like an Excel sheet that stores values like tracking numbers as a float. From there, I usually write a cursor to update tables in my system with these values, and when those tables use a column type of varchar or nvarchar, you have to convert from float type to varchar

One would think that using CAST(varchar(50), TrackingNumber) would do the trick, but when this cast is made, the value is stored in scientific notation.

The real trick is to first convert the int value to a bigint and THEN convert it to a varchar, as shown below:

CONVERT(varchar(50), CONVERT(bigint, TrackingNumber))

Preloading Websites on IIS 7.5

Earlier this year, I built a .Net Core Web Application and deployed it on IIS 7.5. I noticed right away that it was extremely slow on initial load. This was confusing because I tested deployment to Azure and the performance was great. I struggled to figure out why it loaded so slowly but all of my .Net Framework sites ran quickly.

I struggled to find an answer for a long time, but while reading through documentation while setting up another application I came across this bit of information:

http://cdn.rssbus.com/help/ARC/mft/pg_serveriis7dot5.htm

Preloading Applications

You can make use of the preloading feature to have applications running before users connect. In your ApplicationHost.config, add the preloadEnabled attribute to the <application> element associated with the application. The application node is a child element of the sites node:

<sites>
<site name="Default Web Site" id="1">
  <application path="/rssbus" applicationPool="DefaultAppPool"  preloadEnabled="true">
  
  ...

When PreloadEnabled is set to true, IIS will simulate a user request to the default page of the website or virtual directory so that the application initializes.

While it technically is a bit of a workaround since it doesn’t solve the root problem I experience with preloading, it has kept my application loading quickly since I enabled it.

Enabling TLS 1.2 on IIS 7.5 and Discovering a Great Tool (IIS Crypto) Along the Way

TLDR; summary of the fastest way to enable TLS 1.2 on IIS 7.5:

  • Download IIS Crypto at https://www.nartac.com/Products/IISCrypto/
  • Run the executable on your server
  • On the user interface, click the “Best Practices” button (located at bottom left)
  • Click “Apply” (located at bottom right)
  • Reboot Server

The full details:

Today I was contacted by a third-party company that exchanges data with mine and they informed me that they were requiring TLS 1.2 connections as of the new year. Reviewing information about my server’s crypto configuration, I found that, indeed, TLS 1.1 and TLS 1.2 were not enabled.

In setting out to resolve the problem, I ran across a couple of posts that talked about updating registry keys and doing some other messy stuff. And then, I found this post on ServerFault about an awesome tool called IIS Crypto.

From the IIS Crypto website:

IIS Crypto is a free tool that gives administrators the ability to enable or disable protocols, ciphers, hashes and key exchange algorithms on Windows Server 2008, 2012 and 2016. It also lets you reorder SSL/TLS cipher suites offered by IIS, implement best practices with a single click, create custom templates and test your website

Not only is the tool free, it doesn’t even install anything on your machine.

After downloading and running, I looked over the list of available protocols, ciphers, etc. They provide a “Best Practices” button which enables only the protocols, ciphers, etc. that should be enabled using, well, current best practices. This is another awesome feature because the list of everything to review is fairly extensive and not having to do the research myself on these is a huge time saver.

On the program’s menu is a “Site Scanner” tool that will open up a browser and analyze your site. You can use this without running the application. The URL is:

https://www.ssllabs.com/ssltest/analyze.html?d=<your site>&hideResults=on (where <yoursite> is the website you want to analyze)

The analyzer checks your certificate(s), available protocols, and cipher suites, performs handshake simulations with a bevy of operating system / user-agent combinations (well over 50), and analyzes against various attacks. When I first ran the test, the results weren’t so great – there were a number of problems related to my crypto settings.

After reviewing the analyzer, I applied the “Best Practices” settings and restarted the server. Once the server booted back up everything was working and I passed the scanner with flying colors.

For reference, I was working with IIS 7.5 running on Windows Server 2008 R2.

Migrating Azure Resources from one Subscription to Another

I love Azure. It’s a great platform and I’m very happy with the continuing evolution of products and services offered. If you ever have to move resources to a different subscription, there are a lot of little things you have to think about, because sometimes settings are tied to a particular subscription or resource group (which is tied to a subscription).

Some of the non-profit organizations I’ve built applications for have taken advantage of Microsoft’s donation offerings, where they receive Microsoft products and services at a heavily discounted rate. However, these subscriptions often come with a time limit, after which they must be purchased again. When that happens, a new Azure subscription is created and you have to reassign any resources that are under the old subscription to the new one.

The easy part is actually reassigning the subscriptions. There are two ways I see to do this:

  1. Create a new resource group, assigning it to the new subscription ID, and then assign all of the resources you would like to that group
  2. Move the existing resource group to a new subscription. This works better in cases where you have resource groups well-defined
    1. Moving a resource group consists of choosing the resource group in the Azure portal and clicking the “Move,” as shown below:

The trickier part is figuring out any resources that may have been tied to the old resource group name or subscription. Here are a couple I have found:

  • SendGrid (and likely other external/third party applications that can’t use Azure credits) cannot be migrated from one subscription to another. A new API key must be generated for the application(s) of use.
  • Lets Encrypt certificates generated using the extension http://www.siteextensions.net/packages/letsencrypt (detailed in the post http://gagetrader.info/2016/09/27/lets-encrypt-azure-win/) have a couple of keys that are tied to the subscription Id and the resource group. The ones that need to be edited are (to view keys select the resource where the web job was registered from Azure portal -> Application Settings -> Keys section):
    • letsencrypt:SubscriptionId – 7dbf7306-25b3-4e5a-a85a-44017efb9cc5
    • letsencrypt:ResourceGroupName: (New Resource Group Name, if applicable)

    After you have completed this step, you will find that the web job fails with the following message the next time it runs:

    Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: Functions.RenewCertificate —> Microsoft.Rest.Azure.CloudException: The client ‘xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx’ with object id ‘xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx’ does not have authorization to perform action ‘Microsoft.Web/sites/config/list/action’ over scope ‘/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/MyResourceGroup/providers/Microsoft.Web/sites/MySite/config/publishingcredentials’. at Microsoft.Azure.Management.WebSites.WebAppsOperations.

    This long message basically means that we need to assign the let’s encrypt principal created during the configuration of the extension with the Contributor role. This is fairly straightforward:

    1. Make sure Azure Powershell is installed on your machine (Open the Microsoft Web Platform Installer and find Microsoft Azure Powershell on the list if you don’t have it)
    2. Open Powershell as an administrator and sign in using the command:

      Login-AzureRmAccount

    3. Make sure your new Azure Subscription Id is selected. If not, run the following command:

      Select-AzureRmSubscription -SubscriptionId Your-Subscription-Id-Guid-Here

    4. Run the following command to assign the correct permissions to your new subscription Id:

      New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName Your-Service-Principal-Name-From-Extension-Setup

    Once that has been completed, the job should run again and be successful. Now your SSL certificates will continue to auto-renew.

Office 365 – Set Out of Office Response and Forward all User Emails as Exchange Admin

I recently had a member of my organization go on maternity leave, and, because of the way that babies work, she wasn’t able to set an out of office response or a forward.

Thankfully, with Exchange Admin Center, it’s pretty easy to do both.

Setting a User’s Out of Office Response

The first thing is to essentially impersonate a user as the Office Admin:

  1. Navigate to Exchange Admin Center on office.com (you have to be an Administrator to do this, obviously)
  2. Click your Name/Icon in the very upper right-hand corner and choose “Another user…”
  3. Choose the user in your organization that you need to update from the popup window that follows
  4. On the right sidebar of the window that opens for that user, you should see “shortcuts to other things you can do”
    1. In that list is “Set up an automatic reply message”

That’s it. Once you’ve chosen to Set up an automatic reply message, you can format the message however you want (one for internal users and one for external users)

Forwarding a User’s emails

  1. Log into Office 365 Admin Center
  2. Choose Users -> Active Users
  3. Find the User whose email you want to forward and click their name
  4. In the sidebar that opens, expand “Mail Settings” and click “Edit” next to Email Forwarding
  5. Flip forwarding to On and enter the email address where the messages forward
    1. You can optionally choose to keep a copy of the email in the inbox for the original user

Pretty straightforward, but not something I do all that frequently, so I know I’ll forget by the next time I have to do it 🙂