xray

RaspberryPi上实现透明代理

设置网关

  1. 用网线将树莓派接入路由器 LAN 口,假设分给树莓派的 IP 是 192.168.1.253。
  2. 树莓派开启 IP 转发(需要开启 IP 转发才能作为网关)。命令为echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf && sysctl -p 。执行后将出现 net.ipv4.ip_forward=1 的提示。

  3. 手动配置 PC 的网络,将默认网关指向树莓派的地址即 192.168.1.253。此时 PC 应当能正常上网(由于还没设置代理,“正常”是指可以上国内的网站)。

安装xray

bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install

准备XRay Client 配置文件

tproxy-tls-ws.json

root@raspberrypi:~/xray# cat /etc/xray/tproxy-tls-ws.json

{
  "inbounds": [
    {
      "tag":"transparent",
      "port": 12345,
      "protocol": "dokodemo-door",
      "settings": {
        "network": "tcp,udp",
        "followRedirect": true
      },
      "sniffing": {
        "enabled": true,
        "destOverride": [
          "http",
          "tls"
        ]
      },
      "streamSettings": {
        "sockopt": {
          "tproxy": "tproxy" // 透明代理使用 TPROXY 方式
        }
      }
    },
    {
      "port": 1089, 
      "protocol": "socks", // 入口协议为 SOCKS 5
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      },
      "settings": {
        "auth": "noauth"
      }
    }
  ],
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vless", // 代理服务器
      "settings": {
        "vnext": [
                {
            "address": "对应的域名",
            "port": 443,
            "users": [
              {
                "id": "2b0a831c-968c-4f0d-8c12-28a5e3", //替换为对应的ID
                "encryption": "none",
                "alterId": 0
              }
            ]
          }
        ]
      },
            "streamSettings": {
                "network": "ws",
                "security": "tls",
                "tlsSettings": {
                    "allowInsecure": false,
                    "show": false
                },
                "wsSettings": {
                    "path": "/99eab497c4?ed=2048",
                    "headers": {}
                }
            },
      "streamSettings": {
        "sockopt": {
          "mark": 255
        }
      },
      "mux": {
        "enabled": true
      }
    },
    {
      "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": [
      "8.8.8.8", // 非中中国大陆域名使用 Google 的 DNS
      "1.1.1.1", // 非中中国大陆域名使用 Cloudflare 的 DNS(备用)
      "114.114.114.114", // 114 的 DNS (备用)
      {
        "address": "223.5.5.5", //中国大陆域名使用阿里的 DNS
        "port": 53,
        "domains": [
          "geosite:cn",
          "ntp.org",   // NTP 服务器
          "brightmoon.top" // 此处改为你 VPS 的域名
        ]
      }
    ]
  },
  "routing": {
    "domainStrategy": "IPOnDemand",
    "rules": [
      { // 劫持 53 端口 UDP 流量,使用 V2Ray 的 DNS
        "type": "field",
        "inboundTag": [
          "transparent"
        ],
        "port": 53,
        "network": "udp",
        "outboundTag": "dns-out" 
      },    
      { // 直连 123 端口 UDP 流量(NTP 协议)
        "type": "field",
        "inboundTag": [
          "transparent"
        ],
        "port": 123,
        "network": "udp",
        "outboundTag": "direct" 
      },    
      {
        "type": "field", 
        "ip": [ 
          // 设置 DNS 配置中的国内 DNS 服务器地址直连,以达到 DNS 分流目的
          "223.5.5.5",
          "114.114.114.114"
        ],
        "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"
      }
    ]
  }
}

以上是 V2Ray 透明代理的参考配置,关于配置有一些注意点及说明:

确认Raspberry可以FK GFW

执行 curl -so /dev/null -w "%{http_code}" google.com -x socks5://127.0.0.1:1089

确认 V2Ray 已经可以翻墙(命令中 socks5 指 inbound 协议为 socks,1089 指该 inbound 端口是 1089)。

如果执行这个命令出现了 301 或 200 这类数字的话代表可以翻墙

如果长时间没反应或者是 000 的话说明不可以翻墙。

配置iptables 脚本

配置好用于tproxy的iptable脚本

配置透明代理

root@raspberrypi:~/xray# cat iptables_tproxy.sh

# 设置策略路由
ip rule add fwmark 1 table 100 
ip route add local 0.0.0.0/0 dev lo table 100

