前言

随着部署的服务越来越多,从NAS里的 Jellyfin 影音平台,到自建的 OpenWebUI 对话界面,记住一串串 192.168.x.x:端口号 变得越来越痛苦。不仅输入繁琐,而且由于缺乏 SSL 证书支持,浏览器满屏的“不安全”警告也让人心烦。

为了实现像访问互联网一样,通过 https://jellyfin.local 这种优雅的方式访问内网,于是做了基于 DNS 劫持Nginx 反向代理 的链路来实现域名https访问ip:端口的服务。

核心在于两个关键动作:“指路”“分流”

  1. 指路 (DNS): 当你在浏览器输入域名时,路由器上的 dnsmasq 充当了交警的角色。它告诉客户端:“别去公网找,这个域名就在我们家里的 192.168.8.5(Nginx)上。”
  2. 分流 (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 domainlist 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连接路由器

推荐用 SSH 工具(PuTTY / Windows Terminal / macOS Terminal 等)连接路由器

如果没有或不想安装SSH工具也可以使用如下CMD命令

1
ssh root@192.168.8.1

输入路由器密码登录。

  • 添加自定义域名记录

所有域名都指向反代机器 IP 192.168.8.5

1
2
3
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'

保存更改(写入/etc/config/dhcp配置文件)

1
uci commit dhcp

重启 dnsmasq

1
/etc/init.d/dnsmasq restart
  • 主力 PC上验证:
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条目方式

这种方式有两种添加方法,任选一种

  • 后台添加

Openwrt后台添加

  • 命令行添加
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
# ====================== 内网 HTTPS 反向代理(Step-CA 10年证书) ======================

# 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;

location / {
proxy_pass http://192.168.8.223: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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
}
}

# OWU
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.223: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.223: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";
}
}

# HTTP 自动跳转到 HTTPS
server {
listen 80;
server_name jellyfin.lan owu.lan qb.lan;
return 301 https://$host$request_uri;
}

申请SSL

这里使用Step-CA来申请。使用openssl也可以,这个会更简单。

  • 安装Step-CA ,执行以下命令安装
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
  • 初始化本地 CA
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,不适合本地局域网。

之后会让输入账号和密码

  • 修改 ca.json,申请10年证书

如果不修改默认是只能申请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"
}
}

保存退出

  • 启动CA

如果是普通用户初始化的:

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)导出到每台设备(电脑、手机),然后导入“受信任的根证书颁发机构”。

  • win端导入

双击安装证书

选择 本地计算机(重要!不要选当前用户)→ 下一步

选择 将所有的证书放入下列存储浏览 → 选择 受信任的根证书颁发机构

下一步完成 → 。

安全访问

教程结束