XRay终极版:同时作为TLS服务器提供反向代理和Reality客户端提供透明代理

186 次浏览

家庭内网中的设备作为Vless + TLS服务器提供反向代理实现内网穿透,同时作为 Vless + Reality 客户端提供透明代理为局域网设备上网。
公司内网中的设备作为Vless + TLS客户端提供反向代理实现内网穿透,同时作为 Vless + Reality 客户端提供透明代理为局域网设备上网。
移动端内网中的设备作为Vless + TLS客户端提供反向代理实现内网穿透,同时作为 Vless + Reality 客户端提供透明代理为局域网设备上网。
该方案支持IPv6。

1、反向代理服务端配置(同时作为家庭内网设备的旁路由)

1)配置Xray:

sudo nano /usr/local/etc/xray/config.json

内容如下:

{
  "log": {
    "loglevel": "warning",          // 内容从少到多: "none", "error", "warning", "info", "debug"
    "access": "/var/log/xray/access.log", // 访问记录
    "error": "/var/log/xray/error.log"    // 错误记录
  },
  
  "reverse": {
    "portals": [                    // 反向代理实现内网穿透
      {
        "tag": "portal-out-comp",
        "domain": "reverse.comp"    // 与公司内网 bridges 的 domain 对应
      },
      {
        "tag": "portal-out-mobi",
        "domain": "reverse.mobi"    // 与移动端内网 bridges 的 domain 对应
      }
    ]
  },

  "inbounds": [
    {
      "tag": "bridge-in",           // Vless + TLS服务器配置 用于 bridge 反向连接
      "port": 443,                  // 服务器端口,家庭宽带屏蔽443,可使用其他端口
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "UUID",           // 替换为生成的 UUID
            "flow": "xtls-rprx-vision" // 启用 Vision 流控
          }
        ],
        "decryption": "none"
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls", "quic"]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls",
        "tlsSettings": {
          "rejectUnknownSni": true,
          "certificates": [
            {
              "certificateFile": "/etc/letsencrypt/live/example.com/fullchain.pem",
              "keyFile": "/etc/letsencrypt/live/example.com/privkey.pem"
            }
          ]
        }
      }
    },
    {
      "tag": "tproxy-in",           // 透明代理
      "port": 12345,                // 透明代理监听端口
      "protocol": "dokodemo-door",
      "settings": {
        "network": "tcp, udp",
        "followRedirect": true
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls", "quic"]
      },
      "streamSettings": {
        "sockopt": {
          "tproxy": "tproxy"        // 透明代理使用 TPROXY 方式
        }
      }
    }
  ],

  "outbounds": [
    {
      "tag": "direct-out",          // 直接出站
      "protocol": "freedom",        // 使用freedom直接出站
      "settings": {"domainStrategy": "UseIP"},
      "streamSettings": {
        "sockopt": {"mark": 255}
      }
    },
    {
      "tag": "block-out",           // 拦截出站
      "protocol": "blackhole",      // 黑洞协议丢弃所有数据
      "settings": {}
    },
    {
      "tag": "proxy-out",           // Vless + Reality 客户端配置
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "example.com",   // 服务器 IP 地址或域名
            "port": 443,            // 与服务器配置端口一致
            "users": [
              {
                "id": "UUID",       // 与服务端配置一致的 UUID
                "flow": "xtls-rprx-vision", // 与服务端一致的流控
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "serverName": "www.apple.com", // 与服务端 serverNames 相同
          "publicKey": "公钥",       // 替换为生成的公钥
          "shortId": ""             // shortId
        },
        "sockopt": {"mark": 255}
      }
    },
    {
      "tag": "dns-out",             // DNS 转发
      "protocol": "dns",
      "streamSettings": {
        "sockopt": {"mark": 255}
      }
    }
  ],

  "dns": {
    "hosts": {
      "proxy服务端域名": "服务端 IP"
      // outbound 的 proxy 里 address 填的域名:希望代理走ipv4,这里 VPS IP 填VPS的ipv4, 希望代理走ipv6,这里VPS IP 填VPS的ipv6;
      // outbound 的 proxy 里 address 填的 IP,这行不用写。
    },
    "servers": [
      {
        "address": "221.12.1.227",  // 中国大陆域名使用浙江联通的 DNS
        "port": 53,
        "domains": ["geosite:cn"],
        "expectIPs": ["geoip:cn"]
      },
      {
        "address": "223.5.5.5",     //中国大陆域名使用阿里云的 DNS (备用)
        "port": 53,
        "domains": ["geosite:cn"],
        "expectIPs": ["geoip:cn"]
      },
      "8.8.8.8",                   // 非中国大陆域名使用 Google 的 DNS
      "1.1.1.1",                   // 非中国大陆域名使用 Cloudflare 的 DNS (备用)
      "localhost"
    ]
  },

  "routing": {
    "domainMatcher": "mph",
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type":"field",             // 识别公司内网主动发起的反向代理连接
        "inboundTag": ["bridge-in"],
        "domain": ["full:reverse.comp"],
        "outboundTag": "portal-out-comp"
      },
        {
        "type": "field",            // 把对公司内网网段的请求转发给公司内网
        "ip": ["192.168.101.0/24"],
        "outboundTag": "portal-out-comp"
      },
      {
        "type":"field",             // 识别移动端内网主动发起的反向代理连接
        "inboundTag": ["bridge-in"],
        "domain": ["full:reverse.mobi"],
        "outboundTag": "portal-out-mobi"
      },
      {
        "type": "field",            // 把对移动端内网网段的请求转发给移动端内网
        "ip": ["192.168.11.0/24"],
        "outboundTag": "portal-out-mobi"
      },

      {
        "type": "field",            // 广告拦截
        "domain": ["geosite:category-ads-all"],
        "outboundTag": "block-out"
      },
      {
        "type": "field",            // 劫持53端口的DNS流量
        "inboundTag": ["tproxy-in"],
        "port": 53,
        "outboundTag": "dns-out"
      },
      {
        "type": "field",            // 国外 DNS 服务器地址走代理
        "ip": ["8.8.8.8", "1.1.1.1"],
        "outboundTag": "proxy-out"
      },
      {
        "type": "field",            // 本地流量直连
        "ip": ["geoip:private"],
        "outboundTag": "direct-out"
      },
      {
        "type": "field",            // 国外流量走代理
        "ip": ["geoip:!cn"],
        "outboundTag": "proxy-out"
      },
      {
        "type": "field",            // 国外流量走代理
        "domain": ["geosite:geolocation-!cn"],
        "outboundTag": "proxy-out"
      }
      // 其他请求默认直接出站direct-out(outbound中的第一项作为默认出站)
    ]
  }
}

