有很多好用的上网代理软件,知名的如squid,小众的如tinyproxy,polipo,3proxy等等。如果只是个人使用,其实哪个都差不多,因为IP端口都属于秘密。如果说一定范围的公众使用,那么squid拥有用户名密码列表的ACL控制,也能满足特定人群的授权。
但是,如果真想做好一个代理服务,任何一个代理软件自带的feature都无法满足复杂的业务需求。就拿squid来说:
- 会话超时。一段时间空闲或者关闭浏览器后,重新使用代理服务需要输入用户名密码
- 用户VIP业务。用户有不同的付费级别,低级别的用户可能无法访问某些网站
- 每个用户的流量统计
要做到这些功能,就必须要对所使用的代理软件进行二次改造。因为我最终选择的是tinyproxy,所以我介绍下tinyproxy的源码和修改点。
tinyproxy采用的是select+fork的多进程模式,polipo是epoll+事件驱动模式。polipo支持长连接和cache,性能上会更好。本来打算修改polipo用的,结果一看事件驱动那代码的绕口程度,就放弃了。相比之下,tinyproxy是一个连接处理一个请求,处理完就关闭,一整套顺序流程,简单明了。
开始说代码,入口总是main:
- main.c中的main函数,直接找到child_main_loop。tinyproxy总是通过子进程处理每个请求,以获得较好的并发性能。
- child_main_loop在child.c中,调用child_make创建子进程,子进程的主函数是child_main。
- child_main中,多个子进程去accept抢请求,抢到之后通过handle_connection处理。
- handle_connection中check_acl是tinyproxy检查用户ip的ACL,单我是通过用户名密码做身份验证的,所以用不上。
- 自定义的ACL是在get_all_headers后,也就是读取了所有的客户端http headers。从header中取得proxy-authorization,可以检查用户名和密码,取得用户身份什么的。甚至可以从cookie中取出能校验用户身份的内容。
- 在这一步自定义ACL中,还可以做ip之类的检查,控制会话超时,减免用户的认证频率。
- 在process_request的调用中,一般是在config.filter后,参考config.filter的处理,对不同的用户身份给予不同的代理服务。比如免费用户就不要妄想可以看youtube了。
- 回到handle_connection,客户端的请求被转发给服务器,然后调用process_server_headers处理服务器的数据返回。
- 同样是在process_server_headers中get_all_headers后,取到了所有的服务端返回的http header,这时候可以选择插入Set-Cookie,来增强用户的身份认证。
- 最后要统计每个用户的流量,回到handle_connection的relay_connection调用,这里就是纯粹的pipe,这里做好每个用户的数据传输量统计。
好了,我做的就是那么多,通过改代码的方式,为代理服务增加业务功能。squid是epoll+事件驱动模式,其实也都好理解,关键的是能否直观的找到插入自定义代码的地方。
有需要翻土啬的朋友,可考虑一下我的http代理服务,不是VPN或启动客户端这种,只需要将向你提供的自动配置脚本设置到浏览器内即可。
点下方链接,送5天付费版试用,过期后免费版依然可以上推特和google。