Answers: <p>AFAIK there is no built-in module for this purpose, but you can use <code>shell</code> + <code>nc</code>:</p>
  
  <pre><code>---
  - hosts: all
    tasks:
      - shell: nc -z -w 1 -G 1 my.hostname.com {{ item }} || echo "Port {{ item }} is closed"
        with_items: [80,443,8443]
  </code></pre>
  
Answers: CC BY-SA 3.0
Answers: 2017-08-07T17:30:42.687Z
Answers: Thank you, this works also, but I opted to go with first suggestion as it allows me to further customize the play.
Answers: AWhitaker
Answers: CC BY-SA 4.0
Answers: 2019-08-27T07:15:36.973Z
Answers: What is `-G 1` I can't find it in the man pages?
Answers: lonix
Answers: CC BY-SA 4.0
Answers: 2020-10-16T04:46:49.503Z
Answers: @Ionix According to http://manpages.ubuntu.com/manpages/precise/en/man1/nc.traditional.1.html, it's source-routing pointer
Answers: windyzboy
Answers: CC BY-SA 3.0
Answers: 2017-08-03T19:39:08.507Z
Answers: 2017-08-03T19:39:08.507Z
Answers: Konstantin Suvorov
Answers: <p>You can use <a href="https://docs.ansible.com/ansible/2.5/modules/wait_for_module.html#synopsis" rel="nofollow noreferrer">wait_for</a> module for the same</p>
  
  <p>example quoted from the documentation:</p>
  
  <pre><code>- name: Wait 300 seconds for port 8000 of any IP to close active connections, don't start checking for 10 seconds
    wait_for:
      host: 0.0.0.0
      port: 8000
      delay: 10
      state: drained
  </code></pre>
  
