예제 #1
0
    def test_ipv4info_invalid(self):
        tmppath = self.tempfile.mkdtemp()
        set_cwd(tmppath)
        create_cwd(tmppath)

        geo = GeoInfo()
        res = geo.ipv4info("8adna87dasd87asd")
        assert res["country"] == "unknown"
        assert res["country_code"] == "unknown"
        assert res["city"] == "unknown"
예제 #2
0
    def test_ipv4info_unknown(self):
        tmppath = self.tempfile.mkdtemp()
        set_cwd(tmppath)
        create_cwd(tmppath)

        geo = GeoInfo()
        res = geo.ipv4info("10.0.0.5")
        assert res["country"] == "unknown"
        assert res["country_code"] == "unknown"
        assert res["city"] == "unknown"
예제 #3
0
    def test_ipv4info(self):
        tmppath = self.tempfile.mkdtemp()
        set_cwd(tmppath)
        create_cwd(tmppath)

        geo = GeoInfo()
        res = geo.ipv4info("93.184.216.34")
        assert res["country"] == "United States"
        assert res["country_code"] == "US"
        assert res["city"] == "Norwell"
예제 #4
0
파일: manager.py 프로젝트: RicoVZ/socks5man
    def add(self, host, port, username=None, password=None, description=None):
        """Add a socks5 server.

        :param host: IP or a valid hostname of the socks5 server.
            Should be unique.
        :param port: Port of the socks5 server (int)
        :param username: Username of the socks5 server (optional)
        :param password: Password for the socks5 server user (optional).
            Password will be stored in plaintext!
        :param description: Description to store with the socks5 server
            (optional)
        :return: A dictionary containing the provided information,
            the generated id, the determined country, country code, and city.
        :rtype: dict

        :raises: Socks5CreationError

        :example:

        >>> from socks5man.manager import Manager
        >>> Manager().add("example.com", 8456)
            {
                'username': None,
                'city': u'Norwell',
                'host': 'example.com',
                'country_code': u'US',
                'country': u'United States',
                'password': None,
                'port': 8456,
                'id': 1
            }

        .. note::
            It is only possible to provide both a username and a password.
            Hostname/IP should be unique. If a socks5 exists with the provided
            hostname/IP, a Socks5CreationError will be thrown.
        """
        if (not username and password) or (not password and username):
            raise Socks5CreationError(
                "Either no password and no password or both a password and a"
                "username should be provided on socks5 creation. It is not "
                "possible to provide only a username or password"
            )

        valid_entry = validify_host_port(host, port)
        if not valid_entry:
            raise Socks5CreationError(
                "Invalid host or port used. Invalid IP, non-existing hostname"
                ", or an invalid port specified. Host: %s, port: %s" % (
                    host, port
                )
            )

        existing = db.view_socks5(host=host, port=port)
        if existing:
            raise Socks5CreationError(
                "Socks5 host and port combination: '%s:%s' already exists."
                " Socks5 ID is: %s" % (
                    host, port, existing.id
                )
            )

        entry = Dictionary(
            host=host,
            port=port,
            username=username,
            password=password
        )
        entry.update(GeoInfo.ipv4info(valid_entry.ip))
        socksid = db.add_socks5(
            entry.host, entry.port, entry.country, entry.country_code,
            city=entry.city, username=entry.username, password=entry.password,
            description=description
        )

        entry["id"] = socksid
        return entry
