1. 项目背景与核心价值
最近在折腾一个挺有意思的小工具——短信转发服务。起因是我有两部手机,一部主力机随身携带,另一部备用机长期放在家里。但备用机经常收到一些验证码或者重要通知短信,每次都要专门跑回家查看特别麻烦。市面上虽然有些商业短信转发服务,但要么收费不菲,要么隐私安全性存疑。
于是花了两个周末时间,开发了这个开源自建的短信转发工具。它的核心功能很简单:自动将指定手机收到的短信内容,通过互联网转发到你的主力设备上(可以是另一部手机、电脑或者任何能接收网络消息的平台)。整个系统设计遵循"轻量、安全、可控"原则,所有数据流转都在自己掌控中,无需依赖第三方服务。
这个方案特别适合以下场景:
- 多设备用户需要集中管理短信
- 将老旧手机改造成专用短信接收机
- 需要异地获取短信验证码的场景
- 对隐私安全要求较高的用户群体
2. 技术架构解析
2.1 整体设计思路
系统采用典型的客户端-服务端架构:
- 客户端:运行在Android设备上的APP,负责监听短信接收事件
- 服务端:处理消息路由和转发的核心服务
- 接收端:可以是任何能接收HTTP请求的设备/应用
这种解耦设计带来几个优势:
- 客户端只需关注短信捕获,代码量小,稳定性高
- 服务端可以独立升级扩展,支持多种转发协议
- 接收端完全自定义,可按需对接不同平台
2.2 关键技术选型
客户端技术栈:
- 使用Android的BroadcastReceiver监听短信广播
- 采用Kotlin编写,兼容Android 5.0+系统
- 通过WorkManager实现后台任务调度
服务端技术栈:
- 基于Spring Boot构建REST API
- 使用Redis作为消息队列缓冲
- 采用JWT进行设备认证
- 支持WebSocket实时推送
安全方案:
- 端到端AES-256加密
- 双向设备认证
- 消息内容签名防篡改
- 可选的IP白名单限制
3. 详细部署指南
3.1 服务端部署
推荐使用Docker一键部署:
bash复制docker run -d \
-p 8080:8080 \
-e REDIS_HOST=your_redis_server \
-e JWT_SECRET=your_strong_secret \
--name sms-forwarder \
ghcr.io/your-repo/sms-forwarder:latest
关键配置参数说明:
REDIS_HOST: Redis服务器地址(建议使用云Redis服务)JWT_SECRET: 至少32位的随机字符串MESSAGE_TTL: 消息存活时间(默认300秒)RATE_LIMIT: 每分钟最大请求数(默认60次)
重要提示:生产环境务必配置HTTPS,可以使用Let's Encrypt免费证书
3.2 客户端配置
- 下载并安装APK(已提供预编译版本)
- 首次启动时需要:
- 输入服务端URL(如https://your-domain.com)
- 扫描服务端生成的配对二维码
- 授予短信读取权限
客户端主要配置项:
xml复制<preferences>
<forwarding enabled="true">
<target url="https://your-domain.com/api/v1/message"/>
<filter>
<sender pattern=".*"/> <!-- 转发所有号码 -->
<content exclude="广告"/> <!-- 过滤包含"广告"的短信 -->
</filter>
</forwarding>
<retry policy="exponential" maxAttempts="3"/>
</preferences>
3.3 接收端集成
提供多种接收方式:
- WebHook回调:服务端收到短信后POST到指定URL
- WebSocket实时推送:适合需要即时响应的场景
- 邮件转发:内置SMTP支持(需配置发件箱)
- Telegram Bot:通过官方API推送消息
示例WebHook接收处理(Node.js):
javascript复制app.post('/sms-webhook', (req, res) => {
const { sender, content, timestamp } = req.body;
console.log(`[${timestamp}] ${sender}: ${content}`);
// 处理验证码等场景
const code = content.match(/\d{6}/)?.[0];
if(code) {
// 自动填充到业务系统
}
res.sendStatus(200);
});
4. 高级功能实现
4.1 智能短信处理
通过正则表达式实现自动分类:
java复制// 识别验证码短信
Pattern CODE_PATTERN = Pattern.compile("验证码(\\d{6})");
// 识别快递取件码
Pattern EXPRESS_PATTERN = Pattern.compile("取件码(\\w{6})");
// 识别银行交易通知
Pattern BANK_PATTERN = Pattern.compile("支出(\\d+\\.?\\d*)元");
4.2 多设备路由策略
在服务端配置路由规则:
yaml复制routing:
rules:
- match: "sender=10086"
targets: ["deviceA", "deviceB"]
- match: "content~='验证码'"
targets: ["deviceC"]
- default: ["deviceA"]
4.3 历史记录查询
内置Elasticsearch支持全文检索:
json复制{
"query": {
"bool": {
"must": [
{"match": {"content": "验证码"}},
{"range": {"timestamp": {"gte": "now-7d/d"}}}
]
}
}
}
5. 安全加固方案
5.1 通信安全
- 强制TLS 1.2+加密
- 使用HPKP防止中间人攻击
- 定期轮换JWT签名密钥
5.2 数据安全
- 短信内容加密存储(AES-GCM)
- 敏感字段单独加密(如手机号)
- 自动清除7天前的历史记录
5.3 访问控制
- 基于OAuth 2.0的设备认证
- 细粒度的权限控制(RBAC)
- 登录失败锁定机制
6. 性能优化实践
6.1 客户端优化
- 使用JobScheduler替代AlarmManager
- 批量发送消息(每30秒或满10条)
- 智能休眠策略(夜间模式)
6.2 服务端优化
- 消息异步处理(非阻塞IO)
- Redis管道批量操作
- 热点数据本地缓存
6.3 数据库优化
- 短信表按月份分片
- 建立复合索引(sender + timestamp)
- 定期归档冷数据
7. 常见问题排查
7.1 消息延迟问题
- 检查客户端网络状态
- 确认WorkManager是否被系统限制
- 查看服务端消息队列积压情况
7.2 消息丢失处理
- 客户端本地SQLite暂存未发送消息
- 服务端消息确认机制(ACK)
- 定时任务补偿发送
7.3 电池优化适配
- 适配Android Doze模式
- 使用Foreground Service保活
- 白名单引导用户设置
8. 扩展开发指南
8.1 插件系统设计
java复制public interface SmsPlugin {
void onMessageReceived(SmsMessage message);
void onMessageSent(SmsMessage message);
}
// 示例:统计插件
class StatsPlugin implements SmsPlugin {
private AtomicInteger counter = new AtomicInteger();
@Override
public void onMessageReceived(SmsMessage msg) {
counter.incrementAndGet();
}
}
8.2 多协议支持
- 短信转发到Matrix聊天室
- 支持Mattermost WebHook
- Discord Bot集成
8.3 硬件扩展
- 树莓派短信网关
- 4G模块直连方案
- 企业级短信猫集成
在实际使用中,我发现这套系统最实用的场景是:将旧手机放在信号更好的位置作为短信接收专用机,然后所有短信实时同步到日常使用的设备上。特别是对于需要频繁接收验证码的开发者来说,可以大幅提升工作效率。系统运行三个月来保持零故障,日均处理消息量约120条,服务器负载始终低于10%。