display open ports grouped by process - bash

given a netstat output, how can i display the selected open ports grouped by process?
what i got so far:
:~# netstat -tnlp | awk '/25|80|443|465|636|993/ {proc=split($7,pr,"/"); port=split($4,po,":"); print pr[2], po[port]}'
haproxy 636
haproxy 993
haproxy 993
haproxy 465
haproxy 465
exim4 25
apache2 80
exim4 25
apache2 443
desired output (in one line):
apache2 (80 443), exim4 (25), haproxy (465 636 993)
please note:
i have duplicated lines because they listen on different IPs, but i only need one (sort -u is ok)
if possible, id like to sort by process and then by port
the main goal is to have this single line displayed to the user on ssh logon, using motd (i got this part covered)

netstat -tnlp|awk '/25|80|443|465|636|993/ {proc=split($7,pr,"/"); port=split($4,po,":"); print pr[2], po[port]}'|sort|uniq|awk '{a[$1]=a[$1](" "$2" "$3)}END{for (i in a) printf "%s (%s),",i,a[i]}'
try this, Later addition
sort|uniq|awk '{a[$1]=a[$1](" "$2" "$3)}END{for (i in a) printf "%s (%s),",i,a[i]}'

Related

Have script find all lines containing x, prepend these lines to each line that follows unless the line has another x in it, at which point repeat

