Skip to main content

Cloud box frp client (aarch64 frpc bundled)

Project description

meiyoufrpclient(云盒 frp 客户端)

在蜂窝模块(如 Quectel RM500U)拨号联网后,从控制面 HTTP 拉取 frp 参数,生成本地 frpc 配置并启动客户端;同时提供本机状态 HTTP 接口,便于观测联网与配置阶段。

日志:运行目录下按天落盘 djcloudbox-YYYY-MM-DD.log(见 src/meiyoufrpclient/main.py)。

配置文件默认路径 ~/deploy/meiyoufrpclient.env(见 PyPI 安装);也可用 MEIYOUFRP_ENV 指定路径。包内提供 meiyoufrpclient.env.example 作模板。

启动流程简图(中文)

flowchart TD
  A[启动入口 main] --> B[初始化日志 setup_logging]
  B --> C[进入主编排 run_forever]
  C --> D[执行 bootstrap]

  D --> E[读取 client_sn]
  E --> F[初始化云盒状态 cloud_state]
  F --> G[启动本机状态接口 status_api]
  G --> H[DNS 预检查 ensure_dns_configured]

  H --> I[等待网络就绪 wait_network_ready]
  I --> J{ICMP 探测是否可用}
  J -->|可用| K[尝试预取远程配置 _try_fetch_config_as_connectivity]
  J -->|不可用| L[后台拨号 sim_dial]
  L --> M[拨号后 DNS 再检查]
  M --> I

  K --> N{是否已拿到配置}
  N -->|是| O[写入 frpc.toml]
  N -->|否| P[循环拉远程配置 wait_remote_config]
  P --> O

  O --> Q[启动 frpc 子进程]
  Q --> R[进入看门狗循环]

  R --> S[周期性网络检测 check_network_connection]
  S --> T[更新 cloud_state 网络状态]
  T --> T1[触发本机 D-BUS NetworkStatusChanged]
  T1 --> SUB[订阅端如 MeiyouDrone 可转 MQTT]
  T1 --> U[sleep 间隔]
  U --> R