注意:本配置会劫持所有发往 53 端口的流量以解决 DNS 污染问题,所局域网设备和本机的 DNS 服务器的地址可以随意配置。建议设置为旁路由 IP,防止 DNS 泄露。

测试并重载XRay:

# 检查配置语法
sudo xray run -test -config /usr/local/etc/xray/config.json

# 重启服务
sudo systemctl restart xray

# 检查服务状态
sudo systemctl status xray

2)Netfilter 配置

使用下述命令设置策略路由

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

# 设置策略路由 v6
ip -6 rule add fwmark 1 table 106
ip -6 route add local ::/0 dev lo table 106

3)配置透明代理规则

nftables 规则:
新建一个文件用于保存nfptables 规则。

sudo nano /etc/nftables.rules

内容如下:

#!/usr/sbin/nft -f

flush ruleset

table inet xray {
        chain prerouting {
                type filter hook prerouting priority filter; policy accept;
                ip daddr { 127.0.0.0/8, 224.0.0.0/4, 255.255.255.255 } return
                meta l4proto tcp ip daddr 192.168.1.0/24 return
                ip daddr 192.168.1.0/24 udp dport != 53 return
                ip6 daddr { ::1, fe80::/10 } return
                meta l4proto tcp ip6 daddr fd00::/8 return
                ip6 daddr fd00::/8 udp dport != 53 return
                meta mark 0x000000ff return
                meta l4proto { tcp, udp } meta mark set 0x00000001 tproxy ip to 127.0.0.1:12345 accept
                meta l4proto { tcp, udp } meta mark set 0x00000001 tproxy ip6 to [::1]:12345 accept
        }

        #chain output {
        #        type route hook output priority filter; policy accept;
        #        ip daddr { 127.0.0.0/8, 224.0.0.0/4, 255.255.255.255 } return
        #        meta l4proto tcp ip daddr 192.168.1.0/24 return
        #        ip daddr 192.168.1.0/24 udp dport != 53 return
        #        ip6 daddr { ::1, fe80::/10 } return
        #        meta l4proto tcp ip6 daddr fd00::/8 return
        #        ip6 daddr fd00::/8 udp dport != 53 return
        #        meta mark 0x000000ff return
        #        meta l4proto { tcp, udp } meta mark set 0x00000001 accept
        #}

        #chain divert {
        #        type filter hook prerouting priority mangle; policy accept;
        #        meta l4proto tcp socket transparent 1 meta mark set 0x00000001 accept
        #}
}

注意:使用反向代理时本机流量不走tproxy,否则反向代理可能异常。
其中,网关地址可用以下命令获得:

ip address | grep -w inet | awk '{print $2}'
ip address | grep -w inet6 | awk '{print $2}'

将配置文件赋予可执行权限

chmod 700 /etc/nftables.rules

进入/etc目录后在root权限下执行配置文件

sudo ./nftables.rules
# 或者
source /etc/nftables.rules

检查nftables规则是否生效:

sudo nft list ruleset

4)开机自动运行 Netfilter 配置

将nftables 配置写入nftables.rulesv46文件

nft list ruleset > /etc/nftables.rulesv46

在 /etc/systemd/system/ 目录下创建一个名为 xray-tproxy.service 的文件

sudo nano /etc/systemd/system/xray-tproxy.service

内容如下:

[Unit]
Description=Tproxy rules

[Service]
Type=oneshot
RemainAfterExit=yes

ExecStart=/sbin/ip rule add fwmark 1 table 100 ; \
/sbin/ip -6 rule add fwmark 1 table 106 ; \
/sbin/ip route add local 0.0.0.0/0 dev lo table 100 ; \
/sbin/ip -6 route add local ::/0 dev lo table 106 ; \
/sbin/nft -f /etc/nftables.rulesv46 ;

ExecStop=/sbin/ip rule del fwmark 1 table 100 ; \
/sbin/ip -6 rule del fwmark 1 table 106 ; \
/sbin/ip route del local 0.0.0.0/0 dev lo table 100 ; \
/sbin/ip -6 route del local ::/0 dev lo table 106 ; \
/sbin/nft flush ruleset

[Install]
WantedBy=multi-user.target

启用和测试服务

# 开机自启
sudo systemctl enable xray-tproxy

# 重新加载配置
sudo systemctl daemon-reload

# 启动服务
sudo systemctl start xray-tproxy

# 检查服务状态
sudo systemctl status xray-tproxy

# 检查nftables规则
sudo nft list ruleset

# 测试网络连接
curl -I http://www.google.com
curl -I http://www.baidu.com

2、反向代理客户端配置(同时作为公司内网设备和移动端内网设备的旁路由)

1)配置Xray:

sudo nano /usr/local/etc/xray/config.json

内容如下:

