简单的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权限。

  1. proxy [-p port] [-l logfile] [-dh] [allowed_client_name ...]]
  2.  
  3. -p - Port to bind to
  4. -l - Path to logfile. If not specified, STDOUT is used
  5. -d - Run in the background

  

2) Chrome中的switchsharper插件的配置:

TinyHTTPProxy.py的源代码:

  1. #!/usr/bin/python
  2.  
  3. __doc__ = """Tiny HTTP Proxy.
  4.  
  5. This module implements GET, HEAD, POST, PUT and DELETE methods
  6. on BaseHTTPServer, and behaves as an HTTP proxy. The CONNECT
  7. method is also implemented experimentally, but has not been
  8. tested yet.
  9.  
  10. Any help will be greatly appreciated. SUZUKI Hisao
  11.  
  12. 2009/11/23 - Modified by Mitko Haralanov
  13. * Added very simple FTP file retrieval
  14. * Added custom logging methods
  15. * Added code to make this a standalone application
  16. """
  17.  
  18. __version__ = "0.3.1"
  19.  
  20. import BaseHTTPServer, select, socket, SocketServer, urlparse
  21. import logging
  22. import logging.handlers
  23. import getopt
  24. import sys
  25. import os
  26. import signal
  27. import threading
  28. from types import FrameType, CodeType
  29. from time import sleep
  30. import ftplib
  31.  
  32. DEFAULT_LOG_FILENAME = "proxy.log"
  33.  
  34. class ProxyHandler (BaseHTTPServer.BaseHTTPRequestHandler):
  35. __base = BaseHTTPServer.BaseHTTPRequestHandler
  36. __base_handle = __base.handle
  37.  
  38. server_version = "TinyHTTPProxy/" + __version__
  39. rbufsize = 0 # self.rfile Be unbuffered
  40.  
  41. def handle(self):
  42. (ip, port) = self.client_address
  43. self.server.logger.log (logging.INFO, "Request from '%s'", ip)
  44. if hasattr(self, 'allowed_clients') and ip not in self.allowed_clients:
  45. self.raw_requestline = self.rfile.readline()
  46. if self.parse_request(): self.send_error(403)
  47. else:
  48. self.__base_handle()
  49.  
  50. def _connect_to(self, netloc, soc):
  51. i = netloc.find(':')
  52. if i >= 0:
  53. host_port = netloc[:i], int(netloc[i+1:])
  54. else:
  55. host_port = netloc, 80
  56. self.server.logger.log (logging.INFO, "connect to %s:%d", host_port[0], host_port[1])
  57. try: soc.connect(host_port)
  58. except socket.error, arg:
  59. try: msg = arg[1]
  60. except: msg = arg
  61. self.send_error(404, msg)
  62. return 0
  63. return 1
  64.  
  65. def do_CONNECT(self):
  66. soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  67. try:
  68. if self._connect_to(self.path, soc):
  69. self.log_request(200)
  70. self.wfile.write(self.protocol_version +
  71. " 200 Connection established\r\n")
  72. self.wfile.write("Proxy-agent: %s\r\n" % self.version_string())
  73. self.wfile.write("\r\n")
  74. self._read_write(soc, 300)
  75. finally:
  76. soc.close()
  77. self.connection.close()
  78.  
  79. def do_GET(self):
  80. (scm, netloc, path, params, query, fragment) = urlparse.urlparse(
  81. self.path, 'http')
  82. if scm not in ('http', 'ftp') or fragment or not netloc:
  83. self.send_error(400, "bad url %s" % self.path)
  84. return
  85. soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  86. try:
  87. if scm == 'http':
  88. if self._connect_to(netloc, soc):
  89. self.log_request()
  90. soc.send("%s %s %s\r\n" % (self.command,
  91. urlparse.urlunparse(('', '', path,
  92. params, query,
  93. '')),
  94. self.request_version))
  95. self.headers['Connection'] = 'close'
  96. del self.headers['Proxy-Connection']
  97. for key_val in self.headers.items():
  98. soc.send("%s: %s\r\n" % key_val)
  99. soc.send("\r\n")
  100. self._read_write(soc)
  101. elif scm == 'ftp':
  102. # fish out user and password information
  103. i = netloc.find ('@')
  104. if i >= 0:
  105. login_info, netloc = netloc[:i], netloc[i+1:]
  106. try: user, passwd = login_info.split (':', 1)
  107. except ValueError: user, passwd = "anonymous", None
  108. else: user, passwd ="anonymous", None
  109. self.log_request ()
  110. try:
  111. ftp = ftplib.FTP (netloc)
  112. ftp.login (user, passwd)
  113. if self.command == "GET":
  114. ftp.retrbinary ("RETR %s"%path, self.connection.send)
  115. ftp.quit ()
  116. except Exception, e:
  117. self.server.logger.log (logging.WARNING, "FTP Exception: %s",
  118. e)
  119. finally:
  120. soc.close()
  121. self.connection.close()
  122.  
  123. def _read_write(self, soc, max_idling=20, local=False):
  124. iw = [self.connection, soc]
  125. local_data = ""
  126. ow = []
  127. count = 0
  128. while 1:
  129. count += 1
  130. (ins, _, exs) = select.select(iw, ow, iw, 1)
  131. if exs: break
  132. if ins:
  133. for i in ins:
  134. if i is soc: out = self.connection
  135. else: out = soc
  136. data = i.recv(8192)
  137. if data:
  138. if local: local_data += data
  139. else: out.send(data)
  140. count = 0
  141. if count == max_idling: break
  142. if local: return local_data
  143. return None
  144.  
  145. do_HEAD = do_GET
  146. do_POST = do_GET
  147. do_PUT = do_GET
  148. do_DELETE=do_GET
  149.  
  150. def log_message (self, format, *args):
  151. self.server.logger.log (logging.INFO, "%s %s", self.address_string (),
  152. format % args)
  153.  
  154. def log_error (self, format, *args):
  155. self.server.logger.log (logging.ERROR, "%s %s", self.address_string (),
  156. format % args)
  157.  
  158. class ThreadingHTTPServer (SocketServer.ThreadingMixIn,
  159. BaseHTTPServer.HTTPServer):
  160. def __init__ (self, server_address, RequestHandlerClass, logger=None):
  161. BaseHTTPServer.HTTPServer.__init__ (self, server_address,
  162. RequestHandlerClass)
  163. self.logger = logger
  164.  
  165. def logSetup (filename, log_size, daemon):
  166. logger = logging.getLogger ("TinyHTTPProxy")
  167. logger.setLevel (logging.INFO)
  168. if not filename:
  169. if not daemon:
  170. # display to the screen
  171. handler = logging.StreamHandler ()
  172. else:
  173. handler = logging.handlers.RotatingFileHandler (DEFAULT_LOG_FILENAME,
  174. maxBytes=(log_size*(1<<20)),
  175. backupCount=5)
  176. else:
  177. handler = logging.handlers.RotatingFileHandler (filename,
  178. maxBytes=(log_size*(1<<20)),
  179. backupCount=5)
  180. fmt = logging.Formatter ("[%(asctime)-12s.%(msecs)03d] "
  181. "%(levelname)-8s {%(name)s %(threadName)s}"
  182. " %(message)s",
  183. "%Y-%m-%d %H:%M:%S")
  184. handler.setFormatter (fmt)
  185.  
  186. logger.addHandler (handler)
  187. return logger
  188.  
  189. def usage (msg=None):
  190. if msg: print msg
  191. print sys.argv[0], "[-p port] [-l logfile] [-dh] [allowed_client_name ...]]"
  192. print
  193. print " -p - Port to bind to"
  194. print " -l - Path to logfile. If not specified, STDOUT is used"
  195. print " -d - Run in the background"
  196. print
  197.  
  198. def handler (signo, frame):
  199. while frame and isinstance (frame, FrameType):
  200. if frame.f_code and isinstance (frame.f_code, CodeType):
  201. if "run_event" in frame.f_code.co_varnames:
  202. frame.f_locals["run_event"].set ()
  203. return
  204. frame = frame.f_back
  205.  
  206. def daemonize (logger):
  207. class DevNull (object):
  208. def __init__ (self): self.fd = os.open ("/dev/null", os.O_WRONLY)
  209. def write (self, *args, **kwargs): return 0
  210. def read (self, *args, **kwargs): return 0
  211. def fileno (self): return self.fd
  212. def close (self): os.close (self.fd)
  213. class ErrorLog:
  214. def __init__ (self, obj): self.obj = obj
  215. def write (self, string): self.obj.log (logging.ERROR, string)
  216. def read (self, *args, **kwargs): return 0
  217. def close (self): pass
  218.  
  219. if os.fork () != 0:
  220. ## allow the child pid to instanciate the server
  221. ## class
  222. sleep (1)
  223. sys.exit (0)
  224. os.setsid ()
  225. fd = os.open ('/dev/null', os.O_RDONLY)
  226. if fd != 0:
  227. os.dup2 (fd, 0)
  228. os.close (fd)
  229. null = DevNull ()
  230. log = ErrorLog (logger)
  231. sys.stdout = null
  232. sys.stderr = log
  233. sys.stdin = null
  234. fd = os.open ('/dev/null', os.O_WRONLY)
  235. #if fd != 1: os.dup2 (fd, 1)
  236. os.dup2 (sys.stdout.fileno (), 1)
  237. if fd != 2: os.dup2 (fd, 2)
  238. if fd not in (1, 2): os.close (fd)
  239.  
  240. def main ():
  241. logfile = None
  242. daemon = False
  243. max_log_size = 20
  244. port = 8000
  245. allowed = []
  246. run_event = threading.Event ()
  247. local_hostname = socket.gethostname ()
  248.  
  249. try: opts, args = getopt.getopt (sys.argv[1:], "l:dhp:", [])
  250. except getopt.GetoptError, e:
  251. usage (str (e))
  252. return 1
  253.  
  254. for opt, value in opts:
  255. if opt == "-p": port = int (value)
  256. if opt == "-l": logfile = value
  257. if opt == "-d": daemon = not daemon
  258. if opt == "-h":
  259. usage ()
  260. return 0
  261.  
  262. # setup the log file
  263. logger = logSetup (logfile, max_log_size, daemon)
  264.  
  265. if daemon:
  266. daemonize (logger)
  267. signal.signal (signal.SIGINT, handler)
  268.  
  269. if args:
  270. allowed = []
  271. for name in args:
  272. client = socket.gethostbyname(name)
  273. allowed.append(client)
  274. logger.log (logging.INFO, "Accept: %s (%s)" % (client, name))
  275. ProxyHandler.allowed_clients = allowed
  276. else:
  277. logger.log (logging.INFO, "Any clients will be served...")
  278.  
  279. server_address = (socket.gethostbyname (local_hostname), port)
  280. ProxyHandler.protocol = "HTTP/1.0"
  281. httpd = ThreadingHTTPServer (server_address, ProxyHandler, logger)
  282. sa = httpd.socket.getsockname ()
  283. print "Servering HTTP on", sa[0], "port", sa[1]
  284. req_count = 0
  285. while not run_event.isSet ():
  286. try:
  287. httpd.handle_request ()
  288. req_count += 1
  289. if req_count == 1000:
  290. logger.log (logging.INFO, "Number of active threads: %s",
  291. threading.activeCount ())
  292. req_count = 0
  293. except select.error, e:
  294. if e[0] == 4 and run_event.isSet (): pass
  295. else:
  296. logger.log (logging.CRITICAL, "Errno: %d - %s", e[0], e[1])
  297. logger.log (logging.INFO, "Server shutdown")
  298. return 0
  299.  
  300. if __name__ == '__main__':
  301. 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. Node.js ECONNREFUSED错误

    1 现象 node服务器 遇见此错误,如下:events.js:71throw arguments[1]; // Unhandled 'error' event^Error: connect ECON ...

  2. STM32应用实例六:与MS5837压力传感器的I2C通讯

    MS5837压力传感器是一种可用于电路板上,适用于检测10-1200mbar压力范围的传感器,灵敏度非常高,理论上能够检测到0.01mbar的压力变化,实际使用过程中测试并无明显的变化. MS5837 ...

  3. Dubbo入门---搭建一个最简单的Demo框架

    参考文档: https://blog.csdn.net/noaman_wgs/article/details/70214612/

  4. C++ code:剩余串排列

    方法一: 一种直观的解是,先对第一个字串排序,然后逐个字符在第二个字串中搜索,把搜索不到的字符输出,就是所要的结果. 然而,算法库中有一个集合差运算set_difference,而且要求两个集合容器是 ...

  5. 【ES】代码例子

    #!/usr/bin/env python #coding=utf-8 from elasticsearch import Elasticsearch from elasticsearch_dsl i ...

  6. ROS----TUT-RIM协作机器人和Actin-ROS接口

    TUT-RIM: Collaborative Intelligent Heavy Machinery and Robotics http://www.ros.org/news/2017/02/tutr ...

  7. 使用k8s operator安装和维护etcd集群

    关于Kubernetes Operator这个新生事物,可以参考下文来了解这一技术的来龙去脉: https://yq.aliyun.com/articles/685522?utm_content=g_ ...

  8. Spring之对象依赖关系(依赖注入Dependency Injection)

    承接上篇: Spring中,如何给对象的属性赋值: 1:通过构造函数,如下所示: <!-- 1:构造函数赋初始值 --><bean id="user1" clas ...

  9. python全栈开发day24-__new__、__del__、item系列、异常处理

    一.昨日内容回顾 1.反射 用字符串类型的名字,操作命名空间的变量. 反射使用场景:明显的简化代码,能拿到的变量名本来就是一个字符串类型的时候, 用户输入的,文件读入的,网上传输的 2.__call_ ...

  10. Linux 关闭网络管理服务

    1 将NetworkManager 服务设置开机不启动 chkconfig NetworkManager off 2将NetwokManager服务关闭 service NetworkManager ...