简单的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 ...
随机推荐
- wordpress安装主题时提示无法创建目录
直接上解决办法: 找到wp-content文件夹(我的是在/home/wwwroot/default/wp-cotent) 首先给wp-content这个文件夹一个权限 chmod -R 775 wp ...
- 解决Linux安装 VMware tools 工具的方法
一:启动linux服务器,并用远程登录工具访问linux服务器 1:启动系统 2:用服务器控制台 :查看点ip地址 3:用客户端 连接服务器 二:挂起 vm虚拟机的 tools 安装光盘 三:开始 ...
- 上传本地文件到github仓库基本操作
上传文件到github时老师忘记指令,或者总是出一些错,每次都要百度浪费时间,因此将常用操作指令归纳卸载这里,以后再也不要担心百度找帖子了... 第一步:新建仓库 新建仓库步骤省略,最后我们得到一个仓 ...
- cf797c 栈,字符串
还以为能用单调栈做出来,,想了老半天,最后发现模拟一下很好做的 按顺序把字符压栈即可 #include<bits/stdc++.h> using namespace std; #defin ...
- python 全栈开发,Day10(动态参数,命名空间,作用域,函数嵌套)
一.动态参数 def func(a,b,c,d,e,f,g): pass func(1,2,3,4,5,6,7) 如果加30个参数呢?有没有万能的参数,可以代表一切参数呢? *args 动态参数,万能 ...
- Java入门第一章知识点总结
-d是directory 目录的意思 cls:清楚doc里面的内容 ipconfig:显示网络配置信息 java -version:检查安装的jdk版本信息 是类型自动向上转换. 在输出时,根据当前 ...
- 购物车的实现(jsp的session+Java的Map的结合)
1:电商如此发达的现在,作为一个web开发程序猿,如果不会写购物车,真是有点不好意思找工作.所以抓紧练习啊,从上篇博客中抽离出如何实现购物车的功能. 2:首先需要理解购物车实现的一些基本步骤. 2.1 ...
- canvas百分百特效
这个特效是别的人,非原创.原创地址 http://blog.csdn.net/lecepin/article/details/53536445 背后的水是可以动的 代码我再研究了下,下面是加了注释的代 ...
- Mysql数据库改名
转自:https://www.cnblogs.com/leffss/p/7832100.html #!/bin/bash #作者:fafu_li #时间:2015.08.10 #mysql数据库改名, ...
- 【Java】 剑指offer(63) 股票的最大利润
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖交易该 ...