在上一篇文章《使用squid搭建代理服务器》里,我们知道单单使用墙外的squid代理是不可能实现翻墙的,因为墙内主机到墙外squid之间发送的请求会被GFW监控到。即使是https,报文正文虽然是加密的,但报头是不加密的,依然会被GFW墙掉。 既然如此,如果我们从墙内到墙外squid之间的数据包是加密过的,那不就可以瞒过GFW了?这就需要用到stunnel! Stunnel 是一个自由的跨平台软件,用于提供全局的TLS/SSL服务。针对本身无法进行TLS或SSL通信的客户端及服务器,Stunnel可提供安全的加密连 接。该软件可在许多操作系统下运行,包括Unix-like系统,以及Windows。Stunnel依赖于某个独立的库,如OpenSSL或者 SSLeay,以实现TLS或SSL协议。 ——百度百科 ps:除了stunnel外,比较有名的开源隧道软件还包括:由代理软件varnish-cache的母公司提供的hitch(前身是stud),国内VPN厂商曲径提供的qtunnel 一、squid + stunnel 翻墙大法 squid+stunnel翻墙大法的原理如下图: 用户将tcp包发给stunnel client;stunnel client将包加密,发送给stunnel server;stunnel server解密后发送给squid;squid将包中的http请求进行转发,然后再将请求结果返回给stunnel server;stunnel server加密发给stunnel client;stunnel client解密后交回给用户。这样,由于通过GFW的数据是被stunnel加密过的,用户就能放心的“科学上网”了。 根据stunnel client的部署位置,我们有两套实现方案: 方案1:墙外服务器部署squid + stunnel server;墙内用户主机部署stunnel client,并将浏览器代理设置为本机上的stunnel client。 这个方案的优点就是节约,只需要一台墙外服务器。缺点是墙内每个用户主机都要装stunnel client,如果只是自己一个人用的话还好,用户多的话就麻烦了。而且我个人很讨厌在电脑上装太多后台程序,有洁癖。=。=# 方案2:墙外服务器部署squid + stunnel server;墙内服务器部署stunnel client;墙内用户主机将浏览器代理设置为墙内的stunnel client服务器。 这个方案的优点就是对用户方便,傻瓜操作,只要修改浏览器代理设置即可使用。缺点就是不节约,需要两台服务器,墙外墙内各一台。 好在我就有阿里云跟亚马逊两台云服务器,所以我选择方案2来进行科学上网。 二、TLS/SSL证书 在安装配置stunnel之前,需要先了解下stunnel server与client之间是怎么进行TLS/SSL传输的。由于官方没有好一点的文档,所以可以参考这篇关于https原理的文章,http://blog.csdn.net/clh604/article/details/22179907,我觉的写的很好。这也是stunnel server与client加密传输的基础。 SO,在配置stunnel之前,我们得先准备好一个TLS/SSL证书。我们可以生成证书请求,然后发给权威CA机构,让他们给我们签发证书,权威CA机构签发的证书好处就是一般浏览器都能识别,但就是贵。我们也可以生成自签名的证书,这种证书的好处就是不花钱,但由于不是权威CA机构签发的,浏览器会弹出提示“证书不安全”。不过反正我们现在需要的证书只用在stunnel server与client之间,不用提供给用户浏览器,所以用自签名证书就好了。 2.1 安装openssl 一般linux发行版本都自带openssl,所以这里就不多讲了。 2.2 生成自签名证书 在要做为stunnel server的服务器上使用下面命令生成自签名证书: openssl req -new -x509 -days 3650 -nodes -out stunnel.pem -keyout stunnel.pem req指令,用来创建和管理证书请求(Certificate Signing Request, CSR)以让第三方权威机构CA来签发我们需要的证书。也可以使用-x509参数来生成自签名证书。 -new参数,表示新建证书(或证书请求) -x509参数,表示要生成x.509格式的证书而不是证书请求 -days参数,表示生成的证书的有效时间 -nodes参数,不要加密私钥(如果没有定义这个参数,执行openssl req命令时候会要求输入一个密码,来对要生成的私钥文件进行加密,然后后面stunnel或nginx这些服务器程序要使用这个私钥的时候就会被要求输入密码) -out参数,要生成的证书(certificate)文件名(如果没有定义-x509参数,生成的就是证书请求certificate request) -keyout参数,要生成的私钥(private key)文件名(上面使用了跟证书一样的文件名,并不会覆盖该文件,而是追加到一起) 三、安装配置stunnel 3.1 安装stunnel 我有两台服务器,墙外的亚马逊服务器用作stunnel server,墙内的阿里云服务器用作stunnel client。在两台服务器都安装好stunnel。 有的版本的stunnel安装后自动添加到系统service中了,可以用service stunnel start/stop/restart。有的版本不会自动添加,启动的时候就直接敲stunnel,停的话有个快捷的kill方式: kill <code>{{EJS0}}</code> PS:记得在系统的iptables(如果有的话)以及亚马逊、阿里云控制台的安全组策略中打开stunnel配置中用到的端口。 3.2 配置stunnel server 默认的stunnel配置文件在/etc/stunnel/stunnel.conf。关于更多参数信息,可以参考:https://www.stunnel.org/static/stunnel.html ; 设置工作目录 chroot = /var/run/stunnel/ ; 设置stunnel的pid文件路径(在chroot下) pid = /stunnel.pid ; 设置stunnel工作的用户(组) setuid = root setgid = root ; 开启日志等级:emerg (0), alert (1), crit (2), err (3), warning (4), notice (5), info (6), or debug (7) ; 默认为5 debug = 7 ; 日志文件路径(我的server的版本有个bug,这个文件也被放在chroot路径下了,client的版本则是独立的=。=#) output = /stunnel.log ; 证书文件,就是在本文2.2中用openssl生成的自签名证书(server端必须设置这两项) cert = /etc/stunnel/stunnel.pem ; 私钥文件 key = /etc/stunnel/stunnel.pem ; 设置stunnel服务,可以设置多个服务,监听同的端口,并发给不同的server。 ; 自定义服务名squid-proxy [squid-proxy] ; 服务监听的端口,client要连接这个端口与server通信 accept = 3129 ; 服务要连接的端口,连接到squid的3128端口,将数据发给squid connect = 3128 ; ************************************************************************** ; * 下面这些配置我都注释掉了,但也需要了解下 * ; ************************************************************************** ; 设置是否对传输数据进行压缩,默认不开启。 ; 这是跟openssl相关的,如果你的openssl没有zlib,开启这个设置会导致启动失败(failed to initialize compression method) ;compression = zlib ; 设置ssl版本,这个也是跟安装的openssl有关的 ;sslVersion = TLSv1 ; Authentication stuff needs to be configured to prevent MITM attacks ; It is important to understand that this option was solely designed for access control and not for authorization ; It is not enabled by default! ; 下面这些配置用来定义是否信任对方发过来的证书。就好比浏览器访问https的时候,浏览器默认会信任那些由权威CA机构签发的证书, ; 对于那些自签名证书,浏览器就会弹出对话框提醒用户这个证书可能不安全,是否要信任该证书。 ; 这是有效防止中间人攻击的手段 ; verify 等级2表示需要验证对方发过来的证书(默认0,不需要验证,都信任) ; 因为这个配置是server端的,我们不需要理会client的证书(client也不会没事发证书过来啦) ;verify = 2 ; CAfile 表示受信的证书文件,即如果对方发过来的证书在这个CAfile里,那么就是受信任的证书;否则不信任该证书,断开连接。 ;CAfile = /etc/stunnel/stunnel-client.pem 3.3 配置stunnel client 因为我会在client的配置中开启了证书验证,就是对于对方发过来的证书文件,client需要去CAfile中进行匹配,匹配到的证书才是受信证书,才允许建立连接。这样的话,我们就需要把server端的证书拷贝过来。我是直接打开server端的stunnel.pem,然后将里面CERITIFICATE拷贝到client端新建的/etc/stunnel/stunnel-server.pem文件中。 ; stunnel工作目录 chroot = /var/run/stunnel/…
使用squid搭建代理服务器
squid是一款高效的http代理服务器程序,而且更经常被用来做缓存服务器。官网:http://www.squid-cache.org;还有一位大牛翻译的squid中文权威指南。 一、安装squid 我的安装环境:Ubuntu 14.04.2 LTS sudo apt-get install squid3 可以使用squid3 -v 检查安装好的squid 二、squid配置 squid默认配置文件为/etc/squid/squid.conf 2.1 基本配置 # http_port 设置监听端口,默认为3128 http_port 3128 # access_log 设置access日志,daemon表示在后台将日志写入/var/log/squid/access.log文件, # combined是一个预定义的logformat,也可以使用自定义的logformat access_log daemon:/var/log/squid/access.log combined # visible_hotname 设置代理服务器的主机名 # 默认取本机的hostname visible_hostname funway.aliyun.proxy 注意,在作为正向代理的时候(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中默认的访问控制如下: # ACLs all, manager, localhost, and to_localhost are predefined. acl SSL_ports port 443 acl Safe_ports port 80 # http acl Safe_ports port 21 # ftp acl Safe_ports port 443 # https acl Safe_ports port 70 # gopher acl Safe_ports port 210 # wais acl Safe_ports port 1025-65535 # unregistered ports acl Safe_ports port 280 # http-mgmt acl Safe_ports port 488 # gss-http acl Safe_ports port 591 # filemaker acl Safe_ports port 777 # multiling http acl CONNECT method CONNECT # 拒绝所有非Safe_ports的请求 http_access deny !Safe_ports # 拒绝所有非SSL_prots的CONNECT请求 http_access deny CONNECT !SSL_ports # Only allow cachemgr access from localhost http_access allow localhost manager http_access deny manager # 允许来自本地的请求 http_access allow localhost # 拒绝所有请求,最后兜底的规则 http_access deny all 在squid.conf的默认配置中,拒绝了所有的外部代理请求。这时候如果使用该代理,会返回错误页面: 上图中管理员邮箱由cache_mgr定义的,funway.aliyun.proxy由visible_hostname定义。 所以要想让其他主机使用squid代理,需要在最后一句http_access deny all前面添加我们自定义的规则。 # 定义访问列表AuthClients为183.26.163.xx网段内的所有主机 acl AuthClients src 183.26.163.0/24 # 允许AuthClients的代理请求 http_access allow AuthClients 然后在本地主机(在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配置: # auth_param 设置代理的认证方式 # 用法:auth_param scheme parameter [setting] # scheme表示认证机制,squid支持Basic,Digest,NTLM,Negotiate四种认证机制 # program 设置认证程序为ncsa_auth(squid自带不少认证程序以及其他拓展程序),程序所需密码文件passwd auth_param basic program /usr/lib64/squid/ncsa_auth /etc/squid/passwd # children 设置后台启动几个认证程序进程 auth_param basic children 3 # credentialsttl 设置认证失效时间,过期后需重新认证 auth_param basic credentialsttl 1 minute # realm 设置认证时返回头里夹带的信息“wlecome to using my proxy” auth_param basic realm welecome to using my proxy # !!!上面只是设置了需要认证,并未将认证生效,还需设置acl与http_access # 添加名为AuthUsers访问列表,表示通过认证的用户 acl AuthUsers proxy_auth REQUIRED # 允许AuthUsers的代理请求 http_access…