Code Monkey home page Code Monkey logo

pysocks's Introduction

PySocks

PySocks lets you send traffic through SOCKS proxy servers. It is a modern fork of SocksiPy with bug fixes and extra features.

Acts as a drop-in replacement to the socket module. Seamlessly configure SOCKS proxies for any socket object by calling socket_object.set_proxy().


Features

  • SOCKS proxy client for Python 2.7 and 3.4+
  • TCP supported, UDP mostly supported (issues may occur in some edge cases)
  • HTTP proxy client included but not supported or recommended (you should use requests', or your HTTP client's, own HTTP proxy interface)
  • urllib2 handler included, but not supported. pip install / setup.py install will automatically install the sockshandler module.

Installation

pip install pysocks

Or download the tarball / git clone and...

python setup.py install

These will install both the socks and sockshandler modules.

Alternatively, include just socks.py in your project.

Proxying HTTP Traffic

We highly recommend using the requests library for proxying HTTP traffic with SOCKS or HTTP proxies. It uses PySocks under the hood.

requests.get(url, proxies={"http": "socks5://proxyhostname:9050", "https": "socks5://proxyhostname:9050"})

PySocks has an option for HTTP proxies, but it only supports CONNECT-based HTTP proxies, and in general we recommend using your HTTP client's native proxy support (such as requests' proxies keyword argument) rather than PySocks'.

If you absolutely must, you can use the urllib2 handler in sockshandler.py, but it's not supported (and won't work for non-CONNECT-based HTTP proxies, as stated above).


Usage

socks.socksocket

import socks

s = socks.socksocket() # Same API as socket.socket in the standard lib

s.set_proxy(socks.SOCKS5, "localhost") # SOCKS4 and SOCKS5 use port 1080 by default
# Or
s.set_proxy(socks.SOCKS4, "localhost", 4444)
# Or
s.set_proxy(socks.HTTP, "5.5.5.5", 8888)

# Can be treated like a regular socket object
s.connect(("www.somesite.com", 80))
s.sendall("GET / HTTP/1.1 ...")
print(s.recv(4096))

Monkeypatching

To monkeypatch the entire standard library with a single default proxy:

import urllib2
import socket
import socks

socks.set_default_proxy(socks.SOCKS5, "localhost")
socket.socket = socks.socksocket

Note that monkeypatching may not work for all standard modules or for all third party modules, and generally isn't recommended. Monkeypatching is usually an anti-pattern in Python.


Original SocksiPy README attached below, amended to reflect API changes.


SocksiPy

A Python SOCKS module.

(C) 2006 Dan-Haim. All rights reserved.

See LICENSE file for details.

WHAT IS A SOCKS PROXY?

A SOCKS proxy is a proxy server at the TCP level. In other words, it acts as a tunnel, relaying all traffic going through it without modifying it. SOCKS proxies can be used to relay traffic using any network protocol that uses TCP.

WHAT IS SOCKSIPY?

This Python module allows you to create TCP connections through a SOCKS proxy without any special effort. It also supports relaying UDP packets with a SOCKS5 proxy.

PROXY COMPATIBILITY

SocksiPy is compatible with three different types of proxies:

  1. SOCKS Version 4 (SOCKS4), including the SOCKS4a extension.
  2. SOCKS Version 5 (SOCKS5).
  3. HTTP Proxies which support tunneling using the CONNECT method.

SYSTEM REQUIREMENTS

Being written in Python, SocksiPy can run on any platform that has a Python interpreter and TCP/IP support. This module has been tested with Python 2.3 and should work with greater versions just as well.

INSTALLATION