예제 #5
0
파일: manager.py 프로젝트: RicoVZ/socks5man
    def bulk_add(self, socks5_dict_list, description=None):
        """Bulk add multiple socks5 server. No duplicate checking is done.

        :param socks5_dict_list: A list of dictionaries that at a minimum
            contain the keys and valid values for 'host' and 'port'.
        :param description: A description to be added to all provided servers
        :returns: The amount of socks5 server that were successfully added
        :rtype: int

        :raises: Socks5CreationError

        :example:

        >>> from socks5man.manager import Manager
        >>> Manager().bulk_add([{"host": "example.com", "port": 1234}, {"host": "example.org", "port": 1234}])
        2

        .. note::
            It is only possible to provide both a username and a password for a
            server. Hostname/IP should be unique. Socks5 servers with invalid
            hostnames or missing fields will be skipped. Socks5CreationError
            is raised if no valid servers are in the list.
        """
        new = []
        for entry in socks5_dict_list:
            if "host" not in entry or "port" not in entry:
                continue

            password = entry.get("password")
            username = entry.get("username")
            if (not username and password) or (not password and username):
                log.warning(
                    "Either no password and no password or both a password "
                    "and a username should be provided on socks5 creation. It "
                    "is not possible to provide only a username or password"
                )
                continue

            valid_entry = validify_host_port(entry["host"], entry["port"])

            if not valid_entry:
                log.error("Invalid host or port provided")
                continue

            if description:
                entry["description"] = description

            new_entry = {
                "host": entry["host"],
                "port": valid_entry.port,
                "country": None,
                "country_code": None,
                "city": None,
                "username": username,
                "password": password,
                "operational": False,
                "description": entry.get("description")
            }
            new_entry.update(GeoInfo.ipv4info(valid_entry.ip))
            new.append(new_entry)

        if not new:
            raise Socks5CreationError("No socks5 servers to add provided")

        db.bulk_add_socks5(new)
        return len(new)
예제 #6
0
def update_geodb():
    version_file = cwd("geodb", ".version")
    if not os.path.isfile(version_file):
        log.error("No geodb version file '%s' is missing", version_file)
        return

    with open(version_file, "rb") as fp:
        current_version = fp.read()

    try:
        latest_version = urllib2.urlopen(cfg("geodb", "geodb_md5_url")).read()
    except urllib2.URLError as e:
        log.error("Error retrieving latest geodb version hash: %s", e)
        return

    if current_version == latest_version:
        log.info("GeoIP database at latest version")
        return

    extracted = cwd("geodb", "extracted")
    renamed = None
    if os.path.exists(extracted):
        renamed = cwd("geodb", "old-extracted")
        os.rename(extracted, renamed)

    try:
        url = cfg("geodb", "geodb_url")
        log.info("Downloading latest version: '%s'", url)
        mmdbtar = urllib2.urlopen(url).read()
    except urllib2.URLError as e:
        log.error(
            "Failed to download new mmdb tar. Is the URL correct? %s", e
        )
        if renamed:
            log.error("Restoring old version..")
            os.rename(renamed, extracted)
        return

    tarpath = cwd("geodb", "geodblite.tar.gz")
    with open(tarpath, "wb") as fw:
        fw.write(mmdbtar)

    os.mkdir(extracted)

    unpack_mmdb(tarpath, cwd("geodb", "extracted", "geodblite.mmdb"))
    log.info("Version update complete")

    if renamed:
        log.debug("Removing old version")
        shutil.rmtree(renamed)

    log.info("Updating geo IP information for all existing servers")
    GeoInfo.georeader = None
    for socks5 in db.list_socks5():
        log.debug(
            "Updating server: '%s'. Current country: %s",
            socks5.host, socks5.country
        )
        ip = socks5.host
        if not is_ipv4(ip):
            ip = get_ipv4_hostname(ip)

        geoinfo = GeoInfo.ipv4info(ip)
        old = (socks5.country, socks5.country_code, socks5.city)
        new = (geoinfo["country"], geoinfo["country_code"], geoinfo["city"])
        if old == new:
            log.debug("Geo IP info unchanged")
            continue

        log.debug(
            "Geo IP info changed. New country=%s, country_code=%s, city=%s",
            geoinfo["country"], geoinfo["country_code"], geoinfo["city"]
        )
        db.update_geoinfo(
            socks5.id, country=geoinfo["country"],
            country_code=geoinfo["country_code"], city=geoinfo["city"]
        )
