Ubuntu 无 sudo 安装花生壳并实现 SSH 内网穿透:Conda 环境部署、冲突排查与自动启动

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"

从解压结果中复制 phtunnelphddns_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,避免停止其他用户或其他实例的服务。

重复客户端还可能造成:

复制代码
设备登录账号已退出
多设备登录风险
客户端离线

处理方法是:

  1. 停止重复客户端;
  2. 重启准备长期使用的客户端;
  3. 在管理平台重新绑定账号;
  4. 再次查询 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 和启动逻辑重新组织到普通用户可写目录。

本次排障中最关键的几个结论是:

  1. 同一台机器只能保留一个主花生壳客户端实例;
  2. RPC 端口 16062 冲突会让状态查询落到错误进程;
  3. 客户端与 SSH 位于同一台机器时,内网主机应使用 127.0.0.1
  4. TCP 端口可达不代表 SSH 映射正确,必须检查远端协议头;
  5. 主机指纹变化必须先在可信通道中核对,再更新 known_hosts
  6. 迁移花生壳进程时,应保留一条独立的 Tailscale 或内网 SSH 会话作为恢复通道。
相关推荐
承渊政道1 小时前
Linux系统学习【掌握Ext系列⽂件系统的相关内容】
linux·运维·学习·文件系统·存储结构·inode
池以遇1 小时前
云原生——LVS
运维·云原生·lvs
Ivan CloudBay2 小时前
服务器关机后,网站会发生什么?
运维·服务器
数智化管理手记4 小时前
手工统计指标误差大、效率低?指标管理系统如何告别人工算数痛点?
大数据·运维·数据库·人工智能·云计算
Better Bench10 小时前
WSL2 Ubuntu 中 Claude CLI “command not found” 故障排查与修复
linux·ubuntu·claude·wsl·claudecode
实心儿儿10 小时前
Linux —— 进程间关系和守护进程
linux·运维·服务器
FII工业富联科技服务11 小时前
工业设备运维如何Agentic化?拆解Factory Brain的设备运维架构
大数据·运维·人工智能·架构·制造
Dawn-bit12 小时前
Linux磁盘管理详解
linux·运维·服务器·计算机网络·云计算
RisunJan12 小时前
Linux命令-sftp(SSH 文件传输协议客户端)
linux·运维