Simply copy the file "socks.py" to your Python's lib/site-packages directory, and you're ready to go. [Editor's note: it is better to use python setup.py install for PySocks]

USAGE

First load the socks module with the command:

>>> import socks
>>>

The socks module provides a class called socksocket, which is the base to all of the module's functionality.

The socksocket object has the same initialization parameters as the normal socket object to ensure maximal compatibility, however it should be noted that socksocket will only function with family being AF_INET and type being either SOCK_STREAM or SOCK_DGRAM. Generally, it is best to initialize the socksocket object with no parameters

>>> s = socks.socksocket()
>>>

The socksocket object has an interface which is very similiar to socket's (in fact the socksocket class is derived from socket) with a few extra methods. To select the proxy server you would like to use, use the set_proxy method, whose syntax is:

set_proxy(proxy_type, addr[, port[, rdns[, username[, password]]]])

Explanation of the parameters:

proxy_type - The type of the proxy server. This can be one of three possible choices: PROXY_TYPE_SOCKS4, PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP for SOCKS4, SOCKS5 and HTTP servers respectively. SOCKS4, SOCKS5, and HTTP are all aliases, respectively.

addr - The IP address or DNS name of the proxy server.

port - The port of the proxy server. Defaults to 1080 for socks and 8080 for http.

rdns - This is a boolean flag than modifies the behavior regarding DNS resolving. If it is set to True, DNS resolving will be preformed remotely, on the server. If it is set to False, DNS resolving will be preformed locally. Please note that setting this to True with SOCKS4 servers actually use an extension to the protocol, called SOCKS4a, which may not be supported on all servers (SOCKS5 and http servers always support DNS). The default is True.

username - For SOCKS5 servers, this allows simple username / password authentication with the server. For SOCKS4 servers, this parameter will be sent as the userid. This parameter is ignored if an HTTP server is being used. If it is not provided, authentication will not be used (servers may accept unauthenticated requests).

password - This parameter is valid only for SOCKS5 servers and specifies the respective password for the username provided.

Example of usage:

>>> s.set_proxy(socks.SOCKS5, "socks.example.com") # uses default port 1080
>>> s.set_proxy(socks.SOCKS4, "socks.test.com", 1081)

After the set_proxy method has been called, simply call the connect method with the traditional parameters to establish a connection through the proxy:

>>> s.connect(("www.sourceforge.net", 80))
>>>

Connection will take a bit longer to allow negotiation with the proxy server. Please note that calling connect without calling set_proxy earlier will connect without a proxy (just like a regular socket).

Errors: Any errors in the connection process will trigger exceptions. The exception may either be generated by the underlying socket layer or may be custom module exceptions, whose details follow:

class ProxyError - This is a base exception class. It is not raised directly but rather all other exception classes raised by this module are derived from it. This allows an easy way to catch all proxy-related errors. It descends from IOError.

All ProxyError exceptions have an attribute socket_err, which will contain either a caught socket.error exception, or None if there wasn't any.

class GeneralProxyError - When thrown, it indicates a problem which does not fall into another category.

  • Sent invalid data - This error means that unexpected data has been received from the server. The most common reason is that the server specified as the proxy is not really a SOCKS4/SOCKS5/HTTP proxy, or maybe the proxy type specified is wrong.

  • Connection closed unexpectedly - The proxy server unexpectedly closed the connection. This may indicate that the proxy server is experiencing network or software problems.

  • Bad proxy type - This will be raised if the type of the proxy supplied to the set_proxy function was not one of SOCKS4/SOCKS5/HTTP.

  • Bad input - This will be raised if the connect() method is called with bad input parameters.

class SOCKS5AuthError - This indicates that the connection through a SOCKS5 server failed due to an authentication problem.

  • Authentication is required - This will happen if you use a SOCKS5 server which requires authentication without providing a username / password at all.

  • All offered authentication methods were rejected - This will happen if the proxy requires a special authentication method which is not supported by this module.

  • Unknown username or invalid password - Self descriptive.

class SOCKS5Error - This will be raised for SOCKS5 errors which are not related to authentication. The parameter is a tuple containing a code, as given by the server, and a description of the error. The possible errors, according to the RFC, are:

  • 0x01 - General SOCKS server failure - If for any reason the proxy server is unable to fulfill your request (internal server error).
  • 0x02 - connection not allowed by ruleset - If the address you're trying to connect to is blacklisted on the server or requires authentication.
  • 0x03 - Network unreachable - The target could not be contacted. A router on the network had replied with a destination net unreachable error.
  • 0x04 - Host unreachable - The target could not be contacted. A router on the network had replied with a destination host unreachable error.
  • 0x05 - Connection refused - The target server has actively refused the connection (the requested port is closed).
  • 0x06 - TTL expired - The TTL value of the SYN packet from the proxy to the target server has expired. This usually means that there are network problems causing the packet to be caught in a router-to-router "ping-pong".
  • 0x07 - Command not supported - For instance if the server does not support UDP.
  • 0x08 - Address type not supported - The client has provided an invalid address type. When using this module, this error should not occur.

class SOCKS4Error - This will be raised for SOCKS4 errors. The parameter is a tuple containing a code and a description of the error, as given by the server. The possible error, according to the specification are:

  • 0x5B - Request rejected or failed - Will be raised in the event of an failure for any reason other then the two mentioned next.
  • 0x5C - request rejected because SOCKS server cannot connect to identd on the client - The Socks server had tried an ident lookup on your computer and has failed. In this case you should run an identd server and/or configure your firewall to allow incoming connections to local port 113 from the remote server.
  • 0x5D - request rejected because the client program and identd report different user-ids - The Socks server had performed an ident lookup on your computer and has received a different userid than the one you have provided. Change your userid (through the username parameter of the set_proxy method) to match and try again.

class HTTPError - This will be raised for HTTP errors. The message will contain the HTTP status code and provided error message.

After establishing the connection, the object behaves like a standard socket.

Methods like makefile() and settimeout() should behave just like regular sockets. Call the close() method to close the connection.

In addition to the socksocket class, an additional function worth mentioning is the set_default_proxy function. The parameters are the same as the set_proxy method. This function will set default proxy settings for newly created socksocket objects, in which the proxy settings haven't been changed via the set_proxy method. This is quite useful if you wish to force 3rd party modules to use a SOCKS proxy, by overriding the socket object. For example:

>>> socks.set_default_proxy(socks.SOCKS5, "socks.example.com")
>>> socket.socket = socks.socksocket
>>> urllib.urlopen("http://www.sourceforge.net/")

PROBLEMS

Please open a GitHub issue at https://github.com/Anorov/PySocks

pysocks's People

Contributors

ankostis avatar anorov avatar aww-aww avatar beardypig avatar dbrkv avatar hroncok avatar hugovk avatar jamadden avatar jogo avatar kalou avatar lattice0 avatar loggerhead avatar lorien avatar lukasa avatar lvh avatar mdevaev avatar melhiser avatar mindw avatar mleinart avatar nirgal avatar orangain avatar ov7a avatar pohmelie avatar rianhunter avatar seahoh avatar skelsec avatar utkuzih avatar wojtekerbetowski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pysocks's Issues

AttributeError using socks5 with requests[socks]

Using requests with a socks5 proxy fails on:
AttributeError: 'super' object has no attribute 'settimeout'

Reproduction Steps

pip install requests[socks]==2.14.2
(this installs PySocks v1.6.7)

run a socks proxy on port 9050. I use Tor for that matter.

Simplified code I use is:

import requests
proxies={'http': 'socks5://127.0.0.1:9050'}
url = 'http://www.whatismyip.org/'
requests.get(url, proxies=proxies)

System Information

Windows 7 (x64): 6.1.7601
Python 2.7.12 64bit

Full Traceback

File "c:\Python27\lib\site-packages\requests\api.py", line 72, in get
return request('get', url, params=params, **kwargs)
File "c:\Python27\lib\site-packages\requests\api.py", line 58, in request
return session.request(method=method, url=url, **kwargs)
File "c:\Python27\lib\site-packages\requests\sessions.py", line 518, in request
resp = self.send(prep, **send_kwargs)
File "c:\Python27\lib\site-packages\requests\sessions.py", line 639, in send
r = adapter.send(request, **kwargs)
File "c:\Python27\lib\site-packages\requests\adapters.py", line 438, in send
timeout=timeout
File "c:\Python27\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 600, in urlopen
chunked=chunked)
File "c:\Python27\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 356, in _make_request
conn.request(method, url, **httplib_request_kw)
File "c:\python27\Lib\httplib.py", line 1057,in request
self._send_request(method, url, body, headers)
File "c:\python27\Lib\httplib.py", line 1097, in _send_request
self.endheaders(body)
File "c:\python27\Lib\httplib.py",line 1053, in endheaders
self._send_output(message_body)
File "c:\python27\Lib\httplib.py", line 897, in _send_output
self.send(msg)
File "c:\python27\Lib\httplib.py", line 859,in send
self.connect()
File "c:\Python27\lib\site-packages\requests\packages\urllib3\connection.py", line 166, in connect
conn = self._new_conn()
File "c:\Python27\lib\site-packages\requests\packages\urllib3\contrib\socks.py", line 88, in _new_conn
**extra_kw
File "c:\Python27\lib\site-packages\socks.py", line 229, in create_connection
sock.connect((remote_host, remote_port))
File "c:\Python27\lib\site-packages\socks.py", line 96, in wrapper
return function(*args, **kwargs)
File "c:\Python27\lib\site-packages\socks.py", line 781, in connect
super(socksocket, self).settimeout(self._timeout)
AttributeError: 'super' object has no attribute 'settimeout'