# 代理局域网设备
iptables -t mangle -N XRAY
iptables -t mangle -A XRAY -d 127.0.0.1/32 -j RETURN
iptables -t mangle -A XRAY -d 224.0.0.0/4 -j RETURN 
iptables -t mangle -A XRAY -d 255.255.255.255/32 -j RETURN 
iptables -t mangle -A XRAY -d 192.168.0.0/16 -p tcp -j RETURN # 直连局域网,避免 V2Ray 无法启动时无法连网关的 SSH,如果你配置的是其他网段(如 10.x.x.x 等),则修改成自己的
iptables -t mangle -A XRAY -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN # 直连局域网,53 端口除外(因为要使用 V2Ray 的 DNS)
iptables -t mangle -A XRAY -d 10.0.0.0/8 -p tcp -j RETURN # 直连局域网,避免 V2Ray 无法启动时无法连网关的 SSH,如果你配置的是其他网段(如 10.x.x.x 等),则修改成自己的
iptables -t mangle -A XRAY -d 10.0.0.0/8 -p udp ! --dport 53 -j RETURN # 直连局域网,53 端口除外(因为要使用 V2Ray 的 DNS)
iptables -t mangle -A XRAY -j RETURN -m mark --mark 0xff    # 直连 SO_MARK 为 0xff 的流量(0xff 是 16 进制数,数值上等同与上面V2Ray 配置的 255),此规则目的是解决v2ray占用大量CPU(https://github.com/v2ray/v2ray-core/issues/2621)
iptables -t mangle -A XRAY -p udp -j TPROXY --on-ip 127.0.0.1 --on-port 12345 --tproxy-mark 1 # 给 UDP 打标记 1,转发至 12345 端口
iptables -t mangle -A XRAY -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port 12345 --tproxy-mark 1 # 给 TCP 打标记 1,转发至 12345 端口
iptables -t mangle -A PREROUTING -j XRAY # 应用规则

# 代理网关本机
iptables -t mangle -N XRAY_MASK 
iptables -t mangle -A XRAY_MASK -d 224.0.0.0/4 -j RETURN 
iptables -t mangle -A XRAY_MASK -d 255.255.255.255/32 -j RETURN 
iptables -t mangle -A XRAY_MASK -d 192.168.0.0/16 -p tcp -j RETURN # 直连局域网
iptables -t mangle -A XRAY_MASK -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN # 直连局域网,53 端口除外(因为要使用 V2Ray 的 DNS)
iptables -t mangle -A XRAY_MASK -d 10.0.0.0/8 -p tcp -j RETURN # 直连局域网
iptables -t mangle -A XRAY_MASK -d 10.0.0.0/8 -p udp ! --dport 53 -j RETURN # 直连局域网,53 端口除外(因为要使用 V2Ray 的 DNS)
iptables -t mangle -A XRAY_MASK -j RETURN -m mark --mark 0xff    # 直连 SO_MARK 为 0xff 的流量(0xff 是 16 进制数,数值上等同与上面V2Ray 配置的 255),此规则目的是避免代理本机(网关)流量出现回环问题
iptables -t mangle -A XRAY_MASK -p udp -j MARK --set-mark 1   # 给 UDP 打标记,重路由
iptables -t mangle -A XRAY_MASK -p tcp -j MARK --set-mark 1   # 给 TCP 打标记,重路由
iptables -t mangle -A OUTPUT -j XRAY_MASK # 应用规则

# 新建 DIVERT 规则,避免已有连接的包二次通过 TPROXY,理论上有一定的性能提升
iptables -t mangle -N DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 1
iptables -t mangle -A DIVERT -j ACCEPT
iptables -t mangle -I PREROUTING -p tcp -m socket -j DIVERT

确认开机启动的脚本

xray.service

root@raspberrypi:~/xray# cat /etc/systemd/system/xray.service

[Unit]
Description=XRay Service
After=network.target nss-lookup.target

[Service]
User=nobody
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
NoNewPrivileges=true
ExecStart=/usr/bin/xray -config /etc/xray/tproxy-tls-ws.json
Restart=on-failure
RestartPreventExitStatus=23
LimitNPROC=500
LimitNOFILE=1000000

[Install]
WantedBy=multi-user.target

tproxyrule.service

配置开机自动启动

root@raspberrypi:~/xray# cat /etc/systemd/system/tproxyrule.service

[Unit]
Description=Tproxy rule
After=network.target
Wants=network.target

[Service]

Type=oneshot
RemainAfterExit=yes
# 注意分号前后要有空格
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/iproute2/rules-xray.v5
ExecStop=/sbin/ip rule del fwmark 1 table 100 ; /sbin/ip route del local 0.0.0.0/0 dev lo table 100 ; /sbin/iptables -t mangle -F

# 如果是 nftables,则改为以下命令
# ExecStart=/sbin/ip rule add fwmark 1 table 100 ; /sbin/ip route add local 0.0.0.0/0 dev lo table 100 ; /sbin/nft -f /etc/nftables/rules.v4
# ExecStop=/sbin/ip rule del fwmark 1 table 100 ; /sbin/ip route del local 0.0.0.0/0 dev lo table 100 ; /sbin/nft flush ruleset

[Install]
WantedBy=multi-user.target

systemctl enable tproxyrule

systemctl enable xray

设定 DHCP(可选)

在路由器上设定 DHCP,将网关地址指向网关设备,在本文的举例中即为树莓派的 IP 192.168.1.253; DNS 随意,因为已经配置了劫持 53 端口的 UDP,当然填常规的 DNS 也更是没有问题的。

References

https://guide.v2fly.org/app/tproxy.html.

désert/Linux/xray (last edited 2023-06-30 09:41:31 by merlyn)