使用说明

Home Chat 局域网家庭聊天

找一台电脑当服务器一直开着,家里人手机连同一个 WiFi,浏览器打开就能聊。 不用注册,不用装 App,聊天记录加密存在自己电脑上。

本站不直接放文件,点上面的按钮会跳到网盘去拿(源码在 GitHub 上)。 下面这份说明是按「从零开始」写的 —— 电脑怎么装、手机怎么连、连不上怎么查,都在里面。 全都放在本地,不需要买服务器,也不用域名。

家里的聊天工具。

找一台电脑当服务器,一直开着。家里人手机连同一个 WiFi,浏览器打开就能聊。不用注册,不用装 App,聊天记录加密存在自己电脑上,不上云。

现在只有 macOS 版。Windows 版还在做,功能一样,区别只在怎么装,装法会另外写一份。

初始密码是 123456,跑起来之后记得改成自己的,怎么改往下看。

要准备什么#

一台 Mac,一直开着当服务器 —— macOS 11 以上(Big Sur 之后的都行)。

Node.js 18 以上。没有的话去 nodejs.org 下 LTS 版,双击,一路下一步。

家里人手机和这台 Mac 连同一个 WiFi。

就这几样。不用买服务器,不用域名,不用备案,也不用公网 IP。

手机端不用装 App,浏览器打开就行;想当 App 用,Safari 里点分享、选「添加到主屏幕」。

怎么装#

第一步 · 装 Node.js#

终端里敲:

Terminal window
node -v

能出来版本号就有了。没有就去 nodejs.org 装一个,装完把终端窗口关了重开,再敲一次确认。

第二步 · 装依赖#

整个项目只用了一个外部库(ws,200 多 KB)。

拿到的是我打包好的 zip,里面已经带了,这步跳过。从 GitHub 上 clone 下来的话仓库里没有,装一下:

Terminal window
cd server
npm install

项目里配好了国内镜像,不用梯子。

第三步 · 启动#

双击 启动HomeChat.command。

第一次双击,系统可能说「无法打开,来自身份不明的开发者」—— 右键点它,选「打开」,再点一次「打开」。以后就不问了。

窗口里会刷一堆东西,最后停在两行:

就绪 192.168.1.23:8787
[udp] 设备发现已监听 8787/udp

前面那个 192.168.1.23 就是要记的地址。每台机器不一样,以你自己窗口里打印的为准。 这个窗口别关,关了服务就停了,最小化没问题。

第四步 · 手机连上来#

手机浏览器打开 http://192.168.1.23:8787(换成你自己那个),然后填:

填什么填成什么
电脑地址上面那个
你的名字随便起,比如「爸爸」
密码123456

点连接。第一次不会直接进去 —— 手机还没入册,得先在电脑上放行一次。

第五步 · 在电脑上放行#

双击 打开服务监控.command。

页面上会跳出一条待批准,写着「某某手机想加入」,点【同意】,手机那边立刻就进去了。

也可以看启动服务那个黑窗口,那里也会提示,按 Y 再回车。

放行一次就够了,但每台手机第一次都得放行。

六个快捷方式#

双击这个干什么
启动HomeChat.command开始服务,平时就双击这个
停止HomeChat.command停掉服务
打开服务监控.command看监控面板,新手机也在这里放行
打开电脑版聊天.command在 Mac 上直接聊
改密码.command改聊天密码和后台密码
清空数据.command账号和聊天记录全清掉

监控面板也能自己开浏览器输:http://127.0.0.1:8787/admin。密码跟聊天密码一样,除非你单独设了后台密码。

面板上只有统计数字:谁在线、今天发了多少条、内存占了多少、阅后即焚排掉多少条。聊天内容一条都看不到。

怎么用#

聊天#

电脑上回车是发送,Shift + 回车 是换行。

手机上回车是换行,点右边那个按钮发送 —— 手机键盘没有 Shift,只能这样。

发图片和文件#

点输入框左边的 +。

图片先在手机上压到长边 1280 像素再发,省流量也省电脑内存。原图最大 40MB,压完大概 3MB。普通文件最大 32MB。

