使用便宜的4g模块 配合docker来转发你的短信 libgammu smsforwarder golang

为什么会有这篇文章

刚开始一直在用SmsFordarder在安卓手机上进行短信转发,长期占用安卓手机,老化的电池也不放心,咸鱼发现有便宜可用的支持短信的4g模块,顺带研究一下相关的内容,就自己用golang写了相关服务。

我自己的硬件配置

主板 orange pi5 max 很不错的板子,我在上面跑frigate、jellyfin 能解码,能跑图像识别。
cpu rk3588 x86和arm64都可以
系统 ubuntu server22.04 因为还在跑redroid,需要5.10内核,所有没用24.04系统
4g模块 移远的EC200T-CN 咸鱼10块钱,cat4速率,但是我不需要用它上网,便宜,有短信,有通话接口就行。
usb转4g板子 咸鱼搜 mini pcie转4g模块 20块钱
天线 2根 IPEX一代接口
sim卡信息 中国联通 没其他卡,没测试移动和电信

软件配置

  • docker就行了。
  • 相关代码:
  • 我用golang写的一份读取短信和来电的服务gammu-web
  • 配合golang的通知服务ForwardSMS

准备转发配置文件forward.yaml

# 如果有all这个配置,就是默认所有短信都会转发给这个企业微信机器人,建议发送给管理员,或者直接删除关闭
all:
    rule: all
    type: all
    notify: wechat
    url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxx

# 从上到下依次为 项目名称、规则(使用关键字匹配)
测试:
    rule: 测试DDD
    type: keyword
    notify: wechat
    url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxx

# 正则匹配规则
工单号:
    rule: "\\d{8}" # 匹配8位数字
    type: regex
    notify: gotify
    url: https://gotify.example.com
    token: your_app_token

# 转发给ios用它。
bark:
    notify: bark
    type: all
    rule: all
    url: "https://api.day.app/xxxx"

# 转发给安卓用它。
gtify:
    notify: gotify
    type: all
    rule: all
    url: "https://gotify.example.com"
    token: "your_app_token"

# emm邮箱转发
email:
    notify: email
    type: all
    rule: all
    smtp_host: "smtp.qq.com"
    smtp_port: "587"
    username: "[email protected]"
    password: "授权码"
    from: "[email protected]"
    to: "[email protected]"

配置docker-compose.yaml (支持x86和arm64)

version: "3"
services:
  # https://github.com/scjtqs2/ForwardSMS
  forwardsms:
    image:  ghcr.io/scjtqs2/forwardsms/forwardsms:latest
    environment:
      - FORWARD_SECRET=your_shared_secret_here
      - TZ=Asia/Shanghai
      - HTTP_PORT=8080
    volumes:
      # 挂载上面配置的推送文件
      - ./forward.yaml:/data/config/forward.yaml
    restart: always
    expose:
      - 8080

  # https://github.com/scjtqs2/gammu-web
  gammu-web:
    image: ghcr.io/scjtqs2/gammu-web:latest
    environment:
        - FORWARD_ENABLED=1
        # 写死
        - FORWARD_URL=http://forwardsms:8080/api/v1/sms/receive
        # 和forwardsms里面的要一致。
        - FORWARD_SECRET=your_shared_secret_here
        - TZ=Asia/Shanghai
        # 转发通知携带的标识。
        - PHONE_ID=SMS1_186xxxxxxxx
        - ATCONNECTION=at9600
        # ec200t-cn 默认的管理接口就是/dev/ttyUSB1(能同时收发短信,还能读取来电显示数据用来达到转发来电通知)。根据实际情况自行调整。
        - USB_PORT=/dev/ttyUSB1
        - API_PORT=21234
        # web网页访问用到。
        - API_TOKEN=your_shared_token_here
        - GAMMU_DEBUG=false
        - DEBUG=0
        - CALL_FORWARD_ENABLED=true
        - CALL_FORWARD_URL=http://forwardsms:8080/api/v1/call/receive
    volumes:
      - ./data:/data
    # 加了这个,就不用挨个去映射 /dev/ttyUSBx了
    privileged: true
    restart: always
    ports:
      - 21234:21234

FAQ

1. gammu-web自带一个web页面,可以在上面管理你的短信,登陆的时候,记得勾选“记住”,遇到无线跳转的话手动清理当前页面cookie。

2. 如果遇到端口被占用的情况,需要手动关闭默认的调制解调器。并通过netplan关闭usb 4g网卡。

# 停止所有可能的调制解调器管理服务
sudo systemctl stop ModemManager
sudo systemctl disable ModemManager
sudo pkill -f ModemManager

