Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[萌新求助]vless-tcp-xtls-vision-reality的方式fq, 添加前置Nginx筛选SNI无法fq; #184

Closed
scavenger-caesar opened this issue May 21, 2024 · 4 comments

Comments

@scavenger-caesar
Copy link

scavenger-caesar commented May 21, 2024

(希望能请教一下nginx和xray server的配置要如何修改可以实现如下结果)

1. 期望结果

  1. 流入xray请求的SNI和伪装的目标网站一致
  2. 通过nginx筛选SNI, 不符合伪装的SNI连接均拒绝

2. 尝试过程

2.1 实现思路

前置nginx筛选SNI

2.2 测试环境

利用docker部署测试环境

2.2.1 docker compose内容

networks:
  xray_network:
    external: false

services:
  xray_server:
    image: ghcr.io/xtls/xray-core:latest
    command: run -config /etc/xray/config.jsonc
    restart: unless-stopped
    networks:
      - xray_network
    volumes:
      - ./xray/logs/:/var/log/xray/ # xry的日志输出目录
      - ./xray/config/:/etc/xray/ # xray的配置目录
    environment: 
      TZ: Asia/Shanghai
  
  nginx_server:
    image: nginx:latest
    restart: unless-stopped
    networks:
      - xray_network
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro # nginx的配置路径
      - ./nginx/logs/:/var/log/nginx/ # nginx的日志输出目录
    environment: 
      TZ: Asia/Shanghai
    depends_on:
      - xray_server 

2.2.2 xray server内容

