Nginx 前置 Xray vless-tls-ws 配置及优化方案

Xray-core 官方配置文件样本中并没有包含 Nginx 前置配置方案,主要原因在于作者开发并推广了 Xray 回落机制。此举也是为了便于 xtls 的部署及应用(Nginx 前置反向代理无法实现 xtls-tcp 方案)。

鉴于安全性考虑,为了规避 Go TLS 指纹特征。在此,小编推荐采用 Nginx 前置反向代理 Xray 方案。本文就来整理一份 Nginx 前置代理 Xray vless-tls-ws 方案的配置文件供大家参考。

在本方案中,Xray-core 只需提供 vless + ws 服务,TLS 交给 Nginx 处理便可。另外针对本配置组合给出性能及安全性优化方法。本文假设各位已申请到域名,并已成功获得CA签发的证书(比如 Let’s Encrypt
免费证书)。

Xray 配置

在 Xray-core 中部署 vless + ws 服务。

配置文件如下:

{
    "log": {
        "loglevel": "warning",
        "error": "/var/log/xray/error.log"
    },
    "inbounds": [
        {
            "listen": "/dev/shm/xray_ws.sock,666",
            "protocol": "vless",
            "settings": {
                "clients": [
                    {
                        "id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
                        "level": 0,
                        "email": "[email protected]"
                    }
                ],
                "decryption":"none"
            },
            "streamSettings": {
                "network": "ws",
                "security": "none",
                "wsSettings": {
                    "path": "/xxxxxxxx"
                }
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom",
            "tag": "direct"
        },
        {
            "protocol": "blackhole",
            "tag": "block"
        }
    ]
}

鉴于安全考虑,为避免 VPS IP地址暴露在 CN 环境中遭封锁,可以在 Xray 服务端添加分流规则拒绝代理该区域所属域名及IP(为保证访问畅通性,只需在客户端配置规则直连该区域即可)。

Xray-core 配置文件如下:

{
    "log": {
        "loglevel": "warning",
        "error": "/var/log/xray/error.log"
    },
    "routing": {
        "domainStrategy": "IPIfNonMatch",
        "domainMatcher": "mph",
        "rules": [
            {
                "type": "field",
                "ip": [
                    "geoip:cn",
                    "geoip:private"
                ],
                "outboundTag": "block"
            },
            {
                "type": "field",
                "domain": [
                    "geosite:cn"
                ],
                "outboundTag": "block"
            }
        ]
    },
    "inbounds": [
        {
            "listen": "/dev/shm/xray_ws.sock,666",
            "protocol": "vless",
            "settings": {
                "clients": [
                    {
                        "id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
                        "level": 0,
                        "email": "[email protected]"
                    }
                ],
                "decryption":"none"
            },
            "streamSettings": {
                "network": "ws",
                "security": "none",
                "wsSettings": {
                    "path": "/xxxxxxxx"
                }
            },
            "sniffing": {
                "enabled": true,
                "destOverride": [
                "http",
                "tls"
                ],
               "metadataOnly": true
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom",
            "tag": "direct"
        },
        {
            "protocol": "blackhole",
            "tag": "block"
        }
    ]
}

如果 VPS 支持双栈,在以上基础上想分别针对 IPV4 以及 IPV6进行分流(例如想使用 IPV6 地址解锁 Netflix 以及 Disney 流媒体)。

配置如下:

{
    "log": {
        "loglevel": "warning",
        "error": "/var/log/xray/error.log"
    },
    "routing": {
        "domainStrategy": "IPIfNonMatch",
        "domainMatcher": "mph",
        "rules": [
            {
                "type": "field",
                "ip": [
                    "geoip:cn",
                    "geoip:private"
                ],
                "outboundTag": "block"
            },
            {
                "type": "field",
                "domain": [
                    "geosite:cn"
                ],
                "outboundTag": "block"
            },
            {
                "type": "field",
                "domain": [
                    "geosite:netflix",
                    "geosite:disney"
                ],
                "outboundTag": "ipv6-direct"
            }
        ]
    },
    "inbounds": [
        {
            "listen": "/dev/shm/xray_ws.sock,666",
            "protocol": "vless",
            "settings": {
                "clients": [
                    {
                        "id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
                        "level": 0,
                        "email": "[email protected]"
                    }
                ],
                "decryption":"none"
            },
            "streamSettings": {
                "network": "ws",
                "security": "none",
                "wsSettings": {
                    "path": "/xxxxxxxx"
                }
            },
            "sniffing": {
                "enabled": true,
                "destOverride": [
                "http",
                "tls"
                ],
               "metadataOnly": true
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom",
            "tag": "direct"
        },
        {
            "protocol": "freedom",
            "settings": {
                "domainStrategy": "UseIPv6"
            },
            "tag": "ipv6-direct"
        },
        {
            "protocol": "blackhole",
            "tag": "block"
        }
    ]
}

Xray-core 配置部分完成,在实际部署中,不要忘记将以上 "id": " 以及 "path" 中 xxxxx 部分修改为自己实际参数。需要注意,考虑效率原因,以上配置文件使用了 Unix Socket 服务监听方式。

语句

“listen”: “/dev/shm/xray_ws.sock,666”

中 666 为解决访问权限问题(domain socket permission),需要 Xray-core v1.5.4 及以上版本支持。当然,也可以采用监听 IP 地址以及端口的形式(对应 Nginx 配置也需要修改)。

Nginx 配置

在 Nginx 配置文件 nginx.conf 中 http 末尾添加如下配置:

    upstream  XRAY {
        server unix:/dev/shm/xray_ws.sock;
        keepalive 500;
        keepalive_timeout 7d;
        keepalive_requests 100000;
    }

在 sites-availabe 目录站点配置文件 default 或对应文件 server 部分添加以下配置:

        location /xxxxxxxx { 
                if ($http_upgrade != "websocket") {
                    return 404;
                }

                client_body_timeout 300;
                proxy_connect_timeout 10;
                proxy_read_timeout 1d;
                proxy_send_timeout 1d;
                proxy_set_header Connection "";
                proxy_request_buffering off;
                proxy_pass_request_body off;
                proxy_redirect off;
                proxy_buffering off;
                proxy_pass http://XRAY;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $http_host;

                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

注意,以上 location /xxxxxxxx 需与 Xray-core 中 path 配置保持一致

在实际部署中,我们还需要对 Nginx 性能以及安全性进行优化。开启 http2 支持,TLS 只采用 1.2 及以上版本,ssl_ciphers 也需要优先采用性能以及安全性较高的加密算法。开启 ssl_early_datassl_stapling 以及 ssl_session_cache 等。

完整配置如下:

Nginx http 部分 nginx.conf 配置

user  nginx;
worker_processes  auto;

worker_rlimit_nofile 100000;

error_log  /var/log/nginx/error.log error;
pid        /var/run/nginx.pid;


events {
    worker_connections  4000;
    use epoll;
    multi_accept on;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  off;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;
    server_tokens   off;

    reset_timedout_connection on;
   
    keepalive_timeout  300s;
    keepalive_requests 100000;
    types_hash_max_size 2048;

    ##
    # SSL Settings
    ##
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout 4h;
    ssl_session_tickets off;
    ssl_early_data on;

    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /path/to/your/domain/fullchain.pem;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    ssl_buffer_size 4k;

    ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

    gzip  off;

    upstream  XRAY {
        server unix:/dev/shm/xray_ws.sock;
        keepalive 500;
        keepalive_timeout 7d;
        keepalive_requests 100000;
    }

    #include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

注意,开启 ssl_stapling 后,需将 ssl_trusted_certificate /path/to/your/domain/fullchain.pem 替换为您实际证书路径。

Nginx server 部分配置

为提高网站安全性,防止针对 IP地址 443 端口请求产生的证书泄露,可开启Nginx ssl_reject_handshake 配置项。注意,该配置项只有在 Nginx 1.19.4 及以上版本受得到支持。

server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;

        ssl_reject_handshake on;
}

完整配置:

server {
        #listen 80 default_server;
        #listen [::]:80 default_server;

        # SSL configuration
        #
        listen 443 ssl http2 so_keepalive=on;
        listen [::]:443 ssl http2 so_keepalive=on;

        server_name domain.name;

        access_log off;

        client_header_timeout 300;

        ssl_certificate /path/to/your/domain/fullchain.pem;
        ssl_certificate_key /path/to/your/domain/privkey.pem;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        location /xxxxxx { 
                if ($http_upgrade != "websocket") {
                    return 404;
                }

                client_body_timeout 300;
                proxy_connect_timeout 10;
                proxy_read_timeout 1d;
                proxy_send_timeout 1d;
                proxy_set_header Connection "";
                proxy_request_buffering off;
                proxy_pass_request_body off;
                proxy_redirect off;
                proxy_buffering off;
                proxy_pass http://XRAY;
                proxy_http_version 1.1;
                proxy_set_header Early-Data $ssl_early_data;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $http_host;

                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;

        ssl_reject_handshake on;
}

注意,将以上配置文件中配置项 server_namessl_certificatessl_certificate_keyrootlocation /xxxxxx 替换为您的实际配置。/xxxxxx 需与 Xray-core 配置中 path 保持一致。