跳到主要内容

「LUCKY STUN穿透」使用Homer导航页指示stun穿透后的端口

2025.11.24

关于本教程​

在之前的一系列教程中我们介绍了许多“固定”stun穿透端口的方法

主要用于 MC java 版联机的 SRV 记录方案

适用于大部分HTTP(S)服务的 重定向方案

几乎适用于一切服务的 虚拟专用网络组网方案

以及邮件端口通知方案

但是有些服务 不支持 srv记录 不使用http协议
也不方便安装虚拟专用网络客户端

而使用邮件通知的方案在长期运行和端口变化较为频繁的情况下
会积累大量的通知邮件 查看起来并不方便

我们需要一个更好的方案来实时的查看穿透端口
这里将使用动态的网页来实时显示穿透服务的端口


目标效果和原理​

该导航页面应是一个纯前端页面 使用纯文本配置文件来控制显示条目内容
此处使用 homer 作为导航页
可以换用 其他类型的导航页面 纯前端页面对部署环境的要求低 适应性强

之所以强调用纯文本配置文件来控制显示条目内容
是因为要使用lucky web 服务中的 文本输出功能 替代磁盘上的配置文件

将配置文件的内容写入到文本输出功能中 以便在其中加入用于指示stun穿透端口号的变量
同时建议添加上time变量 用于显示实时的时间 以防止页面或者配置文件被缓存

非HTTP服务​

连接这些服务前通过查看导航页面以获取最新的穿透端口号
在其服务的连接界面手动输入此端口号 以连接服务

HTTP服务​

对于HTTP服务来说也能提供方便
无需要记忆每个服务所对应的子域名

直接点击导航页上的链接就可以实现跳转
导航页只适用于浏览性的HTTP服务 webdev之类的非浏览性服务是不行的
还是需要依靠重定向来实现 反向代理和泛域名解析配置依然是需要的

极简方案​

在牺牲美观性和一定的实用性的前提下 可以极大的简化配置方法
直接使用lucky的文本输出功能显示内容 即以纯文本的形式输出服务名称和端口号

simplified-1 simplified-2

下载和挂载Homer​

Homer项目地址:链接
下载项目压缩包并解压:链接

在lucky web 服务中添加新的子规则
有关lucky web规则设置的具体方法详见之前的教程:链接

add-sub-rule

类型选择 文件服务
挂载目录选择解压后 homer 所在的文件夹

mount-homer

前端域名可以先填写一个简短的不存在的域名 用作测试
在host文件将其指向 127.0.0.1 这里使用 ie12.lan
不建议使用 .local 其有特殊用途

host

访问页面应该可以看到以下内容

homer-pending-configuration

转到 homer 目录下的 assets 文件夹
找到 config.yml.dist 文件 复制一份 去掉名称中的 .dist

这是一个预设的配置文件 我们将在这个配置文件的基础上进行修改
(其实那个 config-demo.yml.dist 也可以 不过那个预设文件更复杂 此处我们用不到)

homer-folder homer-copy-configuration

完成上述操作后 回到浏览器刷新页面应该可以看到 这些预设内容

homer-preset-effect

配置 Homer​

我们将在这个预设配置文件的基础上进行修改 以使其适应我们的需要
此处对这个默认配置文件进行了简单的翻译

配置文件翻译
---
# 主页配置
# 图标选项请参阅 https://fontawesome.com/search

title: "演示仪表盘"
subtitle: "Homer"
logo: "logo.png"
# icon: "fas fa-skull-crossbones" # 可选图标

header: true
footer: '<p>使用 <span class="has-text-danger">❤️</span> 与 <a href="https://bulma.io/">bulma</a>, <a href="https://vuejs.org/">vuejs</a> 及 <a href="https://fontawesome.com/">font awesome</a> 创建 // 在 <a href="https://github.com/bastienwirtz/homer"><i class="fab fa-github-alt"></i></a> 上 Fork 我</p>' # 设为 false 可隐藏

# 可选主题定制
theme: default

# 可选主题定制(颜色覆盖)
# 也可使用 CSS 变量进行覆盖
colors:
light:
highlight-primary: "#3367d6"
highlight-secondary: "#4285f4"
highlight-hover: "#5a95f5"
background: "#f5f5f5"
card-background: "#ffffff"
text: "#363636"
text-header: "#ffffff"
text-title: "#303030"
text-subtitle: "#424242"
card-shadow: rgba(0, 0, 0, 0.1)
link: "#3273dc"
link-hover: "#363636"
dark:
highlight-primary: "#3367d6"
highlight-secondary: "#4285f4"
highlight-hover: "#5a95f5"
background: "#131313"
card-background: "#2b2b2b"
text: "#eaeaea"
text-header: "#ffffff"
text-title: "#fafafa"
text-subtitle: "#f5f5f5"
card-shadow: rgba(0, 0, 0, 0.4)
link: "#3273dc"
link-hover: "#ffdd57"

