这是一个非常经典且常见的网络架构问题。标准且完美的解决方案是:使用反向代理服务器。
这个方案可以完美地满足所有需求:单一公网IP、多个域名、共用80/443端口、全HTTPS加密。
核心解决方案:反向代理 (Reverse Proxy)
1. 工作原理
反向代理服务器(如 Nginx, Apache Traffic Server, HAProxy)位于公网入口,监听80和443端口。它根据客户端请求中的 SNI (Server Name Indication) 字段(即访问的域名)来决定将请求转发到后端的哪个内部系统。
工作流程:
用户访问
https://app1.yourdomain.com,DNS 将该域名解析到您的公网IP。请求到达反向代理服务器的443端口。
反向代理读取 TLS 握手阶段的 SNI 信息,得知用户要访问的域名是
app1.yourdomain.com。根据预先配置好的规则,反向代理将此请求转发至内网中对应的服务器(例如
192.168.1.10:3000)。内部服务器处理请求并将响应返回给反向代理。
反向代理最终将响应返回给用户。
对于
app2.yourdomain.com的请求,过程同上,但会被转发到另一个内部服务器(例如192.168.1.20:4000)。
2. 优势
一个IP,多个服务:完美解决端口冲突问题。
集中化管理SSL证书:所有域的SSL证书都可以在反向代理上统一申请、安装和更新,无需在每个内部系统上单独配置,管理非常方便。
增强安全性:隐藏了内部服务器的真实IP和端口,对外只暴露反向代理,增强了后端服务的安全性。
附加功能:可以轻松实现负载均衡、缓存、压缩、访问控制、日志记录等功能。
具体实施步骤(以最常用的 Nginx 为例)
第1步:部署反向代理服务器
准备一台服务器(可以是物理机、虚拟机或云实例),安装 Linux 系统(如 Ubuntu, CentOS)。
在这台服务器上安装 Nginx(通常包管理器直接安装即可,如
apt install nginx或yum install nginx)。确保此服务器拥有您唯一的公网IP,并且防火墙开放80和443端口。
第2步:配置域名解析
将您所有的域名(如
app1.com,app2.org,service.net)的DNSA记录都指向这个唯一的公网IP。
第3步:申请和安装SSL证书
推荐使用 Certbot 和 Let‘s Encrypt 来自动化免费证书的申请和续签。
在反向代理服务器上安装 Certbot 及其 Nginx 插件(如
apt install certbot python3-certbot-nginx)。执行命令为所有域名申请证书(Nginx插件会自动修改配置):
bash
sudo certbot --nginx -d app1.yourdomain.com -d app2.yourdomain.com -d service.yourdomain.comCertbot 会自动完成证书申请并修改 Nginx 配置以启用HTTPS。它还会设置自动续期任务,您无需担心证书过期。
第4步:配置 Nginx 作为反向代理
这是最关键的一步。您需要为每个域名(或每个服务)创建一个独立的 server block 配置文件(通常在
/etc/nginx/conf.d/或/etc/nginx/sites-available/目录下)。示例配置文件:
/etc/nginx/conf.d/app1.confnginx
# 处理 app1.yourdomain.com 的请求 server { # 监听443端口,并启用SSL,http2是可选的性能优化选项 listen 443 ssl http2; server_name app1.yourdomain.com; # SSL证书和密钥路径(通常Certbot已自动配置好) ssl_certificate /etc/letsencrypt/live/app1.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/app1.yourdomain.com/privkey.pem; # 其他SSL优化配置可以放在这里或一个单独的公共文件中 location / { # 核心反向代理配置:将请求转发到内网的应用服务器 proxy_pass http://192.168.1.10:3000; # 这里填写app1服务器的内网IP和端口 # 以下是一些重要的反向代理头设置,用于向后端传递真实客户信息 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; } } # 强制将HTTP访问重定向到HTTPS server { listen 80; server_name app1.yourdomain.com; return 301 https://$server_name$request_uri; }为第二个服务创建配置文件:
/etc/nginx/conf.d/app2.confnginx
server { listen 443 ssl http2; server_name app2.yourdomain.com; ssl_certificate /etc/letsencrypt/live/app2.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/app2.yourdomain.com/privkey.pem; location / { proxy_pass http://192.168.1.20:4000; # 指向第二个内部系统 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; ... # 其他头设置同上 } } server { listen 80; server_name app2.yourdomain.com; return 301 https://$server_name$request_uri; }
第5步:测试并重载配置
检查 Nginx 配置语法是否正确:
bash
sudo nginx -t如果显示
syntax is ok和test is successful,则重新加载 Nginx 使配置生效:bash
sudo systemctl reload nginx
第6步:配置后端系统
确保您的各个内部系统(
192.168.1.10,192.168.1.20)正在运行并监听正确的端口(3000, 4000)。这些后端系统可以不再需要配置SSL证书,因为与反向代理之间的通信可以在内网中通过HTTP进行(前提是内网是可信的)。如果安全性要求极高,也可以在内部通信中使用HTTPS。
这些后端系统的防火墙不需要对外开放80/443端口,只需允许反向代理服务器的IP访问其服务端口即可。
备选方案
如果由于某些原因不能使用反向代理,可以考虑以下方案,但它们都有明显缺陷:
端口映射 (Port Forwarding)
方法:在出口路由器上,将不同的公网端口映射到不同内网系统的443端口。例如:
公网IP:8443->内网系统1:443公网IP:9443->内网系统2:443
缺点:
URL中必须带端口:用户访问时需要用
https://app1.com:8443,非常不专业且用户体验极差。证书问题:如果证书校验域名,可能会因为端口不匹配而报错。非常不推荐。
TCP层代理 (4层负载均衡)
方法:使用 HAProxy 或 Nginx 的
stream模块在TCP层进行代理。它同样依赖SNI,但不会解析HTTP协议。适用场景:适用于非HTTP协议(如数据库、邮件协议)或需要完全透传TCP数据的场景。对于您的HTTPS Web服务,应用层(7层)的反向代理是更优选择,因为它功能更强大。