예제 #7
0
    def add(self,
            host,
            port,
            username=None,
            password=None,
            dnsport=None,
            description=None,
            private=False):
        """Add a socks5 server.

        :param host: IP or a valid hostname of the socks5 server.
            Should be unique.
        :param port: Port of the socks5 server (int)
        :param username: Username of the socks5 server (optional)
        :param password: Password for the socks5 server user (optional).
            Password will be stored in plaintext!
        :param dnsport: Port to forward dns requests
            (optional)
        :param description: Description to store with the socks5 server
            (optional)
        :param private: IP type, private server
            (optional)
        :return: A dictionary containing the provided information,
            the generated id, the determined country, country code, and city.
        :rtype: dict

        :raises: Socks5CreationError

        :example:

        >>> from socks5man.manager import Manager
        >>> Manager().add("example.com", 8456)
            {
                'username': None,
                'city': u'Norwell',
                'host': 'example.com',
                'country_code': u'US',
                'country': u'United States',
                'password': None,
                'port': 8456,
                'id': 1
            }

        .. note::
            It is only possible to provide both a username and a password.
            Hostname/IP should be unique. If a socks5 exists with the provided
            hostname/IP, a Socks5CreationError will be thrown.
        """
        if (not username and password) or (not password and username):
            raise Socks5CreationError(
                "Either no password and no password or both a password and a"
                "username should be provided on socks5 creation. It is not "
                "possible to provide only a username or password")

        valid_entry = validify_host_port(host, port)
        if not valid_entry:
            raise Socks5CreationError(
                "Invalid host or port used. Invalid IP, non-existing hostname"
                ", or an invalid port specified. Host: %s, port: %s" %
                (host, port))

        existing = db.view_socks5(host=host, port=port)
        if existing:
            raise Socks5CreationError(
                "Socks5 host and port combination: '%s:%s' already exists."
                " Socks5 ID is: %s" % (host, port, existing.id))

        entry = Dictionary(
            host=host,
            port=port,
            username=username,
            password=password,
        )
        entry.update(GeoInfo.ipv4info(valid_entry.ip))
        socksid = db.add_socks5(
            entry.host,
            entry.port,
            entry.country,
            entry.country_code,
            city=entry.city,
            username=entry.username,
            password=entry.password,
            dnsport=dnsport,
            description=description,
            private=private,
        )

        entry["id"] = socksid
        return entry
예제 #8
0
    def bulk_add(self, socks5_dict_list, description=None):
        """Bulk add multiple socks5 server. No duplicate checking is done.

        :param socks5_dict_list: A list of dictionaries that at a minimum
            contain the keys and valid values for 'host' and 'port'.
        :param description: A description to be added to all provided servers
        :returns: The amount of socks5 server that were successfully added
        :rtype: int

        :raises: Socks5CreationError

        :example:

        >>> from socks5man.manager import Manager
        >>> Manager().bulk_add([{"host": "example.com", "port": 1234}, {"host": "example.org", "port": 1234}])
        2

        .. note::
            It is only possible to provide both a username and a password for a
            server. Hostname/IP should be unique. Socks5 servers with invalid
            hostnames or missing fields will be skipped. Socks5CreationError
            is raised if no valid servers are in the list.
        """
        new = []
        for entry in socks5_dict_list:
            if "host" not in entry or "port" not in entry:
                continue

            password = entry.get("password")
            username = entry.get("username")
            if (not username and password) or (not password and username):
                log.warning(
                    "Either no password and no password or both a password "
                    "and a username should be provided on socks5 creation. It "
                    "is not possible to provide only a username or password")
                continue

            valid_entry = validify_host_port(entry["host"], entry["port"])

            if not valid_entry:
                log.error("Invalid host or port provided")
                continue

            if description:
                entry["description"] = description

            new_entry = {
                "host": entry["host"],
                "port": valid_entry.port,
                "country": None,
                "country_code": None,
                "city": None,
                "username": username,
                "password": password,
                "operational": False,
                "dnsport": entry.get("dnsport"),
                "description": entry.get("description"),
                "private": entry.get("private"),
            }
            new_entry.update(GeoInfo.ipv4info(valid_entry.ip))
            new.append(new_entry)

        if not new:
            raise Socks5CreationError("No socks5 servers to add provided")

        db.bulk_add_socks5(new)
        return len(new)