Extras

I want to suggest the closest issue I have found, that is on gevent:
gevent/gevent#937

Replacing all occurences of (in socks.py):
super(socksocket, self).settimeout
with:
self.settimeout
solves the issue, but I don't know if there are any other side effects

Include sockshandler in pip package maybe?

As you said

sockshandler.py is just a "recipe"/utility for easy integration with urllib2. So, I don't think there is a need for an__init__.py because socks.py is the only file intended for importion.

Why not? One can use PySocks just for urllib2 (like I do). So maybe it would be a nice choice to add sockshandler in pip package?

Crashes when connecting to IPv6 services

Trying one of the use cases described in the docs (in this case socksifying through tor)

In [1]: import socks
In [2]: import socket
In [3]: import urllib2
In [4]: socks.set_default_proxy(socks.SOCKS5, "localhost", 9050)
In [5]: socket.socket = socks.socksocket
In [6]: urllib2.urlopen("https://google.com")

Produces the following error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-728442f30dba> in <module>()
----> 1 urllib2.urlopen("https://google.com")

/usr/lib/python2.7/urllib2.pyc in urlopen(url, data, timeout, cafile, capath, cadefault, context)
    152     else:
    153         opener = _opener
--> 154     return opener.open(url, data, timeout)
    155 
    156 def install_opener(opener):

