简单的proxy之TinyHTTPProxy.py
简单的proxy之TinyHTTPProxy.py
如果是在外企工作的话,可以访问美国的机器,这样就可以在美国的机器上为自己装个proxy,然后本地就可以很容易的使用proxy来上网了。
TinyHTTPProxy.py :
主页:http://www.voidtrance.net/2010/01/simple-python-http-proxy/
下载:http://www.voidtrance.net/downloads/tiny-proxy-0.3.1.tar.gz
使用方法:
1)很好用,下载然后在后台运行。只依赖于基本的python modules,运行的时候不需要root权限。
proxy [-p port] [-l logfile] [-dh] [allowed_client_name ...]] -p - Port to bind to
-l - Path to logfile. If not specified, STDOUT is used
-d - Run in the background
2) Chrome中的switchsharper插件的配置:


TinyHTTPProxy.py的源代码:
#!/usr/bin/python __doc__ = """Tiny HTTP Proxy. This module implements GET, HEAD, POST, PUT and DELETE methods
on BaseHTTPServer, and behaves as an HTTP proxy. The CONNECT
method is also implemented experimentally, but has not been
tested yet. Any help will be greatly appreciated. SUZUKI Hisao 2009/11/23 - Modified by Mitko Haralanov
* Added very simple FTP file retrieval
* Added custom logging methods
* Added code to make this a standalone application
""" __version__ = "0.3.1" import BaseHTTPServer, select, socket, SocketServer, urlparse
import logging
import logging.handlers
import getopt
import sys
import os
import signal
import threading
from types import FrameType, CodeType
from time import sleep
import ftplib DEFAULT_LOG_FILENAME = "proxy.log" class ProxyHandler (BaseHTTPServer.BaseHTTPRequestHandler):
__base = BaseHTTPServer.BaseHTTPRequestHandler
__base_handle = __base.handle server_version = "TinyHTTPProxy/" + __version__
rbufsize = 0 # self.rfile Be unbuffered def handle(self):
(ip, port) = self.client_address
self.server.logger.log (logging.INFO, "Request from '%s'", ip)
if hasattr(self, 'allowed_clients') and ip not in self.allowed_clients:
self.raw_requestline = self.rfile.readline()
if self.parse_request(): self.send_error(403)
else:
self.__base_handle() def _connect_to(self, netloc, soc):
i = netloc.find(':')
if i >= 0:
host_port = netloc[:i], int(netloc[i+1:])
else:
host_port = netloc, 80
self.server.logger.log (logging.INFO, "connect to %s:%d", host_port[0], host_port[1])
try: soc.connect(host_port)
except socket.error, arg:
try: msg = arg[1]
except: msg = arg
self.send_error(404, msg)
return 0
return 1 def do_CONNECT(self):
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
if self._connect_to(self.path, soc):
self.log_request(200)
self.wfile.write(self.protocol_version +
" 200 Connection established\r\n")
self.wfile.write("Proxy-agent: %s\r\n" % self.version_string())
self.wfile.write("\r\n")
self._read_write(soc, 300)
finally:
soc.close()
self.connection.close() def do_GET(self):
(scm, netloc, path, params, query, fragment) = urlparse.urlparse(
self.path, 'http')
if scm not in ('http', 'ftp') or fragment or not netloc:
self.send_error(400, "bad url %s" % self.path)
return
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
if scm == 'http':
if self._connect_to(netloc, soc):
self.log_request()
soc.send("%s %s %s\r\n" % (self.command,
urlparse.urlunparse(('', '', path,
params, query,
'')),
self.request_version))
self.headers['Connection'] = 'close'
del self.headers['Proxy-Connection']
for key_val in self.headers.items():
soc.send("%s: %s\r\n" % key_val)
soc.send("\r\n")
self._read_write(soc)
elif scm == 'ftp':
# fish out user and password information
i = netloc.find ('@')
if i >= 0:
login_info, netloc = netloc[:i], netloc[i+1:]
try: user, passwd = login_info.split (':', 1)
except ValueError: user, passwd = "anonymous", None
else: user, passwd ="anonymous", None
self.log_request ()
try:
ftp = ftplib.FTP (netloc)
ftp.login (user, passwd)
if self.command == "GET":
ftp.retrbinary ("RETR %s"%path, self.connection.send)
ftp.quit ()
except Exception, e:
self.server.logger.log (logging.WARNING, "FTP Exception: %s",
e)
finally:
soc.close()
self.connection.close() def _read_write(self, soc, max_idling=20, local=False):
iw = [self.connection, soc]
local_data = ""
ow = []
count = 0
while 1:
count += 1
(ins, _, exs) = select.select(iw, ow, iw, 1)
if exs: break
if ins:
for i in ins:
if i is soc: out = self.connection
else: out = soc
data = i.recv(8192)
if data:
if local: local_data += data
else: out.send(data)
count = 0
if count == max_idling: break
if local: return local_data
return None do_HEAD = do_GET
do_POST = do_GET
do_PUT = do_GET
do_DELETE=do_GET def log_message (self, format, *args):
self.server.logger.log (logging.INFO, "%s %s", self.address_string (),
format % args) def log_error (self, format, *args):
self.server.logger.log (logging.ERROR, "%s %s", self.address_string (),
format % args) class ThreadingHTTPServer (SocketServer.ThreadingMixIn,
BaseHTTPServer.HTTPServer):
def __init__ (self, server_address, RequestHandlerClass, logger=None):
BaseHTTPServer.HTTPServer.__init__ (self, server_address,
RequestHandlerClass)
self.logger = logger def logSetup (filename, log_size, daemon):
logger = logging.getLogger ("TinyHTTPProxy")
logger.setLevel (logging.INFO)
if not filename:
if not daemon:
# display to the screen
handler = logging.StreamHandler ()
else:
handler = logging.handlers.RotatingFileHandler (DEFAULT_LOG_FILENAME,
maxBytes=(log_size*(1<<20)),
backupCount=5)
else:
handler = logging.handlers.RotatingFileHandler (filename,
maxBytes=(log_size*(1<<20)),
backupCount=5)
fmt = logging.Formatter ("[%(asctime)-12s.%(msecs)03d] "
"%(levelname)-8s {%(name)s %(threadName)s}"
" %(message)s",
"%Y-%m-%d %H:%M:%S")
handler.setFormatter (fmt) logger.addHandler (handler)
return logger def usage (msg=None):
if msg: print msg
print sys.argv[0], "[-p port] [-l logfile] [-dh] [allowed_client_name ...]]"
print " -p - Port to bind to"
print " -l - Path to logfile. If not specified, STDOUT is used"
print " -d - Run in the background"
print def handler (signo, frame):
while frame and isinstance (frame, FrameType):
if frame.f_code and isinstance (frame.f_code, CodeType):
if "run_event" in frame.f_code.co_varnames:
frame.f_locals["run_event"].set ()
return
frame = frame.f_back def daemonize (logger):
class DevNull (object):
def __init__ (self): self.fd = os.open ("/dev/null", os.O_WRONLY)
def write (self, *args, **kwargs): return 0
def read (self, *args, **kwargs): return 0
def fileno (self): return self.fd
def close (self): os.close (self.fd)
class ErrorLog:
def __init__ (self, obj): self.obj = obj
def write (self, string): self.obj.log (logging.ERROR, string)
def read (self, *args, **kwargs): return 0
def close (self): pass if os.fork () != 0:
## allow the child pid to instanciate the server
## class
sleep (1)
sys.exit (0)
os.setsid ()
fd = os.open ('/dev/null', os.O_RDONLY)
if fd != 0:
os.dup2 (fd, 0)
os.close (fd)
null = DevNull ()
log = ErrorLog (logger)
sys.stdout = null
sys.stderr = log
sys.stdin = null
fd = os.open ('/dev/null', os.O_WRONLY)
#if fd != 1: os.dup2 (fd, 1)
os.dup2 (sys.stdout.fileno (), 1)
if fd != 2: os.dup2 (fd, 2)
if fd not in (1, 2): os.close (fd) def main ():
logfile = None
daemon = False
max_log_size = 20
port = 8000
allowed = []
run_event = threading.Event ()
local_hostname = socket.gethostname () try: opts, args = getopt.getopt (sys.argv[1:], "l:dhp:", [])
except getopt.GetoptError, e:
usage (str (e))
return 1 for opt, value in opts:
if opt == "-p": port = int (value)
if opt == "-l": logfile = value
if opt == "-d": daemon = not daemon
if opt == "-h":
usage ()
return 0 # setup the log file
logger = logSetup (logfile, max_log_size, daemon) if daemon:
daemonize (logger)
signal.signal (signal.SIGINT, handler) if args:
allowed = []
for name in args:
client = socket.gethostbyname(name)
allowed.append(client)
logger.log (logging.INFO, "Accept: %s (%s)" % (client, name))
ProxyHandler.allowed_clients = allowed
else:
logger.log (logging.INFO, "Any clients will be served...") server_address = (socket.gethostbyname (local_hostname), port)
ProxyHandler.protocol = "HTTP/1.0"
httpd = ThreadingHTTPServer (server_address, ProxyHandler, logger)
sa = httpd.socket.getsockname ()
print "Servering HTTP on", sa[0], "port", sa[1]
req_count = 0
while not run_event.isSet ():
try:
httpd.handle_request ()
req_count += 1
if req_count == 1000:
logger.log (logging.INFO, "Number of active threads: %s",
threading.activeCount ())
req_count = 0
except select.error, e:
if e[0] == 4 and run_event.isSet (): pass
else:
logger.log (logging.CRITICAL, "Errno: %d - %s", e[0], e[1])
logger.log (logging.INFO, "Server shutdown")
return 0 if __name__ == '__main__':
sys.exit (main ())
其他的python proxy:
https://github.com/senko/tornado-proxy
完!
简单的proxy之TinyHTTPProxy.py的更多相关文章
- ExtJS笔记 Proxy
Proxies are used by Stores to handle the loading and saving of Model data. Usually developers will n ...
- 如何制作python安装模块(setup.py)
Python模块的安装方法: 1. 单文件模块:直接把文件拷贝到$python_dir/lib 2. 多文件模块,带setup.py:python setup.py install 3. egg文件, ...
- Nginx uWSGI web.py 站点搭建
一.安装nginx 在安装nginx前,需要先装nginx的依赖包. 1.如果没有yum则先安装yum 删除原有的yum rpm -aq|grep yum|xargs rpm -e --node ...
- python-web.py 入门介绍
内容来源:webpy.org 介绍: 1.python中web.py 是一个轻量级Python web框架,它简单而且功能强大.web.py是一个开源项目. 2.安装很简单:pip install w ...
- DCGAN 代码简单解读
之前在DCGAN文章简单解读里说明了DCGAN的原理.本次来实现一个DCGAN,并在数据集上实际测试它的效果.本次的代码来自github开源代码DCGAN-tensorflow,感谢carpedm20 ...
- python 中的__init__.py的用法与个人理解
使用Python模块常见的情况是,事先写好A.py文件,需要import B.py文件时,先拷贝到当前目录,然后再import 这样的做法在程序量较小的情况下是可行的,如果程序交互复杂程度稍高,就很费 ...
- Linux 下面 Sqlserver 2017 的简单安装
1. 公司网络太烂 yum 在线安装失败 2. 解决方法 找微软的官网 百度网盘 离线下载rpm包. https://packages.microsoft.com/rhel/7/mssql-serve ...
- 生产者&消费者.py
1.最简单的 --生产者消费者 send.py# !/usr/bin/env python3.5# -*- coding:utf-8 -*-# __author__ == 'LuoTianShuai' ...
- Django框架----路由系统、视图和模板(简单介绍)
一.路由配置系统(urls) URL配置(URLconf)就像Django所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表: 你就是以这种方式告诉Django,对于这个URL ...
随机推荐
- ios 获取视频截图
#pragma mark -- 获取视频截图- (UIImage *)getThumbnailImage:(NSString *)videoURL{ AVURLAsset *asset = [ ...
- Windows Server 2003 R2标准版 SP2 64位 (简体中文)官方原版ISO镜像
Windows Server 2003 R2标准版 SP2 64位 (简体中文)官方原版ISO镜像迅雷下载 软件简介 Windows Server 2003 R2标准版是继Windows Serv ...
- OCM_第十四天课程:Section6 —》数据库性能调优_各类索引 /调优工具使用/SQL 优化建议
注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...
- 用javascript判断当前是安卓平台还是ios平台
通常判断运行环境都是通过navigator.userAgent if (/android/gi.test(navigator.userAgent)){ // todo : android} if (/ ...
- hdu2888 二维ST表(RMQ)
二维RMQ其实和一维差不太多,但是dp时要用四维 /* 二维rmq */ #include<iostream> #include<cstring> #include<cs ...
- (第1篇)什么是hadoop大数据?我又为什么要写这篇文章?
摘要: hadoop是什么?hadoop是如何发展起来的?怎样才能正确安装hadoop环境? 这些天,有很多人咨询我大数据相关的一些信息,觉得大数据再未来会是一个朝阳行业,希望能尽早学会.入行,借这个 ...
- Thinkphp基础配置
访问项目中的index.phpApplication下会自动生成一些文件 在Application下建两个目录 一个Admin用来放后台中的文件 一个Public用来放公共文件 然后去Appplica ...
- css position[转
2.详细展示 2.1 position:absolute 2.2.1 说明: 绝对定位:脱离文档流的布局,遗留下来的空间由后面的元素填充.定位的起始位置为最近的父元素(postion不为static) ...
- Python 时间复杂度
引用自:https://www.cnblogs.com/sch01ar/p/8552295.html
- spring继承Rabbitmq client-----------------------待研究
一:概述 1.官网 https://spring.io/ 2.进入project 3.找到spring AMQP 二:程序 1.结构 2.pom <?xml version="1.0& ...