起风了 梦开始
www.myvary.cn

使用squid搭建代理服务器

squid是一款高效的http代理服务器程序,而且更经常被用来做缓存服务器。官网:http://www.squid-cache.org;还有一位大牛翻译的squid中文权威指南

一、安装squid

我的安装环境:Ubuntu 14.04.2 LTS

可以使用squid3 -v 检查安装好的squid

二、squid配置

squid默认配置文件为/etc/squid/squid.conf

2.1 基本配置

注意,在作为正向代理的时候(squid默认配置),http_port 3128端口也可以处理https代理请求,因为作正向代理时squid并不需要参与ssl的加密解密,只需要帮忙从用户到网站的443端口建立tcp连接,然后无脑转发用户到网站之间的加密数据即可。只有当要将squid用作反向代理的时候,才需要用到squid的https_port配置,为squid设置证书。

2.2 访问控制

acl指令用来定义访问列表(Access List),用法:acl  aclname  acltype  argument

http_access指令用来定义接收还是拒绝来自acl的访问,用法:http_access  allow|deny  [!]aclname

squid.conf中默认的访问控制如下:

在squid.conf的默认配置中,拒绝了所有的外部代理请求。这时候如果使用该代理,会返回错误页面:

上图中管理员邮箱由cache_mgr定义的,funway.aliyun.proxy由visible_hostname定义。

所以要想让其他主机使用squid代理,需要在最后一句http_access deny all前面添加我们自定义的规则。

然后在本地主机(在AuthClients网段中的)的浏览器上设置代理:(我用的Chrome +SwitchySharp插件)

通过代理访问http://www.hawu.me,打开开发者工具中的网络窗口,检查该请求的状态,可以看到Remote Address为我们设置的代理,在Response Headers里还有我定义的代理服务器名”funway.aliyun.proxy”,表示这个请求是通过我们的代理服务器返回的。

注意:squid的http_access是按照配置文件中定义的顺序依次进行判断的!遇到第一个满足条件的http_access(allow或者deny)就立即返回!不再进行后续http_access判断。可以通过打开日志等级debug_options 28,5来查看http_access记录。

2.3 高级访问控制:用户验证

2.2介绍的是开启某个ip段的访问权限,除了限定ip,squid acl还可以做很多类型的访问控制,更详细的请参考官方文档。这里就打算介绍下如何使用squid自带的用户验证程序进行http basic authentication。

首先,我觉得需要先了解一下什么叫http authentication。这篇文章写得比较浅显易懂:http://blog.csdn.net/kiwi_coder/article/details/28677651

要让squid进行http authentication,需要用到auth_param配置:

另外,我们需要手动生成密码文件/etc/squid/passwd,可以借组htpasswd程序(htpasswd是apache的一个命令行工具,用于生成管理 http 基本认证的密码文件。so,要使用htpasswd需要先安装apache)

 

然后根据提示输入密码。就在passwd文件中生成了funway用户。

最后重启squid服务:service  squid  restart

浏览器首次通过代理进行访问的时候会弹出要求输入用户名密码的对话框:

ps:squid自带的拓展程序通常放在目录/usr/lib/squid下(64位的centos是/usr/lib64/squid),比如里面squid_db_auth程序可以用来做用户数据库方式的认证,ldap_auth可以用来连接ldap服务器进行用户验证。另外,除了使用squid自带的验证程序,我们还可以编写自己的验证程序让squid来调用,具体参考squid文档与google。

屏幕快照 2016-04-02 下午2.38.23

又ps:http_access的顺序会对结果有一些影响,最好要在上线前做好测试。比如说如果2.2中定义的AuthClients与2.3中定义的AuthClients共存的话,如果http_access allow AuthClients在前,那么满足AutchClients的注解无效用户认证就能访问,如果是http_access allow AuthUsers在前,那么就必须满足AuthUsers的用户才能访问。


