跳至主要内容

简易 APN Proxy (APN代理)的搭建

2012年2月1日,新增加了一种方案,请看 《搭建增强型代理服务器(APN Proxy)

2012-01-03 更新 3proxy 及 监控进程脚本,分别见 B 3) 和


曾经在twitter被封锁的时候,我在长城宽带干过一件事,那就是将twitter的请求和通讯使用SSH,让全网用户可以无阻访问,不过也因此付出了代价,略不去说了。

后来得厨神 @paveo 的创意,何不将其用在手机等移动设备上?厨神的APN现在已经很成熟并在免费有限量专供中。我今天这里写得,是如何搭建自己的APN Proxy(APN 代理),但在阅读下面内容之前,需要一个刚性要求:一台在国内的Unix-Like的主机(可以是Linux/FreeBSD/Mac Osx Server/Solaris等等)并且是公网IP地址以及在国外的VPS主机(Unix类)。这个要求可以看出成本比较高,所以我看到淘宝上已经有人开始出售APN代理了,这个可以理解。

第一部分 原理



原理图1

如上图所示,我们要实现的功能原理是,将上网请求先发送到“国内VPS”,再由“国内VPS”通过SSH隧道转送到国外,最终实现无阻上网。点击查看大图可以看出,主要配置是在“国内VPS”上,包括配置SSH -D、Squid、Privoxy或者Polipo(socks代理程序你可以选自己喜欢的)。

第二 配置

1 国外VPS
国外VPS上,你需要有一个SSH帐户,并且请注意,使用密钥方式登录你的SSH而非密码,之所以如此,是为了下一步建立长久的SSH以及断线自动重连做准备,这个很重要。关于“SSH 免密码 密钥 登录”请使用google看一下。

这里有一个小插曲,部分centos 上如果默认的话,SSH帐户会报错,大约 是adminitstatly close之类,这有可能是 openfile数目问题,可以轻松解决。我非Linux爱好者,所以是临时google,并没有记录下来,你只要记得如果遇到同样问题,5分钟之内就可以google解决。


2 国内VPS
这一节将会是我们的主战场,基本上,我将会按下面的逻辑图来进行配置,这其中会涉及很多文件的配置,需要你注意哦,最后部分我会提供部分配置文档下载,由于我使用的是FreeBSD,因此会有少量差异,我想这不会难倒你,对么?

原理图2

A SSH 隧道

其实就是我们平时上网用的 SSH -D 方式,在本地打开 7070端口到国外VPS的SSH建立隧道,这样我们出国的流量就经过加密了。我们平时使用 ssh -qN -D 7070 demo@excample.com 来连接,但是现在我们要站在服务器的角度考虑问题:如果SSH -D方式中断了,怎么办?

这里我们要做的事情是,建立一个机制,使得在SSH隧道出现问题的时候可以自动重启自动连接,有一个现成的工具可以使用 autossh  (FreeBSD请使用 whereis autossh ),autossh 可以传递大多数ssh的参数,包含 -D ,然后会监视这个会话连接,如果出现中断就可以自动重连接。

不过,如果 ssh 连接本身没有中断,但是进程卡死,sleep 状态,autossh 也不顶了怎么办?于是又要写一个脚本,定时检查 autossh 进程或者干脆定时重启 autossh 。


以下为脚本



#!/bin/sh
export AUTOSSH_PIDFILE=/var/run/autossh.pid
pidfile="/var/run/autossh.pid"
if [ -f $pidfile ];then
kill  `cat $pidfile`
touch $pidfile
else
touch $pidfile
fi

/usr/local/bin/autossh -M 9000 -f -q -N -D 7070 root@excample.com



######################
#脚本 autossh.sh 结束#
######################

注意上面最后一句 autossh -M ,这个参数是监控端口,大体是通过此端口来判断 ssh 隧道是不是有问题,这个端口你可以随意指定。
你也可以将这个脚本加入到 crontab 中(使用crontab -e),比如我,设定半小时执行一次,目的是每半小时无论SSH连接是否正常都会重启一下隧道连接,也可以设定在夜间重启,总之,随你如何了。






接下来,为了防止假死情况发生(我指autossh本身),我又再次写了一段脚本,用来实时监控 autossh 进程,一旦进程中断,这个新脚本就可以重新启动SSH连接。这个脚本是用来监控进程PID是否存在,PidFile有没有进程号,端口7070存在否。(注意,这是在FreeBSD写得脚本,因此你需要改成适用于你系统的,比如 sockstat 其他系统没有这个命令,用以查看端口使用,你可以使用 netstat 来取代 )


