Using a Custom WinRM Port with Ansible Causes 'SSLError'

Using a Custom WinRM Port with Ansible Causes 'SSLError'
Image is courtesy of Anita S.

Using custom WinRM ports when configuring Windows computers with Ansible can cause problems if you don’t know the rules for configuring the ports or just assume you do.

The Scenario.

I have two Windows computers behind a NAT gateway which isn’t much of an issue. I need to connect to them with Ansible using WinRM but I can use port forwarding to make that work.

The Ansible inventory for computer1 is in host_vars/computer1.yml::

---
ansible_host: 'computer1.mynetwork.local'
ansible_winrm_server_cert_validation: 'ignore'
ansible_connection: 'winrm'
ansible_port: '5985'
ansible_winrm_transport: 'ntlm'

I’ve forwarded the port 5985 through the firewall to the same 5985 port on computer1.

For computer2 I have the Ansible inventory host_vars/computer2.yml as:

---
ansible_host: 'computer2.mynetwork.local'
ansible_winrm_server_cert_validation: 'ignore'
ansible_connection: 'winrm'
ansible_port: '55985'
ansible_winrm_transport: 'ntlm'

This time I’ve forwarded port 55985 through the firewall to port 5985 on computer2.

Everything looks good. Now to test it.

The Error.

When I try to connect to computer1, everything works as expected. When I try to connect to computer 2, it doesn’t go so well. I get an SSL Error in Ansible Tower:

{
    "unreachable": true,
    "msg": "ntlm: HTTPSConnectionPool(host='computer2.mynetwork.local', port=55985): Max retries exceeded with url: /wsman (Caused by SSLError(SSLError(\"bad handshake: Error([('SSL routines', 'ssl3_get_record', 'wrong version number')],)\",),))",
    "changed": false
}

I thought this was a transient error so I waited a few minutes and tried again but got exactly the same error. Cut scene to me trying this over and over with no change to the error.

Trying an internet search for the error didn’t turn up much. One post suggested running the ConfigureRemotingForAnsible.ps1 with the -ForceNewSSLCert parameter as it was suggested the certificate had expired. Tried that and it didn’t work.

Don’t guess.

So after a frustrating search it actually dawned on me. The error I’m receiving is an SSL error but I’m not using WinRM over HTTPS. I’m using it over port 5985 which is HTTP. But Ansible is using port 55985 to connect and I bet it doesn’t know what protocol to use. Something about a WinRM scheme was ringing a bell in my head.

Read the docs.

According to the docs, Ansible will by default use https unless the ansible_port is 5985:

ansible_winrm_scheme: Specify the connection scheme (http or https) to use for the WinRM connection. Ansible uses https by default unless ansible_port is 5985

Once the inventory for computer2 is updated, the connection works first time:

---
ansible_host: 'computer2.mynetwork.local'
ansible_winrm_server_cert_validation: 'ignore'
ansible_connection: 'winrm'
ansible_port: '55985'
ansible_winrm_transport: 'ntlm'
ansible_winrm_scheme: 'http'

To be fair this was an ID10T error and not so much an Ansible one. Ansible can only take a guess at what scheme it should use based on the port unless you tell it otherwise. Which I think is reasonable. When we are doing complex configurations we need to be explicit about the protocol to use for WinRM.