Summary: I'm trying to create a Bash script that selects an IP address and it's associated open ports, then run each IP through Nmap and display/store the results.
The format of the ports file (portsList):
192.168.1.1 53 udp
192.168.1.1 80 tcp
192.168.1.1 1900 tcp
192.168.1.110 135 tcp
192.168.1.115 1080 tcp
The format of the IP file (ipList):
192.168.1.1
192.168.1.110
192.168.1.115
My Bash script:
#!/bin/bash
portsvar="$(cat formattedPorts)"
hostvar="$(cat oneHost)"
while read -r line;
do
echo "$line" > oneHost
grep -wf oneHost portsList | awk '{print $2}' | tr '\n' ',' > formattedPorts
nmap -n -sV -p"$portsvar" "$hostvar" >> scanResults
cat scanResults
done < ipList
I spent several hours, trying multiple variations of this code and tried to find a solution online. But to no avail. The most this script can do is scan and output for the first selected IP and ports.
Additional considerations would be; if a port is UDP, to append 'U:' on the ports option. Also, if there is a way to display the output of Nmap scanning, while it is being redirected '>>' to a file.
Bash is what I'm most familiar with, but I'm open to learning a solution in a different language.
Edit
I tried jhnc's solution below by replacing:
echo "$line" > oneHost
grep -wf oneHost portsList | awk '{print $2}' | tr '\n' ',' > formattedPorts
nmap -n -sV -p"$portsvar" "$hostvar" >> scanResults
cat scanResults
with jhnc's code in the comment below. the resulting output was:
nmap -n -sV -p T:135 192.168.1.110
nmap -n -sV -p T:5985 192.168.1.112
nmap -n -sV -p T:54112,T:60000,T:8009,T:8888 192.168.1.131
nmap -n -sV -p T:5040 192.168.1.132
nmap -n -sV -p T:1041,T:1900,T:20005,T:33344,T:49152,T:49153,T:80 192.168.1.1
This output was echo'ed onto the terminal 5 times. From this I'll try to find a solution to have the input of this group of IP's ran once.
I am working on an application of multiple devices in the same network. One of them takes the lead and performs some functions. I arbitrate the "lead" by the highest IP I find.
My application is intended to be fault-tolerant and if I loose the controller, next in the line should take over.
I am running the script below.
#define SHELLSCRIPT "\
#/bin/bash \n\
echo $(ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1) > IP.txt\n\
while read LINE; do echo $LINE | grep -i -E 192.168 | grep -v .254 | cut -c1-13; done < /proc/net/arp >> IP.txt\n\
"
The problem I have found is that the ARP cache does not refresh automatically. Does anyone has any idea how to "refresh" the ARP table (without using arp commands).
I have already tried "ip -s neigh flush all", but it seems to have a delay to refresh the ARP table.
Anyway, I would appreciate any suggestion.
You can disable and enable the use of the ARP protocol on interface at the same time.
ARP cache will be cleared quitly fast.
ip link set arp off dev eth0 ; ip link set arp on dev eth0
Please, at first run this on test environment for checking and be sure there no connection interruption.
I try to save results from nmap scan to a txt file. I use this command
nmap -n -Pn -p T:3389 -T5 -sS -iR 0 | grep "scan" | awk '{ print $5 }' > test.txt
cat test.txt
the output looks like this :
xx.xx.xx.xx
xx.xx.xx.xx
xx.xx.xx.xx
xx.xx.xx.xx
xx.xx.xx.xx
xx.xx.xx.xx
It is working perfectly.
I want to scan only for open ports, and for this I try to use the --open option like this :
nmap -n -Pn -p T:3389 --open -T5 -sS -iR 0 | grep "scan" | awk '{ print $5 }' > test.txt
It does not work, the test.txt is empty. I try to use tail -f test.txt to see live results, but it's not working. Can someone explain what I'm doing, wrong?
I was expecting to see the result as the first time.
xx.xx.xx.xx
xx.xx.xx.xx
xx.xx.xx.xx
xx.xx.xx.xx
xx.xx.xx.xx
xx.xx.xx.xx
after I want to add the port number after all ip like this
xx.xx.xx.xx:3389
xx.xx.xx.xx:3389
xx.xx.xx.xx:3389
xx.xx.xx.xx:3389
xx.xx.xx.xx:3389
xx.xx.xx.xx:3389
and for that I want to use sed -i s/$/:3389/ test.txt
I wonder if it is possible to get this result with only one command.
I try something like this :
nmap -n -Pn -p T:3389 --open -T5 -sS 192.168.0.1/24 | grep "scan" | awk '{ print $5 }' > test.txt; sed -i s/$/:3389/ test.txt
cat test.txt and this is the result :
192.168.0.2:3389
192.168.0.16:3389
addresses:3389
I do not know why addresses:3389 appear at the end. But this works.
I want to get the same result but whit this command :
nmap -n -Pn -p T:3389 --open -T5 -sS -iR 0 | grep "scan" | awk '{ print $5 }' > test.txt; sed -i s/$/:3389/ test.txt
I try this command but not working. I want to use this command in a bash script. any help or suggestion is appreciated.
nmap -n -Pn -p T:3389 --open -T5 -sS -iR 0
This is the output:
Nmap scan report for 187.3.104.223
Host is up (0.29s latency).
PORT STATE SERVICE
3389/tcp open ms-wbt-server
Nmap scan report for 118.89.215.203
Host is up (0.29s latency).
PORT STATE SERVICE
3389/tcp open ms-wbt-server
I found a way to make it work. This is the command :
nmap -n -Pn -p T:3389 -T5 -sS -iR 5000 --open | grep scan | grep -v addresses | awk '{print $5}' | sed 's/$/:3389/' > test
cat test
The output:
35.190.27.36:3389
35.214.139.176:3389
132.190.70.226:3389
109.228.13.61:3389
103.10.175.4:3389
113.134.99.14:3389
35.168.9.215:3389
167.93.112.130:3389
115.220.6.216:3389
137.32.209.1:3389
35.206.198.136:3389
I can change the -iR 5000 if i need it, and it still works. It doesn't work with 0
I hope to be helpful if someone need it. Thank you all
The "addresses" is from the summary ending line of the Nmap output, 5th word:
Nmap done: 256 IP addresses (10 hosts up) scanned in 3.12 seconds
To remove the addresses from the output run:
nmap -n -Pn -p T:3389 --open -T5 -sS -iR 0 |grep scan|grep -v addresses|awk '{print $5}' | sed 's/$/:3389/' > test.txt
Post your output if it's not what you expected / wanted to get
I am trying to save the output of a grep filter to a file.
I want to run tcpdump for a long time, and filter a certain IP to a file.
tcpdump -i eth0 -n -s 0 port 5060 -vvv | grep "A.B.C."
This works fine. It shows me IP's from my network.
But when I add >> file.dump at the end, the file is always empty.
My script:
tcpdump -i eth0 -n -s 0 port 5060 -vvv | grep "A.B.C." >> file.dump
And yes, it must be grep. I don't want to use tcpdump filters because it gives me millions of lines and with grep I get only one line per IP.
How can I redirect (append) the full output of the grep command to a file?
The output of tcpdump is probably going through stderr, not stdout. This means that grep won't catch it unless you convert it into stdout.
To do this you can use |&:
tcpdump -i eth0 -n -s 0 port 5060 -vvv |& grep "A.B.C."
Then, it may happen that the output is a continuous stream, so that you somehow have to tell grep to use line buffering. For this you have the option --line-buffered option.
All together, say:
tcpdump ... |& grep --line-buffered "A.B.C" >> file.dump
On Linux, I can use netstat -pntl | grep $PORT or fuser -n tcp $PORT to find out which process (PID) is listening on the specified TCP port. How do I get the same information on Mac OS X?
On macOS Big Sur and later, use this command:
sudo lsof -i -P | grep LISTEN | grep :$PORT
or to just see just IPv4:
sudo lsof -nP -i4TCP:$PORT | grep LISTEN
On older versions, use one of the following forms:
sudo lsof -nP -iTCP:$PORT | grep LISTEN
sudo lsof -nP -i:$PORT | grep LISTEN
Substitute $PORT with the port number or a comma-separated list of port numbers.
Prepend sudo (followed by a space) if you need information on ports below #1024.
The -n flag is for displaying IP addresses instead of host names. This makes the command execute much faster, because DNS lookups to get the host names can be slow (several seconds or a minute for many hosts).
The -P flag is for displaying raw port numbers instead of resolved names like http, ftp or more esoteric service names like dpserve, socalia.
See the comments for more options.
For completeness, because frequently used together:
To kill the PID:
sudo kill -9 <PID>
# kill -9 60401
Up to macOS 13 Ventura, every version of macOS supports this:
sudo lsof -iTCP -sTCP:LISTEN -n -P
Personally I've end up with this simple function in my ~/.bash_profile:
listening() {
if [ $# -eq 0 ]; then
sudo lsof -iTCP -sTCP:LISTEN -n -P
elif [ $# -eq 1 ]; then
sudo lsof -iTCP -sTCP:LISTEN -n -P | grep -i --color $1
else
echo "Usage: listening [pattern]"
fi
}
Then listening command gives you a listing of processes listening on some port and listening smth greps this for some pattern.
Having this, it's quite easy to ask about particular process, e.g. listening dropbox, or port, e.g. listening 22.
lsof command has some specialized options for asking about port, protocol, process etc. but personally I've found above function much more handy, since I don't need to remember all these low-level options. lsof is quite powerful tool, but unfortunately not so comfy to use.
You can also use:
sudo lsof -i -n -P | grep TCP
This works in Mavericks.
Update January 2016
Really surprised no-one has suggested:
lsof -i :PORT_NUMBER
to get the basic information required. For instance, checking on port 1337:
lsof -i :1337
Other variations, depending on circumstances:
sudo lsof -i :1337
lsof -i tcp:1337
You can easily build on this to extract the PID itself. For example:
lsof -t -i :1337
which is also equivalent (in result) to this command:
lsof -i :1337 | awk '{ print $2; }' | head -n 2 | grep -v PID
Quick illustration:
For completeness, because frequently used together:
To kill the PID:
kill -9 <PID>
# kill -9 60401
or as a one liner:
kill -9 $(lsof -t -i :1337)
For the LISTEN, ESTABLISHED and CLOSED ports
sudo lsof -n -i -P | grep TCP
For the LISTEN ports only
sudo lsof -n -i -P | grep LISTEN
For a specific LISTEN port, ex: port 80
sudo lsof -n -i -P | grep ':80 (LISTEN)'
Or if you just want a compact summary [no service/apps described], go by NETSTAT. The good side here is, no sudo needed
netstat -a -n | grep 'LISTEN '
Explaining the items used:
-n suppress the host name
-i for IPv4 and IPv6 protocols
-P omit port names
-a [over netstat] for all sockets
-n [over netstat] don't resolve names, show network addresses as numbers
Tested on High Sierra 10.13.3 and Mojave 10.14.3
the last syntax netstat works on linux too
on OS X you can use the -v option for netstat to give the associated pid.
type:
netstat -anv | grep [.]PORT
the output will look like this:
tcp46 0 0 *.8080 *.* LISTEN 131072 131072 3105 0
The PID is the number before the last column, 3105 for this case
On macOS, here's an easy way to get the process ID that's listening on a specific port with netstat. This example looks for a process serving content on port 80:
find server running on port 80
netstat -anv | egrep -w [.]80.*LISTEN
sample output
tcp4 0 0 *.80 *.* LISTEN 131072 131072 715 0
The 2nd from the last column is the PID. In above, it's 715.
options
-a - show all ports, including those used by servers
-n - show numbers, don't look up names. This makes the command a lot faster
-v - verbose output, to get the process IDs
-w - search words. Otherwise the command will return info for ports 8000 and 8001, not just "80"
LISTEN - give info only for ports in LISTEN mode, i.e. servers
On the latest macOS version you can use this command:
lsof -nP -i4TCP:$PORT | grep LISTEN
If you find it hard to remember then maybe you should create a bash function and export it with a friendlier name like so
vi ~/.bash_profile
and then add the following lines to that file and save it.
function listening_on() {
lsof -nP -i4TCP:"$1" | grep LISTEN
}
Now you can type listening_on 80 in your Terminal and see which process is listening on port 80.
On Snow Leopard (OS X 10.6.8), running 'man lsof' yields:
lsof -i 4 -a
(actual manual entry is 'lsof -i 4 -a -p 1234')
The previous answers didn't work on Snow Leopard, but I was trying to use 'netstat -nlp' until I saw the use of 'lsof' in the answer by pts.
I am a Linux guy. In Linux it is extremely easy with netstat -ltpn or any combination of those letters. But in Mac OS X netstat -an | grep LISTEN is the most humane. Others are very ugly and very difficult to remember when troubleshooting.
checkout this project/tool: procs
install on MacOs: brew install procs
This allows you control what to display with procs.
To see TCP/UDP Ports, add below to ~/.procs.toml after installing the tool.
[[columns]]
kind = "TcpPort"
style = "BrightYellow|Yellow"
numeric_search = true
nonnumeric_search = false
align = "Left"
[[columns]]
kind = "UdpPort"
style = "BrightGreen|Green"
numeric_search = false
nonnumeric_search = true
align = "Left"
Here is a sample output:
lsof -n -i | awk '{ print $1,$9; }' | sort -u
This displays who's doing what. Remove -n to see hostnames (a bit slower).
This did what I needed.
ps -eaf | grep `lsof -t -i:$PORT`
I made a small script to see not only who is listening where but also to display established connections and to which countries. Works on OSX Siera
#!/bin/bash
printf "\nchecking established connections\n\n"
for i in $(sudo lsof -i -n -P | grep TCP | grep ESTABLISHED | grep -v IPv6 |
grep -v 127.0.0.1 | cut -d ">" -f2 | cut -d " " -f1 | cut -d ":" -f1); do
printf "$i : " & curl freegeoip.net/xml/$i -s -S | grep CountryName |
cut -d ">" -f2 | cut -d"<" -f1
done
printf "\ndisplaying listening ports\n\n"
sudo lsof -i -n -P | grep TCP | grep LISTEN | cut -d " " -f 1,32-35
#EOF
Sample output
checking established connections
107.178.244.155 : United States
17.188.136.186 : United States
17.252.76.19 : United States
17.252.76.19 : United States
17.188.136.186 : United States
5.45.62.118 : Netherlands
40.101.42.66 : Ireland
151.101.1.69 : United States
173.194.69.188 : United States
104.25.170.11 : United States
5.45.62.49 : Netherlands
198.252.206.25 : United States
151.101.1.69 : United States
34.198.53.220 : United States
198.252.206.25 : United States
151.101.129.69 : United States
91.225.248.133 : Ireland
216.58.212.234 : United States
displaying listening ports
mysqld TCP *:3306 (LISTEN)
com.avast TCP 127.0.0.1:12080 (LISTEN)
com.avast TCP [::1]:12080 (LISTEN)
com.avast TCP 127.0.0.1:12110 (LISTEN)
com.avast TCP [::1]:12110 (LISTEN)
com.avast TCP 127.0.0.1:12143 (LISTEN)
com.avast TCP [::1]:12143 (LISTEN)
com.avast TCP 127.0.0.1:12995 (LISTEN)
com.avast [::1]:12995 (LISTEN)
com.avast 127.0.0.1:12993 (LISTEN)
com.avast [::1]:12993 (LISTEN)
Google TCP 127.0.0.1:34013 (LISTEN)
This may be useful to check if you are connected to north-korea! ;-)
This is a good way on macOS High Sierra:
netstat -an |grep -i listen
Inspired by user Brent Self:
lsof -i 4 -a | grep LISTEN
For macOS I use two commands together to show information about the processes listening on the machine and process connecting to remote servers. In other words, to check the listening ports and the current (TCP) connections on a host you could use the two following commands together
1. netstat -p tcp -p udp
2. lsof -n -i4TCP -i4UDP
Thought I would add my input, hopefully it can end up helping someone.
Just a slight improvement on MichaĆ Kalinowski's answer (I don't have enough reputation to leave a comment there): if you are trying to find the process listening on a port numbered 255 and below, the grep command might print lines related to the IP address, and which do not correspond to the desired result. For a port with any number, the grep command might also erroneously match the device's MAC address or PID. To improve on this, I suggest changing the command to grep --color ":$1 "