8

Linux「真」全局 HTTP 代理方案

 2 years ago
source link: https://blog.lilydjwg.me/2014/2/7/linux-really-global-http-proxy.42701.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Linux「真」全局 HTTP 代理方案

本文来自依云'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 系统也可以使用类似的方案。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK