Ping and NMAP as REST API

I came across this idea while working on problem statement, where requirement was to run ping and nmap checks on devices and hosts from a jump server.

Best way to offer nmap and ping check without getting users on jump server was to offer ping and nmap in some form of web service.

To do this, I wrote a python module with ping and nmap check functions and then invoked it in python flask based web service. Here is the hierarchy of code


├── checkConnWS.py  <---Flask based web service
└── module
    ├── checkConn.py <--- python code having ping and nmap check functions

Here is the code for checkConn.py sitting in “module” directory.


#!/usr/local/bin/python3
from pythonping import ping
import sys
import ipaddress
import nmap

class checkConn:
   def checkPing(host):
      IPAddress = host
      pingErr = ping(IPAddress, count=5)._responses[4].error_message
      if pingErr is None:
         return({"IPAddress": IPAddress, "Ping": "OK"})
      else:
         return({"IPAddress": IPAddress, "Ping": "Failed", "PingError": pingErr})

   def checkNmap(host, ports):
      IPAddress = host
      nmapArg = "-p "+ports
      portList = ports.split(",")
      hostscan = nmap.PortScanner()
      results = hostscan.scan(hosts=IPAddress, arguments=nmapArg)
      if results.get('scan') != {}:
         scanRes ={}
         for port in portList:
            portState = results.get('scan').get(IPAddress).get('tcp').get(int(port)).get('state')
            scanRes[port]=portState
         return(scanRes)
      else:
         return({"IPAddress": IPAddress, "Message": "NMAP Failed"})

Here is the code of checkConnWS.py


#!/usr/local/bin/python3
from flask import Flask, request, jsonify
from flask_restful import Resource, Api
import json
from module.checkConn import checkConn

app = Flask(__name__)
api = Api(app)

class pingCheck(Resource):
    def get(self, IPAddress):
        return(checkConn.checkPing(IPAddress))

class nmapCheck(Resource):
    def get(self, IPAddress, Ports):
        return(checkConn.checkNmap(IPAddress, Ports))

api.add_resource(pingCheck, '/ping/<string:IPAddress>')
api.add_resource(nmapCheck, '/nmap/<string:IPAddress>/<string:Ports>')

if __name__ == '__main__':
     app.run(host='127.0.0.1', port='8000', debug=True)

Start web service….


./checkConnWS.py
 * Serving Flask app "checkConnWS" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://127.0.0.1:8000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 345-946-361

Send nmap and ping requests to web service….


curl "http://127.0.0.1:8000/nmap/192.168.0.6/22,23,21,8080,80"
{
    "22": "open",
    "23": "closed",
    "21": "closed",
    "8080": "open",
    "80": "closed"
}

curl "http://127.0.0.1:8000/nmap/192.168.0.7/22"
{
    "22": "filtered"
}

curl "http://127.0.0.1:8000/ping/192.168.0.7"
{
    "IPAddress": "192.168.0.7",
    "Ping": "Failed",
    "PingError": "No response"
}

curl "http://127.0.0.1:8000/ping/192.168.0.6"
{
    "IPAddress": "192.168.0.6",
    "Ping": "OK"
}

Please note that nmap scan uses underline nmap binary on operating system. and some nmap arguments work only as “root” user.