Answers: CC BY-SA 4.0
Answers: 2018-07-17T11:06:39.060Z
Answers: Please try to format your post properly, all site on StackExchange network allow the same markdown, documentation for formatting is [here](https://devops.stackexchange.com/help/formatting)
Answers: Tensibai
Answers: CC BY-SA 4.0
Answers: 2018-07-17T11:07:33.470Z
Answers: BTW I fail too see what this answer adds which is not in RichVel answer already
Answers: Tensibai
Answers: CC BY-SA 4.0
Answers: 2018-07-17T10:27:55.610Z
Answers: 2018-07-17T11:05:13.383Z
Answers: 2018-07-17T11:05:13.383Z
Answers: user128364
Answers: <p>We use our tool dda-serverspec (<a href="https://github.com/DomainDrivenArchitecture/dda-serverspec-crate" rel="nofollow noreferrer">https://github.com/DomainDrivenArchitecture/dda-serverspec-crate</a>) for such tasks. You may define your expectation </p>
  
  <p><code>{:netcat [{:host "mywebserver.com" :port "443"}
            {:host "telnet mywebserver.com" :port "80"}
            {:host "telnet mywebserver.com" :port "8443"}]}
  </code></p>
  
  <p>and test these expectation either against localhost or remote by ssh.
  For remote tests you've to define a targets:</p>
  
  <p><code>{:existing [{:node-name "test-vm1"<br>
               :node-ip "35.157.19.218"}<br>
              {:node-name "test-vm2"
               :node-ip "18.194.113.138"}]
   :provisioning-user
    {:login "ubuntu"}}
  </code></p>
  
  <p>You may run the test by <code>java -jar dda-serverspec.jar --targets targets.edn serverspec.edn</code></p>
  
Answers: CC BY-SA 4.0
Answers: 2018-10-26T13:34:55.817Z
Answers: 2018-10-26T13:34:55.817Z
Answers: jerger
Answers: <p>You can use the Ansible <a href="https://docs.ansible.com/ansible/latest/collections/ansible/builtin/wait_for_module.html" rel="noreferrer">wait_for</a> module which checks a specific TCP port is open.</p>
  <p>Since in this case, all ports should be open already, we can use a minimal no. of retries, just enough to cover network issues:</p>
  <pre><code>- name: Check all port numbers are accessible from the current host
    wait_for:
      host: mywebserver.com
      port: &quot;{{ item }}&quot;
      state: started         # Port should be open
      delay: 0               # No wait before first check (sec)
      timeout: 3             # Stop checking after timeout (sec)
    ignore_errors: yes
    with_items:
      - 443
      - 80
      - 80443
  </code></pre>
  <p>By default, Ansible will check once every second (configurable in Ansible 2.3 using the <code>sleep</code> attribute), so this will check 3 times per port.</p>
  <p>Run this in a playbook against your inventory of 400+ hosts - Ansible will check in parallel that all hosts can reach <code>mywebserver.com</code> on those ports.</p>
  <ul>
  <li>the parallelism is subject to the <a href="http://docs.ansible.com/ansible/latest/intro_configuration.html#forks" rel="noreferrer">forks setting</a> in your <code>ansible.cfg</code>.</li>
  </ul>
  <p>We use <code>ignore_errors: yes</code> here so that any errors are marked in red but do not stop execution.</p>
  <p>Open ports are reported as <code>ok</code> items in output and closed ports are reported as <code>failed</code> (you must use <code>-vv</code> flag on <code>ansible-playbook</code> to see this output).</p>
  <h3>Fine-tuning output</h3>
  <p>If you want more specific output for the success and failure cases, the code must be more complex, adding a second task:</p>
  <ul>
  <li><code>wait_for</code> task must <code>register</code> a variable</li>
  <li>the second task produces output using <code>debug</code> based on success/failure condition (e.g. using Jinja2 <a href="https://stackoverflow.com/a/14215034/992887">conditional expression</a>)</li>
  <li>then you need to put both these tasks in an include file (without any <code>with_items</code> loop), and write a main playbook task that uses an <code>include</code> ... <code>with_items</code> to call the include file once per port.</li>
  </ul>
  
Answers: CC BY-SA 3.0
Answers: 2017-08-05T18:18:25.007Z
Answers: Importantly they'd need to set `host: mywebserver.com`.
Answers: Xiong Chiamiov
Answers: CC BY-SA 3.0
Answers: 2017-08-06T09:02:43.087Z
Answers: @XiongChiamiov - `host: x` is not required.  I just re-tested with Ansible 2.3.1 and the `host` attribute of `wait_for` tasks defaults to the current server being processed from inventory.
Answers: RichVel
Answers: CC BY-SA 3.0
Answers: 2017-08-06T15:18:45.007Z
Answers: Exactly, which is why OP needs to override it: they're testing connectivity *to another webserver* from all of their servers (re-read the question).
Answers: Xiong Chiamiov
Answers: CC BY-SA 3.0
Answers: 2017-08-07T06:47:17.733Z
Answers: Good point, have updated the answer with `hosts` attribute.
Answers: RichVel
Answers: CC BY-SA 3.0
Answers: 2017-08-07T17:29:43.870Z
Answers: Thank you! This works for me, and gives me enough to work on.
Answers: AWhitaker
Answers: CC BY-SA 4.0
Answers: 2018-07-18T11:00:34.657Z
Answers: Have to mention that wait_for works only for TCP ports
Answers: storm
Answers: CC BY-SA 4.0
Answers: 2018-07-28T06:45:52.987Z
Answers: @storm - good point, edited to mention TCP only for wait_for.  However, checking for open UDP ports is hard because it has no concept of a connection (only what the application defines) - a UDP check would require various steps beyond scope of Ansible - see [this answer](https://networkengineering.stackexchange.com/a/26542/20183).
Answers: RichVel
Answers: CC BY-SA 4.0
Answers: 2019-02-14T09:36:13.883Z
Answers: Ansible 2.5 has deprecated `with_items` etc, replacing them with the `loop` construct - see [this section](https://docs.ansible.com/ansible/latest/porting_guides/porting_guide_2.5.html#with-items) of the Ansible 2.5 porting guide.  You might want to do a `set_fact` to create a `ports` fact containing list of ports, then use `ports` instead of the `items` in porting guide.
Answers: RichVel
Answers: CC BY-SA 4.0
Answers: 2021-04-09T09:48:40.947Z
Answers: Actually Ansible 2.5 did not deprecate with_items and other lookup-based loops, though it did deprecate some other with* loops - see the top of docs page on loops.  However, it  is possible to re-write them with the `loop` construct.
Answers: RichVel
Answers: CC BY-SA 4.0
Answers: 2017-08-04T13:34:02.313Z
Answers: 2020-10-16T06:32:18.853Z
Answers: 2020-10-16T06:32:18.853Z
Answers: RichVel
Body: <p>I'm new to Ansible. Here's my task ...</p>
  
  <p>I have 400+ hosts, and I need to verify if 5 different ports are open from their end to our web server.</p>
  
  <p>Individually, I could log in and run:</p>
  
  <pre><code>telnet mywebserver.com 443
  telnet mywebserver.com 80
  telnet mywebserver.com 8443
  </code></pre>
  
  <p>..and so on..</p>
  
  <p>What module or plugin could be used in Ansible so I could automate this, and have it report the results (whether open or closed ports) back to my Ansible server?</p>
  
Tags: <ansible><testing><ports>
Title: Ansible: Other option available for telnet check of open ports?
UserDisplayName: AWhitaker
ThreadText: # Ansible: Other option available for telnet check of open ports?
  
  (Asked by: username_0 on 2017-08-03)
  
  I'm new to Ansible. Here's my task ...
  
  I have 400+ hosts, and I need to verify if 5 different ports are open from their end to our web server.
  
  Individually, I could log in and run:
  
  ```
  telnet mywebserver.com 443
  telnet mywebserver.com 80
  telnet mywebserver.com 8443
  
  ```
  
  ..and so on..
  
  What module or plugin could be used in Ansible so I could automate this, and have it report the results (whether open or closed ports) back to my Ansible server?
  
  **Tags:** ansible, testing, ports
  
  
  ---
  
  ## 4 answers
  
  ### Answer by username_7 on 2017-08-04. Score: 37 | Accepted answer
  
  You can use the Ansible [wait\_for](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/wait_for_module.html) module which checks a specific TCP port is open.
  
  Since in this case, all ports should be open already, we can use a minimal no. of retries, just enough to cover network issues:
  
  ```
  - name: Check all port numbers are accessible from the current host
    wait_for:
      host: mywebserver.com
      port: "{{ item }}"
      state: started         # Port should be open
      delay: 0               # No wait before first check (sec)
      timeout: 3             # Stop checking after timeout (sec)
    ignore_errors: yes
    with_items:
      - 443
      - 80
      - 80443
  
  ```
  
  By default, Ansible will check once every second (configurable in Ansible 2.3 using the `sleep` attribute), so this will check 3 times per port.
  
  Run this in a playbook against your inventory of 400+ hosts - Ansible will check in parallel that all hosts can reach `mywebserver.com` on those ports.
  
  * the parallelism is subject to the [forks setting](http://docs.ansible.com/ansible/latest/intro_configuration.html#forks) in your `ansible.cfg`.
  
  We use `ignore_errors: yes` here so that any errors are marked in red but do not stop execution.
  
  Open ports are reported as `ok` items in output and closed ports are reported as `failed` (you must use `-vv` flag on `ansible-playbook` to see this output).
  
  ### Fine-tuning output
  
  If you want more specific output for the success and failure cases, the code must be more complex, adding a second task:
  
  * `wait_for` task must `register` a variable
  * the second task produces output using `debug` based on success/failure condition (e.g. using Jinja2 [conditional expression](https://stackoverflow.com/a/14215034/992887))
  * then you need to put both these tasks in an include file (without any `with_items` loop), and write a main playbook task that uses an `include` ... `with_items` to call the include file once per port.
  
  > **Comments:**
  > **username_8**: Importantly they'd need to set `host: mywebserver.com`.  
  > **username_7**: @username_8 - `host: x` is not required.  I just re-tested with Ansible 2.3.1 and the `host` attribute of `wait_for` tasks defaults to the current server being processed from inventory.  
  > **username_8**: Exactly, which is why OP needs to override it: they're testing connectivity *to another webserver* from all of their servers (re-read the question).  
  > **username_7**: Good point, have updated the answer with `hosts` attribute.  
  > **username_0**: Thank you! This works for me, and gives me enough to work on.  
  > **username_9**: Have to mention that wait_for works only for TCP ports  
  > **username_7**: @username_9 - good point, edited to mention TCP only for wait_for.  However, checking for open UDP ports is hard because it has no concept of a connection (only what the application defines) - a UDP check would require various steps beyond scope of Ansible - see [this answer](https://networkengineering.stackexchange.com/a/26542/20183).  
  > **username_7**: Ansible 2.5 has deprecated `with_items` etc, replacing them with the `loop` construct - see [this section](https://docs.ansible.com/ansible/latest/porting_guides/porting_guide_2.5.html#with-items) of the Ansible 2.5 porting guide.  You might want to do a `set_fact` to create a `ports` fact containing list of ports, then use `ports` instead of the `items` in porting guide.  
  > **username_7**: Actually Ansible 2.5 did not deprecate with_items and other lookup-based loops, though it did deprecate some other with* loops - see the top of docs page on loops.  However, it  is possible to re-write them with the `loop` construct.  
  
  ---
  
  ### Answer by username_1 on 2017-08-03. Score: 2
  
  AFAIK there is no built-in module for this purpose, but you can use `shell` + `nc`:
  
  ```
  ---
  - hosts: all
    tasks:
      - shell: nc -z -w 1 -G 1 my.hostname.com {{ item }} || echo "Port {{ item }} is closed"
        with_items: [80,443,8443]
  
  ```
  
  > **Comments:**
  > **username_0**: Thank you, this works also, but I opted to go with first suggestion as it allows me to further customize the play.  
  > **username_2**: What is `-G 1` I can't find it in the man pages?  
  > **username_3**: @Ionix According to http://manpages.ubuntu.com/manpages/precise/en/man1/nc.traditional.1.html, it's source-routing pointer  
  
  ---
  
  ### Answer by username_4 on 2018-07-17. Score: 0
  
  You can use [wait\_for](https://docs.ansible.com/ansible/2.5/modules/wait_for_module.html#synopsis) module for the same
  
  example quoted from the documentation:
  
  ```
  - name: Wait 300 seconds for port 8000 of any IP to close active connections, don't start checking for 10 seconds
    wait_for:
      host: 0.0.0.0
      port: 8000
      delay: 10
      state: drained
  
  ```
  
  > **Comments:**
  > **username_5**: Please try to format your post properly, all site on StackExchange network allow the same markdown, documentation for formatting is [here](https://devops.stackexchange.com/help/formatting)  
  > **username_5**: BTW I fail too see what this answer adds which is not in username_7 answer already  
  
  ---
  
  ### Answer by username_6 on 2018-10-26. Score: 0
  
  We use our tool dda-serverspec (<https://github.com/DomainDrivenArchitecture/dda-serverspec-crate>) for such tasks. You may define your expectation
  
  `{:netcat [{:host "mywebserver.com" :port "443"}
  {:host "telnet mywebserver.com" :port "80"}
  {:host "telnet mywebserver.com" :port "8443"}]}`
  
  and test these expectation either against localhost or remote by ssh.
  For remote tests you've to define a targets:
  
  `{:existing [{:node-name "test-vm1"  
  :node-ip "35.157.19.218"}  
  {:node-name "test-vm2"
  :node-ip "18.194.113.138"}]
  :provisioning-user
  {:login "ubuntu"}}`
  
  You may run the test by `java -jar dda-serverspec.jar --targets targets.edn serverspec.edn`
  
  
  ---
  
  