From d8d23c9b170991a33f8f2b216c1ea42859c53aa5 Mon Sep 17 00:00:00 2001 From: Pavel Rykov Date: Sat, 16 Jan 2016 17:15:48 +0300 Subject: [PATCH] version 1.4 --- CertTool.py | 3 +++ Docs/changelog.txt | 6 ++++++ ProxHTTPSProxy.py | 43 ++++++++++++++++++++++++++++--------------- ProxyTool.py | 28 ---------------------------- config.ini | 7 ++----- 5 files changed, 39 insertions(+), 48 deletions(-) diff --git a/CertTool.py b/CertTool.py index b9d4fb4..6920b86 100644 --- a/CertTool.py +++ b/CertTool.py @@ -20,6 +20,7 @@ def create_CA(capath): key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) ca = OpenSSL.crypto.X509() ca.set_serial_number(0) + # Value 2 means v3 ca.set_version(2) subj = ca.get_subject() subj.countryName = 'CN' @@ -71,6 +72,8 @@ def dummy_cert(cafile, certfile, commonname): ca = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, content) key = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, content) cert = OpenSSL.crypto.X509() + # Value 2 means v3 + cert.set_version(2) cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notAfter(60 * 60 * 24 * 3652) cert.set_issuer(ca.get_subject()) diff --git a/Docs/changelog.txt b/Docs/changelog.txt index a14143e..29dab4d 100644 --- a/Docs/changelog.txt +++ b/Docs/changelog.txt @@ -1,6 +1,12 @@ ProxHTTPSProxyMII ================= +Version 1.4 (20160112) +-------------- + ++ Socks proxy support (needs urllib3 >= 1.14) +* Certifications are now v3 instead of v1 + Version 1.3.1 (20151001) -------------- diff --git a/ProxHTTPSProxy.py b/ProxHTTPSProxy.py index 76a23f3..c922512 100644 --- a/ProxHTTPSProxy.py +++ b/ProxHTTPSProxy.py @@ -5,7 +5,7 @@ _name = 'ProxHTTPSProxyMII' __author__ = 'phoenix' -__version__ = 'v1.3.1' +__version__ = 'v1.4' CONFIG = "config.ini" CA_CERTS = "cacert.pem" @@ -18,6 +18,7 @@ import logging import threading import ssl import urllib3 +from urllib3.contrib.socks import SOCKSProxyManager #https://urllib3.readthedocs.org/en/latest/security.html#insecurerequestwarning urllib3.disable_warnings() @@ -77,16 +78,12 @@ class ConnectionPools: for section in proxy_sections: proxy = section.split()[1] self.pools.append(dict(proxy=proxy, - # maxsize is the max. number of connections to the same server - pool=[urllib3.ProxyManager(proxy, 10, maxsize=8, timeout=self.timeout, **self.sslparams), - urllib3.ProxyManager(proxy, 10, maxsize=8, timeout=self.timeout)], + pool=self.setProxyPool(proxy), patterns=list(self.conf[section].keys()))) default_proxy = self.conf['GENERAL'].get('DefaultProxy') - default_pool = ([urllib3.ProxyManager(default_proxy, 10, maxsize=8, timeout=self.timeout, **self.sslparams), - urllib3.ProxyManager(default_proxy, 10, maxsize=8, timeout=self.timeout)] - if default_proxy else - [urllib3.PoolManager(10, maxsize=8, timeout=self.timeout, **self.sslparams), - urllib3.PoolManager(10, maxsize=8, timeout=self.timeout)]) + default_pool = (self.setProxyPool(default_proxy) if default_proxy else + [urllib3.PoolManager(num_pools=10, maxsize=8, timeout=self.timeout, **self.sslparams), + urllib3.PoolManager(num_pools=10, maxsize=8, timeout=self.timeout)]) self.pools.append({'proxy': default_proxy, 'pool': default_pool, 'patterns': '*'}) 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'])): 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): """Handle requests in a separate thread.""" 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)) url = self.path self.url = url - prefix = '[P]' if self.proxy else '[D]' - if self.bypass: - prefix += '[B]' pool = self.pool if self.bypass else proxpool 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 @@ -224,11 +233,15 @@ class FrontRequestHandler(ProxyRequestHandler): r = pool.urlopen(self.command, url, body=self.postdata, headers=headers, retries=1, redirect=False, preload_content=False, decode_content=False) if not self.ssltunnel: + if self.bypass: + prefix = '[BP]' if self.proxy else '[BD]' + else: + prefix = '[D]' 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', '-'))) 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', '-'))) self.send_response_only(r.status, r.reason) @@ -367,7 +380,7 @@ try: logger.addHandler(handler) 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 # to avoid trigger front server exception handler timeout=urllib3.util.timeout.Timeout(connect=90.0, read=310.0)) diff --git a/ProxyTool.py b/ProxyTool.py index 1f6383a..7f2baab 100644 --- a/ProxyTool.py +++ b/ProxyTool.py @@ -14,7 +14,6 @@ import threading import cgi import socket import select -import selectors import ssl from http.server import HTTPServer, BaseHTTPRequestHandler from socketserver import ThreadingMixIn @@ -41,33 +40,6 @@ message_format = """\ """ -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): "Read and Write contents between 2 sockets" iw = [socket1, socket2] diff --git a/config.ini b/config.ini index 14161e7..23b08db 100644 --- a/config.ini +++ b/config.ini @@ -2,9 +2,6 @@ ### ### 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 -### -### Socks proxy support -### https://github.com/shazow/urllib3/pull/284 [GENERAL] ProxAddr = http://localhost:8080 @@ -21,11 +18,11 @@ LogLevel = # [seq] matches any character 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 #*.s3.amazonaws.com -[PROXY http://192.168.178.8:8124] +[PROXY socks5://192.168.178.3:1080] test.com ### Ignore SSL certificate verify, Use at your own risk!!!