/usr/lib/python2.7/urllib2.pyc in open(self, fullurl, data, timeout)
    429             req = meth(req)
    430 
--> 431         response = self._open(req, data)
    432 
    433         # post-process response

/usr/lib/python2.7/urllib2.pyc in _open(self, req, data)
    447         protocol = req.get_type()
    448         result = self._call_chain(self.handle_open, protocol, protocol +
--> 449                                   '_open', req)
    450         if result:
    451             return result

/usr/lib/python2.7/urllib2.pyc in _call_chain(self, chain, kind, meth_name, *args)
    407             func = getattr(handler, meth_name)
    408 
--> 409             result = func(*args)
    410             if result is not None:
    411                 return result

/usr/lib/python2.7/urllib2.pyc in https_open(self, req)
   1238         def https_open(self, req):
   1239             return self.do_open(httplib.HTTPSConnection, req,
-> 1240                 context=self._context)
   1241 
   1242         https_request = AbstractHTTPHandler.do_request_

/usr/lib/python2.7/urllib2.pyc in do_open(self, http_class, req, **http_conn_args)
   1192 
   1193         try:
-> 1194             h.request(req.get_method(), req.get_selector(), req.data, headers)
   1195         except socket.error, err: # XXX what error?
   1196             h.close()

/usr/lib/python2.7/httplib.pyc in request(self, method, url, body, headers)
    999     def request(self, method, url, body=None, headers={}):
   1000         """Send a complete request to the server."""
-> 1001         self._send_request(method, url, body, headers)
   1002 
   1003     def _set_content_length(self, body):

/usr/lib/python2.7/httplib.pyc in _send_request(self, method, url, body, headers)
   1033         for hdr, value in headers.iteritems():
   1034             self.putheader(hdr, value)
-> 1035         self.endheaders(body)
   1036 
   1037     def getresponse(self, buffering=False):

/usr/lib/python2.7/httplib.pyc in endheaders(self, message_body)
    995         else:
    996             raise CannotSendHeader()
--> 997         self._send_output(message_body)
    998 
    999     def request(self, method, url, body=None, headers={}):

/usr/lib/python2.7/httplib.pyc in _send_output(self, message_body)
    848             msg += message_body
    849             message_body = None
--> 850         self.send(msg)
    851         if message_body is not None:
    852             #message_body was not a string (i.e. it is a file) and

/usr/lib/python2.7/httplib.pyc in send(self, data)
    810         if self.sock is None:
    811             if self.auto_open:
--> 812                 self.connect()
    813             else:
    814                 raise NotConnected()

/usr/lib/python2.7/httplib.pyc in connect(self)
   1202             "Connect to a host on a given (SSL) port."
   1203 
-> 1204             HTTPConnection.connect(self)
   1205 
   1206             if self._tunnel_host:

/usr/lib/python2.7/httplib.pyc in connect(self)
    791         """Connect to the host and port specified in __init__."""
    792         self.sock = self._create_connection((self.host,self.port),
--> 793                                            self.timeout, self.source_address)
    794 
    795         if self._tunnel_host:

/usr/lib/python2.7/socket.pyc in create_connection(address, timeout, source_address)
    561                 sock.bind(source_address)
    562             print "SA is", sa
--> 563             sock.connect(sa)
    564             return sock
    565 

