I am trying to cycle through some ports for connecting via ssh. New to shell/bash not quite sure how to accomplish this.
startingPort=xxxx
endingPort=yyyy
ssh(){
ssh admin#localhost -p $startingPort
}
the output of an invalid port is ssh: connect to host localhost port 8801: Connection refused
I need to capture this and then try the next port in the range
I am trying to iterate through the port numbers until i see
Password authentication
Password:
To get the output of the ssh command, you can check it with "$?".
As an example, if you want to log errors :
//inside the loop (of muzido answer)
ssh admin#localhost -p $port
if [ "$?" -ne 0 ] ; then
//write into logfile
fi
Thank you muzido and Theo Pnv; the two answers combined helped me get this task accomplished..
log_file=/directory/log_file.txt
startingPort=8801
endingPort=8899
port=''
sshToStuff(){
for (( port=$startingPort; port<=$endingPort; port++ ))
do
if [ "$?" -ne 0 ] ; then
echo "`date -u`" " ssh: connect to host localhost port $port: Connection refused" >> $log_file2;
fi
ssh admin#localhost -p $port
done
}
sshToKaraf
try something like this;
#!/bin/bash
startingPort=10
endingPort=40
for (( port=$startingPort; port<=$endingPort; port++ ))
do
ssh admin#localhost -p $port
done
Related
code works but won't continue to run the loop stuck in the inner loop not sure where the problem is, or maybe port scan just takes alot of time
#!/bin/bash
up()
{
ping -c 1 $1 > /dev/null
[ $? -eq 0 ] && echo IP: $i is up.
}
for i in 192.168.0.{1..255}
do
up $i & disown
for port in {1..100};do
2>/dev/null echo > /dev/tcp/$i/$port
if [ $? == 0 ]
then
{
echo "port $port is open"
continue
}
fi
done
done
exit
Scan Ping + TCP in bash
I've tried to limit script to 8182 forks in order to stay polite.
This script scan /etc/services, then could scan all (desired) ports. (see comments).
Full scan of my complex private subnet take more than 5 minutes to complete (scanning 303 ports on 255 hosts, found 27 up)!
#!/bin/bash
BaseIP=${1:-192.168.1}
ports=(21 22 25 80 443 9100)
# ports=({1..100}) # Uncomment this for ports 1-100
while IFS=$' \t\r\n/' read serv port prot comm ;do
[ "$prot" = "tcp" ] && printf -v $prot[$port] %s "$serv"
done </etc/services
# ports=(${!tcp[#]}) # Uncomment this for all known ports
isup() { ping -W 1 -c1 -n $1 &>/dev/null && printf "IP: %-17sis up.\n" $1;}
tstport() { local _tst _prot=${3:-tcp}; local -n _var=$_prot[$2]
{
exec {_tst}<>/dev/$_prot/$1/$2 && exec {_tst}<&- &&
printf "IP: %-16s port %6d open (%s)\n" $1 $2 ${_var:-unassigned}
} 2>/dev/null
}
step=$((8180/(${#ports[#]}+1)))
for ((i=1;i < 255;i+=step)) {
max=$((i+step>255?255:i+step))
for ((l=i;l<max;l++)) {
isup $BaseIP.$l &
exec {dummy}< <(:)
for port in ${ports[#]} ;do
exec {dummy2}< <(:)
tstport $BaseIP.$l $port & read -u $dummy2 -t .02
exec {dummy2}<&-
done &
read -u $dummy -t .02
exec {dummy}<&-
} |
sed -une /./p
}
Sorted ouptut could look like:
IP: 192.168.1.1 is up.
IP: 192.168.1.3 is up.
IP: 192.168.1.3 port 22 open (ssh)
IP: 192.168.1.15 is up.
IP: 192.168.1.15 port 22 open (ssh)
IP: 192.168.1.15 port 139 open (netbios-ssn)
IP: 192.168.1.15 port 445 open (microsoft-ds)
IP: 192.168.1.15 port 515 open (printer)
IP: 192.168.1.39 is up.
IP: 192.168.1.39 port 22 open (ssh)
I am trying to wait my docker container is up to start some commands.
i am doing the following :
#!/bin/bash
DOCKER_IP=192.168.99.100
ES_PORT=9300
docker-compose up -d
while [ -z "$(nc -z $DOCKER_IP $ES_PORT)" ]; do
sleep 1
done
echo "Do some stuff now it's up !"
I already check with cat -e the return of nc -z is empty, without the quotes, with [ ! -n $(nc ...)] as conditional expression ...
When the return of nc is not empty, i have Connection to 192.168.99.100 port 9300 [tcp/vrace] succeeded! in loop and it never exit.
Why this simple loop condition is not working ?
The problem is most probably because nc prints the message "Connection to 192.168.99.100 port 9300 [tcp/vrace] succeeded!" on the standard error rather than standard output (otherwise you shouldn't see it). You can redirect standard error (so that it is captured by the command substitution) as follows:
while [ -z "$(nc -z $DOCKER_IP $ES_PORT 2>&1)" ]; do
sleep 1
done
However, not all versions of nc print such a message when connection succeeds (mine doesn't). So why don't you simply use the exit status of nc -z:
while ! nc -z $DOCKER_IP $ES_PORT
do
sleep 1
done
I'm writing a file transfer script and it gets pretty complex. So in the beginning when I generate my IP address to transfer from, I want to validate that I can indeed connect to it. The code in the area looks like this:
USER_ID=$1
if [[ $GROUP == "A" ]]; then
ADDRESS="${USER_ID}#morgan.company.gov"
elif [[ $GROUP == "B" ]]; then
ADDRESS="${USER_ID}#mendel.company.gov"
else
log_msg fatal "Couldn't resolve group $GROUP. Exiting"
exit 1;
fi
// HERE I want to test that $ADDRESS exists, and I can connect right now I
// have what is below. I just think there is a better way to do it
ssh -q $ADDRESS exit
if [ $? != 0 ]; then
log_msg fatal "Couldn't resolve host, do you have login privileges with $ADDRESS"
fi
... // lots of other things happen
scp $ADDRESS:$INCOMING_FILE $NEW_FILE
What I have works, but it doesn't seem like its an elegant solution. I'd prefer not to actually ssh and exit the server, just test the connection.
You can use this shell function that tests wether the host has the ssh port open or not:
#!/bin/bash
function isUp(){
local ip=$1
local sshport=22
if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
if [[ $(nmap -P0 $ip -p$sshport | grep ^$sshport | cut -d' ' -f2) == "open" ]]; then
return 0
else
return 1
fi
fi
}
if isUp $1; then
ssh $1 uptime
else
echo "Host $1 is not available"
fi
or make use of this (new to me) bash functionality:
#!/bin/bash
function isUp(){
local ip=$1
if echo > /dev/tcp/$ip/22 >/dev/null 2>&1; then
return 0
else
return 1
fi
}
If you want to thoroughly check for the connection then you are better off analyzing the return codes from an scp connection. This will allow you to understand the reason why your connection failed and act in consequence (there may be various reasons at different levels, from a general lack of connectivity to issues with the keys for instance).
If you are just interested in a binary answer ("is my connection OK as it is?") then your code is fine, though I would directly use scp.
There is nothing wrong with your line:
ssh -q $ADDRESS exit
This is the best/fastest way to test a connection.
I have the following code in bash:
check_port()
{
local host=${1}
local port=${2}
echo $host
echo $port
while true; do
if nc -w 5 -z 127.0.0.1 111 && nc -w 5 -z 127.0.0.1 5001 ;
then
echo -e "\a\n => Port at host is open"
break
else
echo -e "\a\n => Port at host is closed"
break
fi
}
For some reason, I get the following error:
syntax error near unexpected token `}'
`}'
I don't understand why: } is closing the scope of the function.
You need a done line to terminate your while loop, between the fi line and the closing brace }.
However, I'm not entirely certain why you even have the while true loop since you break out of it regardless of whether the if evaluates to true or false. Hence it's superfluous, unless you plan on changing the behaviour of one of those blocks at some point.
If you're not planning that, you're better off with the much simpler:
check_port()
{
local host=${1}
local port=${2}
echo $host
echo $port
if nc -w 5 -z 127.0.0.1 111 && nc -w 5 -z 127.0.0.1 5001 ; then
echo -e "\a\n => Port at host is open"
else
echo -e "\a\n => Port at host is closed"
fi
}
I'm also not entirely certain of the sanity of passing in the host and port and then ignoring them (instead using localhost with two hard-coded ports).
However, I'm going to assume that you're still in the development/testing phase rather than the possibility you've gone insane :-)
The done at the end of the while loop is missing
....
break
fi
done;
}
Is there any way, using basic Unix commands, to find the next unused port number, starting at port 4444 and going upwards? I'm ssh'ed (via openssh) into a Windows XP machine, running Cygwin tools and using a bash shell.
Thanks, - Dave
Try this:
for port in $(seq 4444 65000); do echo -ne "\035" | telnet 127.0.0.1 $port > /dev/null 2>&1; [ $? -eq 1 ] && echo "unused $port" && break; done
where
seq 4444 65000 - port range for check
echo -ne "\035" - escape character to force close telnet session (^])
if telnet finishes with exit code 1 that mean connection refused:
$ telnet 127.0.0.1 4444
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
telnet: Unable to connect to remote host
$ echo $?
1
else we decided that connection was success with exit code 0.
EDIT:
Special for cygwin: You need to install additional package inetutils that is contain telnet port and use the script as follows:
for port in $(seq 4444 65000); do echo -ne "\035" | /usr/bin/telnet 127.0.0.1 $port > /dev/null 2>&1; [ $? -eq 1 ] && echo "unused $port" && break; done
Same as above, but written as a function
function get_unused_port() {
for port in $(seq 4444 65000);
do
echo -ne "\035" | telnet 127.0.0.1 $port > /dev/null 2>&1;
[ $? -eq 1 ] && echo "$port" && break;
done
}
FREE_PORT="$(get_unused_port)"
echo $FREE_PORT
The following function doesn't depend on telnet/netcat as it generates a random port in the local port range and compares it with a list of ports currently used by running applications.
Should work on any *nix that supports proc filesystem. Generates a free ephemeral port to be used by your application.
function EPHEMERAL_PORT(){
while true; do
LISTENING_PORTS=$(cat /proc/net/tcp | awk 'NR >1 {print $2}' | awk -F':' '{print $2}');
LISTENING_PORTS=$(for PORT in ${LISTENING_PORTS}; do echo $((16#${PORT})); done|sort -g);
# echo "32768 60999" | read LPORT UPORT
read LPORT UPORT < /proc/sys/net/ipv4/ip_local_port_range
MPORT=$[$LPORT + ($RANDOM % $UPORT)];
if (echo "${LISTENING_PORTS[#]}" | grep -xqv $MPORT); then
echo $MPORT;
break;
fi
done
}
Apparently TCP connections can be used as file descriptors on linux. The following function uses that technique and should be faster than the previous one.
function EPHYMERAL_PORT(){
LPORT=32768;
UPORT=60999;
while true; do
MPORT=$[$LPORT + ($RANDOM % $UPORT)];
(echo "" >/dev/tcp/127.0.0.1/${MPORT}) >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo $MPORT;
return 0;
fi
done
}
This is a cross platform function that uses osquery to get a list of listening ports. Should also work on Windows.
function EPHYMERAL_PORT(){
while true; do
echo "32768 60999" | read LPORT UPORT
MPORT=$[$LPORT + ($RANDOM % $UPORT)];
LISTENING_PORTS=$(osqueryi --header=false --list "select port from listening_ports order by port");
if (echo "${LISTENING_PORTS[#]}" | grep -xqv $MPORT); then
echo $MPORT;
break;
fi
done
}
Usage instructions. Bind the output to a variable and use in scripts. Tested on Ubuntu 16.04
root#ubuntu:~> EPHYMERAL_PORT
59453
root#ubuntu:~> PORT=$(EPHYMERAL_PORT)