I have a file called file.txt which contains either an IP or a FQDN, followed by ports that were found to be open. I want my bash script to prepend all ports with their associated IP/FQDN (always above them in the file), replace the forward slash with a whitespace, and then delete the IP/FQDN line that isn't associated with a port.
Breaking it down, I thought:
Read the next line
If the line contains a "." in it (IP or FQDN), prepend it into all following lines, unless:
If the following line has a "." in it (another IP or FQDN), make that line the new one to prepend and repeat the process for all following lines
Replace all "/" with a " " (one single whitespace)
Remove all lines that are not associated with a port (probably easier just to grep for "tcp" and "udp" as that will display all open ports with associated IP/FQDN
To make it easier, I can easily create a tmp file if necessary within the process. I have tried various iterartions of "while" and "if" and nothing seems to work...!
E.g:
cat file.txt
www.thisisawebsite.com:
80/tcp
443/tcp
500/udp
192.168.1.5:
80/tcp
dev.anothersite.co.uk:
22/tcp
443/tcp
5050/udp
21000/tcp
10.10.10.10:
4000/udp
8000/udp
Then, running the bash script, it should become:
www.thisisawebsite.com:80 tcp
www.thisisawebsite.com:443 tcp
www.thisisawebsite.com:500 udp
192.168.1.5:80 tcp
dev.anothersite.co.uk:22 tcp
dev.anothersite.co.uk:433 tcp
dev.anothersite.co.uk:5050 udp
dev.anothersite.co.uk:21000 tcp
10.10.10.10:4000 udp
10.10.10.10:8000 udp
Looks like a job for awk:
awk -F/ '/\./ {d=$0; next} {print d":"$1, $2}'

retrieve a specific section of a webpage

I need to populate a list in a BASH script with data retrieved from a portion of a webpage. Currently, I have manually created a static list but I want the list contents to be generated dynamically. That way if new items get added to the page, subsequent runs of the script will reflect those new items.
source page: https://support.apple.com/en-us/HT210060
I would like to extract the section entitled "macOS, iOS, and tvOS" to wind up with a list like:
updateServers="appldnld.apple.com 80
gg.apple.com 80
gg.apple.com 443
gnf-mdn.apple.com 443
gnf-mr.apple.com 443
gs.apple.com 80
gs.apple.com 443
ig.apple.com 443
mesu.apple.com 80
mesu.apple.com 443
ns.itunes.apple.com 443
oscdn.apple.com 80
oscdn.apple.com 443
osrecovery.apple.com 80
osrecovery.apple.com 443
skl.apple.com 443
swcdn.apple.com 80
swdist.apple.com 443
swdownload.apple.com 80
swdownload.apple.com 443
swpost.apple.com 80
swscan.apple.com 443
updates-http.cdn-apple.com 80
updates.cdn-apple.com 443
xp.apple.com 443"
Ultimately I'd like to output each section of the page into its own separate list, but for now the portion above is my main concern.
Thank you all in advance. This is a great community.
A HTML parser is a better tool for this type tasks (e.g. Ruby's Nokogiri or Python's Beautifulsoup). For a pure-Bash solution you can use this script (assuming -P support for grep):
#!/bin/bash
wget -q https://support.apple.com/en-us/HT210060 -O- \
| \grep -ziP "(?s)<h3>macos.*?<h3>" \
| xargs -0 \
| \grep -P "<tr><td>|<td>[\d, ]+</td>" \
| sed 's:.*<td>\(.*\)</td>:\1:'
How it works:
wget with -O- downloads the website and sends it to standard output
grep -ziP "(?s)..." uses PCRE to make a multi-line search from one until the next one
the rest of the script gets the text inside host and port columns
Output:
$ script.sh
appldnld.apple.com
80
gg.apple.com
443, 80
...
80
updates.cdn-apple.com
443
xp.apple.com
443

Splitting extra columns in a text file into separate lines (keeping first column)

I'm going to try to describe my problem and my end goal as best as I can, here it goes:
I have a script that fetches AWS ELB information (elb name + ports that's associated with a specific certifican arn).
So, in the end I have a text file (I call it elb_ports) and it looks something like this:
ccds-lb 636
cf-router 443 4443
dev-cf-router 443 4443
eng-jenkins-monit 443
gitlab-lb 443
gitlab-mattermost-elb 443
jenkins-np-elb 443
saml 443
uaa 443
I have another script that comes after that which I want it to go through that elb_ports file and replace the certificates with a new one, but according to Amazon's documentation: It says in order to replace the certificates, I need two things from that elb_ports file. The load balancer name and the load balancer port.
So basically their command looks like this
aws elb set-load-balancer-listener-ssl-certificate \
--load-balancer-name my-load-balancer \
--load-balancer-port 443 \
--ssl-certificate-id arn:aws:iam::123456789012:server-certificate/my-new-certificate
I want to be able to loop through the file and execute the command above to each elb and port, but my problem is with the elbs that has multiple ports associated with the cert like: cf-router 443 4443 for example.
So my idea was to split that into two lines, so like this:
cf-router 443
cf-router 4443
But I'm not sure how to add cf-router (for example) to the ports that come after the first one (there could be more than two ports using the same cert).
I hope I was able to explain my problem and end goal clearly, if this isn't a good method, I'm open to suggestions also.
EDIT: Perhaps something like this is beneficial, but not sure how to tailor it to my needs.. Like put each line in an array and the space as a delimiter and then loop through each line putting arr(1) (load balancer name) and then the load balancer port, but not sure how to count and go through >arr(2) in bash.
To split out your extra columns into separate lines:
while read -r lb_name lb_ports_str; do ## split line into lb name and port list string
read -r -a lb_ports <<<"$lb_ports_str" ## split out port list string into an array
for port in "${lb_ports[#]}"; do ## iterate through that array
printf '%s %s\n' "$lb_name" "$port" ## handle each port separately
done
done <elb_ports ## reading lines from elb_ports
Of course, that printf could be any other line referring to $lb_name and $port -- meaning you could potentially run your code that's installing new certificates here.

Bash ping server with addres and port and get short info

How I can connect to sever by ip and port, and get short info about it?
I tried to do it with netcat and curl, but info is too long. I also tried to use telnet but it is not a good way for me.
I have a script which connect to some addresses on specified ports and I if it is connected I want to show short info about it.
Is it possible? Is any other method to solve this problem?
IP addresses are different. They can be a http, mysql, ssl, etc.
I attach a code with a connection's function:
if nc -w 10 -z $1 $i; then
printf "\n$1:$i - Port is open\n\nSERVER INFO:\n";
printf "\n$(curl -IL $1)\n";
else
printf "\n$1:$i - Port is closed\n"
fi;
EDIT:
Example of response from server I would like to get
{IP number}: ssh - OpenSSH 6.0pl1, http - apache 1.3.67, https - httpd 2.0.57
You were pretty close. You can include the host just as you have in your script.
for port in $(seq 21 23); do
out=$(nc -w 1 -q 1 localhost $port)
echo port ${port}: $out
done
#port 21:
#port 22: SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.7
#port 23:

(OS X) Port in use, however it is not shown by netstat or lsof

Sorry for my english.
I was trying to forward port 80 from my vagrant box to host machine (OS X) and got this message
"The forwarded port to 80 is already in use on the host machine."
So, in order to figure out which program uses port 80 i ran this:
➜ ~ sudo lsof -n -i:80 | grep LISTEN
➜ ~
However, as you can see, it shows nothing.I have also tried netstat, but result was the same. Then i tried to use netcat + tcpdump to look at tcp session:
➜ ~ nc -vvv 127.0.0.1 80
Connection to 127.0.0.1 80 port [tcp/http] succeeded!
➜ ~
In another window:
➜ ~ sudo tcpdump -ni lo0 port 80
Password:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo0, link-type NULL (BSD loopback), capture size 65535 bytes
00:03:47.019805 IP 127.0.0.1.50666 > 127.0.0.1.80: Flags [S], seq 2187569264, win 65535, options [mss 16344,nop,wscale 4,nop,nop,TS val 194193524 ecr 0,sackOK,eol], length 0
00:03:47.019834 IP 127.0.0.1.80 > 127.0.0.1.50666: Flags [R.], seq 0, ack 2187569265, win 0, length 0
So it looks like the port is closed, because it immediately sent RESET flag, but why did nc show that connection was successful and lsof show nothing.
I'm really confused. Can anyone tell me what is going on, or what am i doing wrong?
I can provide additional information if needed.
Thanks!
Looks like that's firewall reset connection.
Turn off Avast WebShield if it exists.

Resources