简单的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
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的更多相关文章

  1. ExtJS笔记 Proxy

    Proxies are used by Stores to handle the loading and saving of Model data. Usually developers will n ...

  2. 如何制作python安装模块(setup.py)

    Python模块的安装方法: 1. 单文件模块:直接把文件拷贝到$python_dir/lib 2. 多文件模块,带setup.py:python setup.py install 3. egg文件, ...

  3. Nginx uWSGI web.py 站点搭建

    一.安装nginx 在安装nginx前,需要先装nginx的依赖包. 1.如果没有yum则先安装yum   删除原有的yum  rpm -aq|grep yum|xargs rpm -e --node ...

  4. python-web.py 入门介绍

    内容来源:webpy.org 介绍: 1.python中web.py 是一个轻量级Python web框架,它简单而且功能强大.web.py是一个开源项目. 2.安装很简单:pip install w ...

  5. DCGAN 代码简单解读

    之前在DCGAN文章简单解读里说明了DCGAN的原理.本次来实现一个DCGAN,并在数据集上实际测试它的效果.本次的代码来自github开源代码DCGAN-tensorflow,感谢carpedm20 ...

  6. python 中的__init__.py的用法与个人理解

    使用Python模块常见的情况是,事先写好A.py文件,需要import B.py文件时,先拷贝到当前目录,然后再import 这样的做法在程序量较小的情况下是可行的,如果程序交互复杂程度稍高,就很费 ...

  7. Linux 下面 Sqlserver 2017 的简单安装

    1. 公司网络太烂 yum 在线安装失败 2. 解决方法 找微软的官网 百度网盘 离线下载rpm包. https://packages.microsoft.com/rhel/7/mssql-serve ...

  8. 生产者&消费者.py

    1.最简单的 --生产者消费者 send.py# !/usr/bin/env python3.5# -*- coding:utf-8 -*-# __author__ == 'LuoTianShuai' ...

  9. Django框架----路由系统、视图和模板(简单介绍)

    一.路由配置系统(urls) URL配置(URLconf)就像Django所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表: 你就是以这种方式告诉Django,对于这个URL ...

随机推荐

  1. visual studio 2017 installer 安装包制作过程出现的问题---此安装程序需要.NET Framework 版本 3.5,请安装该版本,然后重新运行此安装程序,可以从Web获得.NET Framework 。要立即做此事吗?

    图一 visual studio 2017 installer 打包完成以后进行安装时,提示信息 “安装此安装程序需要.NET Framework 版本 3.5,请安装该版本,然后重新运行此安装程序, ...

  2. Windows环境selenium+Python环境配置

    1.安装Python 访问Python官方网站. 根据自己的操作系统32/64 位,选择相应的版本. 安装过程我就不详细描述了,动动手指头,Google一下,你就知道.我的安装目录为:C:\Pytho ...

  3. LeetCode(52):N皇后 II

    Hard! 题目描述: n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 上图为 8 皇后问题的一种解法. 给定一个整数 n,返回 n 皇后不同的解决方 ...

  4. system

    system("cls"); //清屏 system("color f2") //改变控制台颜色 f2为颜色样式,可以是e2.f3等等 Original:htt ...

  5. poj1436水平可见线

    还是线段树区间更新,这次不需要对线段离散化,但是要把线段纵坐标*2,可以举例模拟 #include<iostream> #include<cstring> #include&l ...

  6. hdu4812 逆元+树分治

    逆元链接:https://www.cnblogs.com/zzqc/p/7192436.html 经典的树分治题 #pragma comment("linker,"/STACK:1 ...

  7. easyUI基础入门

    头部需要引人文件:<!DOCTYPE html><html><head> <meta charset="utf-8"> <ti ...

  8. nginx部署网站

    部署单个网站非常简单,只要将网站HTML文件和资源文件(.jpg .css .js等)全部复制到nginx-1.13.12\html目录下. 然后启动 启动进入cmd,切换到nginx-1.13.12 ...

  9. HDU 3746 将字符串的全部字符最少循环2次需要添加的字符数

    Sample Input3aaaabcaabcde Sample Output025 题目大意:给你一个字符串,要求将字符串的全部字符最少循环2次需要添加的字符数.例子:abcabc 已经循环2次,添 ...

  10. thinkphp自定义分页类

    先来看下这个分页的样式,没写css,确实丑 什么时候写样式再来上传下css吧...... 就是多一个页面跳转功能 先把这个代码贴一下 <?php namespace Component; cla ...