I have installed ansible 2.7 rc1 because I need a way to install stuff on a windows machine via Linux server as a tunnel.
After reading and trial and error, I have realized that it cannot be done using WinRM but only using psrp with ansible 2.7.
I’m not sure what should be configured in the ansible_psrp_proxy parameter and how can ansible know that the tunnel is server is a Linux one that needs to connect using ssh.
I have tried to configure the ansible.cfg to read a ssh.cfg file with the following content:
ForwardAgent yes
ControlMaster auto
ControlPath ~/.ssh/ansible-%r@%h:%p
ControlPersist 5m
Error message looks like that:
ConnectTimeout: HTTPSConnectionPool(host=‘’, port=5986): Max retries exceeded with url: /wsman (Caused by ConnectTimeoutError(<urllib3.connection.VerifiedHTTPSConnection object at 0x7fb8ed6901d0>, u’Connection to timed out. (connect timeout=30)'))
The psrp connection plugin is similar to winrm and uses the same underlying protocol (http) to connect to hosts. The ansible_psrp_proxy variable can be used to specify a HTTP proxy to a server in the form of a URL. This can’t be used to tunnel traffic through SSH unfortunately.
Slight amendment to the above, I haven’t tested it but the underlying library behind psrp uses requests to send each HTTP requests and that is also meant to support SOCKS. It requires that you have installed PySocks through ‘pip install requests[socks]’ and then configure the ‘ansible_psrp_proxy’ value to be like ‘socks5://user:pass@host:port’.
Thanks, Jordan!
So no plan to have an ssh tunnel to windows servers?
If the above is true, I’ll need to rethink my AWS architecture or think of a different way to install the environment.
No explicit plans to natively support it in Ansible right now, I’ve heard people talking about chaining connections, e.g. use SSH to a host then WinRM from there but’s that quite complex and I don’t expect anything anytime soon. So while you can’t set all this up end to end with an inventory configuration you can still achieve what you want using a SOCKS proxy. Basically the only extra step needed to setup this proxy is to bind the local port and setup the SSH connection.
Here is a very basic example of how to do all this, in my example I set up my local SSH connection to listen on port 12345
`
install the requests socks dependency packages
pip install requests[socks]
set up the following in your inventory
[socks]
windows-host
[socks:vars]
ansible_user=username
ansible_password=password
ansible_connection=psrp
ansible_port=5985 # this is the port of the WinRM instance your Windows host is listening on
ansible_psrp_proxy=socks5://localhost:12345
in a separate terminal on your Ansible host run the following which will
start an SSH connection you need to keep active until you have finished with Ansible
ssh -D 12345 username@bastionhost
# now run your playbook
ansible -i inventory.ini socks -m win_ping
`
I just tested this out and confirmed with Wireshark that there was no traffic over port 5985 to my host and the actual data was being sent over SSH to my bastion host and then from there it is sending the WinRM requests over port 5985.
What happens in that example is that your localhost will setup an SSH connection that listens on port 12345 and any data received on that port will be tunneled to your bastion host. From the bastion host will then act as a client and send the WinRM request as per usual to the Windows host which it should have access to. Any responses are then tunneled back over the SSH connection and then finally sent back to Ansible to process.
You can get tricky and play around with SSH to set up a ControlPath that you can use to run your SSH connection in the background and bring it up and down or even use a separate host to act as your SOCKS proxy and handle all the SSH connections but that’s a separate conversation from this.
First thanks a lot for the detailed description!
I have tried the sock example but for some reason it does not work for me.
I configured the inventory as you have suggested (changed user and pass), installed socks package (had some issues with pip but made it work with system pip), in a different terminal connected to my bastion (had to use -i ) and run the ansible command. Not sure were it fails: ConnectionError: SOCKSHTTPConnectionPool(host=‘’, port=5985): Max retries exceeded with url: /wsman (Caused by NewConnectionError(‘<urllib3.contrib.socks.SOCKSConnection object at 0x7f494a320450>: Failed to establish a new connection: [Errno 111] Connection refused’,))
Actually the error is a bit different: ConnectTimeout: SOCKSHTTPConnectionPool(host=‘’, port=5985): Max retries exceeded with url: /wsman (Caused by ConnectTimeoutError(<urllib3.contrib.socks.SOCKSConnection object at 0x7f2a7d269450>, ‘Connection to timed out. (connect timeout=30)’))
When I run tcmdump on the bastion, I see that it tries to connect to the windows host but does not get any response.
When I try to directly connect to the windows machine using psrp it works just fine.
Have you tried to connect from your bastion host to the Windows ones manually? The best test would be to install Ansible there and run with the same inventory minus the proxy variable.
I see. Good idea. The two machines (Linux and Windows) have a public IP address meaning they should be open to each other.
I was able to make winrm and psrp work from my laptop directly to the Windows machine.
Anyhow, I’ll try what you have suggested to be on the safe side.
Should and could are always 2 different things Considering you can see your bastion host attempts to connect but fails with a connection timeout then it seems like it can”t.
I’ve moved this task to a college of mine.
I’ll make sure to get back with the results of this experiment but unfortunately we are at holidays now and it might take a week or so.
I finally was able to document this a bit more thoroughly with a step by step example at http://www.bloggingforlogging.com/2018/10/14/windows-host-through-ssh-bastion-on-ansible/. No idea if you are still working on this but potentially you need to define the proxy with the schema “socks5h://”, the extra h on the end means all DNS resolution is done on the bastion host and not the Ansible client.
Got back to that now. Joined forces with other team members but it just doesn’t work.
We always get the error message:
ConnectionError: SOCKSHTTPConnectionPool(host=‘...’, port=5985): Max retries exceeded with url: /wsman (Caused by NewConnectionError(‘<urllib3.contrib.socks.SOCKSConnection object at 0x7f7fbe844450>: Failed to establish a new connection: [Errno 111] Connection ref
used’,))
We’ve tried lots of stuff. Both ports (5985 and 5986). We’ve set the following parameters in the playbook:
Host bastion
Hostname
User ubuntu
IdentityFile ~/.ssh/keyFile.pem
ControlMaster auto
ControlPath ~/.ssh/ansible-%r@%h:%p
ControlPersist 5
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
What else are we missing here? Everything works from inside a docker container. The bastion is an AWS instance and the remote machine is also an AWS instance.
We thought that it might be a firewall on the way so we’ve created a another AWS instance and run everything from there. Nothing!
If you’ll ever see this thread again, I just want to emphasize a very important point that I think should be added to your blog.
When running ansible on a non-ssh machine, ssh configurations are not being read during the connection phase. Meaning, the only way to use the socks proxy is by running the command you’ve written in your blog before running the ansible-playbook command.
One cannot add that socks tunnel to an ssh configuration file or a ssh_args under the ssh_connection section in the ansible.cfg file.