# 可选消息
message:
#url: https://b4bz.io
style: "is-dark" # 样式选项请参阅 https://bulma.io/documentation/components/message/#colors
title: "演示!"
icon: "fa fa-grin"
content: "这是一个示例主页演示。<br />更多信息请访问 <a href='https://github.com/bastienwirtz/homer'>github.com/bastienwirtz/homer</a>"

# 可选导航栏
# links: [] # 允许创建无链接的导航栏(暗黑模式、布局和搜索)
links:
- name: "参与贡献"
icon: "fab fa-github"
url: "https://github.com/bastienwirtz/homer"
target: "_blank" # 可选的 html a 标签 target 属性
- name: "维基"
icon: "fas fa-book"
url: "https://www.wikipedia.org/"
# 此链接将指向第二个 homer 页面,该页面将从 additional-page.yml 加载配置,并保留 config.yml 文件中的默认配置值
# 参见 url 字段及此示例中使用的 assets/additional-page.yml.dist:
#- name: "另一个页面!"
# icon: "fas fa-file-alt"
# url: "#additional-page"

# 服务
# 第一级数组代表一个分组。
# 如果不使用分组,则仅保留 "items" 键(分组名称、图标和标签样式是可选的,不会显示分组分隔)。
services:
- name: "应用程序"
icon: "fas fa-cloud"
items:
- name: "快速开始"
icon: "fa-solid fa-download"
subtitle: "几分钟内开始使用 Homer"
tag: "setup"
url: "https://github.com/bastienwirtz/homer?tab=readme-ov-file#get-started"
- name: "配置"
icon: "fa-solid fa-sliders"
subtitle: "配置选项文档"
tag: "setup"
url: "https://github.com/bastienwirtz/homer/blob/main/docs/configuration.md"
- name: "主题定制"
icon: "fa-solid fa-palette"
subtitle: "自定义 Homer 外观"
tag: "theming"
url: "https://github.com/bastienwirtz/homer/blob/main/docs/theming.md"
- name: "智能卡片"
icon: "fa-solid fa-palette"
subtitle: "显示动态信息或操作。"
tag: "setup"
url: "https://github.com/bastienwirtz/homer/blob/main/docs/customservices.md"
- name: "仪表盘图标"
icon: "fa-solid fa-icons"
subtitle: "仪表盘图标"
tag: "setup"
url: "https://github.com/walkxcode/dashboard-icons"

服务卡片​

最重要的部分是 services 它控制着这些服务卡片的内容

homer-grouping-and-cards

其中缩进少且带 items 项的为 分组 可以对服务卡片进行归类
items 下的内容就是服务卡片了

  • name 用于控制显示名称
  • subtitle 副标题 但在服务卡片中其更像是描述
  • url 用于填写超链接 非http服务可留空
  • target 在其中填写 _blank 可使链接在新窗口中打开
  • icon 和 logo 用于显示 图标

其中 icon 表示使用 https://fontawesome.com/search 上的字体图标
可以在该网站上搜索其他的字体图标 将其对应的名称复制到此处即可
而 logo 则表示使用图像文件作为图标

对于 非HTTP服务 来说我们不需要 url 项 直接在 subtitle 中写端口即可
为了动态的显示 STUN 穿透端口 我们需要使用全局变量来实现
写法为 {STUN_规则名_PORT} 其中的规则名称 要替换为具体的STUN规则名称

lucky的全局变量详见:链接
至于IP地址的更新应交由 动态域名解析(DDNS) 处理 此处不填写
该域名应已预先输入到需要的服务中 其不需要在每次连接时都进行输入

而对于 HTTP服务 而则需要填写 url 项 以实现跳转
建议先按照之前的教程 设置反向代理 使所有HTTP服务共用同一个端口
这样 只需要一条STUN穿透规则 就能承载所有HTTP服务

如果在之前 已经使用了重定向或页面规则方案
则在此处 填写 重定向后的域名 即可

若之前未使用过重定向方案 则请先按照 页面规则方案 中方法
为所有服务设置 重定向后的域名 及其解析

对于 不支持重定向的HTTP服务 来说其设置与非HTTP服务相同

标题​

homer-title-display homer-title-configuration
  • title 主标题内容
  • subtitle 副标题内容
  • logo 图标内容

图标文件在 \assets\icons\ 中之后自定义的图片资源也可以存放在此处

消息​

homer-message-display homer-message-configuration

可以用于显示一些提示消息 在本教程中此处将用于显示实时时间
当然显示时间的功能也可以放到服务卡片中
若不需要显示则 全部使用 # 注释掉即可

  • style 用于控制消息框的显示样式
  • content 为消息内容 由html格式写成

菜单栏​

homer-menu-display homer-menu-configuration

可添加一些常用的链接

页脚​

homer-footer-display homer-footer-configuration

页面底部的信息显示 可修改 填写的内容为html格式

图标资源​

除了 上文中提到的 fontawesome.com 所提供的字符图标外
这些存储库也提供了许多常见服务的矢量图或高分辨率位图

示例效果​

demo-effect-1
配置文件展示
---
# Homepage configuration
# See https://fontawesome.com/search for icons options

title: "STUN穿透导航"
subtitle: "lucky"
logo: "/assets/icons/lucky.svg"
# icon: "fas fa-skull-crossbones" # Optional icon