/usr/local/lib/python2.7/dist-packages/socks.pyc in connect(self, dest_pair)
    626         dest_pair - 2-tuple of (IP/hostname, port).
    627         """
--> 628         dest_addr, dest_port = dest_pair
    629 
    630         if self.type == socket.SOCK_DGRAM:

ValueError: too many values to unpack

It seems that socks's connect() method is being called with a 4-tuple, ('2607:f8b0:4005:802::1000', 443, 0, 0) in this case.

Should architecture specific binary test/bin/3proxy be removed?

Hi,

I wonder whether an architecture specific binary should be present in the version control and in the release tar.gz files? The file is for Linux amd64 only. It is not usable by anybody on other architectures (e.g. Debian has 10 "official" architectures alone). And those on Linux amd64 should be sceptical about binary executables in version control and remove it anyway :~) If 3proxy is needed for testing, it should declared as requirement instead, right?

Thanks in advance!

Socks5 proxy and gevent error AttributeError: 'super' object has no attribute 'getpeername

same problem after update

urllib

from gevent import monkey
monkey.patch_all()

import urllib.request
import socks
from sockshandler import SocksiPyHandler

request = urllib.request.Request('http://myip.dnsomatic.com')
opener = urllib.request.build_opener(SocksiPyHandler(socks.SOCKS5, '127.0.0.1', 9050))
urllib.request.install_opener(opener)

handle = urllib.request.urlopen(request, timeout=60)
print(handle.read())

Tag releases

Please add tag for new releases, for example 1.5.6.

Thanks

running sockshandler.py problem

I ran sockshandler.py in the git.
Of course, I changed proxy server address and port accordingly.
Requesting http works well, while requesting from https site met with problems.
I tested a several sites, including example site https://httpbin.org/ip
Results are below, I wonder why it does not work with ssl. Thank you.

HTTP: {
"origin": "107.178.200.206"
}

HTTPS:
Traceback (most recent call last):
File "sockshandler.py", line 61, in
print "HTTPS:", opener.open("https://httpbin.org/ip").read()
File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 431, in open
response = self._open(req, data)
File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 449, in _open
'_open', req)
File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "sockshandler.py", line 55, in https_open
return self.do_open(build, req)
File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1197, in do_open
raise URLError(err)
urllib2.URLError: <urlopen error [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:581)>

if not set proxy , getpeername() is return None

if not set proxy, then getpeername() will get None. following code

sock_out = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
ret = sock_out.connect_ex(('127.0.0.1', 3306 ))
print ret                           # 0
print sock_out.getpeername()    # None

in the source code:

    def get_peername(self):
        """
        Returns the IP address and port number of the destination
        machine (note: get_proxy_peername returns the proxy)
        """
        return self.proxy_peername

    getpeername = get_peername

    def connect(...):
        ...
        if proxy_type is None:
            # Treat like regular socket object
            _BaseSocket.connect(self, (dest_addr, dest_port))
            return
        ...

in connect(), it just use _BaseSocket.connect , howere self.proxy_peername is None

Support for ssl.wrap_socket?

I'll try to debug later when I have more free time but I'm getting:

Exception in thread 2:
Traceback (most recent call last):
  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.4/threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)
  File "/home/mike/Desktop/Projects/Python/HttpRace/HttpRace.py", line 166, in execute_run
    self.__socket.send(str.encode("%s%s" % (self.__CRLF, self.__CRLF)))
  File "/usr/lib/python3.4/ssl.py", line 684, in send
    v = self._sslobj.write(data)
BrokenPipeError: [Errno 32] Broken pipe

Creation:
https://github.com/a904guy/HttpRace/blob/master/HttpRace.py#L121-L131

Error:
https://github.com/a904guy/HttpRace/blob/master/HttpRace.py#L166

I understand this isn't the appropriate use of sockets proxy for https/http ahead of time, but the application in nature calls for it really, and the socket proxy allows me to debug via Charles a lot easier.

PySocks Compatibility with Connect_EX / asyncore / asyncio

The Python socket library has connect_ex which returns errors instead of raising exceptions (iirc) and asyncore, asyncio and etc all use connect_ex instead of connect which makes pysocks incompatible with these libraries. Can support be added. Thanks.

Support of general packages

Is it possible to use PySocks with a general package, e.g., wget or SQL related packages (without using Monkeypatching)?

urllib2 timeout and gevent 1.0

when using urllib2 + gevent 1.0 and setting timeout on request i got error
"send() got an unexpected keyword argument 'timeout'

backtrace [...
 ('/usr/lib64/python2.7/urllib2.py', 400, 'open', 'response = self._open(req, data)'), ('/usr/lib64/python2.7/urllib2.py', 418, '_open', "'_open', req)"), ('/usr/lib64/python2.7/urllib2.py', 378, '_call_chain', 'result = func(*args)'), ('./main/sockshandler.py', 49, 'http_open', 'return self.do_open(build, req)'), ('/usr/lib64/python2.7/urllib2.py', 1174, 'do_open', 'h.request(req.get_method(), req.get_selector(), req.data, headers)'), ('/usr/lib64/python2.7/httplib.py', 958, 'request', 'self._send_request(method, url, body, headers)'), ('/usr/lib64/python2.7/httplib.py', 992, '_send_request', 'self.endheaders(body)'), ('/usr/lib64/python2.7/httplib.py', 954, 'endheaders', 'self._send_output(message_body)'), ('/usr/lib64/python2.7/httplib.py', 814, '_send_output', 'self.send(msg)'), ('/usr/lib64/python2.7/httplib.py', 776, 'send', 'self.connect()'), 
('./main/sockshandler.py', 24, 'connect', 'self.sock.connect((self.host, self.port))'), ('.../v/lib/python2.7/site-packages/socks.py', 668, 'connect', 'negotiate(self, dest_addr, dest_port)'), ('.../v/lib/python2.7/site-packages/socks.py', 378, '_negotiate_SOCKS5', 'CONNECT, dest_addr)'), ('.../v/lib/python2.7/site-packages/socks.py', 460, '_SOCKS5_request', 'writer.close()'), ('/usr/lib64/python2.7/socket.py', 279, 'close', 'self.flush()'), 
('/usr/lib64/python2.7/socket.py', 303, 'flush', 'self._sock.sendall(view[write_offset:write_offset+buffer_size])'), 
('.../v/lib/python2.7/site-packages/gevent/socket.py', 464, 'sendall', 'data_sent += self.send(_get_memory(data, data_sent), flags, timeout=timeleft)')]```

Monkeypatch socket DNS resolving functions

I recently became aware of the fact that functions like socket.gethostbyname and socket.getaddrinfo do not construct socket objects and so will not go through the proxy when the socket class is monkeypatched. For many applications this is not a problem, but anything that manually calls the DNS resolving functions may run into problems and will also suffer from a major privacy leak, as the DNS requests will be sent unproxied.

These functions are defined in C, in socketmodule.c and getaddrinfo.c. Currently trying to determine the best way of monkeypatching these. I'd prefer not to edit and compile the C extensions themselves.

[BUG]getpeername

File "/home/liuyang/.virtualenvs/3.5/lib/python3.5/site-packages/socks.py", line 289, in settimeout
peer = self.get_proxy_peername()
File "/home/liuyang/.virtualenvs/3.5/lib/python3.5/site-packages/socks.py", line 430, in get_proxy_peername
return _BaseSocket.getpeername(self)
AttributeError: type object '_BaseSocket' has no attribute 'getpeername'

`recvfrom` read less than request

This problem can be repro by following code:

import socket
import socks

BUF_SIZE = 1024

conn = socks.socksocket(socket.AF_INET, socket.SOCK_DGRAM, socket.SOL_UDP)
conn.set_proxy(socks.SOCKS5, "127.0.0.1", 1080)
conn.sendto(b'a' * BUF_SIZE, ('127.0.0.1', 8000))
data, _ = conn.recvfrom(BUF_SIZE)
# less exact 10 bytes than request
assert len(data) == BUF_SIZE - 10

This is caused by following lines in recvfrom:

        buf = BytesIO(_BaseSocket.recv(self, bufsize, flags))
        # remain BUF_SIZE - 2
        buf.seek(2, SEEK_CUR)
        # remain BUF_SIZE - 3
        frag = buf.read(1)
        if ord(frag):
            raise NotImplementedError("Received UDP packet fragment")
        # remain BUF_SIZE - 10
        fromhost, fromport = self._read_SOCKS5_address(buf)

Compatibility with `asyncore`

PySocks fails when used with asyncore:

  • asyncore uses connect_ex instead of connect which is not implemented by PySocks and silently calls socket.connect_ex
  • socksocket.connect fails with non blocking sockets.

I managed to make it work on Linux by re-implementing asyncore connect and create_socket. The code is a draft and could be cleaned up.

iot-lab/aggregation-tools@c0fa46d#diff-08168129224d3895b73aa8df60b11a26L63

For connect_ex I just called connect and catched the exceptions and tried to handle them. Maybe just implementing connect_hex that return 0 or ERROR would be enough for asyncore, even if not all errors are correctly implemented.

I then got the issues with non blocking sockets. Looking at the implementation it's normal that it fails when connecting.
However just passing it 'blocking' for the connection time would be enough to be usable directly,
and then restore the previous configuration after connecting.

added a timeout api

--- /home/cfsego/.local/lib/python3.5/site-packages/socks.py    2017-05-08 21:08:01.781956877 +0800
+++ socks.py    2017-05-08 21:05:47.601957161 +0800
@@ -154,6 +154,14 @@
                                 username.encode() if username else None,
                                 password.encode() if password else None)
 
+def set_default_timeout(timeout=None):
+    """
+    set_default_timeout(timeout)
+
+    Sets a default timeout which all further socksocket objects will use.
+    """
+    socksocket.default_timeout = timeout
+
 def setdefaultproxy(*args, **kwargs):
     if 'proxytype' in kwargs:
         kwargs['proxy_type'] = kwargs.pop('proxytype')
@@ -276,6 +284,7 @@
     """
 
     default_proxy = None