{
  "log": {
    "loglevel": "warning",          // 内容从少到多: "none", "error", "warning", "info", "debug"
    "access": "/var/log/xray/access.log", // 访问记录
    "error": "/var/log/xray/error.log"    // 错误记录
  },

  "reverse": {
    "bridges": [                    // 反向代理实现内网穿透
      {
        "tag": "bridge-in",
        "domain": "reverse.comp"    // 与中转服务器 portals 的 domain 对应
      }
    ]
  },

  "inbounds": [
    {
      "tag": "tproxy-in",
      "port": 12345,                // 透明代理监听端口
      "protocol": "dokodemo-door",
      "settings": {
        "network": "tcp, udp",
        "followRedirect": true
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls", "quic"]
      },
      "streamSettings": {
        "sockopt": {
          "tproxy": "tproxy"        // 透明代理使用 TPROXY 方式
        }
      }
    },
    {
      "tag": "socks-in",            // socks5协议作本地转发
      "listen": "127.0.0.1",        // 改为 0.0.0.0 允许来着 LAN 的请求
      "port": 10808,
      "protocol": "socks",
      "settings": {
         "udp": true
      },
      "sniffing": {
         "enabled": true,
         "destOverride": ["http", "tls", "quic"]
      }
    }
  ],

  "outbounds": [
    {
      "tag": "direct-out",          // 直接出站
      "protocol": "freedom",        // 使用freedom直接出站
      "settings": {"domainStrategy": "UseIP"},
      "streamSettings": {
        "sockopt": {"mark": 255}
      }
    },
    {
      "tag": "block-out",           // 拦截出站
      "protocol": "blackhole",      // 黑洞协议丢弃所有数据
      "settings": {}
    },
    {
      "tag": "proxy-out",           // Vless + Reality 客户端配置
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "example.com",   // 服务器 IP 地址或域名
            "port": 443,            // 与服务器配置端口一致
            "users": [
              {
                "id": "UUID",       // 与服务端配置一致的 UUID
                "flow": "xtls-rprx-vision", // 与服务端一致的流控
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "serverName": "www.apple.com", // 与服务端 serverNames 相同
          "publicKey": "公钥",       // 替换为生成的公钥
          "shortId": ""             // shortId
        },
        "sockopt": {"mark": 255}
      }
    },
    {
      "tag": "portal-out",          // Vless + TLS 客户端配置,连接到 portal
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "yourdomain.com",   // 服务器域名
            "port": 443,            // 与服务器配置端口一致
            "users": [
              {
                "id": "UUID",       // 与服务端配置一致的 UUID
                "flow": "xtls-rprx-vision",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls",
        "tlsSettings": {
          "serverName": "yourdomain.com", // 服务器域名
          "allowInsecure": false    // 禁止不安全证书
        },
        "sockopt": {"mark": 255}
      }
    },
    {
      "tag": "dns-out",             // DNS 转发
      "protocol": "dns",
      "streamSettings": {
        "sockopt": {"mark": 255}
      }
    }
  ],

  "dns": {
    "hosts": {
      "proxy服务端域名": "服务端 IP"
      // outbound 的 proxy 里 address 填的域名:希望代理走ipv4,这里 VPS IP 填VPS的ipv4, 希望代理走ipv6,这里VPS IP 填VPS的ipv6;
      // outbound 的 proxy 里 address 填的 IP,这行不用写。
    },
    "servers": [
      {
        "address": "221.12.1.227",  // 中国大陆域名使用浙江联通的 DNS
        "port": 53,
        "domains": ["geosite:cn"],
        "expectIPs": ["geoip:cn"]
      },
      {
        "address": "223.5.5.5",     //中国大陆域名使用阿里云的 DNS (备用)
        "port": 53,
        "domains": ["geosite:cn"],
        "expectIPs": ["geoip:cn"]
      },
      "8.8.8.8",                   // 非中国大陆域名使用 Google 的 DNS
      "1.1.1.1",                   // 非中国大陆域名使用 Cloudflare 的 DNS (备用)
      "localhost"
    ]
  },

  "routing": {
    "domainMatcher": "mph",
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",            // 识别反向桥接流量
        "inboundTag": ["bridge-in"],
        "domain": ["full:reverse.comp"],
        "outboundTag": "portal-out" // 转发到 portal 代理服务器
      },
      {
        "type":"field",             // 从 portal 过来的流量,也会从 bridge 进来,但是不带上面的domain
        "inboundTag": ["bridge-in"],
        "outboundTag": "direct-out" // 最终连接本地服务
      },
      {
        "type": "field",
        "ip": ["192.168.1.0/24"],
        "outboundTag": "portal-out" // 对家庭内网的访问转发到 portal 代理服务器
      },

      {
        "type": "field",            // 广告拦截
        "domain": ["geosite:category-ads-all"],
        "outboundTag": "block-out"
      },
      {
        "type": "field",            // 劫持53端口的DNS流量
        "inboundTag": ["tproxy-in"],
        "port": 53,
        "outboundTag": "dns-out"
      },
      {
        "type": "field",            // 国外 DNS 服务器地址走代理
        "ip": ["8.8.8.8", "1.1.1.1"],
        "outboundTag": "proxy-out"
      },
      {
        "type": "field",            // 本地流量直连
        "ip": ["geoip:private"],
        "outboundTag": "direct-out"
      },
      {
        "type": "field",            // 国外流量走代理
        "ip": ["geoip:!cn"],
        "outboundTag": "proxy-out"
      },
      {
        "type": "field",            // 国外流量走代理
        "domain": ["geosite:geolocation-!cn"],
        "outboundTag": "proxy-out"
      }
      // 其他请求默认直接出站direct-out(outbound中的第一项作为默认出站)
    ]
  }
}

2)其余配置同服务端中的配置

3)局域网内设备配置

将局域网内设备的IP设置为静态 IP,将网关指向透明代理设备的 IP。

3、反向代理客户端配置(同时作为公司内网设备和移动端内网设备的主路由 如 OpenWRT)

1)OpenWRT中安装Xray及相关依赖:

opkg update
opkg install xray-core
opkg install v2ray-geoip
opkg install v2ray-geosite
opkg install kmod-nft-tproxy
opkg install kmod-nft-socket

2)配置xray-core:

UCI中配置开机自启

nano /etc/config/xray

将 option enabled ‘0’ 改为 option enabled ‘1’

config xray 'enabled'
        option enabled '1'

config xray 'config'
        option confdir '/etc/xray'
        list conffiles '/etc/xray/config.json'
        option datadir '/usr/share/xray'
        option dialer ''
        option format 'json'

修改配置文件:

nano /etc/xray/config.json

配置文件内容同上述客户端配置

启动和检查xray

# 检查配置语法
xray run -test -config /etc/xray/config.json

# 启动服务
/etc/init.d/xray enable
/etc/init.d/xray start

# 检查运行状态
ps | grep xray
netstat -lnpt | grep xray

3)设置策略路由

nano /etc/rc.local

添加如下内容:

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

# 设置策略路由 v6
ip -6 rule add fwmark 1 table 106
ip -6 route add local ::/0 dev lo table 106

4)配置透明代理规则

创建nftables规则文件,必须以.nft结尾

nano /etc/nftables.d/20-xray-rules.nft

内容如下:

chain xray_prerouting {
        type filter hook prerouting priority filter; policy accept;
        ip daddr { 127.0.0.0/8, 224.0.0.0/4, 255.255.255.255 } return
        meta l4proto tcp ip daddr 192.168.1.0/24 return
        ip daddr 192.168.1.0/24 udp dport != 53 return
        ip6 daddr { ::1, fe80::/10 } return
        meta l4proto tcp ip6 daddr fd00::/8 return
        ip6 daddr fd00::/8 udp dport != 53 return
        meta mark 0x000000ff return
        meta l4proto { tcp, udp } meta mark set 0x00000001 tproxy ip to 127.0.0.1:12345 accept
        meta l4proto { tcp, udp } meta mark set 0x00000001 tproxy ip6 to [::1]:12345 accept
}

#chain xray_output {
#        type route hook output priority filter; policy accept;
#        ip daddr { 127.0.0.0/8, 224.0.0.0/4, 255.255.255.255 } return
#        meta l4proto tcp ip daddr 192.168.1.0/24 return
#        ip daddr 192.168.1.0/24 udp dport != 53 return
#        ip6 daddr { ::1, fe80::/10 } return
#        meta l4proto tcp ip6 daddr fd00::/8 return
#        ip6 daddr fd00::/8 udp dport != 53 return
#        meta mark 0x000000ff return
#        meta l4proto { tcp, udp } meta mark set 0x00000001 accept
#}

#chain xray_divert {
#        type filter hook prerouting priority mangle; policy accept;
#        meta l4proto tcp socket transparent 1 meta mark set 0x00000001 accept
#}

注意:使用反向代理时本机流量不走tproxy,否则反向代理可能异常。

参考资料:

https://xtls.github.io/document/level-2/tproxy_ipv4_and_ipv6.html

4、外网客户端配置

1)小火箭配置修改

default.conf 配置:点击【配置】,选择【本地文件】中的【default.conf】,进入配置界面,点击【规则】,添加规则:类型IP-CIDR,策略PROXY,不解析域名开启,IP CDIR 192.168.1.0/24(公司内网地址)点击【规则】,添加规则:类型IP-CIDR,策略PROXY,不解析域名开启,IP CDIR 192.168.31.0/24(家庭内网地址)修改网络设置(SMB和远程桌面需要):点击【设置】,点击【隧道】,开启【包括所有网络】。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部