header: true
footer: '<a>STUN穿透导航 演示</a>' # set false if you want to hide it.

# Optional theme customization
theme: default

# Optional theme customization (color overrrides)
# overrrides can also be done using CSS vars
colors:
light:
highlight-primary: "#3367d6"
highlight-secondary: "#4285f4"
highlight-hover: "#5a95f5"
background: "#f5f5f5"
card-background: "#ffffff"
text: "#363636"
text-header: "#ffffff"
text-title: "#303030"
text-subtitle: "#424242"
card-shadow: rgba(0, 0, 0, 0.1)
link: "#3273dc"
link-hover: "#363636"
dark:
highlight-primary: "#3367d6"
highlight-secondary: "#4285f4"
highlight-hover: "#5a95f5"
background: "#131313"
card-background: "#2b2b2b"
text: "#eaeaea"
text-header: "#ffffff"
text-title: "#fafafa"
text-subtitle: "#f5f5f5"
card-shadow: rgba(0, 0, 0, 0.4)
link: "#3273dc"
link-hover: "#ffdd57"

# Optional message
message:
#url: https://b4bz.io
style: "is-success" # See https://bulma.io/documentation/components/message/#colors for styling options.
title: "实时时间"
icon: "fa-regular fa-clock"
content: "<a>当前时间: {time} </a>"

# Optional navbar
# links: [] # Allows for navbar (dark mode, layout, and search) without any links
links:
- name: "Contribute"
icon: "fab fa-github"
url: ""
target: "_blank" # optional html a tag target attribute
- name: "Wiki"
icon: "fas fa-book"
url: ""
# this will link to a second homer page that will load config from additional-page.yml and keep default config values as in config.yml file
# see url field and assets/additional-page.yml.dist used in this example:
#- name: "another page!"
# icon: "fas fa-file-alt"
# url: "#additional-page"

# Services
# First level array represent a group.
# Leave only a "items" key if not using group (group name, icon & tagstyle are optional, section separation will not be displayed).
services:
- name: "非HTTP服务"
icon: "fa-solid fa-ethernet"
items:
- name: "OpenVPN"
logo: "/assets/icons/openvpn.png"
subtitle: "TCP:端口: {STUN_openvpn_PORT} "
url: ""
- name: "WireGuard"
logo: "/assets/icons/wireguard.png"
subtitle: "UDP端口: {STUN_wg_PORT} "
url: ""
- name: "网络唤醒"
icon: "fa-solid fa-power-off"
subtitle: "端口: {STUN_wol_PORT} "
url: ""
- name: "HTTP服务"
icon: "fa-solid fa-server"
items:
- name: "OpenWrt WebUI"
logo: "/assets/icons/openwrt.png"
subtitle: ""
url: "https://对应服务的重定向后域名:{STUN_http_PORT}"
target: "_blank"
- name: "qbittorrent WebUI"
logo: "/assets/icons/qbittorrent.svg"
subtitle: ""
url: "https://对应服务的重定向后域名:{STUN_http_PORT}"
target: "_blank"
- name: "Jellyfin"
logo: "/assets/icons/jellyfin.png"
subtitle: ""
url: "https://对应服务重定向后域名:{STUN_http_PORT}"
target: "_blank"

不难注意到 这些变量事实上并没有实际生效
这是因为它们写在了文件中而不是lucky内
接下来我们就需要使用lucky的 文本输出功能 来输出这些配置文件


挂载配置文件​

要想使配置文件中的 全局变量 生效 我们需要将配置文件
迁移到 lucky的 文本输出功能 中

在web规则中添加新的子规则 类型选择 文本输出
前端地址为 homer主域名/assets/config.yml
其路径与之前在磁盘上的配置文件路径相同

mount-configuration-file

输出内容为之前的写好的配置
为防止冲突 要修改原有配置文件的文件名 使其失效

modify-configuration-file-extension

完成这些设置后刷新页面 应该可以看到之前的变量已经起作用了
若刷新后无效 则需要在F12中禁用缓存再刷新 或在隐私/无痕 模式打开

demo-effect-2

如果变量依然无法显示 请检查对应的STUN穿透规则是否穿透成功


访问控制​

为提高安全性可为导航页面主体和配置文件 添加 basic验证
主体页面和配置文都件都设置相同的用户名和密码

用户名和密码以英文冒号隔开 每行一条 允许配置多条
这样只有在登录后才能显示页面并读取配置文件

basic-authentication authentication-popup

导航页对外访问​

在完成上述设置后 接下来需要做的是要让导航页面本身 可以方便的被访问到
由于导航页面本身也是依靠stun穿透实现对外访问的

因此我们也需要给导航页面本身 “固定”一下端口
比较好的方法就是沿用之前的 CF的页面规则和重定向方案
两个方案二选一即可 更推荐重定向方案其扩展性更强


结尾​

至此我们就完成了使用Homer导航页指示stun穿透后的端口的设置
事实上 homer 还有一些更高级的功能没有介绍到有兴趣的用户可自行探索