1. 背景
有些实验室服务器或共享工作站只提供普通用户权限,无法执行 sudo dpkg -i,但又需要从公网通过 SSH 访问服务器。
本文记录一种实际可行的方案:
- 不使用
sudo; - 将花生壳客户端安装在指定 Conda 环境;
- 使用 TCP 映射发布本机 SSH 服务;
- 排查重复客户端、端口冲突、设备离线和 SSH 主机指纹变化;
- 使用普通用户的
crontab实现开机启动与定时守护。
安全说明:文中的用户名、设备 SN、域名、IP、端口和密钥均使用占位符。请勿在公开文章、截图或日志中泄露自己的真实信息。
2. 环境与目标
示例环境:
系统:Ubuntu x86_64
权限:普通用户,无 sudo
Conda 环境:<CONDA_PREFIX>
本地 SSH:127.0.0.1:22
映射协议:TCP
先确认系统架构和 SSH 服务:
dpkg --print-architecture
timeout 3 bash -c \
'exec 3<>/dev/tcp/127.0.0.1/22; head -n 1 <&3'
正常情况下会得到:
amd64
SSH-2.0-OpenSSH_...
3. 下载并解压客户端
从贝锐花生壳官方网站下载与系统架构匹配的 Linux DEB 安装包。由于没有管理员权限,不能执行 dpkg -i,改用 dpkg-deb 解压。
conda activate <ENV_NAME>
export ORAY_PREFIX="$CONDA_PREFIX/opt/oray"
mkdir -p "$ORAY_PREFIX/rootfs" "$ORAY_PREFIX/control"
cd /tmp
wget -c <OFFICIAL_DEB_DOWNLOAD_URL> -O phddns_amd64.deb
dpkg-deb -x phddns_amd64.deb "$ORAY_PREFIX/rootfs"
dpkg-deb -e phddns_amd64.deb "$ORAY_PREFIX/control"
find "$ORAY_PREFIX" -maxdepth 5 -type f -printf '%p\n'
确认目录中存在 phtunnel、管理页面文件以及安装脚本。
查看客户端支持的参数:
"$ORAY_PREFIX/rootfs/usr/bin/phtunnel" --help
常用参数包括:
-l, --log 日志路径
-c, --config 配置文件
-p, --pid PID 文件
-r, --rpc 启用本地 RPC
-P, --rpcport RPC 端口,默认为 16062
-f, --forward 本地管理页面转发地址
4. 用户级运行目录
建议将配置、日志和 PID 文件全部放在 Conda 环境中:
export ORAY_HOME="$CONDA_PREFIX/opt/oray"
mkdir -p \
"$ORAY_HOME/bin" \
"$ORAY_HOME/state" \
"$ORAY_HOME/log" \
"$ORAY_HOME/run" \
"$ORAY_HOME/www"
从解压结果中复制 phtunnel、phddns_mini_httpd 和管理页面资源到上述目录。启动时应使用安装包自带脚本中的 App ID、App Key 和设备信息参数,不要将这些值发布到公开仓库或博客。
推荐把启动命令封装为:
$CONDA_PREFIX/opt/oray/bin/start.sh
$CONDA_PREFIX/opt/oray/bin/stop.sh
$CONDA_PREFIX/opt/oray/bin/status.sh
启动后检查进程:
pgrep -af 'phtunnel|phddns_mini_httpd'
5. 获取设备状态并绑定账号
启用本地 RPC 后,可查询设备状态:
wget -qO- -T 5 \
http://127.0.0.1:16062/ora_service/getsn
echo
返回示例:
{
"result_code": 0,
"data": {
"device_sn": "<DEVICE_SN>",
"device_sn_pwd": "<DEVICE_PASSWORD>",
"status": 1,
"public_ip": "<PUBLIC_IP>"
}
}
状态值含义:
0:离线或尚未绑定
1:在线
2:登录中
3:重试中
在贝锐管理平台使用设备 SN 登录,然后绑定自己的贝锐账号。绑定账号的输入框应填写"贝锐账号",不要误填设备 SN。
6. 常见故障一:RPC 端口 16062 被占用
如果日志出现:
bind address(127.0.0.1) with port(16062) failed(98)
说明已经有另一个花生壳客户端占用 RPC 端口。检查所有相关进程:
pgrep -af 'phtunnel|phddns_mini_httpd|phdaemon'
ss -lntp 'sport = :16062'
只保留一个客户端。不要直接执行不加范围的 killall phtunnel,应先确认进程路径和 PID,避免停止其他用户或其他实例的服务。
重复客户端还可能造成:
设备登录账号已退出
多设备登录风险
客户端离线
处理方法是:
- 停止重复客户端;
- 重启准备长期使用的客户端;
- 在管理平台重新绑定账号;
- 再次查询 RPC,确认
"status":1。
7. 创建 SSH TCP 映射
进入花生壳管理平台的"内网穿透",创建或修改映射:
映射名称:Ubuntu-SSH
映射协议:TCP
内网主机:127.0.0.1
内网端口:22
外网域名:平台分配的域名
外网端口:平台分配的数字端口
访问密码/二次验证:按需配置
如果花生壳客户端和 SSH 服务在同一台服务器上,内网主机应优先填写:
127.0.0.1
将它误填为其他局域网地址,可能导致外网端口可以建立 TCP 连接,却无法获得 SSH 协议头。
8. Windows 端测试
先检查公网端口:
Test-NetConnection <PUBLIC_DOMAIN> -Port <PUBLIC_PORT>
再连接 SSH:
ssh -o ConnectTimeout=10
-p <PUBLIC_PORT>
<LINUX_USER>@<PUBLIC_DOMAIN>
如果出现:
banner exchange: invalid format
使用详细模式查看远端返回内容:
ssh -vv -o ConnectTimeout=10
-p <PUBLIC_PORT>
<LINUX_USER>@<PUBLIC_DOMAIN>
若日志显示 HTTP/1.1 200 OK 或 HTML 内容,说明当前外网端口不是原始 SSH 流量,通常需要检查:
- 映射是否为 TCP;
- 内网主机是否为
127.0.0.1; - 内网端口是否为
22; - 是否启用了访问密码或 Web 验证;
- 使用的是否为真正的 SSH 映射地址,而不是花生壳管理入口。
9. 主机指纹变化的正确处理
修改映射目标后,Windows 可能提示:
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
不要立即删除记录。先在可信的内网或 Tailscale 会话中读取服务器指纹:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
确认它与 Windows 警告中显示的指纹完全一致,再删除对应的旧记录:
ssh-keygen -R "[<PUBLIC_DOMAIN>]:<PUBLIC_PORT>"
随后重新连接并接受正确的新指纹。
10. Windows DNS 临时异常
如果公共 DNS 可以解析域名,但 Windows 暂时提示无法解析,可尝试:
ipconfig /flushdns
Resolve-DnsName <PUBLIC_DOMAIN>
-Type A
-Server 223.5.5.5
排障期间也可以临时使用花生壳中转 IP,但长期连接建议使用域名,因为中转 IP 可能变化。
11. 无 sudo 自动启动
普通用户可以使用 crontab:
crontab -e
加入:
@reboot sleep 45 && <CONDA_PREFIX>/opt/oray/bin/start.sh >> <CONDA_PREFIX>/opt/oray/log/watchdog.log 2>&1
*/5 * * * * <CONDA_PREFIX>/opt/oray/bin/start.sh >> <CONDA_PREFIX>/opt/oray/log/watchdog.log 2>&1
第一行用于开机启动,第二行每五分钟检查并恢复进程。start.sh 必须具备幂等性:客户端已经运行时不能重复启动新实例。
检查配置:
crontab -l
pgrep -af \
'<CONDA_PREFIX>/opt/oray/bin/(phtunnel|phddns_mini_httpd)'
12. Conda 环境内的管理命令
可以在 $CONDA_PREFIX/bin/phddns 中封装以下子命令:
phddns start
phddns stop
phddns restart
phddns status
phddns log
phddns version
如果当前激活的是其他 Conda 环境,出现:
phddns: command not found
这是正常现象。激活目标环境:
conda activate <ENV_NAME>
hash -r
command -v phddns
也可以直接使用绝对路径:
<CONDA_PREFIX>/bin/phddns status
13. 最终检查清单
# 客户端在线
wget -qO- -T 5 \
http://127.0.0.1:16062/ora_service/getsn
# SSH 服务正常
timeout 3 bash -c \
'exec 3<>/dev/tcp/127.0.0.1/22; head -n 1 <&3'
# 进程来自目标 Conda 环境
pgrep -af 'phtunnel|phddns_mini_httpd'
# 自动启动配置正确
crontab -l
Windows 端最终测试:
ssh -p <PUBLIC_PORT> <LINUX_USER>@<PUBLIC_DOMAIN>
当设备状态为 1、本机 SSH 返回 SSH-2.0-OpenSSH、公网 SSH 可以登录,并且进程路径位于目标 Conda 环境时,整个部署即完成。
14. 总结
无 sudo 部署花生壳的核心不是"安装 DEB",而是将 DEB 中的二进制文件、配置、日志、PID 和启动逻辑重新组织到普通用户可写目录。
本次排障中最关键的几个结论是:
- 同一台机器只能保留一个主花生壳客户端实例;
- RPC 端口
16062冲突会让状态查询落到错误进程; - 客户端与 SSH 位于同一台机器时,内网主机应使用
127.0.0.1; - TCP 端口可达不代表 SSH 映射正确,必须检查远端协议头;
- 主机指纹变化必须先在可信通道中核对,再更新
known_hosts; - 迁移花生壳进程时,应保留一条独立的 Tailscale 或内网 SSH 会话作为恢复通道。