另外,为了获得比basic auth更强的安全性,推荐使用digest auth。关于digest auth的原理,参考wiki:https://en.wikipedia.org/wiki/Digest_access_authentication(尤其里面的第四节 Example with explanation

以使用squid自带的验证程序digest_pw_auth为例,修改auth_param配置如下:

然后为了生成digest.passwd密码文件,可以使用活雷锋apache提供的htdigest命令行工具,也可以使用如下脚本: $./gen_digest_pw.sh name pass ‘myproxy’ >> digest.passwd

ps:2016.4.11 我后面发现digest_pw_auth有点问题,因为squid3.4+后的版本,对digest auth_param的返回值规则做了修改,而digest_pw_auth似乎没有更新=。=#。所以后来我自己写了一个digest辅助程序,并使用redis作为存储用户信息的数据库,这样读取会更快:https://github.com/funway/digest_redis_auth

又ps:2016.4.12 我发现我也是蛋疼的才想用digest auth,squid还是对basic auth支持的最好。想用acl max_user_ip来限制用户多地登陆,结果折腾了两天发现max_user_ip只支持basic auth,对于其他验证方法,根本没用!!!

2.4 匿名代理

http头中有三个信息是用来给服务器鉴别用户的:remote_addr,http_via,http_x_forwarded_for。

用户不使用代理直接访问网站时,http头包含如下信息:

remote_addr = 用户真实ip

http_via = 不包含

http_x_forwarded_for = 不包含

用户使用普通代理访问时,对方服务器知道用户使用了代理,并且知道用户的真实ip。此时http头包含如下:

remote_addr = 代理服务器ip

http_via = 代理服务器主机名(squid的visible_hostname)

http_x_forwarded_for = 用户真实ip(如果用户使用了多层代理,这里应该是不包括最后一跳的整个ip链)

用户使用匿名代理访问时,对方服务器知道用户使用了代理,但不知道用户的真实ip。此时http头包含如下:

remote_addr = 代理服务器ip

http_via = 代理服务器主机名

http_x_forwarded_for = 代理服务器ip

用户使用高匿名代理访问时,对方服务器不知道用户使用了代理,也不知道用户真实ip。此时的http头包含如下:

remote_addr = 代理服务器ip

http_via = 不包含

http_x_forwarded_for = 不包含

squid默认是作为普通代理的,即开启via,并会写入http_forwarded_for。要想作为匿名代理,只需修改如下两个配置:

2.5 squid层级

在负责的网络环境中,我们可能要使用多个squid服务器构建一个squid集群,squid集群中可以有父子关系、兄弟关系。使用squid层级时,我们还可以定义squid A将某些流量转发给squid B,某些流量直接转发到目标服务器,或者所有流量都由squid B转发。这些主要用到squid的cache_peer、cache_peer_access、always_direct等配置指令。

详细配置可参考:

http://wiki.squid-cache.org/Features/CacheHierarchy

http://home.arcor.de/mailerstar/jeff/squid/chap10.html

2.6 其他配置

三、墙外squid不稳定?被墙了!

其实我有两台云主机,一台墙内的阿里云ali,一台墙外的亚马逊aws。我先是在aws上搭的squid代理,但发现经常会出现连接被重置的情况,有时候能访问,有时候则直接显示ERR_CONNECTION_RESET。

开启squid的debug_options配置(debug_options  ALL,6),检查cache.log,只看到出错请求的后面有“errno 104”。这折腾了我一整天,怎么改配置,查错误都没解决,后来灵机一动,想到难道是因为GFW的原因?

然后我又用同样的配置在阿里云主机上搭了一个squid,发现果然连接正常了,完全不会CONNECTION RESET。看来被狗日的GFW墙了。

