前言
随着部署的服务越来越多,从NAS里的 Jellyfin 影音平台,到自建的 OpenWebUI 对话界面,记住一串串 192.168.x.x:端口号 变得越来越痛苦。不仅输入繁琐,而且由于缺乏 SSL 证书支持,浏览器满屏的“不安全”警告也让人心烦。
为了实现像访问互联网一样,通过 https://jellyfin.local 这种优雅的方式访问内网,于是做了基于 DNS 劫持 与 Nginx 反向代理 的链路来实现域名https访问ip:端口的服务。
核心在于两个关键动作:“指路”与“分流”。
- 指路 (DNS): 当你在浏览器输入域名时,路由器上的
dnsmasq 充当了交警的角色。它告诉客户端:“别去公网找,这个域名就在我们家里的 192.168.8.5(Nginx)上。”
- 分流 (Nginx): 当 Nginx 收到加密的 HTTPS 请求后,它会根据请求里的 SNI(主机名) 信息进行拆解。如果是找 Jellyfin 的,它就默默地把流量转发给
8096 端口;如果是找别的,就转给对应的服务。
设备情况:
主路由器 (GL-MT3000 / OpenWrt): 利用其内置的 dnsmasq 服务,将特定的内网域名请求(如 `*.lan)强制解析到 Nginx 所在的服务器 IP。
流量网关 (N3540 小主机 - 192.168.8.5): 一台低功耗的 Linux 主机,运行 Nginx。它作为唯一的 HTTPS 入口,负责证书卸载(SSL Termination)和请求分发。
后端应用服务器 (Epson ST190E - 192.168.8.223): 核心业务所在地。上面跑着各类自建服务(如 Jellyfin、OpenWebUI 等),通过不同的端口号提供服务。
通信流程:
客户端 → DNS 查询 → 路由器 dnsmasq (192.168.8.1) 返回 192.168.8.5 → 客户端连接 192.168.8.5:443 → Nginx(反向代理)根据 Host 头转发到 服务端192.168.8.223:8096 → 响应返回。
下面是详细的搭建教程。
主机名映射
目标:
局域网设备比如pc,执行以下查询
1 2
| nslookup qb.lan ping.qb.lan
|
可以被正确解析到设定的局域网ip(进行反代设备的ip)
提供两种映射方式,config domain和list address
| 方式 |
写法 |
优点 |
缺点 |
config domain(静态DNS条目) |
config domain option name ‘owu.lan’ option ip ‘192.168.8.5’ |
清晰、可管理多个静态条目,支持 Web UI |
每个域名要写一块 |
list address |
list address '/qb.lan/192.168.8.5' |
快速、可在同一条中添加多个 |
管理多个域名不如 config domain 清晰 |
最简单的方式是静态DNS条目方式,在openwrt后台就能添加;无论哪种方式,当验证的时候发现没有预期的效果,一定记得尝试重启路由器!!!!
listaddress方式
推荐用 SSH 工具(PuTTY / Windows Terminal / macOS Terminal 等)连接路由器
如果没有或不想安装SSH工具也可以使用如下CMD命令
输入路由器密码登录。
所有域名都指向反代机器 IP 192.168.8.5
1 2 3 4 5 6
| uci add_list dhcp.@dnsmasq[0].address='/jellyfin.lan/192.168.8.5' uci add_list dhcp.@dnsmasq[0].address='/owu.lan/192.168.8.5' uci add_list dhcp.@dnsmasq[0].address='/qb.lan/192.168.8.5' uci add_list dhcp.@dnsmasq[0].address='/wp.lan/192.168.8.5' uci add_list dhcp.@dnsmasq[0].address='/music.lan/192.168.8.5' uci add_list dhcp.@dnsmasq[0].address='/book.lan/192.168.8.5'
|
保存更改(写入/etc/config/dhcp配置文件)
重启 dnsmasq
1
| /etc/init.d/dnsmasq restart
|
1 2
| ipconfig /flushdns nslookup qb.lan
|
正确结果应该是:
- Server: 192.168.8.1
- Address: 192.168.8.5
如果不是,路由器断电重启,重新验证
删除配置(配置错误时)
1 2 3
| uci -q del_list dhcp.@dnsmasq[0].address='/jellyfin.lan/192.168.8.5' uci -q del_list dhcp.@dnsmasq[0].address='/owu.lan/192.168.8.5' uci -q del_list dhcp.@dnsmasq[0].address='/qb.lan/192.168.8.5'
|
查看配置是否删除/写入
1
| cat /etc/config/dhcp | grep address
|
静态DNS条目方式
这种方式有两种添加方法,任选一种

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # 添加三个服务的域名记录(指向 NPM IP 192.168.8.5) uci add dhcp domain uci set dhcp.@domain[-1].name='jellyfin.lan' uci set dhcp.@domain[-1].ip='192.168.8.5'
uci add dhcp domain uci set dhcp.@domain[-1].name='owu.lan' uci set dhcp.@domain[-1].ip='192.168.8.5'
uci add dhcp domain uci set dhcp.@domain[-1].name='qb.lan' uci set dhcp.@domain[-1].ip='192.168.8.5'
# 保存并重启 dnsmasq uci commit dhcp /etc/init.d/dnsmasq restart dnsmasq --test
|
PC验证
1 2
| ipconfig /flushdns nslookup jellyfin.lan
|
无法正确解析,尝试重启路由器再次验证
域名反代
nginx配置
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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
| # ====================== 服务配置 ======================
# 反向代理到 Jellyfin server { listen 443 ssl; server_name jellyfin.lan;
ssl_certificate /www/server/nginx/conf.d/lan-fullchain.pem; ssl_certificate_key /www/server/nginx/conf.d/lan-privkey.pem;
client_max_body_size 20M;
location / { proxy_pass http://192.168.8.117:8096; 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_cache off; sendfile on; tcp_nopush on; tcp_nodelay on; }
location /socket { proxy_pass http://192.168.8.117:8096/socket; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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; } }
# 反向代理到 OWU (OpenWebUI) server { listen 443 ssl; server_name owu.lan;
ssl_certificate /www/server/nginx/conf.d/lan-fullchain.pem; ssl_certificate_key /www/server/nginx/conf.d/lan-privkey.pem;
location / { proxy_pass http://192.168.8.117:8180; 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 "upgrade"; } }
# 反向代理到 qBittorrent server { listen 443 ssl; server_name qb.lan;
ssl_certificate /www/server/nginx/conf.d/lan-fullchain.pem; ssl_certificate_key /www/server/nginx/conf.d/lan-privkey.pem;
location / { proxy_pass http://192.168.8.117:8282; 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 "upgrade"; } }
# 反向代理到 Navidrome (音频播放器) server { listen 443 ssl; listen [::]:443 ssl; http2 on; # 建议加上 server_name music.lan;
ssl_certificate /www/server/nginx/conf.d/lan-fullchain.pem; ssl_certificate_key /www/server/nginx/conf.d/lan-privkey.pem;
location / { proxy_pass http://192.168.8.117:16563; proxy_set_header Range $http_range; proxy_set_header If-Range $http_if_range; proxy_buffering off; proxy_cache off; proxy_http_version 1.1; tcp_nopush on; sendfile on; directio 4m; }
location /socket { proxy_pass http://192.168.8.117:16563/socket; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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; } }
# 反向代理到 Calibre-web (电子书库) server { listen 443 ssl; server_name book.lan;
ssl_certificate /www/server/nginx/conf.d/lan-fullchain.pem; ssl_certificate_key /www/server/nginx/conf.d/lan-privkey.pem;
location / { expires 30d; add_header Cache-Control "public, no-transform"; proxy_pass http://192.168.8.117:8983; 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_buffering off; proxy_request_buffering off; proxy_read_timeout 3600s; } }
# 反向代理到 OpenList (网盘) server { listen 443 ssl; server_name wp.lan;
ssl_certificate /www/server/nginx/conf.d/lan-fullchain.pem; ssl_certificate_key /www/server/nginx/conf.d/lan-privkey.pem;
location / { proxy_pass http://192.168.8.117:15244; proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_buffering off; proxy_cache off; proxy_request_buffering off; proxy_read_timeout 3600s; } }
# ====================== HTTP 自动跳转到 HTTPS ====================== server { listen 80; server_name jellyfin.lan owu.lan qb.lan wp.lan music.lan book.lan; return 301 https://$host$request_uri; }
|
jellyfin的部分配置参考解决反向代理JellyFin后播放等待时间过长的问题
申请SSL
这里使用Step-CA来申请。使用openssl也可以,这个会更简单。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| # 1. 更新系统并安装依赖 sudo apt update sudo apt install -y --no-install-recommends curl gpg ca-certificates
# 2. 添加 Smallstep 官方仓库(2026 年最新方式) curl -fsSL https://packages.smallstep.com/keys/apt/repo-signing-key.gpg -o /etc/apt/keyrings/smallstep.asc
cat << EOF | sudo tee /etc/apt/sources.list.d/smallstep.sources Types: deb URIs: https://packages.smallstep.com/stable/debian Suites: debs Components: main Signed-By: /etc/apt/keyrings/smallstep.asc EOF
# 3. 更新仓库并安装 step-cli + step-ca sudo apt update sudo apt install -y step-cli step-ca
|
1 2
| step version step-ca version
|
1 2 3 4 5 6
| sudo step ca init \ --name "Home LAN CA" \ --dns 192.168.8.5 \ --dns localhost \ --dns 127.0.0.1 \ --address 192.168.8.5:8443
|
Standalone → 完全本地 CA,最适合家庭/局域网环境。你可以自己签发证书,不依赖云服务。
Linked → 本地 CA + cloud 功能,适合想要管理/报告/告警的用户。
Hosted → 小步提供的全托管 CA,不适合本地局域网。
之后会让输入账号和密码
如果不修改默认是只能申请24小时的
1
| nano ~/.step/config/ca.json
|
在 "authority" 部分,添加或修改成下面这样(把整个 authority 块替换/补充为以下内容):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| "authority": { "claims": { "minTLSCertDuration": "5m", "maxTLSCertDuration": "87600h", "defaultTLSCertDuration": "87600h" }, "provisioners": [ { "type": "JWK", "name": "\u0016", "key": { ...原有 key 配置保持不变... }, "encryptedKey": "原有 encryptedKey 保持不变", "maxTLSCertDuration": "87600h" } ], "signing": { "defaultTLSDuration": "87600h" } }
|
保存退出
如果是普通用户初始化的:
1
| sudo step-ca /home/<user>/step-ca/config/ca.json
|
如果是在 root 下初始化的:
1
| sudo step-ca /root/.step/config/ca.json
|
需要输入密码才能启动,启动后,会在你初始化时设置的端口监听(127.0.0.1:8443)。
后续每次需要申请证书都要先启动再申请
1 2 3 4 5 6 7 8 9 10 11 12
| cd /www/server/nginx/conf.d
step ca certificate \ jellyfin.lan \ lan-fullchain.pem \ lan-privkey.pem \ --not-after=87600h \ --san jellyfin.lan \ --san owu.lan \ --san qb.lan \ --san 192.168.8.5 \ --san localhost
|
需要输入密码

客户端信任CA
把 Step-CA 的根证书(通常是 /root/.step/certs/root_ca.crt)导出到每台设备(电脑、手机),然后导入“受信任的根证书颁发机构”。
双击安装证书。
选择 本地计算机(重要!不要选当前用户)→ 下一步。
选择 将所有的证书放入下列存储 → 浏览 → 选择 受信任的根证书颁发机构。
下一步 → 完成 → 。

教程结束