查询 35 次,耗时 0.2611 秒

从域名解析到 HTTPS 上线:一套可回滚的 Linux 服务器部署与安全加固流程

speedhacker

New member

speedhacker Rep
0
0
0
Rep
0
speedhacker Vouches
Vouches
0
4 MONTHS
4 4 MONTHS OF SERVICE
speedhacker 获得
0
0
0
获得
0
speedhacker 凭证
0
0
0
凭证
0
主题
7
点赞
0
HakB
4 月
在社区成长 4 月
LEVEL 100 XP
 
背景
很多站点上线失败,并不是应用代码本身有问题,而是域名、DNS、监听端口、反向代理、证书和主机防火墙之间没有形成完整链路。常见表现包括:域名偶尔打不开、IPv6 用户访问失败、证书申请一直等待、Nginx 返回 502、修改解析后旧页面仍然存在,以及服务器暴露了不必要的管理端口。

本文以一台全新 Ubuntu Server 22.04/24.04 云服务器为例,演示如何把一个域名安全地指向服务器,并部署 Nginx 反向代理和本地应用。示例域名统一使用 example.com,公网 IPv4 使用 203.0.113.10,应用监听 127.0.0.1:3000。203.0.113.0/24 属于文档示例地址,实际操作时必须替换为自己的公网地址。所有安全测试仅针对本人拥有或明确获授权的主机。

一、原理和整体链路

用户访问 https://www.example.com 时,流程大致如下:
1. 客户端向递归 DNS 查询 www.example.com。
2. DNS 返回 A 记录对应的 IPv4 地址;如果存在 AAAA 记录,部分客户端还会优先尝试 IPv6。
3. 客户端连接服务器的 TCP 443 端口,并完成 TLS 握手。
4. Nginx 根据 SNI 和 Host 选择站点配置。
5. Nginx 将请求转发到本机的应用进程 127.0.0.1:3000。
6. 应用返回内容,Nginx 再将结果交给客户端。

因此,排查时应按“DNS 是否正确、端口是否可达、Nginx 是否监听、证书是否匹配、后端是否存活”的顺序进行,而不是一开始就反复重启应用。

二、前置条件

1. 已注册域名,并能管理 DNS 解析。
2. 一台具有公网 IPv4 的 Linux 服务器,系统建议保持在受支持版本。
3. 云厂商安全组和服务器本机防火墙均可配置。
4. 已准备一个普通运维账号,并能通过 SSH 登录;不要长期使用 root 直接操作业务。
5. 应用已经能够在服务器本地启动,并监听 127.0.0.1:3000。若应用监听的是其他端口,后续配置要同步修改。
6. 记录当前 DNS、服务器快照和应用配置,便于回滚。

三、先配置 DNS,避免提前暴露错误服务

在 DNS 控制台添加以下记录:

A @ 203.0.113.10
A www 203.0.113.10

如果服务器没有可用 IPv6,不要为了“看起来完整”而添加 AAAA 记录。错误的 AAAA 记录可能导致 IPv6 用户连接到不可达地址,表现为部分地区或部分运营商访问缓慢。若确实配置了 IPv6,应添加正确的 AAAA 记录,并同时确认云安全组、防火墙和 Nginx 都监听 IPv6。

TTL 可以先设置为 300 秒,便于上线阶段调整;稳定运行后再根据 DNS 服务商能力调整。需要注意,TTL 不是严格的缓存清除按钮,递归 DNS、浏览器和本地系统都可能有自己的缓存,因此改解析后不要期待所有用户立即同步。

可使用以下命令检查解析结果:

dig A example.com +short
dig A www.example.com +short
dig AAAA example.com +short
dig NS example.com +short

如果 dig 没有安装,可以执行:

sudo apt update
sudo apt install -y dnsutils

结果应与预期一致。若不同,先检查是否改错了 DNS 托管商:域名注册商处的 NS 记录决定了真正生效的权威 DNS 服务商,单纯在另一个平台添加记录不会生效。

四、服务器基础初始化

先更新系统并创建普通账号:

sudo apt update && sudo apt full-upgrade -y
sudo adduser deploy
sudo usermod -aG sudo deploy

使用 deploy 账号登录后,再编辑 SSH 配置。建议先确认新账号可以正常登录,再考虑关闭 root 登录或密码登录,避免把自己锁在服务器外。可以在本地生成密钥:

ssh-keygen -t ed25519 -C "deploy@example"
ssh-copy-id [email protected]

确认密钥登录成功后,编辑 /etc/ssh/sshd_config,至少检查以下配置:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

修改后先验证语法,再重载服务:

sudo sshd -t
sudo systemctl reload ssh

不要在唯一的 SSH 会话中贸然执行这些操作。建议保留一个已登录的备用会话,并确认云厂商提供网页控制台或串口,以便回滚。

五、配置防火墙和云安全组

云安全组与服务器本机防火墙是两层控制,建议两边都只开放必要端口。云安全组通常开放:TCP 22(仅限自己的办公公网 IP)、TCP 80、TCP 443。不要把应用端口 3000 对公网开放。

在服务器使用 UFW 的示例:

sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from YOUR_OFFICE_IP to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

将 YOUR_OFFICE_IP 替换为固定的办公出口地址。如果办公网络 IP 经常变化,可以暂时允许 22 端口,但应配合密钥登录、Fail2ban 或云厂商的带外访问,并定期收紧来源范围。若启用了 IPv6,还要检查 UFW 的 IPv6 配置是否符合预期。

六、安装并配置 Nginx 反向代理

安装 Nginx:

sudo apt install -y nginx
sudo systemctl enable --now nginx
sudo systemctl status nginx --no-pager

创建站点配置:

sudo nano /etc/nginx/sites-available/example.com

写入以下内容:

server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;

location / {
proxy_pass http://127.0.0.1:3000
proxy_http_version 1.1;
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_read_timeout 60s;
}
}

启用站点并删除默认站点,修改前先检查配置:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

此时可以先访问 http://example.com 验证 DNS、80 端口和后端应用是否连通。若返回 502,通常表示 Nginx 无法连接 127.0.0.1:3000,应检查应用进程、监听地址和端口:

ss -lntp
curl -I http://127.0.0.1:3000
sudo journalctl -u nginx -n 100 --no-pager

七、使用 systemd 管理应用

不要依赖 SSH 会话中直接运行 node、python 或其他命令,否则断开会话后进程可能退出。下面是 systemd 示例,假设应用目录为 /opt/myapp,启动命令为 /usr/bin/node /opt/myapp/server.js:

sudo nano /etc/systemd/system/myapp.service

内容如下:

[Unit]
Description=My Web Application
After=network.target

[Service]
User=deploy
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node /opt/myapp/server.js
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target

执行:

sudo systemctl daemon-reload
sudo systemctl enable --now myapp
sudo systemctl status myapp --no-pager
sudo journalctl -u myapp -f

实际项目中应根据运行时调整 ExecStart。不要把数据库密码直接写进公开仓库;可以使用受限权限的 EnvironmentFile,并确保文件权限为 600。对于需要写入目录的应用,还要明确授予 deploy 用户最小范围的写权限。

八、申请 HTTPS 证书并强制跳转

确认 HTTP 站点已经可以从公网访问后,安装 Certbot:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

按照提示填写邮箱并选择同意条款。Certbot 通常会自动修改 Nginx 配置并创建 HTTP 到 HTTPS 的跳转。完成后检查:

sudo nginx -t
sudo systemctl reload nginx
curl -I http://example.com
curl -I https://example.com
sudo certbot renew --dry-run

证书自动续期依赖定时器,不能只申请一次就不管。若使用 DNS 验证、CDN 或自定义 DNS,续期方式可能不同,应查看 certbot timers 和日志。生产环境不要把私钥复制到不受控的电脑或聊天工具中。

如果不希望 Certbot 自动改配置,也可以先用 webroot 模式,但必须确保验证目录能被 Nginx 正确访问。证书问题排查时,检查域名是否解析到当前服务器、80/443 是否被安全组拦截、站点 server_name 是否匹配,以及系统时间是否正确。

