TLS and PowerShell Web Requests

Apparently, TLS versions matter when working with PowerShell. It matters for PowerShell and Invoke-WebRequest commands. I have some schedule tasks that ran pulling small bits of information from them and sending email notifications on a daily basis. In the end, it’s a web scrape, find new info, send email. What I didn’t pay attention to was the methodology (under the hood) of how those connections were made. The connections were defaulting to TLS 1.0. This was working up for quite some time and then the emails stopped being sent.

After some testing and experimentation, I was able to narrow it down to TLS/SSL. See below:


That error is what I receive when I attempted to run the Invoke-WebRequest cmdlet by itself and not scheduled. Well. That was quite helpful. With some searching, I was able to find a solution… So… How do we determine what the local machine is using for these PowerShell Invoke-WebRequests?
[sourcecode language=”powershell”]
[Net.ServicePointManager]::SecurityProtocol
[/sourcecode]
When we run them on different OS’s we can see what the default available protocols are:

Windows Server 2016


Windows 10


Windows Server 2019


Notice how Windows Server 2019 and Window 10 have TLS12 available. Well, my task was schedule don a Windows 2016 server which only has SSL3 and TLS.,br.
Solution

There are two ways to resolve an issue with TLS1.2 and PowerShell scripts. First is to move the scripts to a Windows 10 or Windows 2019 server. This would ensure that TLS12 would be available to a PowerShell session. The other way is to add these lines to any script that will perform a web request:
[sourcecode language=”powershell”]
# Use TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
[/sourcecode]

Conclusion

So, what did we learn from this? Invoke-WebRequest’s rely in underlying protocols to make a connection. Sometimes these protocols are not as updated as we think they are with the OS we are running. Also, troubleshooting a scheduled task may mean taking lines of code out of a script and running them manually to see if it’s the task itself, the code itself, or just certain lines. In our case, we were relying on an older protocol that web sites were no longer responding to or allowing connections from. With a bit of research, a workable solution was found and we can move on to other issues.

Related Post