A hidden TLS fallback can silently break external resources in SSRS. Enforcing the right protocol setup is key to restoring functionality and ensuring secure, stable communication
We were migrating reports to SQL Server Reporting Services 2022 when I noticed that external images weren’t loading, while the same reports worked fine in Power BI Report Server. There were no error messages, just broken placeholders, so we suspected an issue with how SSRS 2022 handled secure connections.
We set up two test environments and used Wireshark to compare network traffic. The clue came from a TLS error: “tlsv1 record layer alert (level fatal, description protocol version).” SSRS 2022 was trying to use outdated TLS 1.0, which the image server had already deprecated. Power BI Report Server, however, used TLS 1.2 and connected without issues.
Now that we understood the root cause, we knew what to do: force SSRS 2022 to use TLS 1.2 for outbound connections. Here’s a detailed step-by-step guide of what we did to fix it, in case you ever run into something similar. Let me walk you through how we applied the fix.
1. SSRS Security Prep: Patches & Certificates
Before installing any patches, it’s important to first verify that the SQL Server updates for TLS 1.2 support are already in place. Once confirmed, the next step is to install the latest .NET Framework patch, which depends on your operating system version. You can find the appropriate installer in the following knowledge base article:
https://support.microsoft.com/en-us/kb/3154520
If the patch is already installed, re-running the installer will simply show a message indicating that no changes are needed.
As an additional security measure, we also made sure to disable HTTP access in the Reporting Services Configuration Manager and force all access through HTTPS (port 443). While this didn’t directly solve the TLS negotiation issue with external image hosting, it’s a best practice to avoid unsecured connections to the SSRS web portal.
If you’re testing in a lab environment, using a self-signed certificate is usually enough to configure HTTPS and test secure access to SSRS.
In production, you’ll typically have a certificate issued by a trusted certificate authority already installed.
In both cases, make sure the certificate is properly placed under the Trusted Root Certification Authorities store on the server. This ensures that SSRS can use it without any trust-related errors when accessed over HTTPS.
2. Registry Changes to Enforce TLS 1.2
2a. Modify SCHANNEL Protocol Settings
Even after installing the required patches, Windows may still default to using TLS 1.0 unless explicitly configured otherwise. In our case, SSRS 2022 was capable of using TLS 1.2, but continued initiating connections over TLS 1.0 by default.
To force the use of only TLS 1.2, we modified the Windows Registry at:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols
We explicitly disabled SSL 2.0, SSL 3.0, and TLS 1.0, and enabled only TLS 1.2, using the following settings:
[…SSL 2.0\Client]
“DisabledByDefault”=dword:00000001
“Enabled”=dword:00000000
[…SSL 3.0\Client]
“DisabledByDefault”=dword:00000001
“Enabled”=dword:00000000
[…TLS 1.0\Client]
“DisabledByDefault”=dword:00000001
“Enabled”=dword:00000000
[…TLS 1.2\Client]
“DisabledByDefault”=dword:00000000
“Enabled”=dword:00000001
We repeated the same for the Server sections under each protocol.
Important: Before making these changes, we exported the existing registry keys as a backup.
While not strictly required (some applications hardcoded for TLS 1.2 will still connect successfully), this step is essential if your goal is to fully disable legacy protocols and enforce TLS 1.2 across all SSRS communications.
2b. Configure .NET Framework to Use System Default TLS
In addition to the SCHANNEL changes, we made sure the .NET Framework itself was configured to default to secure protocols. This is especially important for components still running on older framework versions like .NET 2.0/3.5.
We added the following registry keys:
For 32-bit applications:
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v2.0.50727]
“SystemDefaultTlsVersions”=dword:00000001
For 64-bit applications:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727]
“SystemDefaultTlsVersions”=dword:00000001
These keys tell the .NET Framework to respect the operating system’s default TLS protocol, which in this case is TLS 1.2.
2c. Reboot the Server
Once all registry changes were complete, we restarted the server to ensure they were fully applied. Without a reboot, the SCHANNEL and .NET settings won’t take effect.
3. Ensure TLS 1.2 Support Across All Connected Systems
At this point, Server 2 is fully configured to communicate securely over TLS 1.2. However, to avoid inconsistencies or fallback behavior, it’s critical to verify that the other systems involved like Server 3 and Server 1, are also properly aligned with TLS 1.2 requirements.
3a. SQL Server Configuration (Server 3)
While SQL Server typically acts as a passive endpoint (receiving requests from SSRS), it still needs to be configured to accept connections over TLS 1.2 only, especially if older protocols are still enabled by default.
To do this, we replicated the exact same SCHANNEL registry changes described in Step 2a (Modify SCHANNEL Protocol Settings) on Server 3. That means disabling SSL 2.0, SSL 3.0, and TLS 1.0, and explicitly enabling TLS 1.2.
We also ensured that the SQL Server instance had the required TLS 1.2 compatibility update installed.
After applying the registry and patch updates, we restarted the server to apply the changes. To confirm that communication between SSRS and SQL Server was occurring over TLS 1.2, we used Fiddler to inspect the traffic.
3b. Application-Level Configuration (Server 1)
If your environment includes custom applications that interact with SSRS, such as calling its web service or embedding reports, you also need to ensure those apps are TLS 1.2-compliant.
This is especially relevant when these applications are hosted on a separate machine.
Here’s what we did on the application server:
1. Windows Patch
We installed the .NET Framework patch (KB3154520) to ensure the OS and .NET runtime supported TLS 1.2: https://support.microsoft.com/en-us/kb/3154520
2. Registry Changes
We applied the same protocol-level registry changes (as in Step 2a), disabling legacy protocols and enabling TLS 1.2.
3. Application Code Changes
If the application explicitly manages its TLS protocol, we updated it to force TLS 1.2. For example:
Net.ServicePointManager.SecurityProtocol = SecurityProtocolTypeExtensions.Tls12;
Or if using SslStream.AuthenticateAsClient(…), we passed SslProtocols.Tls12.
We included the following helper classes in our codebase:
SecurityProtocolTypeExtensions.cs
namespace System.Net
{
using System.Security.Authentication;
public static class SecurityProtocolTypeExtensions
{
public const SecurityProtocolType Tls12 = (SecurityProtocolType)SslProtocolsExtensions.Tls12;
public const SecurityProtocolType Tls11 = (SecurityProtocolType)SslProtocolsExtensions.Tls11;
public const SecurityProtocolType SystemDefault = (SecurityProtocolType)0;
}
}
SslProtocolsExtensions.cs
namespace System.Security.Authentication
{
public static class SslProtocolsExtensions
{
public const SslProtocols Tls12 = (SslProtocols)0x00000C00;
public const SslProtocols Tls11 = (SslProtocols)0x00000300;
}
}
Once implemented, the application began initiating all outbound connections over TLS 1.2.
As with the other servers, we confirmed this using Fiddler, and performed a server reboot to apply all registry changes correctly.