Test if a server is reachable from host and has port open with Ansible - ansible

I want to test if the host I am provisioning can reach a specific server and connect to a specific TCP port. If it can't the playbook should fail.
How can I do that?

There is wait_for module for this.
To check that target.host can access remote.host:8080:
- hosts: target.host
tasks:
- wait_for: host=remote.host port=8080 timeout=1
- debug: msg=ok
There are a lot of other examples in the documentation.

Using wait_for is fine, however it requires the service is actually running and gives a reply.
If you just like to check whether the port is open in your firewall, you can use curl.
- name: Check if host is reachable
shell:
cmd: "/usr/bin/curl --connect-timeout 10 --silent --show-error remote.host:8080"
warn: no
executable: /bin/bash
register: res
failed_when: res.rc in [28] or res.stderr is search("No route to host")
When the port is open but service does not run you get an curl: (7) Failed connect to 10.192.147.224:27019; Connection refused" which you would consider as OK.
A connection blocked by firewall will return curl: (28) Connection timed out after 10001 milliseconds

Related

Run Http GET from Ansible to remote server by connecting via localhost

I am creating an ansible-playbook which is doing HTTP GET to a remote elastic server. The problem is that this ES server doesn't accept any other connection apart from localhost. Is there a way how to connect to the remote ES server and execute the curl command with localhost ?
- name: check current version
uri: url=http://localhost:{{ es_http_port }} method=GET
register: version_found
retries: 10
delay: 10

Can we create a playbook to install a package in our own system?

I'm using Ubuntu Linux
I have created an inventory file and I have put my own system IP address there.
I have written a playbook to install the nginx package.
I'm getting the following error:
false, msg" : Failed to connect to the host via ssh: connect to host myip : Connection refused, unreachable=true
How can I solve this?
You could use the hosts keyword with the value localhost
- name: Install nginx package
hosts: localhost
tasks:
- name: Install nginx package
apt:
name: nginx
state: latest
Putting your host IP directly in your inventory treats your local machine as any other remote target. Although this can work, ansible will use the ssh connection plugin by default to reach your IP. If an ssh server is not installed/configured/running on your host it will fail (as you have experienced), as well as if you did not configure the needed credentials (ssh keys, etc.).
You don't need to (and in most common situations you don't want to) declare localhost in your inventory to use it as it is implicit by default. The implicit localhost uses the local connection plugin which does not need ssh at all and will use the same user to run the tasks as the one running the playbook.
For more information on connection plugins, see the current list
See #gary lopez answer for an example playbook to use localhost as target.

Ansible: connect to a remote host via proxy

I'm working on a playbook that needs to connect to a couple of different servers through a proxy.
I was able to test the connection using putty and the proxy.
Basically, went to connections --> proxy, then select HTTP and added the proxy host.
But, I was not able to reproduce it with SSH from the Ansible server.
I tried different ssh commands:
ssh -L jumphost.example.org:80 fred#server.example.org -p 443
ssh -J jumphost.example.org:80 fred#server.example.org
ssh -o ProxyCommand="ssh -W %h:%p jumphost.example.org" server.example.org
ssh -tt jumphost.example.org ssh -tt server.example.org
I know there are different options that use nc but I didn't try them, because its not installed on the server.
Is there any way to connect to the remote host in ansible using the proxy?
Thanks
Can you try this ?
- hosts: all
remote_user: root
tasks:
- name: Install cobbler
package:
name: cobbler
state: present
environment:
http_proxy: http://proxy.example.com:8080
from: playbooks_environment

Ansible Wait_For Module

