Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
08e0a6c
py3first in
doomedraven Oct 13, 2019
31e5ab5
Update setup.py
doomedraven Oct 13, 2019
60ff544
Update setup.py
doomedraven Oct 13, 2019
1d93385
Merge branch 'master' into master
doomedraven Oct 13, 2019
0b3c54f
fix bytes vs string
doomedraven Oct 13, 2019
f05cfea
more py3 friendly and better error handling
doomedraven Oct 13, 2019
b3aeffa
Merge branch 'master' of https://github.com/doomedraven/socks5man
doomedraven Oct 13, 2019
8543e18
remove six, pure py3, tests update
doomedraven Oct 15, 2019
7ec61a0
Update .travis.yml
doomedraven Oct 17, 2019
51a3e5a
Update test_socks5.py
doomedraven Oct 17, 2019
4cfa302
coerceutf8
doomedraven Oct 17, 2019
5e8981e
no coerce utf-8
doomedraven Oct 17, 2019
c07d5bd
fixes
doomedraven Oct 17, 2019
e8dfdbf
fix them all yey
doomedraven Oct 17, 2019
96889f1
update version and base python3.6 as lower
doomedraven Oct 17, 2019
ac2db90
fix travis and appveyor
doomedraven Oct 17, 2019
060fca4
test
doomedraven Oct 17, 2019
3db7c65
Merge branch 'py3' into master
doomedraven Oct 18, 2019
53b4efd
Update .travis.yml
doomedraven Oct 18, 2019
5da3629
few fixes
doomedraven Oct 18, 2019
2ff616c
Merge branch 'master' of https://github.com/doomedraven/socks5man
doomedraven Oct 18, 2019
7a19065
Merge branch 'py3' into master
doomedraven Oct 18, 2019
c2c0453
sync
doomedraven Oct 18, 2019
07049d8
test
doomedraven Oct 18, 2019
1927d62
we don't need to encode data to late decode
doomedraven Oct 20, 2019
9edcc2b
Update helpers.py
doomedraven Oct 20, 2019
1d7d615
fixes
doomedraven Oct 20, 2019
5ad5d32
improve main
doomedraven Oct 20, 2019
f4ef76a
add private option for server if ip isn't in privare ip range
doomedraven Oct 20, 2019
0edeac7
fix unit tests
doomedraven Oct 20, 2019
12ed669
Update .travis.yml
doomedraven Oct 20, 2019
0392f4d
test me hard
doomedraven Oct 20, 2019
3b42c15
Update .travis.yml
doomedraven Oct 20, 2019
e9f2af8
Update .travis.yml
doomedraven Oct 20, 2019
9685d0e
Update .travis.yml
doomedraven Oct 20, 2019
777ddab
Update .travis.yml
doomedraven Oct 20, 2019
be81c9c
Update .travis.yml
doomedraven Oct 20, 2019
8c7cf2b
Update .travis.yml
doomedraven Oct 20, 2019
a316a69
Update .travis.yml
doomedraven Oct 20, 2019
1c3af42
Update .travis.yml
doomedraven Oct 20, 2019
a9fbc6d
Update .travis.yml
doomedraven Oct 20, 2019
c24137b
Update .travis.yml
doomedraven Oct 20, 2019
413a4f7
Update pythonpackage.yml
doomedraven Oct 20, 2019
dce11c3
Update pythonpackage.yml
doomedraven Oct 20, 2019
5af2016
Update pythonpackage.yml
doomedraven Oct 20, 2019
921e467
Update pythonpackage.yml
doomedraven Oct 20, 2019
a37f34c
Update pythonpackage.yml
doomedraven Oct 20, 2019
401b446
Update pythonpackage.yml
doomedraven Oct 20, 2019
9918103
Delete pythonpackage.yml
doomedraven Oct 20, 2019
56c1dd6
Create pythonpackage.yml
doomedraven Oct 20, 2019
8fd5de8
Delete .travis.yml
doomedraven Oct 20, 2019
a430cfb
Delete appveyor.yml
doomedraven Oct 20, 2019
552ee34
Update pythonpackage.yml
doomedraven Oct 20, 2019
f2f089e
swap badfges from travis to github actions
doomedraven Oct 20, 2019
ad0f33b
Update setup.py
doomedraven Oct 31, 2019
f5398b6
Update pythonpackage.yml
doomedraven Jun 2, 2020
f79974f
Update pythonpackage.yml
doomedraven Jun 2, 2020
c53ccaa
Update pythonpackage.yml
doomedraven Jun 2, 2020
3f5193e
Update setup.py
doomedraven Jun 4, 2020
d207af2
Update requirements.txt
doomedraven Feb 15, 2021
dd4c2cd
Create requirements.txt
doomedraven Feb 15, 2021
3880eb0
Update requirements.txt
doomedraven Jun 3, 2021
9695020
Update setup.py
doomedraven Jun 24, 2021
7b335d0
Update pythonpackage.yml
doomedraven Jun 24, 2021
7d02d40
Update pythonpackage.yml
doomedraven Jan 20, 2023
f4b34c4
Update requirements.txt
doomedraven Mar 9, 2023
7526c0d
fixed #1
federicofantini Mar 10, 2023
0fbe295
Merge pull request #11 from federicofantini/master
doomedraven Mar 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: build

