Python 拦截浏览器的网络流量
我想用Python创建一个简单的网页过滤应用。我的想法是监控tcp 80和443端口(也就是http和https),如果有流量进来,我想先检查一下这些流量,然后再决定是否放行。如果检查不通过,我希望能把用户重定向到我指定的页面。
所以我想问的是,当用户在浏览器里访问 http://www.google.com 时,有没有办法拦截这个请求?还有,我能不能把他们重定向到我想要的其他页面呢?
3 个回答
如果是某个特定的网站,比如 google.com,你可以通过修改 hosts 文件来解决问题。这虽然不是个好办法,但很简单。
如果你想找到这个文件,它的位置是:
C:/windows/system32/drivers/hosts.txt
在 Linux 系统中,这个文件也在 etc
文件夹里,不过我不太确定具体在哪...
这是我之前写的一篇博客文章中的内容,讲的是如何使用webob和paste。TransparentProxy可以把请求转发到请求中指定的任何网址。你可以写一些中间件,在请求被转交给transparentproxy之前,对请求做一些处理。
然后,只需将你的浏览器的代理设置成你的代理服务器运行的地址就可以了。
这个例子会打印出请求和响应。在你的情况下,你需要检查响应的状态,比如404或302等,然后调用你自己写的代码来处理。
from webob.dec import wsgify
from paste import httpserver
from paste.proxy import TransparentProxy
def print_trip(request, response):
"""
just prints the request and response
"""
print "Request\n==========\n\n"
print str(request)
print "\n\n"
print "Response\n==========\n\n"
print str(response)
print "\n\n"
class HTTPMiddleware(object):
"""
serializes every request and response
"""
def __init__(self, app, record_func=print_trip):
self._app = app
self._record = record_func
@wsgify
def __call__(self, req):
result = req.get_response(self._app)
try:
self._record(req.copy(), result.copy())
except Exception, ex: #return response at all costs
print ex
return result
httpserver.serve(HTTPMiddleware(TransparentProxy()), "0.0.0.0", port=8088)
补充:
这里有一个我写的中间件的例子,这样我就可以拦截某个路径并返回不同的响应。我用这个来测试一个重度依赖JavaScript的应用程序,因为它是为生产环境硬编码的,我拦截了config.js,并输出我自己的配置,这个配置是针对单元测试的特定设置。
class FileIntercept(object):
"""
wsgi: middleware
given request.path will call wsgi app matching that path instead
of dispatching to the wrapped application
"""
def __init__(self, app, file_intercept={}):
self._app = app
self._f = file_intercept
def __call__(self, environ, start_response):
request = Request(environ)
if request.path.lower() in self._f:
response = request.get_response(self._f[request.path.lower()])
else:
response = request.get_response(self._app)
return response(environ, start_response)
作为一个例子,我会这样初始化它……
app = FileIntercept(TransparentProxy(),
file_intercept={"/js/config.js":Response("/*new settings*/")})
httpserver.serve(HTTPMiddleware(app), "0.0.0.0", port=8088)
你需要写一个网络代理,然后把你的网络客户端的代理服务器设置为 http://localhost:8000/(或者其他你设置的代理地址)。
这样,你的网络客户端就会发送类似这样的HTTP请求:
这个请求会发送到你的代理服务器,代理服务器需要把它改写成:
GET /
然后再把这个请求发送到www.google.com,获取到响应后,再把响应通过原来的连接返回给客户端。需要注意的是,这个解释是非常简化的。
总之,这些都是标准的内容,我猜应该已经有现成的Python网络代理可以让你去修改和使用。