#!/bin/sh
while :
do
        stillRunning=$(ps awx |grep "(autossh)" |grep -v "grep" | awk '{print $1}')
        dead=`cat /var/run/autossh.pid` 
        port=`sockstat -4l | grep :7070`
        [ -z "$stillRunning" -o -z "$dead" -o -z "$port" ] && /etc/autossh.sh 
  sleep 10

done




########################
#mon-autossh.sh脚本结束#
########################






mon-autossh.sh中使用了无限循环,你也可以使用crontab来做定时检测,使用上面的脚本会吃系统资源尽管对于单服务类型的主机来说这一点也不是问题。


做完以上步骤,这时候我们就在本地建立了一个端口映射,即一个 7070端口的 socks5 代理。
我们即将进行下一步,但有个问题挡在面前,为何我们不直接将这个sokes5代理应用到squid上却非要安装 Privoxy或者polipo?这是因为,squid 虽然支持二级代理,但是要求父代理必须是 HTTP ,因此我们的 ssh  生成的 socks5 代理就不能用了,我们就借助第三方软件来给squid 穿上 ssh 的外衣,这就是即将用到的 privoxy 或者 polipo 中的一种,注意,你只需要安装其中一种,我之所以将两种都写出来,是因二者有不同,希望你能了解个中不同,选择自己需要的。

B 代理转换 Privoxy 或者 Polipo,以及最好用的 3Proxy
  
  1) Privoxy 

我想使用过Tor的人应该很熟悉这个软件,或者使用opera浏览器的人。这个程序强大的地方除了可以将 socks5 代理转为 HTTP 外,还在于它支持按照规则转发(比如将GFW认证的网站与普通网站区分开)、广告过滤。也就是说,Privoxy 这个程序已经可以取代 squid 的功能,所以若你选择了 Privoxy 配置完好,就可以不看下面的部分了(只是认证环节我一直无法搞定)。不多说了,下面附上配置,分为两部分 Privoxy 的 config 和 gfw.action ,前者是全局设定,后者则是只将gfw的网站代理出国,其他网站仍然走国内路由,提高访问速度。

########
#以下是 privoxy 的 config 
########

user-manual /usr/local/share/doc/privoxy/user-manual
confdir /usr/local/etc/privoxy
logdir /var/log/privoxy
actionsfile match-all.action 
actionsfile default.action  

### 下面这个 block.action 就是默认的过滤规则,可以去广告 
#actionsfile block.action

#### 下面 gfw.action 就是我们需要的,只有符合这个规则才走国外代理
#### 请在 config 同目录下创建 gfw.action

actionsfile gfw.action
filterfile default.filter
#filterfile user.filter
logfile logfile
hostname www.chinablock.me
#forward-socks5 / 127.0.0.1:7070 .
# 下面这一行表示 打开 8118端口,你可以用手机直接连接进来
###################################################
listen-address  0.0.0.0:8118

### 下面的配置我不多说,都是必要项,有兴趣的可以日后研究
###
toggle  1
enable-remote-toggle  1
enable-remote-http-toggle  0
enable-edit-actions 0
enforce-blocks 0
buffer-limit 5120
#connection-sharing 0
forwarded-connect-retries  3
accept-intercepted-requests 0
allow-cgi-request-crunching 0
activity-animation 1
split-large-forms 0
keep-alive-timeout 0
socket-timeout 120
handle-as-empty-doc-returns-ok 1

#### 配置结束 #######################################

OK了,这个就默认的 Privoxy 的 config 了,接下来我们要定义 gfw.action ,要把 autoproxy 里的那么多网址加进来,会累死你的,幸运地有网友已经提前做好了,请访问这里 

然后修改 gfw.action 为 {+forward-override{forward-socks5 127.0.0.1:7070 .}} ,注意 那个“ . ”,很必要。




如果按以上方式,其实你已经配置好了代理,并且打开你的手机,在代理那里输入 IP : 8118 就可以访问世界了。iphone/ipad/touch/需要到app store 下载安装“易apn”这个软件,然后在专网那里自定一个 apn 代理就可以了。




当然,选用squid自有选用的道理,配置完之后同样也可以被squid拿来使用。我们接着配置另一个代理 polipo (两个代理软件,你只需要选择一个)

2) Polipo

我想大家可以注意到 tor的默认组合已经从 tor + Privoxy 转换到了 tor + polipo ,前者我们在上面已经说过优点,缺点就是太难配置了(其实我觉得也不难啊,就是规则写起来麻烦点点),而polipo优点是自带缓存功能,有一定的加速效果,再者就是可以将几个SSH通道做负载均衡,就是说你可以建立多个SSH -D连接然后绑定到一个polipo上。另一个好处就是配置简单易用,不过过滤功能就比privoxy弱了许多(也可以ad-block,不过真没必要)。

所以我当前在用的方案就是 Squid + Polipo ,polipo 可以不设置缓存,设置了也不会影响,缓存工作交给squid来就OK。这一部分的配置可以参阅 http://xijie.wordpress.com/2011/05/28/squid3polipo-use-sock5/ ,但是只参阅而不要使用这个配置,除非同时连接多个ssh主机。下面给出我的polipo配置

#config file for polipo @ /usr/local/etc/polipo/

proxyAddress = "0.0.0.0"    # IPv4 only
proxyPort = 8119
allowedClients = 127.0.0.1,211.161.103.253
allowedPorts=1-65535
proxyName = "APN代理"
socksParentProxy = "localhost:7070"
socksProxyType = socks5
 chunkHighMark = 819200
 objectHighMark = 128
diskCacheFilePermissions=0640
diskCacheDirectoryPermissions=0750
disableIndexing = false
disableServersList = false
dnsQueryIPv6 = no
disableVia=false
censoredHeaders = from, accept-language
 pmmFirstSize = 16384
 pmmSize = 8192
maxConnectionAge = 5m
maxConnectionRequests = 120
serverMaxSlots = 8
serverSlots = 4
tunnelAllowedPorts = 1-65535

#End

大体上,如上的配置,就已经成功,同 B 1) 一样,这个时候只要设置代理为 8119 就可以上网了,可以不必向下阅读Squid部分了。

 3) 3Proxy 

尽管我很喜欢使用polipo,但是在和squid配合使用时会有点点小毛病,而且3Proxy的功能更合乎我的需求:多端口代理,同时开放 socks5和http,并且可以做负载均衡,本例中不介绍,你可以查阅相关文章,我直接附上我的配置

###########################################
#!/usr/local/bin/3proxy
config /usr/local/etc/3proxy.cfg

nserver 8.8.8.8
nscache 65536



timeouts 1 5 30 60 180 1800 15 60


daemon


log /var/log/3proxy.log D

rotate 10

logformat "- +_L%t.%.  %N.%p %E %U %C:%c %R:%r %O %I %h %T"


archiver gz /usr/bin/gzip %F


auth iponly

allow * 127.0.0.1,220.161.103.253 * *
parent 1000 socks5  127.0.0.1 7070  #使用父代理SSH -D
proxy -a -p8117                     #-a 是指匿名,-p指端口
external 12.34.56.78
internal 12.34.56.78  #你可以在这里改成127.0.0.1,原文档中有说明

allow * * * 80-88,8080-8088 HTTP
allow * * * 443,8443 HTTPS



#####################
##    脚本结束  #####
#####################

需要说明的是,3Proxy的配置文件 3proxy.cfg,你可以加上执行权限,直接就可以运行。这也是目前我在使用的 Squid + 3Proxy 构架,建议各位可以尝试一下这个。

C Squid 配置

如果你可以使用Squid 3.1 ,那么请选择它,但是它的性能不如 Squid 2.7 可是多了一个特性,就是可以限速,这个在 Squid 2.7 上是没有的,我使用的是 Squid 2.7 ,性能最好的一个版本。

我在这里要说的是,使用squid的原因是为了更大的缓存,限速以及更好的根据IP和域名区分国内国外网站从而决定是否走国外代理。所以我摘要解释一下配置,并提供一个配置下载连接。
由于我是squid 2.7 ,有些参数 squid 3.0+已经不再支持 比如  acl all         src 0.0.0.0/0 ,这一条如果是在 squid 3.0中就会有问题,需要删除,因为squid 3.0 已经默认 All 这个分组了。

首先是squid的密码验证,你可以设置也可以不设置,在我的配置文件中已经为你默认注释掉,但是都已经配置好,包括摘要验证digest和基本验证basic,还有 auth ttl 都已经设定好,需要的话,自己创建一个password文件然后就可以用了,password直接使用明文 plaint_txt 就可以,或者用httpd 一个password生成器(有web端,google 一下就OK)。

然后设定squid 引用我们在 B 中设定的代理,使用:

cache_peer 127.0.0.1 parent 8119 6000  no-query 