想了好久的原因,用wireshark抓包,惊奇的发现有到google.com的包(cache.log中有记录,我之前没注意到=。=#),想起来我用的是chrome浏览器,并且登录了我的gmail账号,后台会不时跟google同步,而这个流量也走了aws代理。所以当chrome后台通过aws代理请求google.com的时候,这个包被GFW监控到,然后GFW就直接把我的ip给墙了。

后面再请求weibo.com,此时我的ip已经被GFW记住了(大概会墙1、2分钟),GFW直接返回ERR_CONNECTION_RESET,并断开连接。

至于请求包,有可能会到达aws代理,也有可能不会到达而直接被GFW丢弃。因为我检查过squid日志,在google.com的记录后,我被墙期间的请求,有的会有记录,有的没有记录。但即使请求到了squid,也无法返回了,所有的后续日志都有一条“errno 104”,表示对端socket连接已经关闭。

这个问题的解决办法其实很简单,在浏览器的代理设置里忽略google.com即可:

 

四、squid + stunnel >> 科学上网

squid可以很方便的搭建http代理服务器,但从上面被墙的案例我们看到,单单使用墙外的squid代理是无法进行科学上网的。这时候就需要在墙内用户与墙外squid之间加一个stunnel,将我们发送给squid的请求进行加密。更详细的介绍请看下一篇文章http://www.hawu.me/operation/886

 

五、squid高级进阶

5.1 开发squid辅助程序

官方说明:http://wiki.squid-cache.org/Features/AddonHelpers

可以用任意语言开发squid辅助程序,只要能读写stdin与stdout。squid通过每次写一行数据到stdin,辅助程序解析该行数据,再从stdout返回一行结果给squid。

我自己尝试用python+redis写了两个squid的辅助程序,用来进行用户验证与限制。

5.2 内容篡改

squid有几个基本指令可以用来做内容篡改。

url_rewrite_program可以用来修改用户请求,将其转发到我们指定的url。这个指令有个简单粗暴的应用就是url过滤,禁止用户访问不受允许的网站,不想自己写url_rewrite_program辅助程序的话可以使用squidguard这个插件。

还有一个比较黑嘿嘿的应用就是篡改广告,举个栗子🌰,判断到用户请求的url是某个推广链接(就是浏览器右下角老弹出来的那种小广告)那么就可以将它rewrite到我们自己的推广链接。还有更隐蔽的做法,可以判断请求的是否js文件,如果是,后台下载过来然后篡改这个js文件加入我们想要执行的脚本,再放到我们自己的web服务器上通过url_rewrite_program返回给用户。简直bad、bad。


request_header_replacereply_header_replace、request_header_add、reply_header_add这几个指令可以用来篡改用户的http头。但对于http body就无能为力了。如果我们想篡改response body,嘿嘿,铛铛铛当!可以使用icap、ecap扩展,官方说明:http://wiki.squid-cache.org/SquidFaq/ContentAdaptation。感觉应该是icap好开发一些,但效率不如ecap。

我现在有一个点子似乎就得用到内容篡改,我想在返回给用户的cookie中加上代理自己的sessionid,模仿http会话的效果,这样做的原因有两个,因为使用http auth进行用户验证的话,每次请求头都要带上用户验证信息,效率低不说,有些垃圾浏览器还不会自动记住用户名密码,会每次都弹出窗口叫用户重新输入,这就有点不友好了。如果能在用户的cookie中加上代理自己的proxy-session-id,然后服务器将这个proxy-session-id放在内存或redis中,每次只要验证用户cookie就可以了,proxy-session-id超时了才重新进行http auth验证。这其实用reply_header_add应该可以实现,但我觉得reply_header_add实现起来好像很不方便,而且必须得用squid 4.0以上版本。以后有空了实践一下吧。

5.3 监控

5.3.1 access.log日志监控与分析

有很多access日志分析的软件,不过只有squidanalyzer是在持续更新的,http://squidanalyzer.darold.net/

5.3.2 snmp协议进行流量与资源监控

http://wiki.squid-cache.org/Features/Snmp

打赏

未经允许,不得转载本站任何文章:刘鑫的博客 » 使用squid搭建代理服务器

分享到:更多 ()