如果你在局域网里维护过三五个服务,一定会遇到同一个烦恼:服务器上跑着文件共享、远程桌面、本地模型 Web 界面,手机在同一 WiFi 下要访问它们,每次都得手输 IP 和端口。出门之后想继续访问,还得面对公网隧道这堵墙。dsh-pocket 就是我把这两件事接起来之后沉淀下来的最短路径:局域网内扫码直达服务页,公网侧用一条隧道把关键服务接出去。这篇文章按我实测的顺序,把部署、扫码、隧道配置到最终验证的每一步都写清楚,踩过的坑直接标出来,你可以照着抄。
1. dsh-pocket 到底在解决什么问题:入口、扫码和隧道的关系
1.1 局域网服务入口混乱是第一个痛点
一个上规模的局域网,服务数量很快就会超过你的记忆上限。我自己家里就有路由器后台、NAS 的文件管理页、两台台式机的远程桌面、一台跑 WAMP 的老笔记本、再加上本地模型服务,加起来六个入口。每个入口都是"IP:端口",排成一串,手机浏览器又没有书签栏让你长期存着,每次访问都是在碰运气。局域网 IP 扫描软件能帮你找到设备,但它只解决"发现"这一步,不解决"访问"这一步。
dsh-pocket 做的就是把发现和访问合并:它先把局域网内可达的服务扫出来、登记好,再用一个页面把这些入口统一展示,最后把页面地址做成二维码。这样访问一个服务就从"回忆地址"变成了"扫码再点卡片"。这个转变看着不起眼,但一天访问十几次的时候,省下来的时间和耐心是实打实的。
1.2 dsh-pocket 的工作逻辑
你可以把它理解成一个"局域网服务管家",分三层。第一层是发现:它会扫你指定的 IP 段,默认根据本机网卡自动算,也可以手动填段,探测常见端口,把识别出来的 SMB、RDP、HTTP 服务列出来。第二层是登记:扫描结果只是参考,你还可以手动添加服务,把名称、IP、端口、协议类型填进去,这样哪怕某个服务不在常见端口上也能被管理。第三层是入口:所有登记过的服务会出现在一个 dashboard 页面上,点击直接跳转,不再需要输入端口。
这个 dashboard 的地址本身可以被生成二维码,每个服务也可以单独生成二维码。所谓"口袋",就在于它把整套流程塞进了很小的安装包和很短的操作路径里,不需要你维护一个复杂的门户系统。它不做权限管理那套重活,也不替代防火墙,它只负责把入口收拢,剩下的安全策略你该配还得配。
1.3 它适合谁,不适合谁
适合三类人:一是家里有 NAS、文件共享、远程桌面需求,手机又经常要在局域网里访问的人;二是小办公室,想把同事常用的内网入口统一成一张页面,省得每个人都在记 IP;三是跑本地大模型服务的用户,比如 DeepSeek Harness 这类,想在离线局域网环境下把 Web 界面推到手机上用,这也是 dsh 这个名字经常和"离线局域网"一起出现的原因。
不适合的人也有:你根本没有一台常年开机的局域网机器,那扫码入口就没有着落;或者你所有服务都有正规的外网域名和运维体系,那再用这套反而多余。工具是拿来解决具体问题的,别为了上工具而上工具。
2. 部署 dsh-pocket:先让局域网内扫码这件事成立
2.1 部署环境和最小依赖
最理想的环境是一台常年开机的 Linux 机器或 NAS,因为后面公网隧道也要靠它长期挂着。我用的是一台 NUC,系统是 Debian,机器本身性能一般,但省电、体积小、本来就常年不开关机,正好适合当这个角色。安装方式我用的是 Docker,一条命令就能拉起来:
docker run -d --name dsh-pocket --restart unless-stopped \ -p 8080:8080 \ -v /opt/dsh-pocket/data:/data \ dsh-pocket/dsh-pocket:latest如果你不想用 Docker,官方也提供单个二进制文件,下载后直接./dsh-pocket serve --listen :8080就能跑。启动后用浏览器打开http://本机IP:8080,看到配置向导就说明成功了。这里有一个容易被忽略的点:容器端口映射-p 8080:8080默认绑定在主机的 0.0.0.0 上,所以局域网内其他设备才能访问;如果以后发现手机打不开,先怀疑这里。
2.2 把局域网里的服务登记进来
打开 dashboard 后,第一步是设置扫描范围。如果主机 IP 是 192.168.1.20,默认扫描段就是 192.168.1.0/24,这个判断对大多数家用路由器都成立。扫描起来很快,几百台设备的网段也就几秒到十几秒。扫描结果的识别规则大致是这样的:
| 端口 | 识别结果 |
|---|---|
| 445 | SMB 文件共享 |
| 3389 | Windows 远程桌面 |
| 80 / 8080 | HTTP Web 服务 |
| 11434 | Ollama 本地模型服务 |
| 62222 | 部分 NAS 的管理端口 |
扫描只是帮你发现,真正要纳入管理还是建议手动添加,尤其是那些没有固定端口、或者只对特定设备开放的服务。添加时填四项:显示名称、IP、端口、协议类型(HTTP 或 TCP)。HTTP 类型后面会以跳转方式打开,TCP 类型用来记录远程桌面这类非 HTTP 服务的入口信息。协议类型别搞错,否则扫码后浏览器会尝试用网页去打开一个 TCP 端口,大概率只看到一片空白。
2.3 生成第一个二维码
登记完服务,dashboard 会为每个服务生成独立的二维码,页面顶部也有一个整页二维码。二维码内容本质上就是 URL,格式是http://192.168.1.20:8080或http://192.168.1.20:8080/svc/xxx。手机连同一个 WiFi 后扫整页二维码,就能直接打开 dashboard。
第一次扫通的时候你是感受不到什么魔力的,因为整个动作太快了,但对比一下以前"找地址再敲端口"的流程,差距立刻出来。有一点要提前说明:微信自带扫码打开局域网地址时,有些版本会提示"非官方页面"或者干脆拦截,这不是 dsh-pocket 的问题,用手机系统自带的相机扫,或者扫码后选择在系统浏览器里打开,体验会顺畅很多。
3. 手机扫码打不开?访问链路上的三个典型伏笔
我帮同事排查过四五次"扫码打不开"的情况,最后发现原因基本都逃不出下面这三类。它们单独看都是小事,叠在一起能把人绕晕。
3.1 监听在 127.0.0.1 上的服务,局域网永远够不着
第一个经典坑:服务本身没病,但监听地址写的是 127.0.0.1。在主机上用curl http://localhost:8080一切正常,二维码也没错,但手机一访问就是"连接被拒绝"。原因很简单,监听在 127.0.0.1 意味着只有本机能连,局域网里其他设备从网络层面就被拒了。排查方法是在主机上执行:
netstat -tlnp | grep 8080看到监听地址是 127.0.0.1:8080 而不是 0.0.0.0:8080,问题就实锤了。解决办法要么改服务配置里的监听地址,要么用 Docker 时确认-p参数绑定了 0.0.0.0。这个坑在 WAMP、各种开发服务器、以及不少默认配置保守的工具上特别常见,值得优先排查。
3.2 路由器 AP 隔离和系统防火墙的拦截
第二个坑更隐蔽。手机明明连着同一个 WiFi,既能上外网,也能访问互联网上的任何 IP,但就是访问不了局域网主机。这时候先别怀疑 dsh-pocket,去检查路由器是不是开了"AP 隔离"或"访客网络隔离"。很多双频路由默认把访客网络和主网络隔开,手机如果连的是访客 SSID,设备之间互相不可见,扫码当然没用。把手机切到主 WiFi 试试,通了就说明是这个问题。
另外还要看主机系统防火墙:Windows 上如果服务端口没有加"入站允许"规则,局域网设备一样会被挡。顺手检查路由器后台里有没有开"无线隔离"之类的开关,有些路由叫法不一样,但作用相同。排查这类网络隔离问题,有个口诀:先同段、再互通、后端口。先确认手机和主机在同一个网段,再确认两个设备互相能 ping 通,最后才轮到分析端口。
3.3 DHCP 漂移:二维码里写死的 IP 会过期
二维码里存的是 URL,URL 里写死了 IP。今天主机是 192.168.1.20,明天路由器 DHCP 一续约,可能就变成 192.168.1.33,那二维码就等于作废了。这个问题在部署前期不容易发现,因为刚配好的时候 IP 没变,一切正常,过几天突然打不开,很容易误判成隧道或服务的故障。
我的做法是两步:第一步,在路由器后台给这台主机的 MAC 绑定固定 IP,DHCP 静态绑定是家用路由器都有的功能;第二步,把 dsh-pocket 里的服务地址统一改成固定 IP,不用主机名,避免局域网里解析出问题。如果你的路由器老到不支持静态绑定,那就只能在主机上手动配置静态 IP,同时把 DHCP 地址池范围往旁边挪一挪,避免冲突。
4. 走出局域网:公网隧道选型与最短配置
局域网内扫码解决的是"在家里"的问题,人一出门,这套就失效了。把局域网服务接到公网,核心思路是让外部设备经过一台公网可达的机器,再转回你内网的服务。这个"中转"的位置就是隧道。
4.1 判断自己有没有公网 IP 是第一步
选择方案之前先花两分钟判断网络现状。登录路由器管理后台,看 WAN 口 IP:如果 WAN IP 是 100.64.x.x、192.168.x.x 这类保留地址,而你确认自己的宽带本身就是拨号上网,那基本可以断定处于运营商的大内网(CGNAT)后面,外界无法直接访问你。用手机流量访问"查 IP"类网站,把结果和路由器 WAN IP 对比:一致说明你可能真有公网 IP,不一致说明中间隔了一层 NAT。
有公网 IP 的人可以直接在路由器上做端口转发,不需要隧道;但很多人现在不具备这个条件,尤其 IPv4 地址资源紧张,所以隧道方案成了通用解。另外要提醒:就算有公网 IP,80 和 443 这样的常用端口也可能被限制,做端口转发时尽量用高位端口,省得到时候明明通了却"假装不通"。
4.2 隧道工具怎么选
隧道工具本质上分两类:自建和托管。自建的代表是 frp,需要你有一台公网服务器(云主机即可),服务端装在服务器上,客户端装在局域网主机上;托管的代表是 cpolar、花生壳这类,它们把服务器那一端给你准备好了,你只需要在局域网机器上跑一个客户端。
| 方案 | 需要什么 | 优点 | 注意点 |
|---|---|---|---|
| frp 自建 | 一台公网云服务器 | 配置自由、端口和域名完全自主 | 服务器要自己维护,有最低成本 |
| cpolar | 注册账号、装客户端 | 上手快,临时隧道一条命令 | 免费版域名随机,固定域名要付费 |
| 花生壳 | 注册账号、装客户端 | 中文界面友好,适合不折腾命令行的人 | 免费带宽有限,规则多 |
选型逻辑很简单:如果你本来就有云服务器,frp 几乎是零额外成本,性能也可控;如果你不想碰服务器,只想快点把服务接到外网,用托管隧道更省心。我个人是 frp 和 cpolar 都在用,长期服务走 frp,临时演示给别人看的时候开一条 cpolar 隧道。
4.3 frp 自建隧道的最短配置
frp 的配置说穿了就两个文件。服务端(frps):
[common] bind_port = 7000 vhost_http_port = 18080 token = 你的随机长字符串客户端(frpc):
[common] server_addr = 云服务器IP或域名 server_port = 7000 token = 你的随机长字符串 [dsh-pocket] type = http local_ip = 127.0.0.1 local_port = 8080 custom_domains = dsh.example.com服务端一条命令./frps -c frps.ini,客户端./frpc -c frpc.ini,通了之后你在公网访问http://dsh.example.com:18080就能回到内网 8080。这里custom_domains需要你把这个域名解析到云服务器。如果你没有域名,也可以改成 TCP 映射,核心字段变成type = tcp、local_port = 8080、remote_port = 18080,这样公网访问就是云服务器IP:18080。TCP 映射最简单,但它只有一个 IP 加一个端口,看起来比较丑;域名方式更规整,但要多一步解析工作。
token 一定要设成随机长字符串,别用默认值,因为所有连到你这台 frps 的客户端都靠它验证身份。这个配置里每一个字段都有用途,别看着多就删;尤其是local_ip在 frpc 本机写 127.0.0.1 没问题,因为 frpc 和 dsh-pocket 跑在同一台机器上。
4.4 不想碰服务器就用托管隧道
托管隧道的优势就是快。以 cpolar 为例,装好客户端后一条命令:
cpolar http 8080它会给你一个随机域名,公网立刻可以访问局域网里的 8080。免费版的问题在于这个域名每次重启都会变,你要是拿它做长期入口,体验就很差,所以我只在临时演示时用。长期用的话建议升级固定域名,或者干脆用 frp 自建。花生壳的逻辑类似,客户端图形界面更友好,适合不愿意碰命令行的朋友,但免费带宽比较紧张,访问量稍大就会卡。托管隧道普遍自带 HTTPS 证书,这一点倒是比 frp 裸 HTTP 舒服,不需要自己折腾。
顺便说一句,"有公网服务器但不想折腾 frp"的中间派,还可以在服务器上直接装 caddy 之类的转发层,把某个域名转发到 frp 暴露出来的端口,这样 HTTPS 证书和优雅的域名都能拿到。链路长了一层,但换来的是干净地址和浏览器不报错,值。
5. 内网和外网统一入口:把隧道地址接回 dsh-pocket
隧道配通了,dsh-pocket 这边还要做最后一步:让它在内网和外网两种场景下都能给出正确的入口。这一步不做,你出门后依然得手动记"云服务器IP:端口"。
5.1 端口映射关系先理顺
先把你要暴露的服务列个清单,明确内网端口和公网端口之间的对应关系。以我为例:
| 内网服务 | 内网地址 | 公网映射 |
|---|---|---|
| dsh-pocket dashboard | 192.168.1.20:8080 | 1.2.3.4:18080 |
| Windows 远程桌面 | 192.168.1.10:3389 | 1.2.3.4:13389 |
| 本地模型 Web 界面 | 192.168.1.20:8088 | 1.2.3.4:18088 |
端口规划有个经验:公网侧全部用高位端口(大于 1024),不要图省事把 8080 直接映射成 8080,也要避免常见的 20xx、80xx 这些容易被端口扫描盯上的数字。每一条映射都要在 frpc 配置里再检查一遍local_port和remote_port有没有填反,我因为这两个字段填反白折腾过一个小时。
5.2 内外两套二维码,各扫各的
dsh-pocket 的 dashboard 里可以配置"外网入口"。填上http://1.2.3.4:18080/dashboard之后,它会自动生成第二套二维码,和局域网版本的二维码并存。我的习惯是:把内网二维码放在手机相册里,专门在家里用;公网二维码放在另一个相簿,出门就扫它。两个二维码内容不同,但指向的是同一个服务的两种入口,切换对用户无感。
这里有个常见错误:有人把二维码内容直接填成http://localhost:8080,自己扫的时候当然打不开,因为手机上的 localhost 是手机自己。记住一点:内网入口必须填局域网能解析的 IP,公网入口必须填公网可达的域名或 IP。这一步虽然简单,但它是整条链路里最容易偷懒出错的一环。
5.3 跨局域网远程桌面的完整例子
远程桌面是"跨局域网"需求里最典型的一个。局域网内,我在电脑上开远程桌面连接,地址填192.168.1.10就行。出了门之后,如果我已经把 3389 端口用 frp 映射成了云服务器的 13389,那远程桌面客户端里地址就要填1.2.3.4:13389,用户名密码照旧。手机端的 Microsoft Remote Desktop 也是同样的写法。
这个链路我实测下来基本顺畅,前提是注意三点:第一,frpc 客户端必须设置成开机自启,否则主机一重启,映射就断了,配一个 systemd 服务或者在 frp 官方脚本里勾选自启都行;第二,远程桌面直接暴露公网会被端口扫描器盯上,默认 3389 的爆破尝试非常多,能换端口就换端口,操作系统账户务必设强密码;第三,如果有条件,给远程桌面套一层有身份验证的跳板,哪怕只有一道登录页,安全压力都会小很多。在 dsh-pocket 里,把"远程桌面"这个服务条目标记为"需要口令",扫码后先过登录页,再进系统,算是一个轻量级的缓解措施。
6. 实测中最常翻车的场景与安全底线
最后一部分是经验值,把我在这条链路上翻过的车和最终沉淀下来的安全习惯写清楚。
6.1 五个高频故障和排查顺序
最常见的故障基本就这些:
| 现象 | 根因 | 处理 |
|---|---|---|
| 公网访问超时 | frpc 没启动或挂了 | 检查 frpc 进程,配 systemd 开机自启 |
| remote_port 起不来 | 服务器上该端口被占 | frps 换一个高位端口 |
| 客户端握手失败 | token 不一致 | 看 frpc 日志,对比两个配置文件的 token |
| 手机扫码打不开 | 二维码用了 localhost 或服务只监听 127.0.0.1 | 改成局域网 IP / 0.0.0.0 |
| 域名能访问但证书报错 | frp 裸 HTTP 没证书 | 用托管隧道,或用 caddy 给域名加 HTTPS |
排查顺序建议从内到外:先在局域网主机上用curl测本地服务通不通;再用同一局域网里的手机直连192.168.x.x:端口测;然后到公网用另一台设备访问云服务器IP:端口。在哪一步断,问题就在哪一段。千万别一上来就重装 frp,八成是在浪费力气。记住一条:链路越长,越要先从链路最靠近自己的一端查起。
6.2 暴露到公网的安全边界
不是所有服务都适合通过隧道暴露到公网。我把自己的服务按"能不能暴露"分了三级:第一级是坚决不能暴露的,比如 SMB 共享、路由器的管理后台、没有任何登录验证的页面;第二级是可以暴露但要加条件的,比如远程桌面(要换端口、强密码)、文件下载页(只读权限)、本地模型服务的 Web 界面(必须带登录);第三级是本身就有完善认证的,可以放心一点。
我的安全底线就三条:固定 IP 减少意外入口,强密码挡住弱口令扫描,最小暴露原则——只映射真正要远程访问的那一两个端口,其他全部留在局域网里。日志也要偶尔翻一翻,frps 的日志里突然出现大量来自陌生 IP 的连接尝试,那就要警觉,该关映射就关,绝不让它过夜。
最后再分享一个小习惯:我把 dsh-pocket 的整页二维码同时放进了手机相册和冰箱贴旁边,内网二维码配公网二维码并排摆。有人来家里做客想要共享文件或连服务,顺手扫一下就能看到我能共享出去的几个页面,完全不用我再口头报 IP。这套流程跑通之后,我最大的体会是:内网访问和公网访问本来是两个问题,但用一个工具把它们接在一起,路径反而最短。