3. 重启模块命令:echo -e "AT+CFUN=1,1\r" > /dev/ttyUSB2

4. 调试建议使用apt install minicom,然后用

minicom -D /dev/ttyUSB2(如果你的 /dev/ttyUSB2已经被gammu-web占用了,用/dev/ttyUSB1也可以查询部分数据)连接。

退出的话,按下ctrl+a,放开键盘再按x,点击确定。 使用ATI来查看模块信息。

然后输入 AT+COPS?AT+QNWINFO 查询是否已经注册到运营商网络,大概会返回如下信息

5. 如果不喜欢模块自带的cdc网络连接,我这有脚本关掉它。disable_cdc.sh:

#!/bin/bash

# 自动禁用CDC Ethernet接口脚本
# 文件名: disable_cdc.sh

set -e

echo "=== 正在扫描CDC Ethernet接口 ==="

# 检查cdc_ether驱动目录是否存在
if [ ! -d "/sys/bus/usb/drivers/cdc_ether" ]; then
    echo "❌ cdc_ether驱动目录不存在,可能没有CDC设备连接"
    exit 1
fi

# 获取所有绑定到cdc_ether的设备
devices=(ls /sys/bus/usb/drivers/cdc_ether/ | grep -E '^[0-9]+-[0-9]+:[0-9]+\.[0-9]+' 2>/dev/null || true)

if [ -z "devices" ]; then
    echo "ℹ️  没有找到绑定到cdc_ether的设备"
    exit 0
fi

echo "找到以下CDC Ethernet设备:"
echo "devices"

# 禁用每个设备
disabled_count=0
for device in devices; do
    echo "🔄 正在禁用设备:device"
    if echo "device" | sudo tee /sys/bus/usb/drivers/cdc_ether/unbind>/dev/null 2>&1; then
        echo "✅ 成功禁用:device"
        ((disabled_count++))
    else
        echo "❌ 禁用失败: device"
    fi
done

echo "=== 完成 ==="
echo "共禁用了disabled_count 个CDC Ethernet接口"

# 验证结果
remaining_devices=(ls /sys/bus/usb/drivers/cdc_ether/ | grep -E '^[0-9]+-[0-9]+:[0-9]+\.[0-9]+' 2>/dev/null | wc -l)
if [ "remaining_devices" -eq 0 ]; then
    echo "🎉 所有CDC Ethernet接口已成功禁用"
else
    echo "⚠️  仍有remaining_devices 个接口未禁用"
fi

6. 对应的恢复脚本enable_cdc.sh:

#!/bin/bash
set -euo pipefail

DRIVER_DIR="/sys/bus/usb/drivers/cdc_ether"

echo "== 恢复 CDC Ethernet (cdc_ether) =="

# 确保驱动目录存在(若模块没加载,尝试 modprobe)
if [ ! -d "DRIVER_DIR" ]; then
  echo "cdc_ether 驱动目录不存在,尝试加载模块..."
  sudo modprobe cdc_ether || true
  sleep 1
  if [ ! -d "DRIVER_DIR" ]; then
    echo "❌ cdc_ether 驱动仍不可用,退出。"
    exit 1
  fi
fi

bound=0
for iface in /sys/bus/usb/devices/*:*; do
  [ -d "iface" ] || continue
  name=(basename "iface")

  # 读取接口类(支持 '2'、'02'、'0x02')
  cls=(cat "iface/bInterfaceClass" 2>/dev/null || true)
  case "cls" in
    2|02|0x02) ;;
    *) continue ;;  # 不是通信/网络类,跳过
  esac

  if [ -e "iface/driver" ]; then
    echo "ℹ️  接口name 已绑定驱动,跳过。"
    continue
  fi

  echo "🔧  尝试绑定接口 name 到 cdc_ether..."
  if sudo sh -c "echo -n 'name' > DRIVER_DIR/bind"; then
    echo "✅  绑定成功:name"
    bound=((bound+1))
    # 等待 sysfs 创建 net 子目录再尝试 up
    sleep 1
    netdir="iface/net"
    if [ -d "netdir" ]; then
      for ifn in "netdir"/*; do
        ifn=(basename "ifn")
        echo "⤴️  设置网络接口 ifn up"
        sudo ip link set "ifn" up || true
      done
    fi
  else
    echo "❌  绑定失败: name"
  fi
done

if [ "bound" -eq 0 ]; then
  echo "⚠️  未找到可绑定的 CDC 接口(或绑定失败)。请检查 lsusb/dmesg。"
else
  echo "🎉 共绑定 $bound 个接口。"
fi

打赏
Bookmark the permalink.
0 0 投票数
文章评分
订阅评论
提醒
guest

0 评论
内联反馈
查看所有评论