+    default_timeout = None
 
     def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, *args, **kwargs):
         if type not in (socket.SOCK_STREAM, socket.SOCK_DGRAM):
@@ -292,7 +301,7 @@
         self.proxy_sockname = None
         self.proxy_peername = None
 
-        self._timeout = None
+        self._timeout = self.default_timeout 
 
     def _readall(self, file, count):
         """

Monkeypatch throws stacktrace

import socket, socks
import urllib2

socks.set_default_proxy(socks.SOCKS5, "localhost", 44000)
socket.socket = socks.socksocket

urllib2 call
[...]
socks.GeneralProxyError: Socket error: timed out

Request is a more elegant way to handle time outs. Allowing me to skip and print something to stdout would be great! :)

socks.create_connection doesn't propagate its timeout properly.

The timeout keyword argument to create_connection doesn't always propagate the timeout correctly. In particular, the timeout ends up not applying during the call to negotiate, because connect applies the timeout after the call to negotiate, not before.

This seems wrong to me.

Reset the state ?

Hi,

I need to make multiple calls in a script, with or without proxies.

For now, I do this:

if proxy:
            socks.set_default_proxy(socks.SOCKS5, proxy, port)
            socket.socket = socks.socksocket
handler = urlopen(url)

My problem is that I then need to reset socket.socket to prevent using SOCKS proxy for further calls. My method for now is to store socket.socket in a global var before and then to restore it when needed.

Is there a better way ?

Maybe calling socks.set_default_proxy() should remove all default proxies. What do you think about it ?

Thanks

Import code redundancy

if os.name == 'nt':
    try:
        import win_inet_pton
        import socket
    except ImportError:
        raise ImportError('To run PySocks under windows you need to install win_inet_pton')
else:
    import socket

I think that import socket in the two rows is not necessary.

Remote DNS resolution bug when using create_connection

The call to sock.set_proxy inside create_connection fails to correctly pass the rdns parameter. The result is that remote dns resolution is not performed.

A workaround is to set the username to True (because the username is sent where rdns should be)

if proxy_type is not None:
    sock.set_proxy(proxy_type, proxy_addr, proxy_port,
                   proxy_username, proxy_password)

should be

if proxy_type is not None:
    sock.set_proxy(proxy_type, proxy_addr, proxy_port, rdns
                   proxy_username, proxy_password)

HTTPS support

Could you please add a recipe to create sockshandler for urllib2 with ability to connect both HTTP and HTTPS?

Does socks support direct TCP socket?

I tried socks with "my-ip.heroku.com" and it worked great. But when I tried private IP address (programming a TCP socket) at one of my remote lab PC, the program gave an error:
raise SOCKS5Error("{:#04x}: {}".format(status, error))
socks.SOCKS5Error: 0x01: General SOCKS server failure

Tor suggests me to use SOCKS4A, but it seems not supported right now (line # 375).
Could you please add the support to direct private IP addr.?

Does PySocks work with SQLAlchemy

I'm having to route all outgoing connections from SQLAlchemy via a proxy server. Is this the right library to accomplish this task? Thanks!

Pysocks + Python 2.7 Windows Broken

socket.inet_ntop & socket.inet_pton are available for windows only for Python 3.4+. Almost all urllib3 tests fail when using pysocks 1.5.7 on windows (tested on win7).

caused by #35.

SOCKS5 and UDP error

I'm trying to write a small test application to test if a Proxy supports UDP over SOCKS5.

Currently the application seems to be sending messages correctly but receiving is falling over when receiving the echoed data.
File "E:\pacs\socks.py", line 330, in recvfrom
peerhost, peerport = self.proxy_peername
TypeError: 'NoneType' object is not iterable

I cannot see how self.proxy_peername is being initialized with socks5 proxy. My test environment is using proxy plus (free edition) with SOCKS activated and the following code

#! /usr/bin/env python

# Client and server for udp (datagram) echo.
#
# Usage: udpecho -s [port]            (to start a server)
# or:    udpecho -c host [port] <file (client)

import sys
import socks
from socket import *

ECHO_PORT = 50000 + 7
BUFSIZE = 1024

def main():
    if len(sys.argv) < 2:
        usage()
    if sys.argv[1] == '-s':
        server()
    elif sys.argv[1] == '-c':
        client()
    elif sys.argv[1] == '-ss':
        sockserver()
    elif sys.argv[1] == '-sc':
        sockclient()
    else:
        usage()

def usage():
    sys.stdout = sys.stderr
    print 'Usage: udpecho -s [port]            (server)'
    print 'or:    udpecho -c host [port] <file (client)'
    sys.exit(2)

def server():
    if len(sys.argv) > 2:
        port = eval(sys.argv[2])
    else:
        port = ECHO_PORT
    s = socket(AF_INET, SOCK_DGRAM)
    s.bind(('', port))
    print 'udp echo server ready'
    while 1:
        data, addr = s.recvfrom(BUFSIZE)
        print 'server received', `data`, 'from', `addr`
        s.sendto(data, addr)

def client():
    if len(sys.argv) < 3:
        usage()
    host = sys.argv[2]
    if len(sys.argv) > 3:
        port = eval(sys.argv[3])
    else:
        port = ECHO_PORT
    addr = host, port
    s = socket(AF_INET, SOCK_DGRAM)
    s.settimeout(100)
    s.bind(('', 0))
    print 'udp echo client ready, reading stdin'
    while 1:
        line = sys.stdin.readline()
        if not line:
            break
        s.sendto(line, addr)
        data, fromaddr = s.recvfrom(BUFSIZE)
        print 'client received', `data`, 'from', `fromaddr`

def sockserver():
    if len(sys.argv) > 2:
        port = eval(sys.argv[2])
    else:
        port = ECHO_PORT
    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 1080)
    s = socks.socksocket(AF_INET, SOCK_DGRAM)
    s.bind(('', port))
    print 'udp echo server ready'
    while 1:
        data, addr = s.recvfrom(BUFSIZE)
        print 'server received', `data`, 'from', `addr`
        s.sendto(data, addr)

def sockclient():
    if len(sys.argv) < 3:
        usage()
    host = sys.argv[2]
    if len(sys.argv) > 3:
        port = eval(sys.argv[3])
    else:
        port = ECHO_PORT
    addr = host, port
    s = socks.socksocket(AF_INET, SOCK_DGRAM)
    s.set_proxy(socks.SOCKS5, "localhost")
    s.settimeout(100)
    s.bind(('', 0))

    print 'udp echo client ready, reading stdin'
    try:
        while 1:
            line = sys.stdin.readline()
            if not line:
                break
            print 'sending', line, 'to', addr
            s.sendto(line, addr)
            res = s.recvfrom(BUFSIZE)
            print '%r' % res
            print 'client received', `data`, 'from', `fromaddr`
    except KeyboardInterrupt:
        print 'Bye'
        pass

main()

In one command window I run:
udpecho.py -s

In the another window:
udpecho.py -sc localhost
test

The send is working as the server sees
udp echo server ready
server received 'test\n' from ('127.0.0.1', 49165)

But the receive is failing.

IPV6 not supported

s = socks.socksocket()
s.set_proxy(socks.SOCKS4, "10.10.10.10", 1080)

s.connect('www.google.com')
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib64/python3.4/site-packages/socks.py", line 96, in wrapper
return function(*args, **kwargs)
File "/usr/lib64/python3.4/site-packages/socks.py", line 752, in connect
raise socket.error("PySocks doesn't support IPv6: %s" % str(dest_pair))
OSError: PySocks doesn't support IPv6: www.google.com

Mainter for this project

Hi Anorov,

Some weeks ago I email you, at my company, we're heavily using this project and really depends on it. So
since you're no longer supporting it, I'll like to take care of the project to maintain it, also makes some improvements maybe.

How tests work?

Trying to understand how to run tests.
I see twisted socks4 server on 1080, tornado http server on port 8081.
I see socks5 tests send request to 1081 port? Who is listening on that port?

Add MANIFEST (w/ LICENSE)

Would it be possible to get a MANIFEST for this package? I'm putting together a build for conda-forge, and ideally we'd like to include a link to the original license file in the build. Doing so requires a manifest with a link.

Add LICENSE to tarball.

The license file states that:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

... which means that, in order to be compliant with its own license, the tarball shipped to pypi needs to include the LICENSE file too.

It's easy to do! You must add include LICENSE to a file called MANIFEST.in and it should show up in the next tarball there.

Can't ignore/enforce SSL Cert verification.

I have the following I am building:

opener = urllib2.build_opener(
            SocksiPyHandler(socks.PROXY_TYPE_SOCKS5, socks_hostname, socks_port, True, socks_username, socks_password))
    request = urllib2.Request(url)
    response = opener.open(request).read()

But how do I pass my:

context = ssl._create_unverified_context()

It seems to just ignore it when I pass it into ScoksiPyHandler.

Is there any solution for this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.