Ports in an array

Hi All,

I’m new to the forum. I’m working on a function to test ports against a target ip. I am adding what I have for the code below. This the initial code was pulled from an online post after doing a search online. When I run the code, it appears to target the ip address, however it appears that it’s looping through the port number over and over even if I only specify one port. I’m trying to just target one port right now. If I specify port 80 for example, I get 8 and 0 on two separate lines. Any thoughts on where I am off? Thanks!

\
import socket

target = input(‘enter ip address’)
ports_to_scan = input(‘enter port number’)

def port_scanner(target, port):
try:
# Create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Set a timeout for the connection
s.settimeout(1)
# Attempt to connect to the target and Ip port
s.connect((target, port))
# Close the socket
s.close()
return True
except:
return False

for port in ports_to_scan:

if port_scanner(target, port):
    print(f"Port {port} on {target} is OPEN")
else:
    print(f"Port {port} on {target} is CLOSED")

\\

The markup to format your code is three backticks (` character, to the left of 1 on a US keyboard), rather than a backslash.

import socket

target = input('enter ip address')
ports_to_scan = input('enter port number')

def port_scanner(target, port):
    try:
        # Create a socket object
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # Set a timeout for the connection
        s.settimeout(1)
        # Attempt to connect to the target and Ip port
        s.connect((target, port))
        # Close the socket
        s.close()
        return True
    except:
        return False

for port in ports_to_scan:

    if port_scanner(target, port):
        print(f"Port {port} on {target} is OPEN")
    else:
        print(f"Port {port} on {target} is CLOSED")

To answer your question: input always returns a string. So if you input 80 it will get the string "80" and your loop for port in ports_to_scan will loop through that string character-by-character: "8" and then "0".

You will need to convert the input to an integer, and if you want to input multiple ports you will need to define some format for that and do the conversion.

Ok, thanks. I thought input was what I needed to allow a prompt from the user. I even tried 443 and got for example:

4
3
3

I’ll study on how to make this happen. PowerShell, though different, is the only (coding) if you will that I am familiar with. I’m trying to emulate what I do in PowerShell in Python, and this is just one function.

It is how to prompt the user, but it returns a string, not a number or array of numbers. If you type 443 for input(), it’ll give you the string "443", and iterating through the string will give you one character at a time: ["4", "4", "3"] (not 4 3 3, I assume that’s a typo).

We can substitute the value into your code:

target = input('enter ip address')
ports_to_scan = "443"

def port_scanner(target, port):
    ...

for port in "443":
    # the value of port will be "4", then "4", then "3" 
    if port_scanner(target, port):
        print(f"Port {port} on {target} is OPEN")
    else:
        print(f"Port {port} on {target} is CLOSED")

Ok, and yes it was a typo.

Well initially it looks like your problem is just with input(). The
input() function returns a string, because it is something someone has typed.

In Python, strings are iterable things, and iteration gets you each
character (as a 1-character string). So if you have code:

 ports = input("Enter ports to scan: ")

and you type:

 80

you get the string '80', and when you go:

 for port in ports:

Python sets port to the string '8' for the first loop, then to the
string '0' for the second.

This isn’t what you want.

I’m imagining you want to do something like this:

 Enter ports to scan: 80 443

and have a loop which iterates over the numbers 80 and 443.

In Python you get a single string '80 443' from the input(). To
break this up the usual idiom looks like this:

 ports = input("Enter ports to scan: ")
 portnums = [ int(port) for port in ports.split() ]

Strings have a .split() method whose default behaviour is to break a
string up on whitespace. So ports.split() returns this list of
strings:

 [ '80', '443' ]

The socket code is going to want those as integers, so we want to take
each of those and pass it to int(), which is the integer constructor -
given a string, it gives back the corresponding integer. It raises
exceptions if you give it a malformed string. So this
expression:

 portnums = [
     int(port)
     for port in ports.split()
 ]

is a “list comprehension”. It makes a list by taking each value from
ports.split() as the variable port, and putting the result of
int(port) into the list. So it returns this list:

 [ 80, 443 ]

Notice the lack of quote marks: these are now integers, not strings.

Then you can go:

 for portnum in portnums:
     ... scan the port specified by portnum ...

I don’t quite understand. It sounds like you want the user to input only a single number.

Therefore, what is the intended meaning of the loop?

Hi All,

Just now looking at the updates to this thread. Will update after I read. Thanks!

Yes, what you mentioned is what I am trying to do. If they enter one port number then python scans the one port number. If they enter two then it does two and so on. I haven’t worked with python in a bit so I’m rusty.

I was able to make it work! so the int(port) defines it as an integer and the ports.split of course breaks up each. This is what I was looking for. In Powershell I am use to the foreach loop, of course Python is different. A while back I learned about nmap, which is where the whole scanning ports idea came from. It just one piece I am wanting to put into my tool. The idea is that the user is presented with a list of test to choose, this being one of them. After the test is run they go back to the main menu, creating a desktop troubleshooting tool if you will.

1 Like

Hi All, I added what I got so far. Right now when I choose option one, it never allows me to enter the ip address and finishes with exit code 0. Not sure what I am missing, I know I’m getting there though.

\
import socket

def port_scanner(target, portnums):
try:
# Create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Set a timeout for the connection
s.settimeout(1)
# Attempt to connect to the target and Ip port
s.connect((target, portnum))
# Close the socket
s.close()
return True
except:
return False

mylist =
mylist.append("Desktop - Assistant: ")
mylist.append(“1. Run port scan to target address”)
mylist.append(“2. Run Nslookup”)

print(mylist[0])
print(mylist[1])
print(mylist[2])
print(“”)

Option = input("Choose option above: ")

if Option == 1:

target = input('Enter Target IP Address: ')
ports = input('Enter Port Numbers: ')
portnums = [
    int(port)
    for port in ports.split()
]

for portnum in portnums:

    if port_scanner(target, portnums):
        print(f"Port {portnum} on {target} is OPEN")
    else:
        print(f"Port {portnum} on {target} is CLOSED")

\\

First up, you seem to have missed the stuff about strings never
comparing as equal to numbers. You’ve got this code:

 Option = input("Choose option above: ")
 if Option == 1:

The variable Option is holding str, because input() returns a
str. That will never ==1 because 1 is not a str.

Try Option == "1" instead.

The other thing that strikes me is this code:

 def port_scanner(target, portnums):
     try:
         # Create a socket object
         ... try to connect with a timeout ...
         return True
     except:
         return False

This try/except incantation is what we call a “bare except”: it will
catch any exception. Including stuff like NameError if you misspell
a vairable name or a TypeError if you supply some value of an
incorrect type. And hide them.

The basic deal with exceptions is two fold:

  • catch only what you expect to occur and interpret/handle
  • surround small pieces of code so that you have a good idea of the cause of the exception

I’d just be surrounding the connect call itself with something like:

 try:
     s.connect((target, portnum))
 except socket.timeout:
     # connection timed out
     return False

and another except for connection refused.

Let everything else out. They’re unexpected and need to be understood.

1 Like

Yes I didn’t realize I missed that about the input(). I’ll lock that in my head, thanks for explaining. I changed the code and it works! The try/except was like a try/catch from PowerShell to me, is why that was there, changed. The tool is coming along. I’m sure I will post more on this forum. Thanks for the help guys!