redsocks2 + shadowsocks
几点说明
socket四要素:srcIP + srcPort + destIP + destPort唯一确定一个socket连接。server端
accept
监听到连接请求后,通常会另起一个子进程处理,但accept返回的新socket,与accept监听的端口还是一样的,都是server_port,而不是新开一个port(no new port is opened),参考How does the socket API accept() function work?iptables SNAT/DNAT:
--to
更改TCP/IP包中的IP和Port,通过第三层TCP/IP协议将数据包送达目标机器- 1iptables -t nat -A POSTROUTING -s 172.16.36.0/24 -j SNAT --to $PROXY_IP:$PROXY_PORT
默认网关:通过链路层MAC地址将数据包送达目标机器。TCP/IP协议中没有关于默认网关IP的字段,通过ARP协议获取到默认网关IP对应的MAC地址,数据包发送出去时,在第二层链路层添加MAC地址,这样数据包就会被默认网关接收到
iptables redirect:会把原来的目标地址和端口改掉。REDIRECT使用了ip_conntrack模块,可以通过函数接口获取原来目的地址
if you redirect TCP traffic, the ip_conntrack provides a getsockopt() to get the original destination address.
REDIRECT实际上也是一种特殊的NAT
|
|
redsocks2
TCP/IP中的目标地址一旦修改,就无法将数据包发送给真正的目标对象,而所有的socket监听,只有目标地址是自己才能接收,上层应用想代理流量,必须处理这一对矛盾,而iptables的redirect刚好派上用场
redsocks通过修改iptables,将流量redirect到自己监听的端口号,并且通过getdestaddr获取原目标ip和port,然后遵循代理协议格式将流量转发给代理
redsocks2在redsocks基础上进行增强,支持智能代理:只有直接连接失败的才通过代理访问
目前来看,只有使用redsocks真正实现透明代理
项目下载:
方案细节
能刷openwrt固件的路由都容易集成redsocks和shadowsocks,不过路由一般容量受限,例如4M内存+16M Flash,影响发挥
刚好有一块cubieboard2板,装Ubuntu12.04,可以用来布置整套透明代理:redsocks2 + shadowsocks
再从路由器的DHCP配置中将gateway地址修改为cubieboard的IP地址即可,这样局域网所有机器都通过cubieboard代理上网
其他方案
下面列出几种尝试过的方案
pcap_dnsproxy + nginx
基本思路:通过pcap_dnsproxy将需要代理的url IP地址解析为自己的代理服务器地址,流量通过代理服务器nginx反向代理进行访问
问题:浏览器https访问时,会提示网站证书问题,因为我们的nginx透明代理扮演中间人的角色,不被客户端信任。
wget 可以用–no-check-certificate忽略证书,casperjs用–ignore-ssl-errors=yes忽略dnsproxy Host.ini配置:
|
|
语法类似/etc/hosts文件,但可以使用正则匹配,方便很多
- nginx 443端口配置:
|
|
需要生成cert文件,用gencert.sh脚本生成
80端口配置类似
iptables
http://www.cnblogs.com/lexus/archive/2012/02/14/2351939.html
该方法同样有https证书问题,看看加深对socket四要素理解吧
|
|
This solution described in the previous section redirects packets to the proxy server using Network Address Translation to modify the actual packets. The result is that packets arriving at the proxy have a source IP address of the router rather than the original client. As a result, it’s not possible to see the IP address of the originating client in the proxy logs, nor is it possible to apply access rules in the proxy based on the originating client IP address.
|
|
还需要改一下port,否则数据包还是转发到proxy机器的80端口上
|
|