version 1.4

This commit is contained in:
Pavel Rykov 2016-01-16 17:15:48 +03:00
parent 132f51e0a5
commit d8d23c9b17
5 changed files with 39 additions and 48 deletions

View File

@ -20,6 +20,7 @@ def create_CA(capath):
key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
ca = OpenSSL.crypto.X509() ca = OpenSSL.crypto.X509()
ca.set_serial_number(0) ca.set_serial_number(0)
# Value 2 means v3
ca.set_version(2) ca.set_version(2)
subj = ca.get_subject() subj = ca.get_subject()
subj.countryName = 'CN' subj.countryName = 'CN'
@ -71,6 +72,8 @@ def dummy_cert(cafile, certfile, commonname):
ca = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, content) ca = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, content)
key = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, content) key = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, content)
cert = OpenSSL.crypto.X509() cert = OpenSSL.crypto.X509()
# Value 2 means v3
cert.set_version(2)
cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(60 * 60 * 24 * 3652) cert.gmtime_adj_notAfter(60 * 60 * 24 * 3652)
cert.set_issuer(ca.get_subject()) cert.set_issuer(ca.get_subject())

View File

@ -1,6 +1,12 @@
ProxHTTPSProxyMII ProxHTTPSProxyMII
================= =================
Version 1.4 (20160112)
--------------
+ Socks proxy support (needs urllib3 >= 1.14)
* Certifications are now v3 instead of v1
Version 1.3.1 (20151001) Version 1.3.1 (20151001)
-------------- --------------

View File

@ -5,7 +5,7 @@
_name = 'ProxHTTPSProxyMII' _name = 'ProxHTTPSProxyMII'
__author__ = 'phoenix' __author__ = 'phoenix'
__version__ = 'v1.3.1' __version__ = 'v1.4'
CONFIG = "config.ini" CONFIG = "config.ini"
CA_CERTS = "cacert.pem" CA_CERTS = "cacert.pem"
@ -18,6 +18,7 @@ import logging
import threading import threading
import ssl import ssl
import urllib3 import urllib3
from urllib3.contrib.socks import SOCKSProxyManager
#https://urllib3.readthedocs.org/en/latest/security.html#insecurerequestwarning #https://urllib3.readthedocs.org/en/latest/security.html#insecurerequestwarning
urllib3.disable_warnings() urllib3.disable_warnings()
@ -77,16 +78,12 @@ class ConnectionPools:
for section in proxy_sections: for section in proxy_sections:
proxy = section.split()[1] proxy = section.split()[1]
self.pools.append(dict(proxy=proxy, self.pools.append(dict(proxy=proxy,
# maxsize is the max. number of connections to the same server pool=self.setProxyPool(proxy),
pool=[urllib3.ProxyManager(proxy, 10, maxsize=8, timeout=self.timeout, **self.sslparams),
urllib3.ProxyManager(proxy, 10, maxsize=8, timeout=self.timeout)],
patterns=list(self.conf[section].keys()))) patterns=list(self.conf[section].keys())))
default_proxy = self.conf['GENERAL'].get('DefaultProxy') default_proxy = self.conf['GENERAL'].get('DefaultProxy')
default_pool = ([urllib3.ProxyManager(default_proxy, 10, maxsize=8, timeout=self.timeout, **self.sslparams), default_pool = (self.setProxyPool(default_proxy) if default_proxy else
urllib3.ProxyManager(default_proxy, 10, maxsize=8, timeout=self.timeout)] [urllib3.PoolManager(num_pools=10, maxsize=8, timeout=self.timeout, **self.sslparams),
if default_proxy else urllib3.PoolManager(num_pools=10, maxsize=8, timeout=self.timeout)])
[urllib3.PoolManager(10, maxsize=8, timeout=self.timeout, **self.sslparams),
urllib3.PoolManager(10, maxsize=8, timeout=self.timeout)])
self.pools.append({'proxy': default_proxy, 'pool': default_pool, 'patterns': '*'}) self.pools.append({'proxy': default_proxy, 'pool': default_pool, 'patterns': '*'})
self.noverifylist = list(self.conf['SSL No-Verify'].keys()) self.noverifylist = list(self.conf['SSL No-Verify'].keys())
@ -110,6 +107,21 @@ class ConnectionPools:
if any((fnmatch.fnmatch(host, pattern) for pattern in pool['patterns'])): if any((fnmatch.fnmatch(host, pattern) for pattern in pool['patterns'])):
return pool['proxy'], pool['pool'][noverify], noverify return pool['proxy'], pool['pool'][noverify], noverify
def setProxyPool(self, proxy):
scheme = proxy.split(':')[0]
if scheme in ('http', 'https'):
ProxyManager = urllib3.ProxyManager
elif scheme in ('socks4', 'socks5'):
ProxyManager = SOCKSProxyManager
else:
print("Wrong Proxy Format: " + proxy)
print("Proxy should start with http/https/socks4/socks5 .")
input()
raise SystemExit
# maxsize is the max. number of connections to the same server
return [ProxyManager(proxy, num_pools=10, maxsize=8, timeout=self.timeout, **self.sslparams),
ProxyManager(proxy, num_pools=10, maxsize=8, timeout=self.timeout)]
class FrontServer(ThreadingMixIn, HTTPServer): class FrontServer(ThreadingMixIn, HTTPServer):
"""Handle requests in a separate thread.""" """Handle requests in a separate thread."""
pass pass
@ -190,9 +202,6 @@ class FrontRequestHandler(ProxyRequestHandler):
self.bypass = any((fnmatch.fnmatch('http://' + host + urlparse(self.path).path, pattern) for pattern in pools.bypasslist)) self.bypass = any((fnmatch.fnmatch('http://' + host + urlparse(self.path).path, pattern) for pattern in pools.bypasslist))
url = self.path url = self.path
self.url = url self.url = url
prefix = '[P]' if self.proxy else '[D]'
if self.bypass:
prefix += '[B]'
pool = self.pool if self.bypass else proxpool pool = self.pool if self.bypass else proxpool
data_length = self.headers.get("Content-Length") data_length = self.headers.get("Content-Length")
self.postdata = self.rfile.read(int(data_length)) if data_length and int(data_length) > 0 else None self.postdata = self.rfile.read(int(data_length)) if data_length and int(data_length) > 0 else None
@ -224,11 +233,15 @@ class FrontRequestHandler(ProxyRequestHandler):
r = pool.urlopen(self.command, url, body=self.postdata, headers=headers, r = pool.urlopen(self.command, url, body=self.postdata, headers=headers,
retries=1, redirect=False, preload_content=False, decode_content=False) retries=1, redirect=False, preload_content=False, decode_content=False)
if not self.ssltunnel: if not self.ssltunnel:
if self.bypass:
prefix = '[BP]' if self.proxy else '[BD]'
else:
prefix = '[D]'
if self.command in ("GET", "HEAD"): if self.command in ("GET", "HEAD"):
logger.info("%03d " % self.reqNum + Fore.GREEN + '%s "%s %s" %s %s' % logger.info("%03d " % self.reqNum + Fore.MAGENTA + '%s "%s %s" %s %s' %
(prefix, self.command, url, r.status, r.getheader('Content-Length', '-'))) (prefix, self.command, url, r.status, r.getheader('Content-Length', '-')))
else: else:
logger.info("%03d " % self.reqNum + Fore.GREEN + '%s "%s %s %s" %s %s' % logger.info("%03d " % self.reqNum + Fore.MAGENTA + '%s "%s %s %s" %s %s' %
(prefix, self.command, url, data_length, r.status, r.getheader('Content-Length', '-'))) (prefix, self.command, url, data_length, r.status, r.getheader('Content-Length', '-')))
self.send_response_only(r.status, r.reason) self.send_response_only(r.status, r.reason)
@ -367,7 +380,7 @@ try:
logger.addHandler(handler) logger.addHandler(handler)
pools = ConnectionPools(CONFIG) pools = ConnectionPools(CONFIG)
proxpool = urllib3.ProxyManager(config.PROXADDR, 10, maxsize=8, proxpool = urllib3.ProxyManager(config.PROXADDR, num_pools=10, maxsize=8,
# A little longer than timeout of rear pool # A little longer than timeout of rear pool
# to avoid trigger front server exception handler # to avoid trigger front server exception handler
timeout=urllib3.util.timeout.Timeout(connect=90.0, read=310.0)) timeout=urllib3.util.timeout.Timeout(connect=90.0, read=310.0))

View File

@ -14,7 +14,6 @@ import threading
import cgi import cgi
import socket import socket
import select import select
import selectors
import ssl import ssl
from http.server import HTTPServer, BaseHTTPRequestHandler from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn from socketserver import ThreadingMixIn
@ -41,33 +40,6 @@ message_format = """\
</html> </html>
""" """
def read_write(socket1, socket2):
"Read and Write contents between 2 sockets, wait 5s for no data before return"
start = time.time()
with selectors.DefaultSelector() as selector:
socket1.setblocking(False)
socket2.setblocking(False)
selector.register(socket1, selectors.EVENT_READ)
selector.register(socket2, selectors.EVENT_READ)
while True:
tasks = selector.select(5)
if not tasks: break
for key, events in tasks:
if events & selectors.EVENT_READ:
reader = key.fileobj
writer = socket2 if reader is socket1 else socket1
try:
data = reader.recv(1024)
if data:
writer.sendall(data)
else:
# EOF
selector.unregister(reader)
selector.unregister(writer)
except (ConnectionAbortedError, ConnectionResetError, BrokenPipeError):
pass
logger.debug("took %.2Fs" % (time.time()-start))
def read_write(socket1, socket2, max_idling=10): def read_write(socket1, socket2, max_idling=10):
"Read and Write contents between 2 sockets" "Read and Write contents between 2 sockets"
iw = [socket1, socket2] iw = [socket1, socket2]

View File

@ -2,9 +2,6 @@
### ###
### Proxy setting applies to HTTPS requests only, as it is applied by the Rear Server ### Proxy setting applies to HTTPS requests only, as it is applied by the Rear Server
### HTTP requests are passed to and handled by Proxomitron, please set up Proxomitron for proxy ### HTTP requests are passed to and handled by Proxomitron, please set up Proxomitron for proxy
###
### Socks proxy support
### https://github.com/shazow/urllib3/pull/284
[GENERAL] [GENERAL]
ProxAddr = http://localhost:8080 ProxAddr = http://localhost:8080
@ -21,11 +18,11 @@ LogLevel =
# [seq] matches any character in seq # [seq] matches any character in seq
# [!seq] matches any character not in seq # [!seq] matches any character not in seq
[PROXY http://192.168.178.8:8123] [PROXY http://192.168.178.1:8123]
#duckduckgo.com #duckduckgo.com
#*.s3.amazonaws.com #*.s3.amazonaws.com
[PROXY http://192.168.178.8:8124] [PROXY socks5://192.168.178.3:1080]
test.com test.com
### Ignore SSL certificate verify, Use at your own risk!!! ### Ignore SSL certificate verify, Use at your own risk!!!