这篇文章记录一套我更愿意在新 VPS 上采用的部署顺序:先把 SSH 登录、系统更新和防火墙收紧,再部署 Nginx、证书和 Xray,最后从服务器内外分别验证。
全文基于 Debian 13(trixie),目标是搭建下面这套结构:
1
2
3
4
5
6
7
| 公网 80/tcp -> Nginx(HTTP 页面)
公网 443/tcp -> Xray(VLESS + REALITY + Vision)
|
+-> 127.0.0.1:8443
Nginx HTTPS 回落站点
公网 42345/tcp -> OpenSSH(示例端口)
|
它不是一键脚本。每一步都保留了检查命令,方便在真正修改服务之前确认状态,也方便出问题时定位和回滚。
请只在你拥有或获准管理的服务器上使用本文配置,并遵守所在地法律及服务商条款。
开始前先统一变量#
文中使用以下占位值,请先替换成自己的信息:
1
2
3
4
5
6
| 服务器公网 IPv4:YOUR_SERVER_IP
普通登录用户:youruser
SSH 新端口:42345
主域名:domain.com
REALITY 子域名:x.domain.com
ACME 邮箱:[email protected]
|
本文让 Xray 只监听 IPv4,因此 x.domain.com 应配置一条指向 VPS 公网 IPv4 的 A 记录,并在 Cloudflare 中设为 DNS only(灰云)。
如果你还没有为 Xray 配置 IPv6 监听,不要给这个子域名添加 AAAA 记录。否则支持 IPv6 的客户端可能优先连到一个没有服务监听的地址。
云厂商的安全组、网络 ACL 与 VPS 内的 UFW 是两层限制。后文涉及的端口需要在两边都放行:
42345/tcp:SSH 示例端口;80/tcp:Nginx HTTP;443/tcp:Xray REALITY;8443/tcp:只监听回环地址,不要对公网放行。
第一部分:Debian 13 与 SSH 安全加固#
1. 保留旧会话,先创建普通管理员用户#
整个 SSH 加固过程中都不要关闭当前窗口。改完后用第二个终端测试新端口;只有密钥登录与 sudo 都正常,才退出旧会话。
如果 VPS 初始只允许 root 登录,先创建普通用户:
1
2
3
4
| adduser youruser
usermod -aG sudo youruser
su - youruser
sudo whoami
|
最后一条命令应输出:
2. 在本地生成并上传 SSH 密钥#
下面的命令在本地电脑执行:
1
2
3
| ssh-keygen -t ed25519 -a 100 \
-f ~/.ssh/debian13_ed25519 \
-C "debian13-server"
|
建议为私钥设置强口令。生成的私钥绝不能上传或分享:
1
2
| ~/.ssh/debian13_ed25519 # 私钥
~/.ssh/debian13_ed25519.pub # 公钥
|
将公钥复制到服务器:
1
2
| ssh-copy-id -i ~/.ssh/debian13_ed25519.pub \
-p 22 youruser@YOUR_SERVER_IP
|
如果本地没有 ssh-copy-id:
1
2
3
| ssh -p 22 youruser@YOUR_SERVER_IP \
'umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys' \
< ~/.ssh/debian13_ed25519.pub
|
在另一个本地终端中确认密钥可以登录:
1
2
| ssh -i ~/.ssh/debian13_ed25519 \
-p 22 youruser@YOUR_SERVER_IP
|
此时先不要禁用密码登录。
3. 更新系统并安装基础组件#
回到服务器执行:
1
2
3
4
5
6
| sudo apt update
sudo apt full-upgrade -y
sudo apt install -y \
openssh-server ufw fail2ban python3-systemd \
curl wget ca-certificates openssl jq unzip tar \
nginx socat cron dnsutils
|
如果系统升级了内核,先确认没有未完成的配置,再在合适的维护窗口重启:
1
2
| sudo dpkg --audit
test -f /var/run/reboot-required && cat /var/run/reboot-required
|
4. 备份 SSH 配置#
1
2
3
4
5
6
| sudo mkdir -p /root/ssh-hardening-backup
sudo cp -a /etc/ssh/sshd_config \
/root/ssh-hardening-backup/sshd_config.bak.$(date +%F-%H%M%S)
sudo cp -a /etc/ssh/sshd_config.d \
/root/ssh-hardening-backup/sshd_config.d.bak.$(date +%F-%H%M%S)
sudo ls -lah /root/ssh-hardening-backup
|
5. 先放行新端口,再启用 UFW#
先到云厂商控制台放行 42345/tcp,然后在服务器执行:
1
2
3
4
5
6
7
8
9
10
| NEW_SSH_PORT=42345
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'TEMP old SSH port'
sudo ufw allow ${NEW_SSH_PORT}/tcp comment 'SSH high port'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'Xray REALITY'
sudo ufw enable
sudo ufw status verbose
|
如果你有固定公网 IP,可以把 SSH 规则进一步收紧:
1
2
3
4
| sudo ufw delete allow ${NEW_SSH_PORT}/tcp
sudo ufw allow from YOUR_PUBLIC_IP \
to any port ${NEW_SSH_PORT} proto tcp \
comment 'SSH from my IP'
|
家庭宽带公网 IP 经常变化时不要这样做,否则可能把自己挡在服务器外。
6. 使用 drop-in 加固 sshd#
Debian 会在主配置开头加载 /etc/ssh/sshd_config.d/*.conf。OpenSSH 对大多数选项采用“首次取值生效”,而通配文件又按字典序加载,因此这里使用 00-hardening.conf。
1
2
3
4
5
6
7
8
9
10
11
12
| NEW_SSH_PORT=42345
sudo tee /etc/ssh/sshd_config.d/00-hardening.conf >/dev/null <<EOF
Port ${NEW_SSH_PORT}
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PermitEmptyPasswords no
MaxAuthTries 3
X11Forwarding no
EOF
|
如果普通用户还不能稳定登录并使用 sudo,先不要禁用 root。可以临时改为:
1
| PermitRootLogin prohibit-password
|
7. 先验证,再重新加载#
检查语法:
没有输出通常表示语法正确。再查看最终生效值:
1
2
| sudo sshd -T | grep -E \
'^(port|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin|permitemptypasswords|maxauthtries|x11forwarding) '
|
预期结果包括:
1
2
3
4
5
6
7
8
| port 42345
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
permitrootlogin no
permitemptypasswords no
maxauthtries 3
x11forwarding no
|
如果值不一致,先检查全部配置来源:
1
2
3
| sudo grep -RniE \
'^(Port|PubkeyAuthentication|PasswordAuthentication|KbdInteractiveAuthentication|PermitRootLogin|AllowUsers|Match)' \
/etc/ssh/sshd_config /etc/ssh/sshd_config.d/
|
确认无误后重新加载:
1
2
| sudo systemctl reload ssh
sudo systemctl status ssh --no-pager
|
如果失败,可在仍然存活的旧会话中回滚:
1
2
3
4
| sudo mv /etc/ssh/sshd_config.d/00-hardening.conf \
/root/ssh-hardening-backup/00-hardening.conf.disabled
sudo systemctl reload ssh
sudo journalctl -u ssh -n 80 --no-pager
|
8. 用第二个终端验证新登录方式#
在本地新开一个终端:
1
2
| ssh -i ~/.ssh/debian13_ed25519 \
-p 42345 youruser@YOUR_SERVER_IP
|
登录后检查:
1
2
| sudo whoami
sudo ss -tlnp | grep sshd
|
再从本地确认密码认证已关闭:
1
2
3
| ssh -o PubkeyAuthentication=no \
-o PreferredAuthentications=password \
-p 42345 youruser@YOUR_SERVER_IP
|
预期结果是 Permission denied (publickey)。
只有新端口登录、密钥认证和 sudo 三项都确认正常后,才删除 22 端口规则:
1
2
| sudo ufw delete allow 22/tcp
sudo ufw status verbose
|
同时删除云厂商安全组中的 22/tcp 入站规则。
9. 配置 Fail2Ban#
不要直接修改 Fail2Ban 自带的 .conf 文件,把本地覆盖写入 .local:
1
2
3
4
5
6
7
8
9
10
11
12
13
| NEW_SSH_PORT=42345
sudo tee /etc/fail2ban/jail.d/sshd.local >/dev/null <<EOF
[sshd]
enabled = true
port = ${NEW_SSH_PORT}
filter = sshd
backend = systemd
banaction = ufw
maxretry = 5
findtime = 10m
bantime = 1h
EOF
|
如果你有固定公网 IP,可以在 [sshd] 下增加白名单:
1
| ignoreip = 127.0.0.1/8 ::1 YOUR_PUBLIC_IP/32
|
检查并启动:
1
2
3
4
| sudo fail2ban-server -t
sudo systemctl enable --now fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd
|
10. 配置本地 SSH 别名#
在本地编辑 ~/.ssh/config:
Host debian13-server
HostName YOUR_SERVER_IP
User youruser
Port 42345
IdentityFile ~/.ssh/debian13_ed25519
IdentitiesOnly yes
以后直接执行:
修改端口主要是减少扫描日志里的噪音,真正的安全边界仍然是密钥认证、禁用 root 远程登录、及时更新、最小化暴露端口和持续监控。
第二部分:准备 Nginx 与证书#
1. 核对 DNS、端口和服务#
1
2
3
4
5
6
7
8
| DOMAIN=domain.com
SITE_DOMAIN=x.domain.com
dig +short A "$SITE_DOMAIN"
dig +short AAAA "$SITE_DOMAIN"
curl -4 ifconfig.me; echo
sudo ss -tulpen | grep -E ':(80|443|8443|42345)\s' || true
sudo ufw status numbered
|
检查点:
A 记录应指向当前服务器公网 IPv4;- 本文的 IPv4-only 方案不应存在
AAAA 记录; 80 可以由 Nginx 监听;443 与 8443 此时应未被占用;- Cloudflare 中
x.domain.com 必须为灰云。
启动 Nginx 与 cron:
1
2
| sudo systemctl enable --now nginx cron
sudo systemctl status nginx cron --no-pager
|
2. 创建最小权限的 Cloudflare API Token#
在 Cloudflare 控制台创建 API Token,权限限定为:
1
2
3
| Zone - DNS - Edit
Zone - Zone - Read
Zone Resources - Include - Specific zone - domain.com
|
不要使用权限过大的 Global API Key。
进入 root shell,并设置非敏感变量:
安装 acme.sh:
1
2
3
4
| curl https://get.acme.sh | sh -s email="$EMAIL"
ACME=/root/.acme.sh/acme.sh
$ACME --version
$ACME --set-default-ca --server letsencrypt
|
Token 不要直接写在命令行中,否则容易进入 shell history。使用隐藏输入:
1
2
3
| read -rsp 'Cloudflare API Token: ' CF_Token
echo
export CF_Token
|
3. 签发并安装通配符证书#
1
2
3
4
5
6
| $ACME --register-account -m "$EMAIL"
$ACME --issue \
--dns dns_cf \
-d "$DOMAIN" \
-d "*.$DOMAIN" \
-k ec-256
|
为 Nginx 创建稳定的证书路径:
1
2
3
4
5
6
7
8
9
10
11
12
13
| CERT_DIR=/etc/nginx/ssl/$DOMAIN
mkdir -p "$CERT_DIR"
chmod 700 "$CERT_DIR"
$ACME --install-cert \
-d "$DOMAIN" \
--ecc \
--key-file "$CERT_DIR/privkey.pem" \
--fullchain-file "$CERT_DIR/fullchain.pem" \
--reloadcmd "systemctl reload nginx"
chmod 600 "$CERT_DIR/privkey.pem"
chmod 644 "$CERT_DIR/fullchain.pem"
|
验证证书的 SAN:
1
2
3
| openssl x509 \
-in "$CERT_DIR/fullchain.pem" \
-noout -subject -issuer -dates -ext subjectAltName
|
结果必须包含:
1
2
| DNS:domain.com
DNS:*.domain.com
|
acme.sh 会把续期所需的 Cloudflare 凭据保存到自己的账户配置。收紧权限并移除当前 shell 变量:
1
2
3
| chmod 600 /root/.acme.sh/account.conf
chmod 700 /root/.acme.sh
unset CF_Token
|
检查自动续期任务:
1
2
| crontab -l
$ACME --cron --home /root/.acme.sh
|
4. 配置本机 HTTPS 回落站点#
创建站点目录:
1
2
3
4
5
6
| WEB_ROOT=/var/www/$SITE_DOMAIN
CERT_DIR=/etc/nginx/ssl/$DOMAIN
mkdir -p "$WEB_ROOT"
chown -R www-data:www-data "$WEB_ROOT"
chmod 755 "$WEB_ROOT"
|
写入一个普通静态首页:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| tee "$WEB_ROOT/index.html" >/dev/null <<EOF
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>$SITE_DOMAIN</title>
<style>
body { max-width: 720px; margin: 80px auto; padding: 0 24px;
font-family: system-ui, sans-serif; line-height: 1.6; color: #222; }
</style>
</head>
<body>
<h1>$SITE_DOMAIN</h1>
<p>This site is running normally.</p>
</body>
</html>
EOF
|
备份并创建 Nginx 站点配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
| mkdir -p /root/nginx-backup
cp -a /etc/nginx/sites-available \
/root/nginx-backup/sites-available.$(date +%F-%H%M%S)
cp -a /etc/nginx/sites-enabled \
/root/nginx-backup/sites-enabled.$(date +%F-%H%M%S)
tee /etc/nginx/sites-available/$SITE_DOMAIN.conf >/dev/null <<EOF
server {
listen 80;
listen [::]:80;
server_name $SITE_DOMAIN;
root $WEB_ROOT;
index index.html;
location / {
try_files \$uri \$uri/ =404;
}
}
# --------------------------------------------------
# 默认 TLS 拒绝服务器
# 任何没有匹配到明确 server_name 的 TLS 握手都会在这里被拒绝
# --------------------------------------------------
server {
listen 127.0.0.1:8443 ssl default_server;
ssl_reject_handshake on;
access_log off;
}
# --------------------------------------------------
# 合法伪装站点
# 只有 SNI 为 mydomain.com 时才进入这里
# --------------------------------------------------
server {
listen 127.0.0.1:8443 ssl;
http2 on;
server_name $SITE_DOMAIN;
root $WEB_ROOT;
index index.html;
ssl_certificate $CERT_DIR/fullchain.pem;
ssl_certificate_key $CERT_DIR/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
access_log /var/log/nginx/$SITE_DOMAIN.8443.access.log;
error_log /var/log/nginx/$SITE_DOMAIN.8443.error.log;
location / {
try_files \$uri \$uri/ =404;
}
}
EOF
ln -sfn /etc/nginx/sites-available/$SITE_DOMAIN.conf \
/etc/nginx/sites-enabled/$SITE_DOMAIN.conf
|
检查、加载并验证:
1
2
3
4
5
6
7
| nginx -t
systemctl reload nginx
ss -tulpen | grep -E ':(80|443|8443)\s' || true
curl -I "http://$SITE_DOMAIN/"
curl -I --resolve "$SITE_DOMAIN:8443:127.0.0.1" \
"https://$SITE_DOMAIN:8443/"
|
此时应看到公网 80 由 Nginx 监听、127.0.0.1:8443 由 Nginx 监听,公网 443 仍为空闲。8443 不应出现在 0.0.0.0 或公网网卡上。
第三部分:部署 Xray VLESS + REALITY#
1. 安装 Xray-core#
以下步骤继续在 root shell 中执行。官方安装脚本默认让 Xray 以 nobody 用户运行:
1
2
3
4
5
6
7
| bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
command -v xray
xray version
systemctl cat xray --no-pager | head -n 80
systemctl stop xray
systemctl enable xray
|
安装后的主要路径通常是:
1
2
3
4
| /usr/local/bin/xray
/usr/local/etc/xray/config.json
/etc/systemd/system/xray.service
/var/log/xray/
|
2. 生成并保存连接参数#
1
2
| XRAY_UUID=$(xray uuid)
xray x25519
|
当前版本通常输出 PrivateKey、Password 和 Hash32。这里的 Password 实际由服务端私钥派生,供 REALITY 客户端持有;旧版本可能仍把它标成 PublicKey。
把输出中的 PrivateKey 与 Password 分别填入变量:
1
2
3
4
5
6
7
8
| REALITY_PRIVATE_KEY='粘贴 Private key'
REALITY_PASSWORD='粘贴 Password(旧版本为 Public key)'
REALITY_SHORT_ID=$(openssl rand -hex 8)
echo "UUID: $XRAY_UUID"
echo "Private key prefix: ${REALITY_PRIVATE_KEY:0:6}******"
echo "Password prefix: ${REALITY_PASSWORD:0:6}******"
echo "Short ID: $REALITY_SHORT_ID"
|
保存到仅 root 可读的参数文件:
1
2
3
4
5
6
7
8
9
10
11
12
| cat > /root/xray-reality-params.sh <<EOF
XRAY_UUID='$XRAY_UUID'
REALITY_PRIVATE_KEY='$REALITY_PRIVATE_KEY'
REALITY_PASSWORD='$REALITY_PASSWORD'
REALITY_SHORT_ID='$REALITY_SHORT_ID'
SERVER_NAME='x.domain.com'
REALITY_TARGET='127.0.0.1:8443'
LISTEN_PORT='443'
FLOW='xtls-rprx-vision'
EOF
chmod 600 /root/xray-reality-params.sh
|
注意:服务端配置使用 PrivateKey;客户端使用对应的 Password。不要把 PrivateKey 写入分享链接或客户端配置,也不要公开发布完整的客户端连接参数。
3. 写入服务端配置#
先再次确认 443 没有被其他程序占用:
1
| ss -tulpen | grep -E ':(80|443|8443)\s' || true
|
载入参数并备份原配置:
1
2
3
4
| source /root/xray-reality-params.sh
mkdir -p /root/xray-backup
cp -a /usr/local/etc/xray \
/root/xray-backup/xray.$(date +%F-%H%M%S)
|
写入 /usr/local/etc/xray/config.json:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
| cat > /usr/local/etc/xray/config.json <<EOF
{
"log": {
"loglevel": "warning",
"access": "/var/log/xray/access.log",
"error": "/var/log/xray/error.log"
},
"inbounds": [
{
"tag": "vless-reality-in",
"listen": "0.0.0.0",
"port": ${LISTEN_PORT},
"protocol": "vless",
"settings": {
"clients": [
{
"id": "${XRAY_UUID}",
"flow": "${FLOW}",
"email": "main-user"
}
],
"decryption": "none"
},
"streamSettings": {
"method": "raw",
"security": "reality",
"realitySettings": {
"show": false,
"target": "${REALITY_TARGET}",
"xver": 0,
"serverNames": ["${SERVER_NAME}"],
"privateKey": "${REALITY_PRIVATE_KEY}",
"shortIds": ["${REALITY_SHORT_ID}"]
}
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"],
"routeOnly": true
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"protocol": ["bittorrent"],
"outboundTag": "block"
}
]
}
}
EOF
|
官方安装脚本默认使用 User=nobody。在 Debian 中让配置归 root:nogroup、权限为 640,既能让服务读取,又避免其他普通用户直接读取 UUID 与 REALITY 私钥:
1
2
3
| chown root:nogroup /usr/local/etc/xray/config.json
chmod 640 /usr/local/etc/xray/config.json
systemctl show xray -p User -p Group
|
如果你改过 systemd 服务用户或组,请让配置的组与实际运行组一致,不要机械照抄 nogroup。
4. 验证并启动 Xray#
先测试配置,不要直接重启:
1
| xray run -test -config /usr/local/etc/xray/config.json
|
看到 Configuration OK. 后再启动:
1
2
3
| systemctl restart xray
systemctl status xray --no-pager
ss -tulpen | grep -E ':(80|443|8443)\s' || true
|
最终应为:
1
2
3
| 80 -> Nginx
0.0.0.0:443 -> Xray
127.0.0.1:8443 -> Nginx
|
测试非 REALITY 请求是否能由 Xray 转到本机 Nginx:
1
2
3
4
| source /root/xray-reality-params.sh
curl -I --resolve "$SERVER_NAME:443:127.0.0.1" \
"https://$SERVER_NAME/"
|
如果失败,查看:
1
2
| journalctl -u xray -n 100 --no-pager
tail -n 80 /var/log/nginx/x.domain.com.8443.error.log
|
最后在本地电脑测试公网访问:
1
| curl -I https://x.domain.com/
|
普通浏览器访问应看到前面创建的静态页面。
第四部分:生成客户端配置#
1. VLESS URI#
在服务器 root shell 中执行:
1
2
3
4
5
6
7
8
| source /root/xray-reality-params.sh
cat > /root/xray-client-uri.txt <<EOF
vless://${XRAY_UUID}@${SERVER_NAME}:${LISTEN_PORT}?encryption=none&flow=${FLOW}&security=reality&sni=${SERVER_NAME}&fp=chrome&pbk=${REALITY_PASSWORD}&sid=${REALITY_SHORT_ID}&type=tcp&headerType=none#${SERVER_NAME}-reality
EOF
chmod 600 /root/xray-client-uri.txt
cat /root/xray-client-uri.txt
|
不同客户端对分享 URI 的兼容性不完全一致。如果导入失败,可以手动填写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| 协议:VLESS
地址:x.domain.com
端口:443
UUID:XRAY_UUID
加密:none
传输:TCP / RAW
安全:REALITY
Flow:xtls-rprx-vision
SNI:x.domain.com
Fingerprint:chrome
Password / Public Key:REALITY_PASSWORD(名称以客户端 UI 为准)
Short ID:REALITY_SHORT_ID
Allow insecure:false
UDP:true
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| source /root/xray-reality-params.sh
cat > /root/xray-mihomo-proxy.yaml <<EOF
- name: "${SERVER_NAME}-reality"
type: vless
server: ${SERVER_NAME}
port: ${LISTEN_PORT}
uuid: ${XRAY_UUID}
network: tcp
udp: true
tls: true
flow: ${FLOW}
servername: ${SERVER_NAME}
client-fingerprint: chrome
reality-opts:
public-key: ${REALITY_PASSWORD}
short-id: ${REALITY_SHORT_ID}
EOF
chmod 600 /root/xray-mihomo-proxy.yaml
cat /root/xray-mihomo-proxy.yaml
|
3. sing-box outbound 片段#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| source /root/xray-reality-params.sh
cat > /root/xray-singbox-outbound.json <<EOF
{
"type": "vless",
"tag": "${SERVER_NAME}-reality",
"server": "${SERVER_NAME}",
"server_port": ${LISTEN_PORT},
"uuid": "${XRAY_UUID}",
"flow": "${FLOW}",
"packet_encoding": "xudp",
"tls": {
"enabled": true,
"server_name": "${SERVER_NAME}",
"utls": {
"enabled": true,
"fingerprint": "chrome"
},
"reality": {
"enabled": true,
"public_key": "${REALITY_PASSWORD}",
"short_id": "${REALITY_SHORT_ID}"
}
}
}
EOF
chmod 600 /root/xray-singbox-outbound.json
cat /root/xray-singbox-outbound.json
|
这只是一个 outbound 片段,需要放入完整 sing-box 配置的 outbounds 数组中。
第五部分:最终验收与日常维护#
一次性验收清单#
服务器端:
1
2
3
4
5
6
7
| sudo sshd -t
sudo systemctl --no-pager --full status ssh fail2ban nginx xray
sudo fail2ban-client status sshd
sudo nginx -t
sudo xray run -test -config /usr/local/etc/xray/config.json
sudo ss -tulpen | grep -E ':(80|443|8443|42345)\s'
sudo ufw status verbose
|
本地电脑:
1
2
3
| ssh debian13-server
curl -I http://x.domain.com/
curl -I https://x.domain.com/
|
最后用实际客户端导入节点,确认 TCP 与 UDP 的常用访问都正常。
更新与日志#
定期更新 Debian:
1
2
| sudo apt update
sudo apt full-upgrade
|
用官方脚本更新 Xray 后,重新执行配置测试并观察服务:
1
2
3
4
5
| sudo -i
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
xray run -test -config /usr/local/etc/xray/config.json
systemctl restart xray
systemctl status xray --no-pager
|
如果只想更新 geoip.dat 与 geosite.dat,不更新 Xray-core,可以使用官方脚本的 install-geodata:
1
2
3
4
5
6
7
8
| sudo -i
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install-geodata
ls -lh /usr/local/share/xray/geoip.dat \
/usr/local/share/xray/geosite.dat
xray run -test -config /usr/local/etc/xray/config.json
systemctl restart xray
systemctl status xray --no-pager
|
如果配置中使用了 geoip: 或 geosite: 路由规则,更新文件后需要重启 Xray,才能确保当前进程载入新数据。
常用日志:
1
2
3
4
| sudo journalctl -u ssh -n 100 --no-pager
sudo journalctl -u fail2ban -n 100 --no-pager
sudo journalctl -u nginx -n 100 --no-pager
sudo journalctl -u xray -n 100 --no-pager
|
如果服务异常,优先按“配置测试 → 服务状态 → 端口监听 → 防火墙 → DNS”这个顺序排查,不要一上来同时改多处配置。
参考资料#