Commit 39faf654 authored by Ondřej Nový's avatar Ondřej Nový

Import python-socksipy_1.5.7.orig.tar.gz

parent 9c35952c
Copyright 2006 Dan-Haim. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of Dan Haim nor the names of his contributors may be used
to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE.
Metadata-Version: 1.0
Name: PySocks
Version: 1.5.6
Version: 1.5.7
Summary: A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information.
Home-page: https://github.com/Anorov/PySocks
Author: Anorov
......
This diff is collapsed.
#!/usr/bin/env python
from distutils.core import setup
VERSION = "1.5.6"
VERSION = "1.5.7"
setup(
name = "PySocks",
......
"""
SocksiPy - Python SOCKS module.
Version 1.5.6
Version 1.5.7
Copyright 2006 Dan-Haim. All rights reserved.
......@@ -52,7 +52,7 @@ Modifications made by Anorov (https://github.com/Anorov)
-Various small bug fixes
"""
__version__ = "1.5.6"
__version__ = "1.5.7"
import socket
import struct
......@@ -60,6 +60,7 @@ from errno import EOPNOTSUPP, EINVAL, EAGAIN
from io import BytesIO
from os import SEEK_CUR
from collections import Callable
from base64 import b64encode
PROXY_TYPE_SOCKS4 = SOCKS4 = 1
PROXY_TYPE_SOCKS5 = SOCKS5 = 2
......@@ -162,20 +163,48 @@ def create_connection(dest_pair, proxy_type=None, proxy_addr=None,
source_address - tuple (host, port) for the socket to bind to as its source
address before connecting (only for compatibility)
"""
sock = socksocket()
if socket_options is not None:
for opt in socket_options:
sock.setsockopt(*opt)
if isinstance(timeout, (int, float)):
sock.settimeout(timeout)
if proxy_type is not None:
sock.set_proxy(proxy_type, proxy_addr, proxy_port, proxy_rdns,
proxy_username, proxy_password)
if source_address is not None:
sock.bind(source_address)
sock.connect(dest_pair)
return sock
# Remove IPv6 brackets on the remote address and proxy address.
remote_host, remote_port = dest_pair
if remote_host.startswith('['):
remote_host = remote_host.strip('[]')
if proxy_addr and proxy_addr.startswith('['):
proxy_addr = proxy_addr.strip('[]')
err = None
# Allow the SOCKS proxy to be on IPv4 or IPv6 addresses.
for r in socket.getaddrinfo(proxy_addr, proxy_port, 0, socket.SOCK_STREAM):
family, socket_type, proto, canonname, sa = r
sock = None
try:
sock = socksocket(family, socket_type, proto)
if socket_options is not None:
for opt in socket_options:
sock.setsockopt(*opt)
if isinstance(timeout, (int, float)):
sock.settimeout(timeout)
if proxy_type is not None:
sock.set_proxy(proxy_type, proxy_addr, proxy_port, proxy_rdns,
proxy_username, proxy_password)
if source_address is not None:
sock.bind(source_address)
sock.connect((remote_host, remote_port))
return sock
except socket.error as e:
err = e
if sock is not None:
sock.close()
sock = None
if err is not None:
raise err
raise socket.error("gai returned empty list.")
class _BaseSocket(socket.socket):
"""Allows Python 2's "delegated" methods such as send() to be overridden
......@@ -478,25 +507,38 @@ class socksocket(_BaseSocket):
"""
host, port = addr
proxy_type, _, _, rdns, username, password = self.proxy
family_to_byte = {socket.AF_INET: b"\x01", socket.AF_INET6: b"\x04"}
# If the given destination address is an IP address, we'll
# use the IPv4 address request even if remote resolving was specified.
try:
addr_bytes = socket.inet_aton(host)
file.write(b"\x01" + addr_bytes)
host = socket.inet_ntoa(addr_bytes)
except socket.error:
# Well it's not an IP number, so it's probably a DNS name.
if rdns:
# Resolve remotely
host_bytes = host.encode('idna')
file.write(b"\x03" + chr(len(host_bytes)).encode() + host_bytes)
else:
# Resolve locally
addr_bytes = socket.inet_aton(socket.gethostbyname(host))
file.write(b"\x01" + addr_bytes)
host = socket.inet_ntoa(addr_bytes)
# use the IP address request even if remote resolving was specified.
# Detect whether the address is IPv4/6 directly.
for family in (socket.AF_INET, socket.AF_INET6):
try:
addr_bytes = socket.inet_pton(family, host)
file.write(family_to_byte[family] + addr_bytes)
host = socket.inet_ntop(family, addr_bytes)
file.write(struct.pack(">H", port))
return host, port
except socket.error:
continue
# Well it's not an IP number, so it's probably a DNS name.
if rdns:
# Resolve remotely
host_bytes = host.encode('idna')
file.write(b"\x03" + chr(len(host_bytes)).encode() + host_bytes)
else:
# Resolve locally
addresses = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_ADDRCONFIG)
# We can't really work out what IP is reachable, so just pick the
# first.
target_addr = addresses[0]
family = target_addr[0]
host = target_addr[4][0]
addr_bytes = socket.inet_pton(family, host)
file.write(family_to_byte[family] + addr_bytes)
host = socket.inet_ntop(family, addr_bytes)
file.write(struct.pack(">H", port))
return host, port
......@@ -507,6 +549,8 @@ class socksocket(_BaseSocket):
elif atyp == b"\x03":
length = self._readall(file, 1)
addr = self._readall(file, ord(length))
elif atyp == b"\x04":
addr = socket.inet_ntop(socket.AF_INET6, self._readall(file, 16))
else:
raise GeneralProxyError("SOCKS5 proxy server sent invalid data")
......@@ -582,8 +626,17 @@ class socksocket(_BaseSocket):
# If we need to resolve locally, we do this now
addr = dest_addr if rdns else socket.gethostbyname(dest_addr)
self.sendall(b"CONNECT " + addr.encode('idna') + b":" + str(dest_port).encode() +
b" HTTP/1.1\r\n" + b"Host: " + dest_addr.encode('idna') + b"\r\n\r\n")
http_headers = [
b"CONNECT " + addr.encode('idna') + b":" + str(dest_port).encode() + b" HTTP/1.1",
b"Host: " + dest_addr.encode('idna')
]
if username and password:
http_headers.append(b"Proxy-Authorization: basic " + b64encode(username + b":" + password))
http_headers.append(b"\r\n")
self.sendall(b"\r\n".join(http_headers))
# We just need the first line to check if the connection was successful
fobj = self.makefile()
......
Very rudimentary tests for Python 2 and Python 3.
Requirements: tornado, twisted (available through pip)
./test.sh
#!/usr/bin/env python
#
# Simple asynchronous HTTP proxy with tunnelling (CONNECT).
#
# GET/POST proxying based on
# http://groups.google.com/group/python-tornado/msg/7bea08e7a049cf26
#
# Copyright (C) 2012 Senko Rasic <senko.rasic@dobarkod.hr>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import sys
import socket
import tornado.httpserver
import tornado.ioloop
import tornado.iostream
import tornado.web
import tornado.httpclient
__all__ = ['ProxyHandler', 'run_proxy']
class ProxyHandler(tornado.web.RequestHandler):
SUPPORTED_METHODS = ['GET', 'POST', 'CONNECT']
@tornado.web.asynchronous
def get(self):
def handle_response(response):
if response.error and not isinstance(response.error,
tornado.httpclient.HTTPError):
self.set_status(500)
self.write('Internal server error:\n' + str(response.error))
self.finish()
else:
self.set_status(response.code)
for header in ('Date', 'Cache-Control', 'Server',
'Content-Type', 'Location'):
v = response.headers.get(header)
if v:
self.set_header(header, v)
if response.body:
self.write(response.body)
self.finish()
req = tornado.httpclient.HTTPRequest(url=self.request.uri,
method=self.request.method, body=self.request.body,
headers=self.request.headers, follow_redirects=False,
allow_nonstandard_methods=True)
client = tornado.httpclient.AsyncHTTPClient()
try:
client.fetch(req, handle_response)
except tornado.httpclient.HTTPError as e:
if hasattr(e, 'response') and e.response:
self.handle_response(e.response)
else:
self.set_status(500)
self.write('Internal server error:\n' + str(e))
self.finish()
@tornado.web.asynchronous
def post(self):
return self.get()
@tornado.web.asynchronous
def connect(self):
host, port = self.request.uri.split(':')
client = self.request.connection.stream
def read_from_client(data):
upstream.write(data)
def read_from_upstream(data):
client.write(data)
def client_close(data=None):
if upstream.closed():
return
if data:
upstream.write(data)
upstream.close()
def upstream_close(data=None):
if client.closed():
return
if data:
client.write(data)
client.close()
def start_tunnel():
client.read_until_close(client_close, read_from_client)
upstream.read_until_close(upstream_close, read_from_upstream)
client.write(b'HTTP/1.0 200 Connection established\r\n\r\n')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
upstream = tornado.iostream.IOStream(s)
upstream.connect((host, int(port)), start_tunnel)
def run_proxy(port=8080, start_ioloop=True):
"""
Run proxy on the specified port. If start_ioloop is True (default),
the tornado IOLoop will be started immediately.
"""
app = tornado.web.Application([
(r'.*', ProxyHandler),
])
app.listen(port, address="127.0.0.1")
ioloop = tornado.ioloop.IOLoop.instance()
if start_ioloop:
ioloop.start()
if __name__ == '__main__':
port = 8081
if len(sys.argv) > 1:
port = int(sys.argv[1])
print ("Running HTTP proxy server")
run_proxy(port)
File added
#################################################
# #
# Sample configuration file for MOCKS 0.0.2 #
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
# #
# I recommend reading the examples in this file #
# and then extending it to suite your needs. #
# #
#################################################
#########################
#
# General daemon config
# ~~~~~~~~~~~~~~~~~~~~~
#
#########################
PORT = 1081 # Port MOCKS is to listen to
MOCKS_ADDR = 127.0.0.1 # IP adress MOCKS is to bind to
LOG_FILE = mocks.log # MOCKS log file
PID_FILE = mocks.pid # File holding MOCKS's process ID
BUFFER_SIZE = 65536 # Traffic buffer size in bytes
BACKLOG = 5 # Backlog for listen()
NEGOTIATION_TIMEOUT = 5
CONNECTION_IDLE_TIMEOUT = 300
BIND_TIMEOUT = 30
SHUTDOWN_TIMEOUT = 3
MAX_CONNECTIONS = 50
##########################################################################
#
# Client filter config
# ~~~~~~~~~~~~~~~~~~~~
#
# Client filtering means sorting out which clients are allowed
# connection and which are not. This is basically done like this:
# MOCKS has a default behaviour regarding filtering client
# connections. This behaviour is called the 'policy' and can either
# be to ALLOW or to DENY the connection. After setting the policy
# you can specify a list of exceptions. The action MOCKS takes
# for a client matching any of these exceptions is the opposite
# of the policy (that is, if the policy is set to ALLOW the exceptions
# are denied and if the policy is set to DENY the exceptions are allowed).
# An exception is specified in the form ip_address/mask, where mask
# is optional and is an integer ranging from 0 to 32 identifying the
# number of common heading bits that ip_address and the client's IP
# address must have in order to yield a match. If mask is missing,
# 32 will be assumed. For instance, 192.168.1.0/24 will match any IP
# ranging from 192.168.1.1 to 192.168.1.255.
#
# Let's take two examples, one for each type of policy. Let's say we
# only want to allow IPs 10.12.0.0 through 10.12.255.255, 172.23.2.5 and
# 192.168.52.26 to use MOCKS. What we have to to is this:
#
# FILTER_POLICY = DENY
# FILTER_EXCEPTION = 10.12.0.0/16
# FILTER_EXCEPTION = 172.23.2.5 # implied /32
# FILTER_EXCEPTION = 192.168.52.26 # implied /32
#
# Now, let's say this is a public proxy server, but for some reason
# you don't want to let any IP ranging from 192.168.1.1 to 192.168.1.255
# and neither 10.2.5.13 to connect to it:
#
# FILTER_POLICY = ALLOW
# FILTER_EXCEPTION = 192.168.1.0/24
# FILTER_EXCEPTION = 10.2.5.13
#
###########################################################################
FILTER_POLICY = ALLOW
#############################################################################
#
# Upstream proxy config
# ~~~~~~~~~~~~~~~~~~~~~
#
# You can choose to further relay traffic through another proxy server.
# MOCKS supports upstream HTTP CONNECT, SOCKS4 and SOCKS5 proxies. You
# must specify the proxy type (one of HTTPCONNECT, SOCKS4 or SOCKS5), the
# proxy address and the proxy port. Optionally you can specify an user
# name and a password used to authenicate to the upstream proxy. This is
# pretty straight forward, so let's just take an example. Let's say you
# want to use the HTTP CONNECT server at httpconnectproxy.com, on port 3128,
# using the username 'foo' and the password 'bar'. You do it like this:
#
# UP_PROXY_TYPE = HTTPCONNECT
# UP_PROXY_ADDR = httpconnectproxy.com
# UP_PROXY_PORT = 3128
# UP_PROXY_USER = foo # These two can be missing if you
# UP_PROXY_PASSWD = bar # are not required to authenticate
#
#############################################################################
# UP_PROXY_TYPE = HTTPCONNECT
# UP_PROXY_ADDR = 192.168.1.12
# UP_PROXY_PORT = 3128
#!/usr/bin/env python
from twisted.internet import reactor
from twisted.protocols.socks import SOCKSv4Factory
def run_proxy():
reactor.listenTCP(1080, SOCKSv4Factory("/dev/null"), interface="127.0.0.1")
try:
reactor.run()
except (KeyboardInterrupt, SystemExit):
reactor.stop()
if __name__ == "__main__":
print "Running SOCKS4 proxy server"
run_proxy()
import sys
sys.path.append("..")
import socks
import socket
PY3K = sys.version_info[0] == 3
if PY3K:
import urllib.request as urllib2
else:
import sockshandler
import urllib2
def raw_HTTP_request():
req = "GET /ip HTTP/1.1\r\n"
req += "Host: ifconfig.me\r\n"
req += "User-Agent: Mozilla\r\n"
req += "Accept: text/html\r\n"
req += "\r\n"
return req.encode()
def socket_HTTP_test():
s = socks.socksocket()
s.set_proxy(socks.HTTP, "127.0.0.1", 8081)
s.connect(("ifconfig.me", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")
def socket_SOCKS4_test():
s = socks.socksocket()
s.set_proxy(socks.SOCKS4, "127.0.0.1", 1080)
s.connect(("ifconfig.me", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")
def socket_SOCKS5_test():
s = socks.socksocket()
s.set_proxy(socks.SOCKS5, "127.0.0.1", 1081)
s.connect(("ifconfig.me", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")
def SOCKS5_connect_timeout_test():
s = socks.socksocket()
s.settimeout(0.0001)
s.set_proxy(socks.SOCKS5, "8.8.8.8", 80)
try:
s.connect(("ifconfig.me", 80))
except socks.ProxyConnectionError as e:
assert str(e.socket_err) == "timed out"
def SOCKS5_timeout_test():
s = socks.socksocket()
s.settimeout(0.0001)
s.set_proxy(socks.SOCKS5, "127.0.0.1", 1081)
try:
s.connect(("ifconfig.me", 4444))
except socks.GeneralProxyError as e:
assert str(e.socket_err) == "timed out"
def socket_SOCKS5_auth_test():
# TODO: add support for this test. Will need a better SOCKS5 server.
s = socks.socksocket()
s.set_proxy(socks.SOCKS5, "127.0.0.1", 1081, username="a", password="b")
s.connect(("ifconfig.me", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")
def socket_HTTP_IP_test():
s = socks.socksocket()
s.set_proxy(socks.HTTP, "127.0.0.1", 8081)
s.connect(("133.242.129.236", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")
def socket_SOCKS4_IP_test():
s = socks.socksocket()
s.set_proxy(socks.SOCKS4, "127.0.0.1", 1080)
s.connect(("133.242.129.236", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")
def socket_SOCKS5_IP_test():
s = socks.socksocket()
s.set_proxy(socks.SOCKS5, "127.0.0.1", 1081)
s.connect(("133.242.129.236", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")
def urllib2_HTTP_test():
socks.set_default_proxy(socks.HTTP, "127.0.0.1", 8081)
socks.wrap_module(urllib2)
status = urllib2.urlopen("http://ifconfig.me/ip").getcode()
assert status == 200
def urllib2_SOCKS5_test():
socks.set_default_proxy(socks.SOCKS5, "127.0.0.1", 1081)
socks.wrap_module(urllib2)
status = urllib2.urlopen("http://ifconfig.me/ip").getcode()
assert status == 200
def urllib2_handler_HTTP_test():
opener = urllib2.build_opener(sockshandler.SocksiPyHandler(socks.HTTP, "127.0.0.1", 8081))
status = opener.open("http://ifconfig.me/ip").getcode()
assert status == 200
def urllib2_handler_SOCKS5_test():
opener = urllib2.build_opener(sockshandler.SocksiPyHandler(socks.SOCKS5, "127.0.0.1", 1081))
status = opener.open("http://ifconfig.me/ip").getcode()
assert status == 200
def global_override_HTTP_test():
socks.set_default_proxy(socks.HTTP, "127.0.0.1", 8081)
good = socket.socket
socket.socket = socks.socksocket
status = urllib2.urlopen("http://ifconfig.me/ip").getcode()
socket.socket = good
assert status == 200
def global_override_SOCKS5_test():
default_proxy = (socks.SOCKS5, "127.0.0.1", 1081)
socks.set_default_proxy(*default_proxy)
good = socket.socket
socket.socket = socks.socksocket
status = urllib2.urlopen("http://ifconfig.me/ip").getcode()
socket.socket = good
assert status == 200
assert socks.get_default_proxy()[1].decode() == default_proxy[1]
def bail_early_with_ipv6_test():
sock = socks.socksocket()
ipv6_tuple = addr, port, flowinfo, scopeid = "::1", 1234, 0, 0
try:
sock.connect(ipv6_tuple)
except socket.error:
return
else:
assert False, "was expecting"
def main():
print("Running tests...")
socket_HTTP_test()
print("1/13")
socket_SOCKS4_test()
print("2/13")
socket_SOCKS5_test()
print("3/13")
if not PY3K:
urllib2_handler_HTTP_test()
print("3.33/13")
urllib2_handler_SOCKS5_test()
print("3.66/13")
socket_HTTP_IP_test()
print("4/13")
socket_SOCKS4_IP_test()
print("5/13")
socket_SOCKS5_IP_test()
print("6/13")
SOCKS5_connect_timeout_test()
print("7/13")
SOCKS5_timeout_test()
print("8/13")
urllib2_HTTP_test()
print("9/13")
urllib2_SOCKS5_test()
print("10/13")
global_override_HTTP_test()
print("11/13")
global_override_SOCKS5_test()
print("12/13")
bail_early_with_ipv6_test()
print("13/13")
print("All tests ran successfully")
if __name__ == "__main__":
main()
#!/bin/bash
shopt -s expand_aliases
type python2 >/dev/null 2>&1 || alias python2='python'
echo "Starting proxy servers..."
python2 socks4server.py > /dev/null &
python2 httpproxy.py > /dev/null &
./mocks start
sleep 2
echo "Python 2.6 tests"
python2.6 sockstest.py
exit
sleep 2
echo "Python 2.7 tests"
python2.7 sockstest.py
sleep 2
echo "Python 3.x tests"
python3 sockstest.py
pkill python2 > /dev/null
./mocks shutdown
echo "Finished tests"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment