Back
Featured image of post 别让那个流量偷跑掉!

别让那个流量偷跑掉!

我们常用的代理套餐一般都会有流量限制,你是否好奇每天都用了多少流量,是否又莫名其妙就用了大票流量。既然平台不给监控,我们手动做一个,当大量流量偷跑时,是时候抓个正着啦!

技术可行性探索

先要搞定从哪里获得流量使用情况,一般需要登录网站才可以看到,在看到一些软件会展示已用流量/总流量等之时,我想既然他们可以知道,那一定是有办法可以拿到数据的。 其次,我们需要采集数据,越细致就越方便分析,故这里可能要一个定时触发的地方。虽然我们知道像Prometheus可以采集,但它有格式要求,有其它办法吗?当然可以。 再次,采集的数据需要一定呈现,超过我们设定的阈值时给予告警。这点似乎Grafana就很适合,免费享用。

动手搞起

流量采集

我无意中看到Quantumult关于Extra Server Subscription Feature的介绍:

Response Header to Check

Subscription-Userinfo: upload=2375927198; download=12983696043; total=1099511627776

这不正是我们需要的数据源吗?我们只需要:

1
curl -I https://<订阅链接>

通过消息头即可获得了。但是有一些平台不支持Quantumult订阅怎么办?我们只需要指定User-Agent假装是Quantumultx即可:

1
curl -I -ssL -H 'User-Agent: Quantumultx'  'https://<订阅链接>'

触发来源

在之前文章中我介绍过Webhook,它实现上面的采集动作是很简单的。那触发器交给谁,比如想1分钟采集一次呢?我们可以借助一个开源的方案cronicle简单配置一下就可以啦。如果你没搭建过cronicle,可以参考这篇文章轻量的定时任务工具 Cronicle:前篇。只需要照抄个docker-compose相关yaml就好啦。

之后我们添加一个任务,每分钟触发,向我们后面要提供的webhook发送请求即可。这个请求可以不带任何有效payload,只起一个定时触发功效,毕竟在cronicle中写复杂点的逻辑是不太容易的:P 通过Croncile提供定时能力

实现webhook

有定时触发的地方了,又知道如何获得我们的流量数据,现在我打算把获取到的数据存取到一个地方。正好手上有个mysql可用。所以我们先定义一个table:

1
2
3
4
5
6
7
8
9
CREATE TABLE traffic (
    id INT(11) NOT NULL AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    upload BIGINT(20) NOT NULL,
    download BIGINT(20) NOT NULL,
    total BIGINT(20) NOT NULL,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

再简单写一个webhook的shell脚本即可:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/bin/sh

# 函数定义
fetch_and_log_subscription_info() {
    local name=$1
    local domain=$2

    echo "name: $name, domain: $domain"
    # 获取订阅信息
    subinfo=$(curl -I -sSL -H 'User-Agent: Quantumultx' $domain | grep 'subscription-userinfo')
    info=$(echo $subinfo | sed -n '/subscription-userinfo/p' | awk -F ':' '{print $2}')

    echo "name: $name sub_info: $info"

    # 使用awk分别提取每个字段的值
    upload=$(echo $info | awk -F'; ' '{for(i=1;i<=NF;i++) if ($i ~ /upload=/) print $i}' | cut -d'=' -f2)
    download=$(echo $info | awk -F'; ' '{for(i=1;i<=NF;i++) if ($i ~ /download=/) print $i}' | cut -d'=' -f2)
    total=$(echo $info | awk -F'; ' '{for(i=1;i<=NF;i++) if ($i ~ /total=/) print $i}' | cut -d'=' -f2)
    expire=$(echo $info | awk -F'; ' '{for(i=1;i<=NF;i++) if ($i ~ /expire=/) print $i}' | cut -d'=' -f2)

    # 打印结果
    echo "Upload: $upload"
    echo "Download: $download"
    echo "Total: $total"
    echo "Expire: $expire"

    # 数据库配置(请根据需要进行修改)
    DB_NAME="<db>"
    DB_USER="<user>" # 请替换为你的数据库用户名
    DB_PASSWORD="<passowrd>" # 请替换为你的数据库密码
    DB_HOST="<mysql host>" # 或者是数据库所在的主机地址

    # 插入数据
    mysql -h $DB_HOST -u $DB_USER -p$DB_PASSWORD $DB_NAME -e "INSERT INTO traffic (name, upload, download, total) VALUES ('$name', $upload, $download, $total);"

    echo "Data inserted successfully."
}

# 使用函数示例
fetch_and_log_subscription_info "sub-1" "订阅地址1" 
fetch_and_log_subscription_info "sub-2" "订阅地址2" 
# 可继续写更多

关于Webhook如何配置,见之前文章,本处不再多言。

监控面板

我们使用最流行的开源方案Grafana来做监控,它也能很好的支持我们的数据源(mysql)。 Grafana Dashboard示例 主要有几个常用的指标:

  • 流量使用量
  • 流量使用比例

以下给一些示例的查询写法: 查询使用量,即upload+downlad。

1
2
3
4
5
6
7
SELECT
  CONVERT_TZ(timestamp, '+08:00', 'UTC') AS "time",
  (upload + download) AS total_traffic
FROM traffic
WHERE
  name='your-sub-name'
ORDER BY timestamp;

流量的使用比例,除以total即可:

1
2
3
4
5
6
7
8
SELECT
  CONVERT_TZ(timestamp, '+08:00', 'UTC') AS "time",
  name,
  (upload + download)/total AS used_pct
FROM traffic
WHERE
  name='your-sub-name'
ORDER BY timestamp;

如果想有一个示图同时展示流量数据以及使用比例,我们只要在Grafana中配置Overrides使用Grafana覆盖功能 这样只需要一个Panel即完备展示了。

告警

当流量快不够用时,或者短期使用流量过快,我们或许想告警出来。这点借助Grafana的Alert模块就可以了。比如我就在流量使用80%时告警出来,通过Grafana直接对接到Pushover。

在Grafana中配置告警

尾声

这篇文章随手记录了一下折腾的过程。整个过程都是比较基础的内容,是一个功能整合的过程。有时候用什么方案解决问题,取决于你掌握了多少种工具,所以,日常我们得折腾了解更多的工具,对吧?

我是个爱折腾技术的工程师,也乐于分享。欢迎点赞、关注、分享,更欢迎一起探讨技术问题,共同学习,共同进步。为了获得更及时的文章推送,欢迎关注我的公众号:

微信公众号