转载自:https://www.80sy.com/951.html

1.1. 设置网关

  1. 用网线将树莓派接入路由器 LAN 口,假设分给树莓派的 IP 是 192.168.1.22。
  2. 树莓派开启 IP 转发(需要开启 IP 转发才能作为网关)。命令为 echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf && sysctl -p。执行后将出现 net.ipv4.ip_forward=1 的提示。
  3. 手动配置 PC 的网络,将默认网关指向树莓派的地址即 192.168.1.22。此时 PC 应当能正常上网(由于还没设置代理,“正常”是指可以上国内的网站)。

1.2. 树莓派安装配置 V2Ray

  1. 安装 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 内容不一样。

设置网关

  1. 用网线将树莓派接入路由器 LAN 口,假设分给树莓派的 IP 是 192.168.1.22。
  2. 树莓派开启 IP 转发(需要开启 IP 转发才能作为网关)。命令为 echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf && sysctl -p。执行后将出现 net.ipv4.ip_forward=1 的提示。
  3. 手动配置 PC 的网络,将默认网关指向树莓派的地址即 192.168.1.22。此时 PC 应当能正常上网(由于还没设置代理,“正常”是指可以上国内的网站)。

树莓派安装配置 V2Ray

  1. 安装 V2Ray。可以使用 V2Ray 提供的 go.sh 脚本安装,由于 GFW 会恶化对 GitHub 的访问,直接运行脚本几乎无法安装,建议先下载 V2Ray 的压缩包,然后用安装脚本通过 --local 参数进行安装。
  2. 配置 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,否则每次开机的时候就要手动来一遍了。

  1. 由于 iptables 命令有点多,所以先将 iptables 规则保存到 /etc/iptables/rules.v4 中。

    mkdir -p /etc/iptables && iptables-save > /etc/iptables/rules.v4
    
  2. 在 /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
  3. 执行下面的命令使 tproxyrule.service 可以开机自动运行。

    systemctl enable tproxyrule

备注

  1. TPROXY 与 REDIRECT 是针对 TCP 而言的两种透明代理模式,两者的差异主要在于 TPROXY 可以透明代理 IPV6,而 REDIRECT 不行,本文主要是将透明代理模式改为 TPROXY 并且使用了 V2Ray 的 DNS。但我没有 IPV6 环境,无法进行测试,所以本文只适用于 IPV4。
  2. 据我了解,到目前(2019.10)为止,在我所知的具备透明代理功能的翻墙工具中,TCP 透明代理方式可以使用的 TPROXY 的只有 V2Ray。所以你要找其他资料参考的话,要注意透明代理方式,因为基本上都是 REDIRECT 模式的(包括 V2Ray 官网给的示例)。
  3. 在透明代理中,不要用 V2Ray 开放 53 端口做 DNS 服务器。如果这么做了,DNS 会出问题,这应该是个 BUG。(详情见此 Issue)
  4. 我用 NatTypeTester 测试过 NAT 类型,结果是 FullCone,但也看到有反馈说玩游戏依然是 PortRestrictedCone。我也不清楚是怎么回事,这点需要玩游戏的朋友来确认了。不过目前测试发现代理 QUIC 的效果还不不错的。 V2Ray 仍然不支持 FullCone

V2Ray 闪退

  • 如果你使用 Linux 并开启了 systemd,可以使用 journalctl -u v2ray 查看 V2Ray 退出时的日志;
  • 一般情况可以手动运行 v2ray -config=<config-file> -test 来查看错误信息;