九、基础安全加固

1. 最小化暴露面:只开放 SSH、HTTP、HTTPS,数据库和应用端口仅监听 127.0.0.1 或私网地址。
2. 定期更新系统和依赖,更新前制作快照,并查看应用兼容性。
3. 使用 least privilege 原则,不让 Web 应用以 root 身份运行。
4. 关闭 Nginx 版本暴露:在 http 配置块中设置 server_tokens off;但这不是替代补丁管理的安全措施。
5. 为管理后台增加强密码、多因素认证或来源 IP 限制,避免仅依赖隐藏 URL。
6. 配置日志轮转,关注 /var/log/nginx/access.log、error.log 和应用日志,避免磁盘被写满。
7. 备份数据库、上传文件和关键配置,并至少做一次恢复演练。只有“能恢复”的备份才算可靠。
8. 使用授权的本地或预发布环境进行端口和配置验证,例如检查本机监听、审计安全组和核对 HTTP 响应;不要扫描或测试无授权的第三方地址。

十、常见问题与排查顺序

问题一:DNS 已修改但仍访问旧服务器。
先用 dig 查询权威服务器和递归结果,确认 NS 是否正确,再检查本地 DNS 缓存和 TTL。不要只看浏览器结果。

问题二:HTTP 可以访问,HTTPS 失败。
检查 443 是否在云安全组和 UFW 中放行,确认 Nginx 是否监听 443:

sudo ss -lntp | grep -E ':80|:443'
sudo nginx -T | less

问题三:只有部分用户访问失败。
优先检查 AAAA 记录是否指向错误 IPv6、CDN 回源策略以及不同 DNS 线路的返回结果。

问题四:Nginx 返回 502 Bad Gateway。
执行 curl http://127.0.0.1:3000,查看应用是否启动、是否监听了错误地址或端口,再查看 Nginx error.log。若应用只监听 Unix Socket,proxy_pass 配置也要对应修改。

问题五:修改配置后网站完全打不开。
不要连续重启。先执行 sudo nginx -t;若失败,恢复最近一次可用配置,再 reload。上线前把配置文件纳入 Git 或至少保留带日期的备份。

问题六:证书续期失败。
执行 sudo certbot renew --dry-run 并查看日志,确认域名仍指向本机、验证端口可访问、DNS API 凭据未过期。若使用 CDN 的代理模式,需确认验证方式与 CDN 配置兼容。

总结

一个可靠的域名/服务器上线流程,不是“解析域名后装个面板”这么简单,而是要把 DNS、网络入口、Nginx、应用进程、证书、权限、日志和备份串成可验证、可回滚的链路。实际操作建议遵循以下顺序:先确认权威 DNS,再初始化账号和防火墙;先让 HTTP 和本地后端稳定,再申请 HTTPS;先做配置检查和备份,再 reload 或重启。上线后持续观察证书续期、磁盘空间、错误率和异常登录记录,定期用授权环境进行恢复演练,才能把一次成功部署变成长期可维护的服务器。
 

lawrenceyang

New member

lawrenceyang Rep
0
0
0
Rep
0
lawrenceyang Vouches
Vouches
0
1 MONTH
1 1 MONTH OF SERVICE
lawrenceyang 获得
0
0
0
获得
0
lawrenceyang 凭证
0
0
0
凭证
0
主题
3
点赞
0
HakB
1 月
在社区成长 1 月
LEVEL 1 1 XP
 
建议在切换 DNS 前增加一次“指定目标 IP”的 HTTPS 验收:证书配置完成后执行 curl --resolve example.com:443:203.0.113.10 https://example.com/health(替换成实际 IP 和健康检查路径)。这样无需等待解析传播,就能验证目标服务器的 SNI、证书校验和反向代理链路;不要加 -k,否则会掩盖证书问题。另外,若计划把 TTL 降到 300 秒,应至少提前一个旧 TTL 周期调整,切换时旧缓存不会因为新 TTL 自动提前失效。
 
顶部