4
\$\begingroup\$

Here is my attempt at a simple HTTP proxy scanner/checker. I've been learning python for about 6 months now and decided to move beyond simple scripts and data scrapers.

I think the code looks messy and bulky, especially after if __name__ == '__main__' portion. The program runs well, searching thru either a single IP or an IP range pretty quickly. I've set the sock_timeout pretty low (0.01) which reduces accuracy somewhat but still does the job. There is also an option to "spoof" your MAC for those that need that sort of thing, but requires the package MACSpoof.py from PyPi.

What changes/corrections should be made regarding:

  • Portability (works great on my Linux machine.. not so sure about other OS's)?

  • PEP standards ok?

  • More Pythonic methods?

  • Too many modules?

  • Others?

So here's the code:

#!/usr/bin/env python3

''' proxyscan v1 - scan random networks for proxys '''

from socket import *
from netaddr import IPNetwork
from colorama import Fore, Style
from datetime import datetime
import random, os, pause, sys
from servcheck import is_prox

# some pretty colors for the TERM
red = Fore.RED
blue = Fore.BLUE
green = Fore.GREEN
yellow = Fore.YELLOW
bold = Style.BRIGHT
reset = Style.RESET_ALL

start = datetime.now()

def scan(network):
    host_list = []
    ip = IPNetwork(network)
    print("{}{}{}{}: {}{}{}{} available IPs".format(bold, blue, network, reset, bold, green, len(ip), reset))
    for n in range(len(ip)):
        host_list.append(str(ip[n]))

    for host in host_list:
        target(host)

def target(ip):
    # scan most used proxy ports. more can be added, note: more ports = longer scan time.
    pports = [80, 83, 88, 1080, 3128, 4444, 5800, 6588, 6666, 6800, 8080, 8088, 8118, 8888, 9000, 9999, 45554]
    pcount = 0
    proxys = []
    for port in pports:
        # print("Scanning port: {}{}{}".format(yellow, port, reset))
        s = socket(AF_INET, SOCK_STREAM)
        s.settimeout(0.01)
        result = s.connect_ex((ip, port))
        proto = 'tcp'

        if result == 0:
            print("{}{}{}{}:{} is {}{}OPEN{}".format(bold, blue, ip, reset, port, bold, green, reset))
            try:
                pserv = getservbyport(int(port), proto)
                print("Service: {}{}{}{}".format(bold, green, pserv, reset))
                check_host = "http://" + str(ip) + ":" + str(port)
                print('Checking if proxy is available..')
                pcheck = is_prox(check_host)
                if pcheck == 200:
                    print("{}{}{}: Proxy server available. Saving..".format(green, check_host, reset))
                    pserv = 'http'
                    with open('proxy.lst', 'a') as f:
                        f.write(pserv + " " + str(ip) + " " + str(port) +"\n")

                elif pcheck is None:
                    print("{}{}{}: Unable to establish remote connection. Ignoring IP".format(red, ip, reset))

            except OSError as e:
                print("Service: {}{}{}{}".format(bold, red, e, reset))

        elif result != 0:
            pass
        s.close()

    if pcount < 25:
        pass

    elif pcount == 25:
        print("Found {}{}{} available proxy servers.".format(green, str(len(proxys)), reset))
        end = datetime.now()
        print("Scan took approximately {}{}{}{} seconds".format(bold, blue, (end - start).seconds, reset))
        print("Proxy servers have been saved to {}{}\'proxy.lst\'{}".format(bold, green, reset ))
        sys.exit(0)

if __name__ == '__main__':

    with open('ip_ranges_US.txt', 'r') as f:
        subnets = f.readlines()

        netlist = []
        num_ips = len(subnets)
        while len(netlist) < 30:
            rand_ip = random.randint(0, num_ips)
            try:
                netlist.append(subnets[rand_ip])
            except IndexError:
                pass

    print("{}{}_-=-_{}".format(bold, yellow, reset)*5)
    print("{}{}    ProxyScan.py v1       {}".format(bold, blue, reset))
    print("{}{}_-=-_{}".format(bold, yellow, reset)*5)
    need_spoof = input("\nWould you like to spoof your MAC address?(y/n):")
    if need_spoof is 'y':
        if os.geteuid() != 0 or os.path.isfile("mac-spoof.py") is False:
            exit("{} This options requires root access and the script {}mac-spoof.py{}\n"
                 "{} if you do not have the {}MacSpoof script{}{}, please install by typing:\n"
                 "{} sudo -H pip3 install MacSpoof\"{}{} and then re-run proxyscan.py as root{}\n".format(bold, red, reset, bold, red, reset, bold, red, reset, bold, reset))
        try:
            print(os.system("spoof-mac.py list"))
            net_dev = input("Please enter the {}device{} you wish to spoof: ".format(red, reset))
            print("Randomizing MAC address. Please wait..\n")
            pause.seconds(10)
            os.system("spoof-mac.py randomize " + net_dev)
            pause.seconds(15)
        except Exception as e:
            print("Unable to spoof MAC. Skipping..")

    print("{}{}Initializing scanner..\nPlease wait this may take some time.{}".format(bold, yellow, reset))
    for net in netlist:
        ip = net.lstrip().strip('\n')

        try:
            scan(ip)
        except KeyboardInterrupt:
            print("\nExiting..")
            sys.exit(0)

and the code for servcheck module:

#!/usr/bin/env python3
''' Proxy server checker for proxyscan.py '''

import requests

def is_prox(proxy_server):
    proxyDict = {"http": proxy_server,
                 "https": proxy_server,
                 "socks": proxy_server}

    test_site = {"http://www.google.com", "http://whatsmyip.org", "http://www.facebook.com"}
    headers = {'user-agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)'}

    for site in test_site:
        try:
            r = requests.get(site, headers=headers, proxies=proxyDict)
            status = r.status_code
            if status is 200:
                return status     
            else:
                return None
        except Exception:
            return


if __name__ == '__main__':
      is_prox()

Finally the output:

skywalker@endor:~/scripts/python/proxyupdate$ python3 proxyscan.py
_-=-__-=-__-=-__-=-__-=-_
    ProxyScan.py v1       
_-=-__-=-__-=-__-=-__-=-_

Would you like to spoof your MAC address?(y/n):n
Initializing scanner..
Please wait this may take some time.
192.168.2.0/24: 256 available IPs
192.168.2.2:8080 is OPEN
Service: http-alt
Checking if proxy is available..
192.168.2.2: Unable to establish remote connection. Ignoring IP
192.168.2.5:80 is OPEN
Service: http
Checking if proxy is available..
http://192.168.2.5:80: Proxy server available. Saving..
\$\endgroup\$
2
\$\begingroup\$

Looks pretty good.

  • You might factor out the with block under that if __name__ == '__main__' into something like netlist = get_netlist('ip_ranges_US.txt').

  • the 'r' argument to open() is redundant;files are opened read-only by default.

\$\endgroup\$
  • \$\begingroup\$ Oh good point. I actually meant to add an arg to allow users to enter their own network lists, rather than have it hard-coded into the program. Thanks for the tip! \$\endgroup\$ – Aaron Nelson Jul 15 '17 at 12:10
1
\$\begingroup\$

If you are using Python 3.6+, you could be using f-strings. This helps making your string formatting a lot easier to read (especially with all the colors and bold...). Here is your scan function using them:

def scan(network):
    hosts = IPNetwork(network)
    print(f"{bold}{blue}{network}{reset}: {bold}{green}{len(hosts)}{reset} available IPs")
    for host in map(str, hosts):
        target(host)

I also got rid of your host_list, since you don't use it for anything else and all you did was calling str on all the members of ip, anyways.

\$\endgroup\$
  • 1
    \$\begingroup\$ Thanks for the tip on f-strings, I'm self-learning here and haven't come across them yet. Dropping host_list is a good idea since like you said I'm calling str(ip) anyway. I'm going to use your suggested improvement but I'm going to wait awhile before marking it as the accepted answer in case there are other solutions. \$\endgroup\$ – Aaron Nelson Jul 14 '17 at 20:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.