由于我有个内网的服务器,做开发或测试使用,一个个的暴露或者反代 HTTP 服务很不方便。于是就有了这样的想法 —— 动态反向代理。
环境
*请注意,在实验室环境中,内网 IP 和 VMID 所对应。比如 VMID 为 101,则内网 IP 是 192.168.0.101。
虚拟化环境 | Proxmox VE | ||
反向代理 | Nginx | ||
操作系统 | Debian11 | ||
虚拟化 | LXC | ||
内网网段 | 192.168.0.0/24 |
服务名称 | VMID | 端口 |
---|---|---|
Nginx 反向代理 | 123 | 443 |
Nextcloud | 101 | 80 |
Jupyter | 117 | 8080 |
CodeServer | 112 | 8080 |
所有服务监听 IP 都为 0.0.0.0,防火墙均已关闭。
名词解释
名词 | 解释 |
---|---|
name | 服务名称,在这里做区分作用。 |
vmid | 虚拟机在 Proxmox VE 中的唯一 ID。 |
port | 目标 IP 提供 HTTP 服务的端口,常见有 80, 8080。 |
解决方案
将域名泛解析到 Nginx 的服务器,将所有请求交给 Nginx。
在 Nginx 的 server_name 中,使用正则表达式进行模糊匹配,匹配 name, vmid 与 port,并且过滤路由器等地址。
DNS
*.example -> your_nginx_server
安装 Nginx
不做过多说明。
apt install nginx-full -y
配置文件
仅需要编辑默认的 /etc/nginx/sites-available
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80 default_server;
# 监听 IPv6
listen [::]:80 default_server;
listen 443 ssl http2;
#listen 2083 ssl http2;
# 这里改成你的证书(如有需要的话)。
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
error_page 497 https://$host$request_uri;
# 这里是重点,使用正则来匹配 name, vmid 和 port。
server_name ~^(?<name>\w+)\-(?<vmid>\w+)\-(?<port>\w+)\.example\.com example.com;
# 如果 name 为空,则代表域名格式不合法。
if ($name = "") {
return 400 '没有输入服务名称,请检查域名格式。';
}
# 如果 vmid 为空,也就是没有填写被代理的机器。
if ($vmid = "") {
return 400 '格式中缺少被代理的 VMID。';
}
# 如果 port 为空,也就是没有指定要代理的端口。
if ($port = "") {
return 400 '格式中缺少端口。';
}
# 禁止一些 vmid,比如 路由器 等。
if ($vmid = "1") {
return 403;
}
if ($vmid = "2") {
return 403;
}
if ($vmid = "254") {
return 403;
}
# 禁止代理其自己。这里看上面的 环境 表格。
if ($vmid = "123") {
return 400 "无法代理自己。";
}
# 开始反向代理
location / {
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_set_header REMOTE-HOST $remote_addr;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# 这里替换成你的内网网段。
proxy_pass http://192.168.0.$vmid:$port;
proxy_read_timeout 90;
}
}
应用更改
先检查配置文件有无错误。
nginx -t
重新加载 Nginx。
sudo systemctl reload nginx
测试
访问 Jupyter
https://www-117-8080.example.com 访问在 117 上的 8080 端口的 www 服务。
其他服务依次。
其他
还有个 Nginx 搭建流媒体服务器的
这就类似于AWS的开一堆服务那又臭又长的5级以上的域名了,不过这样确实挺方便的
没听懂QAQ
听懂的那一刻你就不再是少年了ヾ(´・ ・`。)ノ”
没听懂
这个 192.168.0.$vmid 的思路确实很清奇,但真的要做反向代理集群的话,这可能会累死(
不做反向代理集群,这个是方便测试环境用的