其中 6000 是一个 icp 端口?反正没什么用,我也不知道。。。。

下面这一句,不用我说你也猜出作用了:

visible_hostname APN-Squid-Proxy-@bao3
http_port 3128






接下来是要求squid按规则区分国内国外路由的文件引用:

include /usr/local/etc/squid/gfw.squid
include /usr/local/etc/squid/proxyroute.squid

好吧,这两个文件我也已经创建好了,在下载链接里,你去下载吧。接下来是告诉 Squid proxyroute 这个规则中的请求直接走国内的IP,而 gfw 这个规则中的域名则不允许直接走国内IP而是走国外IP。最后 never_direct allow all 是要求所有的未在proxyroute 这个规则中的请求都走国外IP上网。( Proxyroute 这个规则中全是IP地址,而且都是中国IP地址 )

always_direct allow proxyroute
never_direct allow gfw
never_direct allow all

#always_direct allow proxyroute
#never_direct allow proxyroute

#always_direct deny gfw

#always_direct allow all






###################################################################

Squdi 配置文件的最后一部分,是关于cache 参数的,我已经设定好但却是依照我的系统进行的,所以你可以自由调整你的需要




文件 gfw.squid ,是存储了绝大多数被国家GFWed了的域名,当一个新域名被封杀时,你可以手动在下面加入。而 proxyroute 则包含了中国所有的IP地址段,你可以定期到 http://code.google.com/p/chnroutes/ 自己手动更新,但是请注意,默认生成的route.txt并不使用squid使用,需要使用vi/emacs/sed/awk 等等自己更正。


https://t.co/0ywZ57Ey  Squid 配置文件夹下载(有用的文件只有 squid.conf gfw.squid proxyroute.squid ,其他的都临时文件或者默认文件 )


最后,也许有人会问,为何你没有提及加密的问题?手机APN 代理 设置好了,可是没有加密怎么办?

我们平时提到加密,一般是口令验证或者通信加密。口令验证是传递回服务器,由squid完成,这个我在配置文件头部已经写好了,但口令验证不能保证通信内容不被监视,这就需要通讯加密。

我们提到通讯加密,最熟悉的就是SSL证书方式,也有其他方式,但这些通讯加密方式都有一个共性----需要在客户端(手机)和服务端(Squid)之间协调算法并能加密和解密。但是我们的手机APN设置那里显然是无法设置解密或者加密方式,直接了当地说,APN Proxy 的设置处无法实现双向通讯加密,如果非要实现,就需要借助特定软件来做到,因为软件可以识别密钥并能正确加密。

当然,以上是基于通信理论和自己实践得出,也可能真的有 APN Proxy 可以在系统 APN 那里设定加密套接字????


祝福各位~~~我反正是爽死了,每天都用着 HTTP Proxy 。




评论

  1. 非常感谢您的教程,我选了3Proxy配合Squid来搭建,但是在Squid配置部分出现了问题,我使用的是您提供的配置文件,覆盖掉了原来的。
    但是在运行squid的时候,报错了,配置有问题:

    2012/01/25 13:52:16| parseConfigFile: line 64 unrecognized: 'include /etc/squid/gfw.squid'
    2012/01/25 13:52:16| parseConfigFile: line 65 unrecognized: 'include /etc/squid/proxyroute.squid'
    2012/01/25 13:52:16| ACL name 'proxyroute.squid' not defined!
    FATAL: Bungled squid.conf line 69: always_direct allow proxyroute.squid
    Squid Cache (Version 2.6.STABLE21): Terminated abnormally.


    请您看一看是哪里出了错,谢谢!

    回复删除
    回复
    1. 楼上的,您好,我春节刚回来。
      我的朋友也有这情况,这是因为他当时与我的版本不同造成,我使用2.7,他使用2.6,所以有这个区别。
      另外,我的squid.conf gfw.squid proxyroute.squid 你都要放在同一目录下,然后就可以解决。

      近日正在思考修改这文章,因为发现了更好玩的方式来配置apn proxy,是加上zipproxy ,这个可以用来压缩流量,只是会使用手持设备耗电增加一点点。

      删除
  2. hi.
    关于3proxy, 文中说:external 12.34.56.78,这个12.34.56.78如何改?改成自己的vps的ip吗

    回复删除
    回复
    1. 抱歉,我很长时间不看评论了。

      现在国家封锁加大了,想要用这个模式,一定要在国内有主机才行。3Proxy不稳定,在线程增多时就会down了。

      另外就是最近 openvpn,pptp都被深度检测,要做什么动作,就用cisco ipsec 吧,在我的另一文章有提到,就是黑莓可用的vpn

      删除
  3. 能否告知下图用的什么工具画的。。。 真心不错啊

    回复删除
    回复
    1. 您好,这个工具是iOS上的,现在中文名叫“圈点”,免费的,配合evernote用的。

      删除
  4. 此评论已被作者删除。

    回复删除

发表评论

读过之后是不是文思泉涌了?快快让大家拜读一下你的高见吧~~~

此博客中的热门博文

使用StrongSwan搭建 IKEv1 IKEv2 VPN服务器

#2016-01-04 决定将本文作废,因我要另再写新版本的配置。这篇作于 2013年,而strongswan已经更新很多版本。 #本文需要有独立的VPS,如果你需要一台速度快,每月30元的左右的VPS,可以使用我的邀请注册 http://www.vultr.com/?ref=6813064 并且在注册时使用 SSDVPS 可以送 $20(或者 $10 不等)。一定要选日本线路,这个到国内延迟约40ms ~ 100ms ,一般是 80ms 左右,非常快非常稳定,一个月32元,可以和几个人合租了。 #LOG:2014-04-30 对ipsec.conf进行修改,增加了android手机的兼容,现在可以支持完整支持android 自带的VPN设置啦~~~~ #LOG:2013-0609 对ipsec.conf进行修改,加入清楚DPD代码,防止IP 地址池不正确占用 #LOG: 2013-0519 删除ipsec.conf 中多余的conn iOS一节,这本是我一年前调试用的,时间不起作用; 删除了 %default中的 rightsubnet ,如果不删除,在定义了多段IP路由的情况下会导致账号无法上网(只有一段IP没这个bug),感谢  JackWindows  ‏ @ JackWindows #LOG 2013-05-12 修正bug,原配置文件会导致一个ID不可以同时多次登陆。得蒙  @ KhaosT   指点,对  strongswan.conf 加入duplicheck.enable = no ,对 ipsec.conf 加如 uniqueids=never #完成度100% 在我们生活的周围,通常要用到很多种VPN: PPTP, L2TP/IPSec, Cisco IPSec, IKEv2, 这些不同类型的VPN覆盖了目前我们常见的所有手机或者电脑平台,比如 iOS, Blackberry OS, BB10, Android, WebOS, Windows XP, Windows Vista/7/8, Unix/Unix-like。 (*如果你正在找blackberry 翻墙方法、ios ipsec vpn、windows IKEv2 VPN、Blackberry BB10 / Z10 VPN、android VPN,建

OCSERV 0.8.5 使用

*注1:本文不包含ocserv的编译、安装,请自行研习 *注2:本文将包含ocserv的证书认证配置,不包含pam (radius)认证 *注3:本文将包含win,mac 端的使用,移动端相对简单,不做介绍 ocserv是OpenConnect SERVer的缩写,基本上就是cisco anyyconnect的开源兼容服务器软件,好处就是这个软件使用的是SSL VPN方式,通常会用DTLS这一层,支持服务器端推送32条路由,实现国内国外按需区分路由;同时各种客户端会长连接方式,一直后台待命,省时省电。我就不废话了。 我的配置是采用了全证书的方式进行,因此不需要用户名密码,如果您要对客户端进行限制,计时方面可以采用证书有效时间;流量限制方面可以使用iptables针对IP进行限制;同时在线人数上如果是多台服务器的话,相互间无法限制(cookie/session分布于不同服务器),如果仅一台服务器话就可以在配置文件搞定。我的完全配置如下,如果你要复制配置文件可以到 这里 : #第一行用以指定认证方式,我是证书 auth = "certificate" #Added @05-10-2014 #加入这个后就可以使用occtl了 #occtl reload && occtl stop now use-occtl = true occtl-socket-file = /var/run/occtl.socket # seccomp default : true #关闭这个可以提高性能,牺牲一丁点安全,更可以避免无法启动的情况(遇到过的都知道那痛苦) use-seccomp = false # listen-host = 0.0.0.0 #最大客户端数量,根据你的服务器IP地址分配多少以及性能设置,自用的话不必很大 max-clients = 36 #这个看英文就知道意思了,你可以加以限制 max-same-clients = 4 tcp-port = 443 udp-port = 443 keepalive = 32400 dpd = 60 mobile-dpd = 1800 #故意为空 mobile-idle-timeout = deny-roaming = false