I created a playbook to reboot my remote servers. I use wait_for to wait for remote servers up before I continue. So I have the following code:
—-
- hosts: hostName
tasks:
- name: reboot
shell: reboot
async: 1
poll: 0
- name: wait for server to come up
Local_action: wait_for
args:
host: hostName
port: 22
state: started
delay: 10
timeout: 600
My targeted server was up about 5 minutes after reboot was initiated. However, the playbook stacked at this play till it timed out and generated error.
My questions are:
1. How doeS wait_for work here? Does it send ssh connection request to target host and time out if it cannot connect to the target host after 600 seconds? Or does it keep pinging the target host till it times out?
2.What could be the problem I am having?
You'll be better off using wait_for_connection in this case. For example, given the play is running at - hosts: hostName
- name: Wait 600 seconds, but only start checking after 10 seconds
wait_for_connection:
delay: 10
timeout: 600
Q: How does wait_for work here?
A: wait_for is waiting for a port to become available.
Q: Does it send the ssh connection request to the target host and time out if it cannot connect to the target host after 600 seconds?
A: No. It's testing the port.
Q: Does it keep pinging the target host till it times out?
A: No. It tries to create a socket. See wait_for.py
s = socket.create_connection((host, port), connect_timeout)
Q: What could be the problem I am having?
A: It's not clear from the data available. Do not run wait_for as local_action. Make sure the host rebooted successfully.

Can't connect to public IP for EC2 instance

I have an EC2 instance which is running with the following security groups:
HTTP - TCP - 80 - 0.0.0.0/0
Custom UDP Rule - UDP - 1194 - 0.0.0.0/0
SSH - TCP - 22 - 0.0.0.0/0
Custom TCP Rule - TCP - 943 - 0.0.0.0/0
HTTPS - TCP - 443 - 0.0.0.0/0
However, when I try to access http://{PUBLIC_IP} or https://{PUBLIC_IP} in the browser, I get a "{IP} refused to connect" error. I'm new to AWS. Am I missing something here? What should I do to debug?
One way to debug this particular class of problem is to use netcat in order to determine where the problem lies.
If you run netcat against port 80 on the public IP address of your instance and just get a hang (no output at all), then most likely your security group isn't allowing traffic through. Here is an example from an EC2 instance that is in a security group that doesn't allow port 80 traffic inbound:
% nc -v 55.35.300.45 80
<just hangs>
Whereas if the security group is changed to allow port 80, but the EC2 instance doesn't have any process listening on port 80, you'll get the following:
% nc -v 55.35.300.45 80
nc: connectx to 52.38.300.43 port 80 (tcp) failed: Connection refused
Given that your browser gave you a similar "connection refused", most likely the problem is that there is no web server running on your instance. You can verify this by ssh'ing into the instance and seeing if you can connect to port 80 there:
ssh ec2-user#55.35.300.45
% nc -v localhost 80
nc: connect to localhost port 80 (tcp) failed: Connection refused
If you get something like the above, you're definitely not running a webserver.
I'm not sure if it's too late to help but I was stuck with a similar issue with my test server
SG Inbound: ssh -> 22
HTTP -> 80
NACL: default allow/deny settings
but still couldn't ping to the server from my browser, then I realize there's nothing running on the server that can serve the request, and I started httpd server (webserver) and it worked.
sudo yum -y install httpd
sudo service httpd start
this way you can test the connectivity if you are playing with SGs and NACLs and of course it's not the only way, just an example if you're figuring your System N/W out.
Have you installed webserver(ngingx/apache) to serve your requests. If so please share your the config files. (So that it will help to troubleshoot)
I think the reason is probably that you did not set up a web server for your EC2 instance, because if you try to access http://{PUBLIC_IP} or https://{PUBLIC_IP}, you need to have a background server to serve the http request as #Niranj Rajasekaran said.
By the way, by simply pinging the {PUBLIC_IP}, you could see if your connection to your EC2 instance is normal or not.
In command prompt or terminal, type
ping {PUBLIC_IP}
In my case, the server was running but available on just 127.0.0.1 so it refused connections from external hosts. To see if this is your situation, you can run
netstat -an | grep <port number>
If it says 127.0.0.1:<port number> instead of 0.0.0.0:<port number>, you have this problem.
Usually there's a flag or an argument in your server code somewhere to set the host to 0.0.0.0:
app.run(host='0.0.0.0') # flask example
However, in my case, I had already set this so I thought that couldn't possibly be the issue, which is how I ended up on this thread, which asks more generally about the problem. Unfortunately, I was using docker, and had set 0.0.0.0 on the container but was mapping that explicitly to 127.0.0.1 on the host in the docker-compose port-mapping:
ports:
- "127.0.0.1:<port number>:<port number>"
Changing that line to remove the host IP specification fixed the problem upon re-deploy:
ports:
- "<port number>:<port number>"

Resources