编排与状态相关环境变量(FRPCLIENT_*

frpc.toml 中 frp 官方字段区分开,本进程编排与状态服务使用 FRPCLIENT_*

变量 默认 作用
FRPCLIENT_POST_DIAL_WAIT_SEC 3 拨号发出后等待几秒再做 DNS 复检
FRPCLIENT_DIAL_TIMEOUT_SEC 30 单轮拨号后持续不通网超过该秒数则重拨
FRPCLIENT_CONFIG_RETRY_SEC 30 拉控制面配置失败后的重试间隔
FRPCLIENT_WATCHDOG_INTERVAL_SEC 5 主循环网络看门狗(ICMP)间隔
FRPCLIENT_STATUS_HOST 127.0.0.1 状态 HTTP 绑定地址
FRPCLIENT_STATUS_PORT 18080 状态 HTTP 端口
FRPCLIENT_NET_FAIL_THRESHOLD 2 连续 ICMP 探测失败多少次后判定“离线”(用于 D-BUS/状态快照)
FRPCLIENT_FRPC_BIN (自动探测) frpc 可执行文件路径;未设置时依次尝试:本变量 → pip 包内 frpc_bin/frpcPATH 中的 frpc
FRPCLIENT_NO_DIAL (无) 设为 1 时跳过 sim_dial(由 systemd 等单独管拨号时使用)
FRPCLIENT_QUECTEL_CM quectel-CM 拨号可执行文件路径
FRPCLIENT_QUECTEL_CM_SUDO 1 设为 0 时不通过 sudo 调用拨号程序
FRPCLIENT_DIAL_VERBOSE 0 设为 1 时在控制台打印 quectel-CM 详细输出;默认静默写日志
FRPCLIENT_DIAL_LOG_PATH quectel-cm-YYYY-MM-DD.log FRPCLIENT_DIAL_VERBOSE=0 时 quectel-CM 输出文件路径

配置文件查找顺序(启动时自动加载文件中全部键,不覆盖已存在的环境变量):

  1. MEIYOUFRP_ENV 指向的路径
  2. ~/deploy/meiyoufrpclient.env
  3. 源码/安装目录旁 deploy/meiyoufrpclient.env

控制面相关(写在上述 env 文件中):

变量 说明
CLOUD_BOX_SN 云盒序列号;常用 eth0 MAC 大写、无冒号(例 XXXXXXXXXXXXXX
CLOUD_CONFIG_URL 控制面 API,支持 {CLOUD_BOX_SN}
CLOUD_API_SECRET 控制面 api_secret(请求头 X-Api-Secret
MEIYOUFRP_ENV 可选,显式指定 env 文件绝对路径

状态接口路由:

  • GET /health{"ok": true}
  • GET /api/v1/net/statuscloud_state 快照,并含 frp_running(是否检测到 frpc 进程)

本机 D-BUS 联网状态信号(可观测联动)

程序会在主循环的网络探测结果变化时,向系统 D-BUS 发出一个联网状态信号,供本机其它脚本订阅联动显示。

  • Bus:默认 system
  • 对象路径:/org/meiyoufrpclient/Network
  • 信号接口/成员:org.meiyoufrpclient.Network.NetworkStatusChanged
  • 信号入参顺序:
    • string client_sn
    • boolean connected
    • int32 delay_ms
    • int32 online_duration_seconds
    • string last_seen
    • string status(在线/离线)

调试订阅:

dbus-monitor --system "type='signal',interface='org.meiyoufrpclient.Network',member='NetworkStatusChanged'"

订阅端建议放在其它包中(本机同机部署 MeiyouDrone 时,由其 dbus_subscriber 订阅 D-BUS 并用业务 MQTT 发布 cloudbox/{云盒SN}/network/status),或使用 dbus-monitor 调试。

可选开关:

  • FRPCLIENT_DBUS_ENABLE=0:禁用 D-BUS 广播
  • FRPCLIENT_DBUS_BUS=session|system:选择 sessionsystem 总线(默认 system)
  • FRPCLIENT_DBUS_OFFLINE_REPEAT_SEC=5:离线状态下重复广播的最小间隔(秒);设为 0 关闭离线重复广播

网卡与探测(CLOUDBOX_*)

NetUtil.py 使用(ICMP 绑网卡顺序:先蜂窝相关接口,再有线):

  • CLOUDBOX_QUECTEL_IFACE:蜂窝接口列表,逗号分隔;默认含 wwan0,并与自动发现的 enx* USB 网卡组合。
  • CLOUDBOX_ETH_IFACE:有线/无线接口列表,逗号分隔(例 wlan0,eth0);默认 eth0
  • DNS_RESOLVECTL_INTERFACE:若填写了本机不存在的网卡名,启动时会 WARNING 提示(不会静默失败)。
  • CLOUDBOX_PING_HOST:ICMP 目标主机;默认 223.5.5.5(IP 直连,避免 DNS 波动影响联网判定)。

若本机 ping 不支持 -I(常见于 BusyBox),会回退为默认路由 ping;需要按网卡探测时可安装 iputils-ping

联网判定策略:先 ICMP(按网卡绑定 + 默认路由兜底)。在拨号阶段会直接尝试访问控制面配置接口,只要能返回合法 JSON 配置,即视为已联网并继续启动 frpc。

控制面 API 字段(v1.0.4+,仅认下列键名)

GET CLOUD_CONFIG_URL 返回 {"code":0,"data":{...}} 时,data 内须包含:

字段 示例 说明
frp_server_addr XXXXXX.com:7000 frps 地址,必须为 host:port
frp_client_port 5007 本机 SSH(22) 映射到云端的端口
frpclient_novnc_remote_port 4007 本机 noVNC(6080) 映射到云端的端口
frp_token XXXXXX 写入 frpc.tomlauth.token(必填)

不再解析旧字段(如 serverAddrFRPCLIENT_NOVNC_REMOTE_PORT、单独 frp_server_port 等)。缺任一项则拉配置失败并重试。

启动后 frpc.toml 含两条 TCP 代理:SSH → frp_client_port;noVNC → frpclient_novnc_remote_port(本地固定 6080,需板子运行 websockify + VNC 5900)。

外网 noVNC 示例(端口以 API 为准):

http://<frp_server_host>:<frpclient_novnc_remote_port>/vnc_auto.html?autoconnect=1&password=XXXXXX

仓库结构

说明:src/ 是源码根目录(src layout),实际 Python 包名是 meiyoufrpclient

meiyou-frpclient/
├── README.md
├── pyproject.toml
├── requirements.txt
├── deploy/
│   ├── meiyoufrpclient.env
│   ├── meiyoufrpclient.service      # 系统级 unit 示例(需 root)
│   └── djifrpclient.user.service    # 用户级 unit 示例
└── src/
    ├── frpc_bin/
    │   └── frpc                     # aarch64 静态链接 frpc(随 pip 包安装)
    └── meiyoufrpclient/
        ├── main.py
        ├── orchestrator.py
        ├── cloud_state.py
        ├── status_api.py
        ├── remote_config.py
        ├── dns_connectivity.py
        ├── NetUtil.py
        ├── device_utils.py
        ├── frp.py
        └── frpc.toml

模块职责一览

模块 作用
src/meiyoufrpclient/main.py 包入口:meiyoufrpclient 脚本调用入口
src/meiyoufrpclient/orchestrator.py 编排核心:状态服务 → DNS → 拨号 → 拉配置 → 启动 frp
src/meiyoufrpclient/cloud_state.py 线程安全快照:phasenetremote_debuglast_config_error
src/meiyoufrpclient/status_api.py 只读 JSON,供现场或其它进程轮询
src/meiyoufrpclient/remote_config.py GET 控制面 JSON;解析 frp_server_addr 等四个 API 字段
src/meiyoufrpclient/dns_connectivity.py DNS 核心逻辑(resolvectl / resolv 兜底 + 自定义 DNS HTTP)
src/meiyoufrpclient/NetUtil.py ICMP 与多网卡探测
src/meiyoufrpclient/device_utils.py sim_dial 等硬件相关调用
src/meiyoufrpclient/frp.py 根据 API 生成 frpc.toml(SSH + noVNC)并 Popen 启动 frpc

PyPI 安装

PyPI:https://pypi.org/project/meiyoufrpclient/

说明
Python 3.8+(嵌入式 Ubuntu 18.04 可用;建议 pip>=21
pip 升级 python3 -m pip install -U pip(3.8 可用 get-pip 3.8
架构 wheel 捆绑 aarch64 frpc;x86 请自备并设 FRPCLIENT_FRPC_BIN

国内用户推荐:

python3 -m pip install -U pip
python3 -m pip install meiyoufrpclient -i https://pypi.tuna.tsinghua.edu.cn/simple

官方源:

pip install meiyoufrpclient

安装后自检(无需先 source env,会自动读 ~/deploy/meiyoufrpclient.env):

meiyoufrpclient --check-config

wheel 内 frpc 位于 site-packages/frpc_bin/frpcfrpc.toml 由运行时写入包目录。env 不会自动创建,请复制模板:

mkdir -p ~/deploy
cp "$(python3 -c "import meiyoufrpclient, os; print(os.path.join(os.path.dirname(meiyoufrpclient.__file__), 'meiyoufrpclient.env.example'))")" ~/deploy/meiyoufrpclient.env
# 源码仓库也可: cp deploy/meiyoufrpclient.env ~/deploy/meiyoufrpclient.env
vi ~/deploy/meiyoufrpclient.env

1. 编辑 env 文件(标准路径 ~/deploy/meiyoufrpclient.env):

写入完整示例(按现场修改 SN、secret、网卡名;FRPCLIENT_FRPC_BIN 可省略):

# ---- 必填 ----
CLOUD_BOX_SN=XXXXXXXXXXXXXX
CLOUD_CONFIG_URL=https://XXXXXX/uav/other/cloudbox/api/box/{CLOUD_BOX_SN}
CLOUD_API_SECRET=XXXXXX

# ---- 主流程 ----
FRPCLIENT_POST_DIAL_WAIT_SEC=31
FRPCLIENT_DIAL_TIMEOUT_SEC=30
FRPCLIENT_CONFIG_RETRY_SEC=30
FRPCLIENT_WATCHDOG_INTERVAL_SEC=5

# ---- 拨号 ----
FRPCLIENT_NO_DIAL=0
FRPCLIENT_QUECTEL_CM=quectel-CM
FRPCLIENT_QUECTEL_CM_SUDO=1
FRPCLIENT_DIAL_VERBOSE=0
FRPCLIENT_DIAL_LOG_PATH=quectel-cm.log

# ---- frpc(可选;默认使用 pip 包内 site-packages/frpc_bin/frpc)----
# FRPCLIENT_FRPC_BIN=/path/to/custom/frpc
# frp / noVNC 云端端口仅由 API 下发,勿设 FRPCLIENT_NOVNC_REMOTE_PORT

# ---- 状态接口 ----
FRPCLIENT_STATUS_HOST=127.0.0.1
FRPCLIENT_STATUS_PORT=18080

# ---- DNS ----
DNS_PROBE_HOST=www.baidu.com
DNS_FALLBACK_NAMESERVERS=223.5.5.5,114.114.114.114
DNS_MANAGE_RESOLV_CONF=1
DNS_RESOLVECTL_INTERFACE=wlan0

# ---- 联网探测 ----
CLOUDBOX_QUECTEL_IFACE=wwan0,enxb657fb68191c
CLOUDBOX_ETH_IFACE=wlan0,eth0
CLOUDBOX_PING_HOST=223.5.5.5

保存:按 Esc,输入 :wq 回车。

2. 前台试运行(程序会自动加载 ~/deploy/meiyoufrpclient.env,一般无需 source):

meiyoufrpclient --check-config   # 建议先自检
meiyoufrpclient

3. 用户级 systemd 自启(推荐)

pip 部署时由 systemd 的 EnvironmentFile 注入全部变量,无需 source。妙算等设备无 sudo 时使用用户级 unit。

启用前先停掉前台或 nohup 实例,避免端口 18080 冲突:

pkill -f '\.local/bin/meiyoufrpclient' 2>/dev/null || true
pkill -x frpc 2>/dev/null || true

新建 unit 文件(示例可直接拷贝,按现场改 Python 版本路径):

mkdir -p ~/.config/systemd/user
vi ~/.config/systemd/user/djifrpclient.service

写入:

[Unit]
Description=meiyoufrpclient (pip install, user service)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
EnvironmentFile=-%h/deploy/meiyoufrpclient.env
ExecStart=%h/.local/bin/meiyoufrpclient
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=default.target

保存后启用:

systemctl --user daemon-reload
systemctl --user enable --now djifrpclient
loginctl enable-linger "$USER"    # 未登录时也保持用户服务运行

说明:%h 为当前用户 home;env 默认 %h/deploy/meiyoufrpclient.env。pip 安装的 unit 示例亦在 share/meiyoufrpclient/systemd/

常用运维:

systemctl --user status djifrpclient
journalctl --user -u djifrpclient -f
systemctl --user restart djifrpclient    # 改 env 后重启
systemctl --user disable --now djifrpclient

4. 系统级 systemd 自启(需 root,可选)

有 sudo 的服务器可用系统级 unit,以指定用户(如 meiyou)运行 pip 安装的 meiyoufrpclient。env 路径为 ~/deploy/meiyoufrpclient.env(须由运行用户创建)。

sudo vi /etc/systemd/system/meiyoufrpclient.service

写入(将 meiyou/home/meiyou 改为实际运行用户):

[Unit]
Description=meiyoufrpclient (pip install)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=meiyou
Group=meiyou
EnvironmentFile=-/home/meiyou/deploy/meiyoufrpclient.env
ExecStart=/home/meiyou/.local/bin/meiyoufrpclient
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

保存后启用:

sudo systemctl daemon-reload
sudo systemctl enable --now meiyoufrpclient
journalctl -u meiyoufrpclient -f

说明:须以目标用户执行 pip install meiyoufrpclient;env 放在该用户 ~/deploy/ 下。妙算等无 sudo 设备用上文 §3 用户级 unit 即可。

Ubuntu 18.04 + aarch64(妙算 / Wheeltec 等)

  1. Python 3.8 + pip:python3 -m pip install -U pip(必要时用 get-pip 3.8 脚本)
  2. pip install meiyoufrpclient -i https://pypi.tuna.tsinghua.edu.cn/simple
  3. mkdir -p ~/deploy,从 meiyoufrpclient.env.example 复制并填写 SN(eth0 MAC 大写无冒号)
  4. meiyoufrpclient --check-configmeiyoufrpclient 或配置用户级 systemd
  5. 状态:curl -sS http://127.0.0.1:18080/api/v1/net/status

启动方式

开发环境运行(不安装,frpc 自动使用 src/frpc_bin/frpc):

PYTHONPATH=src python3 -m meiyoufrpclient.main

源码 editable 安装(同样包含 frpc_bin):

python3.9 -m pip install -e .
meiyoufrpclient

源码部署 + 环境文件:

set -a && source deploy/meiyoufrpclient.env && set +a
python3 -m meiyoufrpclient.main

源码目录用户级 systemd:示例见 deploy/djifrpclient.user.service生产 pip 部署见上文 PyPI 安装 §3

系统级 systemd(需 root):见上文 PyPI 安装 §4;仓库参考 deploy/meiyoufrpclient.service

查看状态:

curl -sS http://127.0.0.1:18080/health
curl -sS http://127.0.0.1:18080/api/v1/net/status

本机快速自检(与客户端相同的 DNS/ICMP 逻辑):

PYTHONPATH=src python3 -m meiyoufrpclient.check_network
PYTHONPATH=src python3 -m meiyoufrpclient.check_network --status

依赖

pyproject.toml:Python ≥ 3.8,psutil>=5.6.4;wheel 捆绑 aarch64 frpc(约 14MB)。变更见 CHANGELOG.md

联网状态通过 D-BUS 发出,由 D-BUS 等订阅端转发 。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

meiyoufrpclient-1.0.4.tar.gz (5.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

meiyoufrpclient-1.0.4-py3-none-any.whl (5.5 MB view details)

Uploaded Python 3

File details

Details for the file meiyoufrpclient-1.0.4.tar.gz.

File metadata

  • Download URL: meiyoufrpclient-1.0.4.tar.gz
  • Upload date:
  • Size: 5.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.0

File hashes

Hashes for meiyoufrpclient-1.0.4.tar.gz
Algorithm Hash digest
SHA256 f5ca341c647226677b7e73c748c24a14b116871a1e0c2f5ba018cd43891a9a22
MD5 4cb9a9309a9d580143642cc27118cef9
BLAKE2b-256 7cf504a060f2be4db8bbf73cf56a551435b3e659f032780fddd56da1bb227a2a

See more details on using hashes here.

File details

Details for the file meiyoufrpclient-1.0.4-py3-none-any.whl.

File metadata

File hashes

Hashes for meiyoufrpclient-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 d793b3b29158b32545f1a9836dd81ed827ca092c97ef48fca1224e68e383dfd1
MD5 014f9688a90dde28fb9976948d7885d4
BLAKE2b-256 46e104c7c4cf0b23f1d31810f72aa2801ccf7a7fb39ba2b2cbc4be64e04c7174

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page