语音#

点输入框左边那个话筒,按住说话。最长 60 秒,到点自动发。

松手不会直接发出去,会先出来一条:

3″ [试听] [重录] [取消] [发送]

先听一遍,不满意点重录,满意了点发送。

阅后即焚#

一直开着,关不掉。对方读完 30 秒,服务端把那条从硬盘上抹掉。

界面上没有任何提示。 没有小火苗,没有倒计时,没有「已销毁」。这是故意的。

撤回#

自己发的消息,2 分钟之内能撤回。长按那条,点撤回。

撤回之后两边都变成「你撤回了一条消息」,服务端硬盘上那条也一起抹掉。

已读#

对方看了,你这条会变成「已读」。纯文字,没有对勾。

搜索#

会话列表顶上搜的是人和群。

想搜聊天记录,进那个聊天,点右上角放大镜,搜的是这个聊天里的内容。

改密码#

双击 改密码.command。

两个密码:聊天密码是家里人手机连上来输的那个,后台密码是开监控面板输的那个。可以设成一样的,省事;也可以分开,更保险 —— 知道聊天密码的人就进不了后台。

改密码的时候会把所有聊天记录重新加密一遍,一条都不会丢。

为什么要重新加密:密码不是存在某个地方等着比对的,它本身就是加密用的钥匙。换钥匙就得把旧数据全解开,再用新钥匙重新封上。

改完之后:

  1. 双击 启动HomeChat.command 重启
  2. 每台手机用新密码重新登一次
  3. 手机上那份旧存档读不出来了(也是旧钥匙加的密),不要紧,重新登录会从电脑上把记录拉回来
  4. 开监控面板用后台密码

改之前会自动备份一份到 data.备份-时间戳,反悔了把那个目录改回 data 就行。

密码存在 data/config.local.json 里,不在代码里,所以项目传到 GitHub 上也不会带出你的密码。那个文件权限是 600,只有你自己读得到。

清空数据#

双击 清空数据.command。

会删掉:聊天记录、成员账号、群聊、备注名、头像、已读位置、撤回记录,还有加密钥匙本身。 不会动:代码,密码设置(密码还是你现在那个)。

手机上的本地存档不归它管,那个在手机里,要清得在手机上清。

跑之前要输 YES 确认,也会先自动备份一份。跑的时候服务端必须是停的,先双击 停止HomeChat.command。

连不上怎么办#

先查这三条,九成的问题都在这:

  1. 手机和电脑是不是同一个 WiFi —— 手机用流量,或者一个连 5G 频段一个连 2.4G,有时候也算两个网
  2. 电脑上那个黑窗口还开着吗 —— 关了服务就停了
  3. 地址有没有抄错 —— 以电脑窗口里打印的为准,别猜

还是不行,多半是路由器的 AP 隔离。

这是连不上的头号原因。不少路由器默认开着「AP 隔离」或者「客户端隔离」,同一个 WiFi 下的设备互相看不见,自然连不上。去路由器后台看看(浏览器打开 192.168.1.1 或 192.168.0.1),在「无线设置」一类的页面里,把 AP 隔离、客户端隔离、无线隔离这几个开关关掉。各家叫法不同,意思都一样。

电脑休眠了怎么办

笔记本合盖就休眠,服务跟着停。想让它一直跑:系统设置 → 锁定屏幕 → 关掉「显示器关闭时自动进入睡眠」,插电那边把「防止电脑自动进入睡眠」打开。台式机(iMac、Mac mini、Mac Pro)不用管这条。

手机那边什么都不用做。醒来自己重连,中间错过的消息一条不差地补回来。

手机上的一些事#

收不到消息提醒 —— 安卓为了省电会杀后台,各家杀法还不一样。进「我的」→「后台收消息」,那里认得出你是什么牌子的手机,会写出对应的设置步骤,点一下还能直接跳到系统设置页。小米、vivo、华为、OPPO、三星、谷歌都做了。

