V2Ray透明代理/透明网关/广告屏蔽/路由器翻墙
转载自:https://www.80sy.com/951.html
1.1. 设置网关
- 用网线将树莓派接入路由器 LAN 口,假设分给树莓派的 IP 是 192.168.1.22。
- 树莓派开启 IP 转发(需要开启 IP 转发才能作为网关)。命令为
echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf && sysctl -p
。执行后将出现 net.ipv4.ip_forward=1 的提示。 - 手动配置 PC 的网络,将默认网关指向树莓派的地址即
192.168.1.22
。此时 PC 应当能正常上网(由于还没设置代理,“正常”是指可以上国内的网站)。
1.2. 树莓派安装配置 V2Ray
- 安装 V2Ray。可以使用 V2Ray 提供的 go.sh 脚本安装,由于 GFW 会恶化对 GitHub 的访问,直接运行脚本几乎无法安装,建议先下载 V2Ray 的压缩包,然后用安装脚本通过 –local 参数进行安装。
因为是国内的网络环境,官方的install.direct一键安装脚本无法正常使用,所以这里改为手动安装,首先下载最新版本的V2Ray/解压:
mkdir -p /opt/v2ray && cd /opt/v2ray
wget https://github.com/v2ray/v2ray-core/releases/download/v4.20.0/v2ray-linux-64.zip
unzip v2ray-linux-64.zip
创建需要的目录:
mkdir -p /usr/bin/v2ray /etc/v2ray
移动文件到对应的目录:
cp v2ctl /usr/bin/v2ray
cp v2ray /usr/bin/v2ray
cp geoip.dat /usr/bin/v2ray
cp geosite.dat /usr/bin/v2ray
cp vpoint_vmess_freedom.json /etc/v2ray/config.json
cp systemd/v2ray.service /etc/systemd/system/v2ray.service
编辑systemd服务文件:
vi /etc/systemd/system/v2ray.service
在[Service]下面加一行,解决too many open files的问题:
LimitNOFILE=1048576
启动V2Ray服务:
systemctl daemon-reload
systemctl start v2ray.service
systemctl enable v2ray.service
现在编辑V2Ray的配置文件,清空里面的所有配置:
第一种、全局代理简单配置
{
"inbounds": [
{
"port": 1080,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
},
{
"port": 12315, // 透明代理开放的端口号
"protocol": "dokodemo-door",
"settings": {
"network": "tcp,udp",
"followRedirect": true // 这里要为true才能接受来自iptables的流量
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}
],
"outbounds": [
{
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "lala.im", // 服务器地址,请修改为你自己的服务器IP或域名。
"port": 50000, // 服务器端口,与服务器上的配置文件要相同
"users": [
{
"id": "你的UUID", // 用户的UUID必须与服务器端配置相同
"alterId": 64 // 此处的值也应当与服务器相同
}
]
}
]
}
}
]
}
第二种、对流量进行智能路由
需要的域名走代理,国内的域名/IP则直连,因为这套配置还使用了外部GEO文件,所以要想正常使用,还需要先下载外部GEO文件到V2Ray的运行目录:
wget https://github.com/ToutyRater/V2Ray-SiteDAT/raw/master/geofiles/h2y.dat -O /usr/bin/v2ray/h2y.dat
配置如下:
{
"log":{
"loglevel":"warning", //Log level, one of "debug", "info", "warning", "error", "none"
"access":"/var/log/v2ray/access.log",
"error":"/var/log/v2ray/error.log"
},
"inbounds": [
{
"port": 1080,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
},
{
"port": 12315, // 透明代理开放的端口号
"protocol": "dokodemo-door",
"settings": {
"network": "tcp,udp",
"followRedirect": true // 这里要为true才能接受来自iptables的流量
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}
],
"outbounds": [
{
"tag": "proxy", // 打一个TAG,让外部GeoFile使用此TAG处理被GFW屏蔽的域名
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "1111.1111.1111", // 服务器地址,请修改为你自己的服务器IP或域名。
"port": 11111, // 服务器端口,与服务器上的配置文件要相同
"users": [
{
"id": "11111111-1111-1111-1111-111111111111", // 用户的UUID必须与服务器端配置相同
"alterId": 1 ,// 此处的值也应当与服务器相同
"email": "t@t.tt",
"security": "auto"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"allowInsecure": false
},
"wsSettings": {
"path": "/"
}
},
"mux": {
"enabled": false,
"concurrency": -1
}
},
{
"tag": "block", // 黑洞TAG,让外部GeoFile使用此TAG屏蔽广告域名
"protocol": "blackhole",
"settings": {}
},
{
"tag": "direct", // 直连TAG,处理国内域名和IP使其直连
"protocol": "freedom",
"settings": {}
}
],
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"outboundTag": "proxy",
"domain": ["ext:h2y.dat:gfw"] // GFWList
},
{
"type": "field",
"outboundTag": "proxy",
"ip": [
// 设置 DNS 配置中的国内 DNS 服务器地址走代理,以达到 DNS 分流目的
"8.8.8.8",
"114.114.114.114"
]
},
{
"type": "field",
"outboundTag": "block",
"domain": ["ext:h2y.dat:ad"] // 广告域名屏蔽
},
{
"type": "field",
"outboundTag": "direct",
"domain": ["geosite:cn"] // 中国大陆主流网站的域名
},
{
"type": "field",
"outboundTag": "direct",
"ip": [
"geoip:cn", // 中国大陆的IP
"geoip:private" // 私有地址IP,如路由器等
]
},
{ // BT 流量直连
"type": "field",
"protocol":["bittorrent"],
"outboundTag": "direct"
}
]
}
}
{
"log":{
"loglevel":"warning", //Log level, one of "debug", "info", "warning", "error", "none"
"access":"/var/log/v2ray/access.log",
"error":"/var/log/v2ray/error.log"
},
"inbounds": [
{
"port": 1080,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
},
{
"port": 12315, // 透明代理开放的端口号
"protocol": "dokodemo-door",
"settings": {
"network": "tcp,udp",
"followRedirect": true // 这里要为true才能接受来自iptables的流量
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}
],
"outbounds": [
{
"tag": "proxy", // 打一个TAG,让外部GeoFile使用此TAG处理被GFW屏蔽的域名
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "111.111.111.111", // 服务器地址,请修改为你自己的服务器IP或域名。
"port": 11111, // 服务器端口,与服务器上的配置文件要相同
"users": [
{
"id": "11111111-1111-1111-1111-111111111111", // 用户的UUID必须与服务器端配置相同
"alterId": 0 ,// 此处的值也应当与服务器相同
"email": "t@t.tt",
"security": "auto"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"wsSettings": {},
"sockopt": {
"mark": 255 //这里是 SO_MARK,用于 iptables 识别,每个 outbound 都要配置;255可以改成其他数值,但要与下面的 iptables 规则对应;如果有多个 outbound,最好奖所有 outbound 的 SO_MARK 都设置成一样的数值
}
},
"mux": {
"enabled": false,
"concurrency": -1
}
},
{
"tag": "block", // 黑洞TAG,让外部GeoFile使用此TAG屏蔽广告域名
"protocol": "blackhole",
"settings": {}
},
{
"tag": "direct", // 直连TAG,处理国内域名和IP使其直连
"protocol": "freedom",
"settings": {},
"streamSettings": {
"sockopt": {
"mark": 255
}
}
}
],
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"outboundTag": "proxy",
"domain": ["ext:h2y.dat:gfw"] // GFWList
},
{
"type": "field",
"outboundTag": "proxy",
"ip": [
// 设置 DNS 配置中的国内 DNS 服务器地址走代理,以达到 DNS 分流目的
"8.8.8.8",
"114.114.114.114"
]
},
{
"type": "field",
"outboundTag": "block",
"domain": ["ext:h2y.dat:ad"] // 广告域名屏蔽
},
{
"type": "field",
"outboundTag": "direct",
"domain": ["geosite:cn"] // 中国大陆主流网站的域名
},
{
"type": "field",
"outboundTag": "direct",
"ip": [
"geoip:cn", // 中国大陆的IP
"geoip:private" // 私有地址IP,如路由器等
]
},
{ // BT 流量直连
"type": "field",
"protocol":["bittorrent"],
"outboundTag": "direct"
}
]
}
}
配置完成之后测试:
/usr/bin/v2ray/v2ray -config /etc/v2ray/config.json -test
有错排错没问题的话重启V2Ray:
systemctl restart v2ray.service
最后创建iptables规则,对流量进行处理:
#创建一个叫V2RAY的链
iptables -t nat -N V2RAY
#忽略服务器的地址,如果不属于内网IP的话一定要注意加上.
#其实下面这句可以省略的, 因为它属于192.168.0.0/16
#iptables -t nat -A V2RAY -d 192.168.45.19 -j RETURN
# 忽略本地地址
iptables -t nat -A V2RAY -d 192.168.0.0/16 -j RETURN
iptables -t nat -A V2RAY -d 0.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 10.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 127.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 169.254.0.0/16 -j RETURN
iptables -t nat -A V2RAY -d 224.0.0.0/4 -j RETURN
iptables -t nat -A V2RAY -d 240.0.0.0/4 -j RETURN
#除上面之外的所有流量都跳转到V2RAY的本地端口(local_port),这里使用端口12315
iptables -t nat -A V2RAY -p tcp -j REDIRECT --to-ports 12315
# 最后是应用上面的规则,将OUTPUT出去的tcp流量全部经过V2RAY链
iptables -t nat -A PREROUTING -p tcp -j V2RAY
iptables -t nat -A PREROUTING -p udp -j V2RAY
iptables -t nat -A PREROUTING -p icmp -j V2RAY
#如果是在openwrt上实现透明代理的话,使用下面被注释了的规则
#iptables -t nat -A OUTPUT -p tcp -j V2RAY
#如果/etc/v2ray/config.json文件outbounds出口流量打了mark标签255
iptables -t nat -A V2RAY -p tcp -j RETURN -m mark --mark 0xff # 直连 SO_MARK 为 0xff 的流量(0xff 是 16 进制数,数值上等同与上面配置的 255),此规则目的是避免代理本机(网关)流量出现回环问题
iptables -t nat -A OUTPUT -p tcp -j V2RAY # 对本机进行透明代理
局域网内的其他机器,修改网关IP为这台虚拟机的IP即可:
现在只要接入你这个网络的设备,无论是电脑还是手机等,都可以实现自动翻墙/广告屏蔽等功能。
一点补充:
如果你使用第一套配置(全局代理)其实也可以实现对流量进行路由,并且据说这种路由方法比V2Ray自带的原生GeoIP方法效率更高,更适合跑在CPU性能不咋地的路由器上。
先重启机器清空所有iptables规则:
reboot
安装ipset:
apt -y install ipset
下载中国IP地址列表:
wget https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt
创建一个ipset链:
ipset -N cn hash:net
将中国的IP都加入到ipset链:
for i in $(cat china_ip_list.txt); do ipset -A cn $i; done
执行下面的命令处理流量:
iptables -t nat -N V2RAY
iptables -t nat -A V2RAY -d 192.168.0.0/16 -j RETURN
iptables -t nat -A V2RAY -p tcp -m set --match-set cn dst -j RETURN
iptables -t nat -A V2RAY -p tcp -j REDIRECT --to-ports 12315
iptables -t nat -A PREROUTING -p tcp -j V2RAY
1.3. v2ray相关
转载自:https://toutyrater.github.io/app/tproxy.html
简单来说,v2ray没有服务端、客户端之分,或者说v2ray的客户端、服务端在一起;inbounds做服务端,接受客户端的请求,与客户端的outbounds相对应;outbounds做客户端,向服务端发起请求,与服务端的inbounds相对应。同一个v2ray的inbounds与outbounds之间用routing来连接,routing就用来定义当我的一个inbounds接收到了流量,该把它发送到outbounds中的哪一个。所以v2ray可以做这种事:inbounds接收流量,然后查routing,根据routing的设置转发到指定的outbounds中。
V2Ray 使用 inbound(传入) 和 outbound(传出) 的结构,这样的结构非常清晰地体现了数据包的流动方向,同时也使得 V2Ray 功能强大复杂的同时而不混乱,清晰明了。形象地说,我们可以把 V2Ray 当作一个盒子,这个盒子有入口和出口(即 inbound 和 outbound),我们将数据包通过某个入口放进这个盒子里,然后这个盒子以某种机制(这个机制其实就是路由,后面会讲到)决定这个数据包从哪个出口吐出来。以这样的角度理解的话,V2Ray 做客户端,则 inbound 接收来自浏览器数据,由 outbound 发出去(通常是发到 V2Ray 服务器);V2Ray 做服务器,则 inbound 接收来自 V2Ray 客户端的数据,由 outbound 发出去(通常是如 Google 等想要访问的目标网站)。
配置文件格式
{
"log": {},
"inbounds": [],
"outbounds": [],
"routing": {},
"transport": {},
"dns": {},
"reverse": {},
"policy": {},
"stats": {},
"api": {}
}
总的来说,V2Ray 的配置有 10 个字段,每个字段都可以进一步展开成具体的配置。
要理解 V2Ray 的工作模式,首先得抛开客户端和服务器的概念(教程中说客户端和服务器是习惯了),我们更应该以中转节点的概念来理解。 V2Ray 只是一个转发数据的软件,只要它从入口当中接收到数据包,不管 V2Ray 对这些数据包做了什么(加密、解密、协议转换等),到最后肯定是要把这些数据包从出口发出去。每一个运行的 V2Ray 都是一个节点,它从上一个节点接收数据,发送到下一个节点,在这样由多个节点组成的代理链中,首节点和末节点就是我们常说的客户端和服务器。更广义地说,每个节点对于上一个节点来说是服务器,对于下一个节点来说是客户端。
协议
无论是出口还是入口,我们首先要明确的是协议,只有协议对了才能正常通信。
V2Ray 的传入协议有 HTTP、SOCKS、VMess、Shadowsocks、Dokodemo-door;传出协议有 VMess、Shadowsocks、Blackhole、Freedom、SOCKS。
在 inbounds 和 outbounds 当中,无论使用了什么协议,inbounds 或者 outbounds 的配置格式都是一样的,区别只在于不同的协议对应的 settings 内容不一样。
设置网关
- 用网线将树莓派接入路由器 LAN 口,假设分给树莓派的 IP 是 192.168.1.22。
- 树莓派开启 IP 转发(需要开启 IP 转发才能作为网关)。命令为
echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf && sysctl -p
。执行后将出现 net.ipv4.ip_forward=1 的提示。 - 手动配置 PC 的网络,将默认网关指向树莓派的地址即
192.168.1.22
。此时 PC 应当能正常上网(由于还没设置代理,“正常”是指可以上国内的网站)。
树莓派安装配置 V2Ray
- 安装 V2Ray。可以使用 V2Ray 提供的 go.sh 脚本安装,由于 GFW 会恶化对 GitHub 的访问,直接运行脚本几乎无法安装,建议先下载 V2Ray 的压缩包,然后用安装脚本通过 --local 参数进行安装。
- 配置 V2Ray。按照前文教程将 V2Ray 配置成客户端形式。然后执行
curl -so /dev/null -w "%{http_code}" google.com -x socks5://127.0.0.1:1080
确认 V2Ray 已经可以翻墙(命令中 socks5 指 inbound 协议为 socks,1080 指该 inbound 端口是 1080)。如果执行这个命令出现了 301 或 200 这类数字的话代表可以翻墙,如果长时间没反应或者是 000 的话说明不可以翻墙。
透明代理(REDIRECT与透明代理REDIRECT)
{
"log":{
"loglevel":"warning", //Log level, one of "debug", "info", "warning", "error", "none"
"access":"/var/log/v2ray/access.log",
"error":"/var/log/v2ray/error.log"
},
"inbounds": [
{
"tag":"trans_tproxy",
"port": 12345,
"protocol": "dokodemo-door",
"settings": {
"network": "tcp,udp",
"followRedirect": true
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
},
"streamSettings": {
"sockopt": {
"tproxy": "tproxy" // 透明代理使用 TPROXY 方式
}
}
},
{
"tag":"trans_redirect",
"port": 12315,
"protocol": "dokodemo-door",
"settings": {
"network": "tcp,udp",
"followRedirect": true // 这里要为 true 才能接受来自 iptables 的流量
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
},
"streamSettings": {
"sockopt": {
"tproxy": "redirect" // 透明代理使用 redirect 方式
}
}
},
{
"port": 1080,
"protocol": "socks", // 入口协议为 SOCKS 5
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
},
"settings": {
"auth": "noauth"
}
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vmess", // 代理服务器
"settings": {
"vnext": [
{
"address": "198.198.198.198", // 服务器地址,请修改为你自己的服务器IP或域名。
"port": 22222, // 服务器端口,与服务器上的配置文件要相同
"users": [
{
"id": "56ab23bq-34ty-7865-901c-1234567890ab", // 用户的UUID必须与服务器端配置相同
"alterId": 0 ,// 此处的值也应当与服务器相同
"email": "t@t.tt",
"security": "auto"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"wsSettings": {},
"sockopt": {
"mark": 255 //这里是 SO_MARK,用于 iptables 识别,每个 outbound 都要配置;255可以改成其他数值,但要与下面的 iptables 规则对应;如果有多个 outbound,最好奖所有 outbound 的 SO_MARK 都设置成一样的数值
}
},
"mux": {
"enabled": false,
"concurrency": -1
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIP"
},
"streamSettings": {
"sockopt": {
"mark": 255
}
}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "http"
}
}
},
{
"tag": "dns-out",
"protocol": "dns",
"streamSettings": {
"sockopt": {
"mark": 255
}
}
}
],
"dns": {
"servers": [
"1.2.4.8", // 中中国大陆域名使用 Cloudflare 的 DNS(备用)
"114.114.114.114", // 114 的 DNS (备用)
{
"address": "8.8.8.8", //非中国大陆域名使用阿里的 DNS
"port": 53,
"domains": [
"geosite:geolocation-!cn"
]
}
]
},
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{ // 劫持 53 端口 UDP 流量,使用 V2Ray 的 DNS
"type": "field",
"inboundTag": [
"trans_tproxy",
"trans_redirect"
],
"port": 53,
"network": "udp",
"outboundTag": "dns-out"
},
{ // 直连 123 端口 UDP 流量(NTP 协议)
"type": "field",
"inboundTag": [
"trans_tproxy",
"trans_redirect"
],
"port": 123,
"network": "udp",
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
// 设置 DNS 配置中的国内 DNS 服务器地址直连,以达到 DNS 分流目的
"114.114.114.114",
"1.2.4.8",
"223.5.5.5"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
// 设置 DNS 配置中的国内 DNS 服务器地址走代理,以达到 DNS 分流目的
"8.8.8.8",
"1.1.1.1"
],
"outboundTag": "proxy" // 改为你自己代理的出站 tag
},
{ // 广告拦截
"type": "field",
"domain": [
"geosite:category-ads-all"
],
"outboundTag": "block"
},
{ // BT 流量直连
"type": "field",
"protocol":["bittorrent"],
"outboundTag": "direct"
},
{ // 直连中国大陆主流网站 ip 和 保留 ip
"type": "field",
"ip": [
"geoip:private",
"geoip:cn"
],
"outboundTag": "direct"
},
{ // 直连中国大陆主流网站域名
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
}
]
}
}
透明代理(REDIRECT)
设定 TCP 透明代理的 iptables 规则,命令如下
iptables -t nat -N V2RAY # 新建一个名为 V2RAY 的链
iptables -t nat -A V2RAY -d 192.168.0.0/16 -j RETURN # 直连 192.168.0.0/16
iptables -t nat -A V2RAY -p tcp -j RETURN -m mark --mark 0xff # 直连 SO_MARK 为 0xff 的流量(0xff 是 16 进制数,数值上等同与上面配置的 255),此规则目的是避免代理本机(网关)流量出现回环问题
iptables -t nat -A V2RAY -p tcp -j REDIRECT --to-ports 12345 # 其余流量转发到 12345 端口(即 V2Ray)
iptables -t nat -A PREROUTING -p tcp -j V2RAY # 对局域网其他设备进行透明代理
iptables -t nat -A OUTPUT -p tcp -j V2RAY # 对本机进行透明代理
然后设定 UDP 流量透明代理的 iptables 规则,命令如下
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100
iptables -t mangle -N V2RAY_MASK
iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A V2RAY_MASK -p udp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A PREROUTING -p udp -j V2RAY_MASK
- 在上面的设置中,假设访问了国外网站,如 Google 等,网关依然会使用的系统 DNS 进行查询,只不过返回的结果是污染过的,而 V2Ray 提供的 sniffing 能够从流量中提取域名信息交由 VPS 解析。也就是说,每次打算访问被墙的网站,DNS 提供商都知道,鉴于国内企业尿性,也许 GFW 也都知道,会不会将这些数据收集喂 AI 也未可知。
- sniffing 目前只能从 TLS 和 HTTP 流量中提取域名,如果上网流量有非这两种类型的慎用 sniffing 解决 DNS 污染。
- 由于对 iptables 不熟,我总感觉上面对 UDP 流量的透明代理的设置使用上有点问题,知道为什么的朋友请反馈一下。如果你只是简单的上上网看看视频等,可以只代理 TCP 流量,不设 UDP 透明代理。
- 喜欢玩网游的朋友可能要失望了,使用 V2Ray 加速游戏效果不是很好。
- V2Ray 只能代理 TCP/UDP 的流量,ICMP 不支持,即就算透明代理成功了之后 ping Google 这类网站也是不通的。
- 按照网上其他的透明代理教程,设置 iptables 肯定要 RETURN 127.0.0.0/8 这类私有地址,但我个人观点是放到 V2Ray 的路由里好一些。
透明代理(TPROXY)
随着 V2Ray 的更新,V2Ray 推出了新的透明代理方式—— TPROXY,原来的叫 REDIRECT。最近测试了一下 TPROXY ,效果还不错,主观感觉比 REDIRECT 好。并且在本文的透明代理中,DNS 服务将由 V2Ray 提供。不过这种方式需要 iptables 的 TPROXY 模块支持,有一些阉割版的系统会精简掉 TPROXY 模块
以上是 V2Ray 透明代理的参考配置
- dokodemo-door 是用来接收透明代理的入站协议,followRedirect 项须为 true 以及 sockopt.tproxy 项须为 tproxy,建议开启 sniffing,否则路由无法匹配域名;
- 本节添加了 DNS 配置,用来对国内外域名进行 DNS 分流,需要
DNS 配置
、DNS 入站
、DNS 出站
和路由
四者配合,在本例中 DNS 入站直接使用透明代理入站,可参考 DNS 及其应用; - 在 DNS 配置中,依次配置了 Google、Cloudflare、114 和阿里的 DNS,由于在阿里的 DNS 中指定了 domain,所以匹配的域名会用阿里的 DNS 查询,其他的先查询 Google 的 DNS,如果查不到的话再依次查 Cloudflare 及 114 的。所以达到了国内外域名 DNS 分流,以及 DNS 备用。要注意把 NTP 服务器和你自己 VPS 域名也加入到直连的 DNS ,否则会导致 V2Ray 无法与 VPS 正常连接;
- DNS 配置只是说明哪些域名查哪个 DNS,至于哪个 DNS 走代理哪个 DNS 直连要在 routing 里设置规则;
- routing 也要设置 123 端口的 UDP 流量直连,不然的话要是时间误差超出允许范围(90s),要使用 NTP 校准时间就要先连上代理,但是连代理又要确保时间准确,结果就是既连不上代理,也无法自动校准时间;
- freedom 的出站设置 domainStrategy 为 UseIP,以避免直连时因为使用本机的 DNS 出现一些奇怪问题;
- 注意要在所有的 outbound 加一个 255 的 mark,这个 mark 与下文 iptables 命令中
iptables -t mangle -A V2RAY_MASK -j RETURN -m mark --mark 0xff
配合,以直连 V2Ray 发出的流量(blackhole 可以不配置 mark)。
配置透明代理规则
执行下面的命令开启透明代理。由于使用了 TPROXY 方式的透明代理,所以 TCP 流量也是使用 mangle 表。以下命令中,以 # 开头的为注释。
# 设置策略路由
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100
# 代理局域网设备
iptables -t mangle -N V2RAY
iptables -t mangle -A V2RAY -d 127.0.0.1/32 -j RETURN
iptables -t mangle -A V2RAY -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A V2RAY -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A V2RAY -d 192.168.0.0/16 -p tcp -j RETURN # 直连局域网,避免 V2Ray 无法启动时无法连网关的 SSH,如果你配置的是其他网段(如 10.x.x.x 等),则修改成自己的
iptables -t mangle -A V2RAY -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN # 直连局域网,53 端口除外(因为要使用 V2Ray 的
iptables -t mangle -A V2RAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 # 给 UDP 打标记 1,转发至 12345 端口
iptables -t mangle -A V2RAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 # 给 TCP 打标记 1,转发至 12345 端口
iptables -t mangle -A PREROUTING -j V2RAY # 应用规则
# 代理网关本机
iptables -t mangle -N V2RAY_MASK
iptables -t mangle -A V2RAY_MASK -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -p tcp -j RETURN # 直连局域网
iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN # 直连局域网,53 端口除外(因为要使用 V2Ray 的 DNS)
iptables -t mangle -A V2RAY_MASK -j RETURN -m mark --mark 0xff # 直连 SO_MARK 为 0xff 的流量(0xff 是 16 进制数,数值上等同与上面V2Ray 配置的 255),此规则目的是避免代理本机(网关)流量出现回环问题
iptables -t mangle -A V2RAY_MASK -p udp -j MARK --set-mark 1 # 给 UDP 打标记,重路由
iptables -t mangle -A V2RAY_MASK -p tcp -j MARK --set-mark 1 # 给 TCP 打标记,重路由
iptables -t mangle -A OUTPUT -j V2RAY_MASK # 应用规则
执行了以上 ip 和 iptables 命令后,局域网同网段的设备以及网关本身就可以直接翻墙了。
在类 ss-redir 透明代理中,有两个观点非常深入人心:
1. UDP 只能 TPROXY
2. TPROXY 不能用于 OUTPUT 链
然后我们从这两个观点很容易得出一个推论:无法在提供透明代理的本机(即本例中的网关)上对 UDP 透明代理。
但实际上,在本例的配置中无论是 TCP 还是 UDP,都可以实现在本机上的透明代理,而且都是用 TPROXY。那好像又跟前面的结论矛盾了?其实关键在于这三句命令:
iptables -t mangle -A V2RAY_MASK -p udp -j MARK --set-mark 1
iptables -t mangle -A V2RAY_MASK -p tcp -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -j V2RAY_MASK
这几句是说给 OUTPUT 链的 TCP 和 UDP 打个标记 1(OUTPUT 应用 V2RAY_MASK 链)。由于 Netfilter 的特性,在 OUTPUT 链打标记会使相应的包重路由到 PREROUTING 链上,在已经配置好了 PREROUTING 相关的透明代理的情况下,OUTPUT 链也可以透明代理了,也就是网关对自身的 UDP 流量透明代理自身(当然 TCP 也不在话下)。因为这是 netfilter 本身的特性,Shadowsocks 应该也可以用同样的方法对本机的 UDP 透明代理,但我没有实际测试过效果。
开机自动运行透明代理规则
由于策略路由以及iptables 有重启会失效的特性,所以当测试配置没有问题之后,需要再弄个服务在开机时自动配置策略路由和 iptables,否则每次开机的时候就要手动来一遍了。
-
由于 iptables 命令有点多,所以先将 iptables 规则保存到 /etc/iptables/rules.v4 中。
mkdir -p /etc/iptables && iptables-save > /etc/iptables/rules.v4
-
在 /etc/systemd/system/ 目录下创建一个名为 tproxyrule.service 的文件,然后添加以下内容并保存。
[Unit] Description=Tproxy rule After=network.target Wants=network.target [Service] Type=oneshot #注意分号前后要有空格 ExecStart=/sbin/ip rule add fwmark 1 table 100 ; /sbin/ip route add local 0.0.0.0/0 dev lo table 100 ; /sbin/iptables-restore /etc/iptables/rules.v4 [Install] WantedBy=multi-user.target
-
执行下面的命令使 tproxyrule.service 可以开机自动运行。
systemctl enable tproxyrule
备注
- TPROXY 与 REDIRECT 是针对 TCP 而言的两种透明代理模式,两者的差异主要在于 TPROXY 可以透明代理 IPV6,而 REDIRECT 不行,本文主要是将透明代理模式改为 TPROXY 并且使用了 V2Ray 的 DNS。但我没有 IPV6 环境,无法进行测试,所以本文只适用于 IPV4。
- 据我了解,到目前(2019.10)为止,在我所知的具备透明代理功能的翻墙工具中,TCP 透明代理方式可以使用的 TPROXY 的只有 V2Ray。所以你要找其他资料参考的话,要注意透明代理方式,因为基本上都是 REDIRECT 模式的(包括 V2Ray 官网给的示例)。
- 在透明代理中,不要用 V2Ray 开放 53 端口做 DNS 服务器。如果这么做了,DNS 会出问题,这应该是个 BUG。(详情见此 Issue)
- 我用 NatTypeTester 测试过 NAT 类型,结果是 FullCone,但也看到有反馈说玩游戏依然是 PortRestrictedCone。我也不清楚是怎么回事,这点需要玩游戏的朋友来确认了。不过目前测试发现代理 QUIC 的效果还不不错的。 V2Ray 仍然不支持 FullCone
V2Ray 闪退
- 如果你使用 Linux 并开启了 systemd,可以使用
journalctl -u v2ray
查看 V2Ray 退出时的日志; - 一般情况可以手动运行
v2ray -config=<config-file> -test
来查看错误信息;
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。