本文来自依云's Blog,转载请注明。
看到 ArchWiki 上 GoAgent 条目的亚全局代理方案,只是设置了代理相关环境变量。我就想,为什么不实现一个真正的全局 HTTP 代理呢?
最终,答案是:Linux 太灵活了,以至于想写一个脚本来搞定很麻烦。不过方案如下,有兴趣的可以折腾折腾。
首先,需要用到的工具:dnsmasq、iptables、redsocks,以及 HTTP 代理工具。dnsmasq 是用来缓存 DNS 请求的,iptables 把 TCP 流转接到 redsocks,而 redsocks 将 TCP 流转接到代理上。
最小 dnsmasq 配置如下:
listen-address=127.0.0.1 cache-size=500 server=127.0.0.1#5353 bogus-nxdomain=127.0.0.1
这里使用了本地的 dnscrypt 服务(假设其在 5353 端口上提供服务)。也可以使用国外服务器,只是需要更细致的配置来迫使其走 TCP。
iptables 命令如下:
# 创建一个叫 REDSOCKS 的链,查看和删除的时候方便 iptables -t nat -N REDSOCKS # 所有输出的数据都使用此链 iptables -t nat -A OUTPUT -j REDSOCKS # 代理自己不要再被重定向,按自己的需求调整/添加。一定不要弄错,否则会造成死循环的 iptables -t nat -I REDSOCKS -m owner --uid-owner redsocks -j RETURN iptables -t nat -I REDSOCKS -m owner --uid-owner goagent -j RETURN iptables -t nat -I REDSOCKS -m owner --uid-owner dnscrypt -j RETURN # 局域网不要代理 iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN # HTTP 和 HTTPS 转到 redsocks iptables -t nat -A REDSOCKS -p tcp --dport 80 -j REDIRECT --to-ports $HTTP_PORT iptables -t nat -A REDSOCKS -p tcp --dport 443 -j REDIRECT --to-ports $HTTPS_PORT # 如果使用国外代理的话,走 UDP 的 DNS 请求转到 redsocks,redsocks 会让其使用 TCP 重试 iptables -t nat -A REDSOCKS -p udp --dport 53 -j REDIRECT --to-ports $DNS_PORT # 如果走 TCP 的 DNS 请求也需要代理的话,使用下边这句。一般不需要 iptables -t nat -A REDSOCKS -p tcp --dport 53 -j REDIRECT --to-ports $HTTPS_PORT
redsocks 的配置:
base { log_debug = off; log_info = off; daemon = on; redirector = iptables; } // 处理 HTTP 请求 redsocks { local_ip = 127.0.0.1; local_port = $HTTP_PORT; ip = $HTTP_PROXY_IP; port = $HTTP_PROXY_PORT; type = http-relay; } // 处理 HTTPS 请求,需要一个支持 HTTP CONNECT 的代理服务器,或者 socks 代理服务器 redsocks { local_ip = 127.0.0.1; local_port = $HTTPS_PORT; ip = $SSL_PROXY_IP; port = $SSL_PROXY_PORT; type = http-connect; // or socks4, socks5 } // 回应 UDP DNS 请求,告诉其需要使用 TCP 协议重试 dnstc { local_ip = 127.0.0.1; local_port = $DNS_PORT; }
然后以相应的用户和配置文件启动 dnsmasq 以及 redsocks。修改/etc/resolv.conf
:
nameserver 127.0.0.1
至于分流的事情,HTTP 部分可以交给 privoxy,但是 HTTPS 部分不好办。可以再设立一个像 GoAgent 那样的中间人型 HTTPS 代理,或者更简单地,直接根据 IP 地址,国内的直接RETURN
掉。
以上就是整个方案了。有些麻烦而我又不需要所以没测试。反正就是这个意思。Android 软件 GAEProxy 就是这么干的(不过它没使用 iptables 的 owner 模块,导致我不小心弄出了死循环)。另外,BSD 系统也可以使用类似的方案。
Feb 07, 2014 07:59:07 PM
看标题还以为是用proxychains启动的login shell, LOL
Feb 07, 2014 09:21:44 PM
为什么我觉得你需要的是一个装了 OpenWrt 的路由……
Feb 08, 2014 11:32:14 AM
看来小白想要理解上面的东东还是有点困难……iptables 的局域网规则收藏了。
发现用 GAE 还是会被一些 Google 的网站屏蔽,写了白名单黑名单,依然有无法解决的问题,受不了最终还是用 socks 代理(VPS)配合 privoxy 一劳永逸。
Feb 08, 2014 01:01:00 PM
REDSOCKS我以前配置过,一直没有成功。回去再试试看。
Feb 10, 2014 04:49:48 PM
那个在 sudo 时也会被重置掉的啦。
Feb 10, 2014 04:50:51 PM
因为你有一个装了 OpenWrt 的路由器 :-)
Feb 10, 2014 05:06:12 PM
HTTPS 请求试试看 sniproxy 哟。
Feb 10, 2014 05:41:41 PM
这个似乎不错呢喵呜~
Apr 06, 2014 10:05:18 PM
我現在在用修改路由表的方案,把apnic上國內ip都走正常網關,default是vpn。還要一個遞歸解析並緩存的dns client……很需要一個 proxychains 這樣的工具,但能更方便的設置代理
Apr 06, 2014 10:37:12 PM
你自己改改 proxychains?
May 21, 2014 05:28:28 PM
博主好,不错的 方案,可以实现。但是 操作起来 遇到个 问题。goagent 和 redsocks 的 --uid-owner 找不到,还有什么方法 解决 gae的流量 被代理吗?
May 21, 2014 06:05:00 PM
「--uid-owner 找不到」?是你的 iptables 不支持按 UID 匹配,还是你的 goagent 和 redsocks 没有用单独的用户?
Jun 02, 2014 09:20:35 PM
之前一直不会设置iptables,老是设置好了就无法打开网页,估计是死循环了,iptables -t nat -I REDSOCKS -m owner --uid-owner root -j RETURN加了root之后就好了,自己也编译了redsocks2安卓版,却无法再安卓上正常使用,提示找不到libevent-2.0.so.5,将编译好的安卓libevent动态库放在/system/lib下,并做软连接为libevent-2.0.so.5,就又提示event_loopbreak错误,希望能指导一下,谢谢,不知道哪里出了问题
Jun 03, 2014 11:14:17 AM
你使用的 Android NDK 编译的吗?完整的错误消息是什么?redsocks2 是 redsocks 的 fork 吗,我没找到它的官网呢。
Jun 03, 2014 10:10:06 PM
是用的Android NDK编译的,方法和编译redsocks一样,redsocks我自己编译好能用,redsocks2的网址:https://github.com/semigodking/redsocks,应该是一个作者的,你看看呢,大概已经分析出原因了,就是redsocks2编译出来时调用动态库的,而redsocks是编译后是静态库,用file命令就你能看出来,不知道怎么把redsocks2也编译成静态库的,求指导
Jun 04, 2014 03:11:04 PM
这个项目用的是 Makefile,你加 CFLAGS=-static 环境变量试试。
NDK 编译出来的动态链接版本应该一样好用的呀,只要把相应的库都放到系统上即可。
Jun 04, 2014 03:15:43 PM
我上午把提示出错的那个库放到手机里,然后就可以用了,正常使用了,谢谢依云的帮助,因为刚学linux,对很多都不是太懂,只能依靠教程,网上这个软件的教程太少了,不知道redsocks与ProxyDroid有什么区别,貌似ProxyDroid这个也是伪全局代理在案桌上,查了资料说redsocks才能在案桌上实现全局代理就试试编译用用了
Jun 09, 2014 06:21:23 PM
依云请教个问题,privoxy是不是只能用在网页的socks转换http,能不能设置对单独的客户端程序也能将socks转换http处理?找个好久没看到相关的方法。还有个问题,有没有在安卓上架设本地socks服务器的软件或者开源项目?
Jun 09, 2014 06:26:23 PM
Privoxy 我知道。它无法得知 HTTP/HTTPS 网络请求的来源,只能是客户端主动通过指定端口利用 Privoxy 。假如软件没有自带代理配置功能,只能靠别的程序来中转网络请求了,例如 proxychains。
Jun 09, 2014 06:35:46 PM
你可以试试 proxytunnel。它会把 HTTP CONNECT proxy 映射为标准输入输出。
可以配合 socat 用。
Jun 09, 2014 10:10:34 PM
我是用在移动cmwap接入点上的,因为移动cmwap开放的代理是10.0.0.172:80,自己先编译了redsocks后做全局代理,发现大部分问题解决,唯有qq,微信,还有游戏类的无法使用,估计这些软件应该是使用socks代理,打算在安卓上架设socks本地服务器(不知道用什么软件能架设),先将所有数据通过本地socks代理,在用Privoxy转化http交给10.0.0.172:80处理,不知道行的通吗?有其他解决方案吗?
Jun 10, 2014 12:05:11 PM
QQ 不是用的 HTTP 啊。cmwap 那个只能用来访问 HTTP(S) 的。为什么不用 cmnet 呢?
Jun 10, 2014 01:51:57 PM
因为被移动限制了只能使用cmwap,只能http或者https,在电脑上可以解决问题,但是在安卓手机端暂时没找到解决qq,微信,游戏类正常使用的方法
Jun 10, 2014 03:04:29 PM
那没办法。找移动去吧。
Jul 05, 2017 08:16:22 AM
仙子,请问你这个教程中$DNS_PORT应该填什么?搞不清,谢谢。
>>> sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:5353 0.0.0.0:* LISTEN 1/init
tcp 0 0 0.0.0.0:53 0.0.0.0:* LISTEN 419/dnsmasq
tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 406/vsftpd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 407/sshd
tcp 0 0 127.0.0.1:1080 0.0.0.0:* LISTEN 528/python2.7
tcp6 0 0 :::53 :::* LISTEN 419/dnsmasq
tcp6 0 0 :::22 :::* LISTEN 407/sshd
Jul 05, 2017 10:52:00 PM
你本地起了干净的 dnsmasq 的话,就不需要再设置了。
Jul 05, 2017 11:42:00 PM
依云兄,之前我防火墙INPUT策略为DROP,总不成功,改为ACCEPT后可以了,谢谢。