Secure your Synology Diskstation local IP via Self-Signed SSL

Since Google released Chrome version 56 (January 2017) the warnings against HTTP only sites that collect passwords and personal details as well as HTTPS sites with untrusted SSL certificates has been stepped up; and this can only be a good thing for the web.

It does mean that now accessing your Synology Diskstation over the local network will throw up a selection of security warnings.

There are 3 choices here for the LAN user:

  1. Ignore the warnings and click through
  2. Register an Internet FQDN to your local IP
  3. Create a self-signed SSL and root CA to sign the SSL

I had been at choice 1, but it was getting bothersome.

Choice 2 is the correct (harder) way to do things but has some financial costs.  You need a public domain name to so you can create a fully qualified domain name (FQDN) for your Diskstation (something like https://ds.mydomain.com). Next you can generate a valid Certificate Signing Request (CSR) for the FQDN and configure DNS to point back to your local LAN and setup whatever routing is required.  This is best if you need to secure a local LAN asset where you do not control all devices accessing the Disktation.

No, you cannot buy a public SSL from a 3rd party Certificate Authority (CA) for an internal IP as the practice was banned in 2016 by the Certificate Authorities Browser Forum to reduce the threat of man-in-the-middle (MITM) attacks.

Choice 3 is what this post is about, but it has some foibles.

  • Your Diskstation must have a fixed IP address on your LAN
  • You must be able to add or assign certificates to devices you want to approve your SSL

In DSM 6.0 -> Control Panel -> Security -> Certificate

Click “Add” to start the process and choose “Create self-signed certificate”

First you create a Certificate Authority (CA) which is the master key that will sign the site usable SSL.

Create root CA SSL

Second you need to supply the details for the certificate itself.

Create self signed SSL

Creating the self-signed certificate from the Synology control panel has a key step that you must complete or the certificate will be invalid.  The Subject Alternative Name (SAN) in the second step must contain BOTH the name of the Disktation on your network (“myDSname”) and its local fixed IP (192.168.1.10)

When I first tried this I gave the SSL certificate common name (CN) field the local fixed IP of my Diskstation and in the SAN field I put ONLY its network name.

When accessing my Diskstation via https://myDSname:5001 all was well, but accessing my https://192.168.1.10 was not recognising the SSL certificate.  After some head scratching (because Chrome now hides the SSL detail under the Security menu in Developer tools) the error “SSL_ERROR_BAD_CERT_DOMAIN” made me suspect the SAN name also needed to include my local IP?

Once your certificate has been generated click “Configure” in DSM to set the new certificate to be the default for the system (The internal web server will restart) so that when you attempt to load the Diskstation site the correct SSL certificate will be presented to your browser.

Now you need to export the newly generated certificates from your Diskstation and import the root CA [and the SSL certificate] into your local machines certificate store so that they will be recognised as valid.

This is the contentious issue; passing a self-signed certificate off as being from a trusted CA!

It comes down to who you are willing to trust?  In your own house on your local LAN, yes your family are likely to trust you (as the root CA) but a guest to your house might not be willing to, hence the need for 3rd party root CA providers to usually sign certificates.

Once setup in your local certificate store (Trusted Root Certificate Authorities in Windows) browsing to either the Diskstation name or IP you specified in the SAN will show as Secure in Google Chrome and all other good web browsers.

Posted in Security, Synology | Leave a comment

Script to export SQL Server Blob data with ADO.Net via PowerShell

Below is a shamelessly copied script from Olaf Helper over at TechNet.

If you have a fully configured FileStream SQL Server, Database and Table Column with the FileStream attribute then the following script is much better and avoids possible bugs with buffers and byte reading.  Check that out here on TechNet

I have reproduced here almost entirely for my own purpose of not having to search endlessly for it when I need to grab some records from older SQL database columns that are holding blob data in a varbinary(MAX).

# Configuration data 
$Server = ".";             # SQL Server Instance, local. 
$Database = "DBname"; # Database 
$Dest = "F:\Export\";     # Path to export to. 
$bufferSize = 8192;         # Stream buffer size in bytes.

# Select-Statement for name & blob 
$Sql = "
SELECT [Nom], [Data]
FROM Table
WHERE Value = 1
"; 
 
# Open ADO.NET Connection 
$con = New-Object Data.SqlClient.SqlConnection; 
$con.ConnectionString = "Data Source=$Server;" + 
 "Integrated Security=True;" + 
 "Initial Catalog=$Database"; 
$con.Open(); 
 
# New Command and Reader 
$cmd = New-Object Data.SqlClient.SqlCommand $Sql, $con; 
$cmd.CommandTimeout = 120 
$rd = $cmd.ExecuteReader(); 
 
# Create a byte array for the stream. 
$out = [array]::CreateInstance('Byte', $bufferSize) 
 
# Looping through records 
While ($rd.Read()) 
{ 
 try 
  { 
   Write-Output ("Exporting: {0}" -f $rd.GetString(0)); 
   # New BinaryWriter 
   $fs = New-Object System.IO.FileStream ($Dest + $rd.GetString(0)), Create, Write; 
   $bw = New-Object System.IO.BinaryWriter $fs; 
 
   $start = 0; 
   # Read first byte stream 
   $received = $rd.GetBytes(1, $start, $out, 0, $bufferSize - 1); 
   While ($received -gt 0) 
   { 
    $bw.Write($out, 0,      $received); 
    $bw.Flush(); 
    $start += $received; 
    # Read next byte stream 
    $received = $rd.GetBytes(1, $start, $out, 0, $bufferSize - 1); 
   } 
   $bw.Close(); 
   $fs.Close(); 
  } 
  catch 
  { 
   Write-Output ($_.Exception.Message) 
  } 
  finally 
  { 
   $fs.Dispose();         
  }
 }  
   
# Closing & Disposing remaining objects 
$rd.Close(); 
$cmd.Dispose(); 
$con.Close(); 
 
Write-Output ("Finished");
Read-Host -Prompt "Press Enter to exit"

All credit to the original authors and contributors

Posted in .Net, Microsoft, PowerShell, SQL Server | Leave a comment