on: [push]

jobs:
tester:
name: Test them all
runs-on: ${{ matrix.operating-system }}
strategy:
max-parallel: 4
matrix:
operating-system: [ubuntu-latest]
python-version: [3.8, 3.11]

steps:
- uses: actions/checkout@v1
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest>=3.6 mock "pytest-cov<2.6.0" codecov win_inet_pton
pip install -r requirements.txt
- name: Test with pytest
run: |
pip install pytest
pytest
18 changes: 0 additions & 18 deletions .travis.yml

This file was deleted.

16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Socks5man is a Socks5 management tool and Python library. It
enables you to add socks5 servers, run a service that verifies if
they are operational, and request these servers in a round-robin fashion
by country, city, average connection time, and bandwidth, using the Python library.

The library also allows for manual operationality, bandwidth, and connection time tests.
A local database is used to lookup country and city information for a host ip.

The documentation can be found at: [https://socks5man.readthedocs.io](https://socks5man.readthedocs.io).

This product includes GeoLite2 data created by MaxMind, available from [maxmind.com](maxmind.com).

![](https://github.com/RicoVZ/socks5man/workflows/build/badge.svg)

* [maxmind.com](http://www.maxmind.com)
* [https://socks5man.readthedocs.io](https://socks5man.readthedocs.io)
26 changes: 0 additions & 26 deletions README.rst

This file was deleted.

20 changes: 0 additions & 20 deletions appveyor.yml

This file was deleted.

1 change: 1 addition & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

# -- Project information -----------------------------------------------------

from __future__ import absolute_import
project = u'Socks5man'
copyright = u'2016-2018'
author = u'Ricardo van Zutphen'
Expand Down
10 changes: 5 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PySocks==1.5.7
geoip2==2.9.0
SQLAlchemy>=1.3.3, <1.4
click==6.6
alembic>=1.0.7, <1.1
PySocks>=1.7
geoip2>=2.9.0
SQLAlchemy
click
alembic
15 changes: 4 additions & 11 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import sys
from __future__ import absolute_import

from setuptools import setup

if sys.version[0] != "2":
sys.exit(
"Socks5man currently only supports Python 2.7. 3.5+ is on the roadmap"
", but is not supported yet. For now, please install it in the"
" following way: `pip2 install -U socks5man`."
)

setup(
name="Socks5man",
version="0.2.0",
version="0.3.0",
author="Ricardo van Zutphen",
author_email="ricardo@hatching.io",
packages=[
Expand All @@ -37,11 +30,11 @@
],
license="GPLv3",
description="SOCKS5 server management tool and library",
long_description=open("README.rst", "rb").read(),
long_description=open("README.md", "r").read(),
include_package_data=True,
url="https://github.com/RicoVZ/socks5man",
install_requires=[r.strip() for r in open("requirements.txt", "r").readlines()],
python_requires=">=2.7, <3.0",
python_requires=">=3.6",
extras_require={
":sys_platform == 'win32'": [
"win-inet-pton==1.0.1",
Expand Down
1 change: 1 addition & 0 deletions socks5man/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

7 changes: 4 additions & 3 deletions socks5man/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ConfigParser
from __future__ import absolute_import
import os
import configparser

from socks5man.exceptions import Socks5ConfigError
from socks5man.misc import cwd
Expand Down Expand Up @@ -43,7 +44,7 @@ def read(self):
if Config._cache:
Config._cache = {}

config = ConfigParser.ConfigParser()
config = configparser.ConfigParser()

confpath = cwd("conf", "socks5man.conf")
if not os.path.isfile(confpath):
Expand All @@ -53,7 +54,7 @@ def read(self):
)
try:
config.read(confpath)
except ConfigParser.Error as e:
except configparser.Error as e:
raise Socks5ConfigError(
"Cannot parse config file. Error: %s" % e
)
Expand Down
23 changes: 11 additions & 12 deletions socks5man/database.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from __future__ import absolute_import
import logging
import os
from datetime import datetime

from sqlalchemy import (
Column, Integer, String, DateTime, Boolean, Text, create_engine,
Float, and_, func
Float, and_, func, inspect
)
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.declarative import declarative_base
Expand Down Expand Up @@ -45,12 +46,14 @@ class Socks5(Base):
connect_time = Column(Float(), nullable=True)
description = Column(Text(), nullable=True)
dnsport = Column(Integer(), nullable=True)
private = Column(Boolean, nullable=True)

def __init__(self, host, port, country, country_code):
def __init__(self, host, port, country, country_code, private):
self.host = host
self.port = port
self.country = country
self.country_code = country_code
self.private = private

def to_dict(self):
"""Converts object to dict.
Expand All @@ -62,7 +65,7 @@ def to_dict(self):
value = getattr(self, column.name)
if isinstance(value, datetime):
socks_dict[column.name] = value.strftime("%Y-%m-%d %H:%M:%S")
elif isinstance(value, (str, basestring)):
elif isinstance(value, str):
socks_dict[column.name] = value.encode("utf-8")
else:
socks_dict[column.name] = value
Expand All @@ -77,9 +80,7 @@ def __repr__(self):
)


class Database(object):

__metaclass__ = Singleton
class Database(object, metaclass=Singleton):

def __init__(self):
self.connect(create=True)
Expand All @@ -90,9 +91,7 @@ def connect(self, create=False):
if create:
if not os.path.exists(cwd("socks5man.db")):
self._create()
elif not self.engine.dialect.has_table(
self.engine, AlembicVersion.__tablename__
):
elif not inspect(self.engine).has_table(AlembicVersion.__tablename__):
AlembicVersion.__table__.create(self.engine)

def _create(self):
Expand All @@ -117,9 +116,9 @@ def db_migratable(self):
ses.close()

def add_socks5(self, host, port, country, country_code, operational=False,
city=None, username=None, password=None, dnsport=None, description=None):
city=None, username=None, password=None, dnsport=None, description=None, private=False):
"""Add new socks5 server to the database"""
socks5 = Socks5(host, port, country, country_code)
socks5 = Socks5(host, port, country, country_code, private)
socks5.operational = operational
socks5.city = city
socks5.username = username
Expand Down Expand Up @@ -381,7 +380,7 @@ def bulk_delete_socks5(self, ids_list):
@param ids_list: A list of socks5 ids to delete"""
chunk = 100
try:
for c in xrange(0, len(ids_list), chunk):
for c in range(0, len(ids_list), chunk):
self.engine.execute(
Socks5.__table__.delete().where(
Socks5.id.in_(ids_list[c:c+chunk])
Expand Down
19 changes: 11 additions & 8 deletions socks5man/helpers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from __future__ import absolute_import
import logging
import socket
import socks
import struct
import time
import urllib2
import urllib.request
import urllib.error

from socks5man.config import cfg
from socks5man.constants import IANA_RESERVERD_IPV4_RANGES
Expand Down Expand Up @@ -48,6 +50,8 @@ def is_ipv4(ip):
"""Try to parse string as Ipv4. Return True if success, False
otherwise"""
try:
if not isinstance(ip, type(str)):
ip = str(ip)
socket.inet_aton(ip)
return True
except socket.error:
Expand Down Expand Up @@ -125,19 +129,18 @@ def validify_host_port(host, port):

def get_over_socks5(url, host, port, username=None, password=None, timeout=3):
"""Make a HTTP GET request over socks5 of the given URL"""
socks.set_default_proxy(
socks.SOCKS5, host, port,
username=username, password=password
)

socks.set_default_proxy(socks.SOCKS5, host, port, username=username, password=password)

response = None
clean_socket = socket.socket
try:
socket.socket = socks.socksocket
response = urllib2.urlopen(url, timeout=timeout).read()
except (socket.error, urllib2.URLError, socks.ProxyError) as e:
response = urllib.request.urlopen(url, timeout=timeout).read()
except urllib.error.URLError as e:
log.error("Error making HTTP GET over socks5: %s", e)
finally:
socket.socket = socket._socketobject
socket.socket = clean_socket
return response

def approximate_bandwidth(host, port, username=None, password=None,
Expand Down
1 change: 1 addition & 0 deletions socks5man/logs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import absolute_import
import copy
import logging
import sys
Expand Down
19 changes: 12 additions & 7 deletions socks5man/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import absolute_import
from __future__ import print_function
import click
import csv
import logging
Expand Down Expand Up @@ -63,7 +65,8 @@ def verify(repeated, operational, non_operational, unverified):
@click.option("-u", "--username", help="Username for this socks5 server")
@click.option("-p", "--password", help="Password for this socks5 server")
@click.option("-d", "--description", help="Description for this socks5 server")
def add(host, port, username, password, description):
@click.option("-pi", "--private", is_flag=True, help="Private server ip")
def add(host, port, username, password, description, private):
"""Add socks5 server."""
if username and not password or password and not username:
log.warning(
Expand All @@ -75,7 +78,7 @@ def add(host, port, username, password, description):
try:
entry = m.add(
host, port, username=username, password=password,
description=unicode(description)
description=description, private=private
)
except Socks5manError as e:
log.error("Failed to add socks5 server: %s", e)
Expand Down Expand Up @@ -217,20 +220,22 @@ def list(country, code, city, host, operational, non_operational, count,
sys.exit(0)

if not export:
print(
print((
"{:<4} {:<12} {:<20} {:<5} {:<16} {:<12} {:<16} {:<16} {:<16}{:<16}".format(
"ID", "Operational", "Host", "Port", "Country", "Country Code", "City",
"Username", "Password", "Description",
)
)
))
for socks5 in socks5s:
print(
"{:<4} {:<12} {:<20} {:<5} {:<16} {:<12} {:<16} {:<16} {:<16} {:<16}".format(
socks5.id, "Yes" if socks5.operational else "No", socks5.host, socks5.port,
socks5.country, socks5.country_code, socks5.city,
socks5.username, socks5.password, socks5.description
socks5.username if socks5.username else "", socks5.password if socks5.password else "",
socks5.description if socks5.description else ""
)
)

sys.exit(0)

if os.path.exists(export):
Expand All @@ -243,10 +248,10 @@ def list(country, code, city, host, operational, non_operational, count,
for socks5 in socks5s:
socks5_d = socks5.to_dict()
if header:
csv_w.writerow(socks5_d.keys())
csv_w.writerow(list(socks5_d.keys()))
header = False

csv_w.writerow(socks5_d.values())
csv_w.writerow(list(socks5_d.values()))


@main.command()
Expand Down
Loading