禁止截屏 —— 安卓上能拦,系统级的,截屏会提示「无法截图」。iPhone 上拦不了,苹果没给这个接口,浏览器里也拦不了。「我的」→「防护状态」会如实告诉你这台到底拦住没有:显示「系统没拦住截屏」就是真没拦住,换个地方也一样。

加到桌面 —— Safari 打开聊天页,点分享,选「添加到主屏幕」,用起来跟 App 差不多。

项目目录里都是什么#

app/ 网页源码,手机和电脑共用这一份
index.html 页面结构
css/ 样式
js/ 逻辑
hc1.js 加密
store.js 本地数据
net.js 跟服务端通信
media.js 图片、语音、文件
ui.js 界面渲染
app.js 主流程
logo.png 登录页图标,想换直接替换这个文件
server/ 服务端
src/
index.js 启动入口
hub.js 消息转发中心
store.js 数据落盘
http.js HTTP 接口
crypto.js 加密实现
net.js 网络看门狗,断网自动停服
filecache.js 文件中转,只在内存里
discovery.js UDP 设备发现
config.js 配置
setpass.js 改密码
cleardata.js 清空数据
showpass.js 把当前密码打出来,给快捷方式用
各种 test.js 自检,跑法看下面
admin/ 监控面板
data/ 你的数据,自动生成,不会传到 GitHub 上
带 .command 的 双击就能跑的脚本

跑测试#

Terminal window
cd server
npm test

想单独跑某一种:

Terminal window
node src/selftest.js 加密层的标准测试向量
node src/domtest.js 页面元素和 JS 引用对不对得上
node src/apitest.js 模块之间调用的方法存不存在
node src/crosstest.js 手机端和服务端的加密对不对得上
node src/webtest.js 页面和各种地址能不能正常加载
node src/boottest.js 把界面启动一遍看会不会崩
node src/voicetest.js 录音权限和语音消息
node src/e2etest.js 两台手机连上来跑完整的收发
node src/audit.js 安全自查,起一个真服务端试各种越权

这些测试都跑在临时目录里,不会碰你的 data/。

技术上的几件事#

加密 —— 内容用 HMAC-SHA256 做的流密码,先加密再签名。钥匙从密码来,PBKDF2-HMAC-SHA256 跑 30 万轮。

局域网里跑的是明文 http。内容本身是密的,但抓包能看出「谁在跟谁说话、什么时候、大概多大的量」。为什么不上 https:家里没域名没证书,自签证书浏览器一片红,还得教家里人点「继续访问」,不划算。

协议 —— 一个 8787 端口干四件事:HTTP 页面、WebSocket 聊天、文件上传、UDP 设备发现。防火墙只开一个口,家里人只记一个地址。

文件中转不写盘 —— 发的图片、语音、文件只在服务端内存里待 5 分钟。对方取走或者超时就丢,一个字节都不落硬盘。所以对方当时不在线就收不到了,消息还在,点开时会说「文件已不在」。单个文件上限 32MB,内存总共 64MB,超了按最老的先丢。

消息不会丢 —— 每条消息有个服务端生成的连续编号。客户端记着「我收到第几号了」,断线、锁屏、切出去再回来,带着这个号去要缺的那一段。不看时间戳 —— 时间戳是发送方手机给的,手机时钟不准就乱套了。

已知限制#

iPhone 后台收不到消息 —— 苹果只让它的推送服务唤醒 App,你家这台 Mac 不在那套体系里。实际用起来是:打开就实时收,锁屏期间的消息在打开那一瞬间全部补上,一条不丢。

安卓 App 被杀之后收不到通知 —— 同上,本地通知得进程活着才能弹。真正的离线推送要接厂商通道,那要注册账号、消息过第三方服务器,跟「不上云」冲突,所以没做。

浏览器里拦不了截屏 —— 网页没有这个接口,只有原生 App 能拦。

电脑休眠等于服务停 —— 醒了自动恢复,手机也会自己重连。

别人拿另一台手机拍你的屏幕 —— 这个任何软件都防不住。

许可#

MIT。随便用,随便改。