Nginx + Xray + Hysteria2 搭建代理

1 week ago
0 comment

关于 Xray Reality 的一些讨论:

首先需要准备一个域名,指向服务器。这里假设是 example.com

目标:

  • 伪装网站使用 Nextcloud Docker,监听 8000/tcp
  • Xray 监听 8444/tcp
  • Hysteria 监听 8445/udp
  • Nginx 监听 80、443、8443 端口
  • 443/udp 流量全部转发给 Hysteria(8445/udp)
  • 443/tcp 使用 ssl_preread 判断请求 hostname,如果是 example.com 则流量直接转发到 Xray(8444/tcp);否则转发到 8443/tcp
  • 8443/tcp 负责所有站点访问请求,这里配置一个 Nextcloud(example.com)的反代,如果有其它正常建站需求也可以继续添加

几种访问路线:

  • Xray 客户端(看起来是访问 example.com) -> Nginx 443/tcp -> 转发到 Xray 8444/tcp -> 发现是合法代理连接,跑代理
  • 浏览器访问 example.com -> Nginx 443/tcp -> 转发到 Xray 8444/tcp -> 发现不是合法代理连接 -> 回落到 Nginx 8443/tcp -> 反代 Nextcloud
  • Hysteria 客户端(看起来是 h3 访问 example.com) -> Nginx 443/udp -> 转发到 Hysteria 8445/udp -> 发现是合法代理连接,跑代理
  • H3 访问 example.com -> Nginx 443/udp -> 转发到 Hysteria 8445/udp -> 发现不是合法代理连接 -> 返回 Nextcloud 内容

Ubuntu 安装 Docker:官方教程

# Add Docker's official GPG key:
apt update
apt install ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF

apt update

apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

检查 Docker 安装是否成功:

docker run hello-world

安装 Nextcloud(宿主机 8000 端口):

docker run --name=nextcloud -d --restart=unless-stopped -p 8000:80 nextcloud

安装 Nginx:

apt install nginx-full

修改 /etc/nginx/nginx.conf(可在 http 上方添加):

stream {
    map $ssl_preread_server_name $backend_name {
        hostnames;
        example.com xray_backend;

        default site_backend;
    }

    upstream xray_backend {
        server 127.0.0.1:8444;
    }

    upstream site_backend {
        server 127.0.0.1:8443;
    }

    server {
        listen 443;
        proxy_pass $backend_name;
        ssl_preread on;
    }

    server {
        listen 443 udp reuseport;
        listen [::]:443 udp reuseport;

        proxy_pass 127.0.0.1:8445;
        proxy_timeout 20s;
    }
}

http 中添加:

        map $http_upgrade $connection_upgrade {
            default upgrade;
            ''      close;
        }

重启 Nginx:

service nginx restart

安装 Certbot:

apt install certbot python3-certbot-nginx

申请证书:

certbot certonly --nginx -d example.com

配置 Nginx 8443 服务(/etc/nginx/sites-available/example.com.conf):

server {
    listen 80;
    server_name example.com;

    location ^~ /.well-known/acme-challenge/ {
        root /var/www/certbot;
        default_type "text/plain";
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    server_name example.com;

    listen 127.0.0.1:8443 ssl http2;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://127.0.0.1:8000;

        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

创建软连接:

ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.conf

重启 Nginx:

service nginx restart

安装 Xray:

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

生成 uuid:

xray uuid

生成密钥对:

xray x25519

生成 shortId:

openssl rand -hex 8

编辑配置文件 /usr/local/etc/xray/config.json(基于官方示例):

{
  "log": {
    "loglevel": "warning"
  },
  "routing": { // blocking data outbound to China
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "ip": [
          "geoip:cn"
        ],
        "outboundTag": "block"
      }
    ]
  },
  "inbounds": [
    {
      "listen": "0.0.0.0",
      "port": 8444,
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "", // run `xray uuid` to generate
            "flow": "xtls-rprx-vision"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "dest": ":8443",
          "serverNames": [
            "example.com" // change to your domain
          ],
          "privateKey": "", // run `xray x25519` to generate. Public and private keys need to be corresponding.
          "shortIds": [
            "0123456789abcdef" // 0 to f, length is a multiple of 2, maximum length is 16, generate with `openssl rand -hex <1-8>`
          ]
        }
      },
      "sniffing": {
        "enabled": true,
        "destOverride": [
          "http",
          "tls",
          "quic"
        ]
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "tag": "direct"
    },
    {
      "protocol": "blackhole",
      "tag": "block"
    }
  ]
}

重启 Xray 服务:

service xray restart

到这里,你的 Xray 应该已经可以用了。

安装 Hysteria2:

bash <(curl -fsSL https://get.hy2.sh/)

修改配置文件:

listen: :8445

tls:
  cert: /etc/letsencrypt/live/example.com/fullchain.pem
  key:  /etc/letsencrypt/live/example.com/privkey.pem

auth:
  type: password
  password: "" # your password here

masquerade:
  type: proxy
  proxy:
    url: https://example.com
    rewriteHost: true
    insecure: false

重启前,需要先让 hysteria 用户能读取证书。安装 acl:

apt install acl

设置目录权限(续签默认提供权限):

setfacl -m u:hysteria:rx /etc
setfacl -m u:hysteria:rx /etc/letsencrypt
setfacl -m u:hysteria:rx /etc/letsencrypt/{live,archive}
setfacl -m u:hysteria:rx /etc/letsencrypt/live/example.com
setfacl -d -m u:hysteria:r /etc/letsencrypt/archive/example.com

设置证书只读权限:

setfacl -m u:hysteria:r /etc/letsencrypt/archive/example.com/*.pem

最后,还要弄一下证书更新自动重启 Nginx 和 Hysteria。修改 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx-hysteria2.sh

#!/usr/bin/env bash
set -e

echo "[certbot] Reload nginx"
systemctl reload nginx

echo "[certbot] Restart hysteria-server"
systemctl restart hysteria-server

保存即可。

至此,所有东西就搞定了。