{
    "log": {
        "loglevel": "debug"
    },
    "inbounds": [
        {
            "listen": "0.0.0.0", // "0.0.0.0" 代表同时监听所有的IPv4和IPv6
            "port": 4443, 
            "protocol": "vless",
            "settings": {
                "clients": [
                    {
                        "id": "3dc3b7b3-56c1-4d8a-9f15-a4831bf8f7a1",
                        "flow": "xtls-rprx-vision"
                    }
                ],
                "decryption": "none"
            },
            "streamSettings": {
                "network": "tcp",
                "security": "reality",
                "realitySettings": {
                    // "xver": 1, // 发送 PROXY protocol; 专用于传递请求的真实来源 IP 和端口
                    "dest": "pytorch.org:443", // A website that support TLS1.3 and h2. You can also use `1.1.1.1:443` as dest
                    // 证书列表里允许的域名
                    "serverNames": [
                        "pytorch.org"    // A server name in the cert of dest site. If you use `1.1.1.1:443` as dest, then you can leave `serverNames` empty, it is a possible ways to bypass Iran's internet speed restrictions.
                    ],
                    "privateKey": "kIuej6RPn2Hgcg_VN9gAhC_w5i-MjecCkizkRJtJzlE", // run `xray x25519` to generate. Public and private keys need to be corresponding.
                    "shortIds": [// Required, list of shortIds available to clients, can be used to distinguish different clients
                        "d88a233765897aa6" // openssl rand -hex <1-8>
                    ]
                }
                // "tcpSettings": {
                //     // 仅用于 inbound,指示是否接收 PROXY protocol
                //     "acceptProxyProtocol": true 
                // }
            },
            "sniffing": {
                "enabled": true,
                "destOverride": [
                    "http",
                    "tls",
                    "quic"
                ]
                // "routeOnly": true
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom",
            "tag": "direct"
        }
    ]
}

2.2.3 nginx配置内容

# /etc/nginx/nginx.conf

# 指定nginx进程以哪个身份运行
user nginx;
# 使用多少个 worker 进程来处理请求。auto 表示 nginx 将根据可用的 CPU 核心数量自动确定工作进程的数量
worker_processes auto;

# 错误日志文件的路径和日志级别
error_log /etc/stderr debug; # 只记录notice级别的错误
# nginx 主进程的 PID 文件路径
pid /var/run/nginx.pid;

events {
    # 指定了每个 worker 进程的最大连接数; 
    worker_connections 1024;
}

stream {
    # 若接收到的SNI为伪装网站则传给xray, 否则阻断
    map $ssl_preread_server_name $backend {
        pytorch.org reality;
        default   close_connection;
    }
    upstream reality {
        server xray_server:4443;
    }
    upstream close_connection { 
        server 127.0.0.1:6767;
    }
    # 分析接收到请求的SNI
    server {
        # reuseport选项允许多个Nginx worker进程在同一个监听端口上同时接收连接; 可以帮助提高Nginx在高并发环境下的网络性能,特别是在多核系统上
        listen 443;
        listen [::]:443;
        proxy_pass      $backend;
        ssl_preread     on; # Enables extracting information from the ClientHello message at the preread phase
        proxy_protocol  on; # Enables the PROXY protocol for connections to a backend
    }
}


http {
    # 自定义的日志格式 main, 用于访问日志
    log_format main '[$time_local] $proxy_protocol_addr "$http_referer" "$http_user_agent"'; # [时间] 客户端地址 引用页 用户代理信息
    # 访问日志文件的路径和使用的日志格式
    access_log /var/log/nginx/access.log main;

    # 用于设置在 HTTP 升级时如何处理连接
    map $http_upgrade $connection_upgrade { 
        default upgrade; # 如果$http_upgrade存在且非空,则将$connection_upgrade设置为upgrade(用于WebSocket连接)
        ""      close; # 如果$http_upgrade为空,则将$connection_upgrade设置为close(关闭连接)
    } # 它在 HTTP 升级时将连接升级为 HTTP/2

	    # 用于处理代理协议头(Proxy Protocol)
    map $proxy_protocol_addr $proxy_forwarded_elem {
        ~^[0-9.]+$        "for=$proxy_protocol_addr"; # 如果$proxy_protocol_addr是IPv4地址(匹配正则表达式~^[0-9.]+$),则将其格式化为for=$proxy_protocol_addr
        ~^[0-9A-Fa-f:.]+$ "for=\"[$proxy_protocol_addr]\""; # 如果$proxy_protocol_addr是IPv6地址(匹配正则表达式~^[0-9A-Fa-f:.]+$),则将其格式化为for="[$proxy_protocol_addr]"
        default           "for=unknown"; # 如果地址格式不匹配上述两种情况,则设置为for=unknown
    } # 确保正确地传递客户端的真实 IP 地址

    # 用于处理 HTTP Forwarded 头;map $http_forwarded $proxy_add_forwarded: 使用map指令将现有的HTTP Forwarded头($http_forwarded)与新生成的代理协议元素($proxy_forwarded_elem)结合,生成新的$proxy_add_forwarded变量
    map $http_forwarded $proxy_add_forwarded {
        # 如果$http_forwarded已经存在且格式正确,则将新生成的$proxy_forwarded_elem追加到现有的$http_forwarded头中
        "~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";
        # 如果$http_forwarded不存在或格式不正确,则仅使用新生成的$proxy_forwarded_elem
        default "$proxy_forwarded_elem";
    }

    server {
        listen 80;
        listen [::]:80;
        return 301 https://$host$request_uri; #  当有 HTTP 请求时,强制重定向到 HTTPS
    }

    # 阻断部分
    server {
        # proxy_protocol:启用了PROXY协议。这意味着Nginx会期望收到来自代理服务器的连接,其中包含客户端的原始连接信息。这对于获取客户端的真实IP地址等信息是有用的
        listen  127.0.0.1:6767 ssl proxy_protocol;
        # ssl_reject_handshake on;:启用这个选项后,Nginx会在接收到客户端的SSL握手请求时立即关闭连接,而不执行实际的SSL握手。这对于拒绝不必要的或不被允许的SSL连接非常有用
        ssl_reject_handshake    on;
        # ssl_protocols TLSv1.2 TLSv1.3;:指定Nginx只支持TLS 1.2和TLS 1.3协议。这有助于确保连接使用现代、安全的加密协议,避免使用已知存在安全漏洞的旧版本TLS
        ssl_protocols              TLSv1.2 TLSv1.3;
    }
}

2.2.4 xray client配置内容

{
    "log": {
        // error 日志的级别
        "loglevel": "debug"
    },
    // 路由功能模块可以将入站数据按不同规则由不同的出站连接发出,以达到按需代理的目的
    "routing": {
        "domainStrategy": "IPIfNonMatch", // 当域名没有匹配任何规则时,将域名解析成 IP(A 记录或 AAAA 记录)再次进行匹配;
        // 域名匹配算法
        "domainMatcher": "hybrid", // 使用新的域名匹配算法,速度更快且占用更少
        // 匹配规则; TIPS: 当没有匹配到任何规则时,流量默认由第一个 outbound 发出
        "rules": [
            {
                "type": "field",
                // 数组每一项是一个域名的匹配
                "domain": [
                    "geosite:cn",
                    "geosite:private"
                ],
                // 对应一个 outbound 的标识
                "outboundTag": "direct"
            },
            {
                "type": "field",
                // 一个数组,数组内每一项代表一个 IP 范围
                "ip": [
                    "geoip:cn",
                    "geoip:private"
                ],
                "outboundTag": "direct"
            }
        ]
    },
    "inbounds": [
        {
            "listen": "0.0.0.0", // Fill in 0.0.0.0 to allow connections from LAN
            "port": 7891, // local socks listening port
            "protocol": "socks",
            "settings": {
                // 是否开启 UDP 协议的支持
                "udp": true // 开启UDP支持
            },
            // 流量探测
            "sniffing": {
                // 是否开启流量探测
                "enabled": true,
                // 当流量为指定类型时,按其中包括的目标地址重置当前连接的目标
                "destOverride": [
                    "http",
                    "tls",
                    "quic"
                ]
            }
        },
        {
            "listen": "0.0.0.0", // Fill in "0.0.0.0" to allow connections from LAN
            "port": 7890, // Local http listening port
            "protocol": "http",
            "sniffing": {
                "enabled": true,
                "destOverride": [
                    "http",
                    "tls",
                    "quic"
                ]
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "x.x.x.x", 
                        "port": 443, 
                        "users": [
                            {
                                "id": "3dc3b7b3-56c1-4d8a-9f15-a4831bf8f7a1", // Needs to match server side
                                "encryption": "none",
                                "flow": "xtls-rprx-vision"
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                // 连接的数据流所使用的传输方式类型
                "network": "tcp",
                // 是否启用传输层加密
                "security": "reality", // 表示使用 REALITY
                "realitySettings": {
                    "fingerprint": "chrome", 
                    "serverName": "pytorch.org", // A website that support TLS1.3 and h2.
                    "publicKey": "7QLvKnnIpzVG_27P3Ixy4BiL3pdLO_15AmoxEvdGSGM", // run `xray x25519` to generate. Public and private keys need to be corresponding.
                    "shortId": "d88a233765897aa6" // Required
                }
            },
            "tag": "proxy"
        },
        {
            "protocol": "freedom", // 可以用来向任意网络发送(正常的) TCP 或 UDP 数据
            "tag": "direct"
        },
        {
            "protocol": "blackhole", // 它会阻碍所有数据的出站,配合 路由配置 一起使用,可以达到禁止访问某些网站的效果
            "tag": "block"
        }
    ]
}

2.3 测试结果

无法正常fq

2.3.1 服务端log (nginx + xray server)

xray_server-1  | Xray 1.8.11 (Xray, Penetrates Everything.) Custom (go1.22.2 linux/amd64)
xray_server-1  | A unified platform for anti-censorship.
xray_server-1  | 2024/05/21 14:54:15 [Info] infra/conf/serial: Reading config: /etc/xray/config.jsonc
xray_server-1  | 2024/05/21 14:54:15 [Debug] app/log: Logger started
xray_server-1  | 2024/05/21 14:54:15 [Debug] app/proxyman/inbound: creating stream worker on 0.0.0.0:4443
xray_server-1  | 2024/05/21 14:54:15 [Info] transport/internet/tcp: listening TCP on 0.0.0.0:4443
xray_server-1  | 2024/05/21 14:54:15 [Warning] core: Xray 1.8.11 started
xray_server-1  | 2024/05/21 14:56:31 [Info] transport/internet/tcp: REALITY: processed invalid connection
...(由于太长无法发表issue,所以去掉了重复内容)
xray_server-1  | 2024/05/21 14:59:31 [Info] transport/internet/tcp: REALITY: processed invalid connection
nginx_server-1  | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
nginx_server-1  | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
nginx_server-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
nginx_server-1  | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
nginx_server-1  | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
nginx_server-1  | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
nginx_server-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
nginx_server-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
nginx_server-1  | /docker-entrypoint.sh: Configuration complete; ready for start up

2.3.2 客户端log (xray client)

startedxray_client-xray_server-1  | Xray 1.8.11 (Xray, Penetrates Everything.) Custom (go1.22.3 linux/amd64)
xray_client-xray_server-1  | A unified platform for anti-censorship.
xray_client-xray_server-1  | 2024/05/21 14:54:30 [Info] infra/conf/serial: Reading config: /etc/xray/client_config.jsonc
xray_client-xray_server-1  | 2024/05/21 14:54:30 [Debug] app/log: Logger started
xray_client-xray_server-1  | 2024/05/21 14:54:30 [Debug] app/router: MphDomainMatcher is enabled for 75384 domain rule(s)
xray_client-xray_server-1  | 2024/05/21 14:54:30 [Debug] app/proxyman/inbound: creating stream worker on 0.0.0.0:7891
xray_client-xray_server-1  | 2024/05/21 14:54:30 [Debug] app/proxyman/inbound: creating stream worker on 0.0.0.0:7890
xray_client-xray_server-1  | 2024/05/21 14:54:30 [Info] transport/internet/tcp: listening TCP on 0.0.0.0:7891
xray_client-xray_server-1  | 2024/05/21 14:54:30 [Info] transport/internet/udp: listening UDP on 0.0.0.0:7891
xray_client-xray_server-1  | 2024/05/21 14:54:30 [Info] transport/internet/tcp: listening TCP on 0.0.0.0:7890
xray_client-xray_server-1  | 2024/05/21 14:54:30 [Warning] core: Xray 1.8.11 started
xray_client-xray_server-1  | 2024/05/21 14:55:07 [Info] [1663647110] proxy/socks: TCP Connect request to tcp:api.github.com:443
xray_client-xray_server-1  | 2024/05/21 14:55:07 [Info] [3384687550] proxy/socks: TCP Connect request to tcp:collector.github.com:443
xray_client-xray_server-1  | 2024/05/21 14:55:07 [Info] [1663647110] app/dispatcher: sniffed domain: api.github.com
xray_client-xray_server-1  | 2024/05/21 14:55:07 [Info] [3384687550] app/dispatcher: sniffed domain: collector.github.com
xray_client-xray_server-1  | 2024/05/21 14:55:07 [Info] [3290573928] proxy/socks: TCP Connect request to tcp:www.google.com:443
xray_client-xray_server-1  | 2024/05/21 14:55:07 [Info] [3290573928] app/dispatcher: sniffed domain: www.google.com
xray_client-xray_server-1  | 2024/05/21 14:55:07 [Info] [3290573928] app/dispatcher: default route for tcp:www.google.com:443
xray_client-xray_server-1  | 2024/05/21 14:55:07 tcp:192.168.80.1:53524 accepted tcp:www.google.com:443 [proxy]
xray_client-xray_server-1  | 2024/05/21 14:55:07 [Info] [3290573928] transport/internet/tcp: dialing TCP to tcp:<my vps ip>:443
xray_client-xray_server-1  | 2024/05/21 14:55:07 [Debug] transport/internet: dialing to tcp:<my vps ip>:443
xray_client-xray_server-1  | 2024/05/21 14:55:08 [Info] [1663647110] app/dispatcher: default route for tcp:api.github.com:443
xray_client-xray_server-1  | 2024/05/21 14:55:08 [Info] [1663647110] transport/internet/tcp: dialing TCP to tcp:<my vps ip>:443
xray_client-xray_server-1  | 2024/05/21 14:55:08 [Debug] transport/internet: dialing to tcp:<my vps ip>:443
@Fangliding
Copy link
Member

不是仓库问题,请前往讨论区或者群聊讨论
不过要自己写也请至少知道你编写的配置文件的含义 网上有stream转发的模板 不要自信的拿个ai生成的玩意就怼上去

@Fangliding Fangliding closed this as not planned Won't fix, can't repro, duplicate, stale May 21, 2024
@chika0801
Copy link
Contributor

参考这里的 https://github.com/chika0801/Xray-examples/tree/main/VLESS-Vision-REALITY

偷自己或nginx前置sni分流,可能是你想要的

@scavenger-caesar
Copy link
Author

@Fangliding 好的,谢谢!@chika0801 我有参考过这里,没看太懂, 可以讨论区再请教一下吗

@chika0801
Copy link
Contributor

你去我发的那个仓库发个ISS问下了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants