前几天正在写博客评点哪吒,结果OVH放货了KS-A,等写完发现,已经卖完了。这不得不拍断大腿了。
赶紧补救,写个监控KS-A放货的玩意,下次一定要把握住了。
程序就是每一分钟去ovh网页上拉一下库存,如果有,就telegram赶紧通知。
先只贴go源代码了,改天有空我看看是不是写个使用说明。
调用格式是 ./ovh -token=tg机器人的token -chatid=自己tg号的id
加上-test,会模拟加拿大有货,给tg发条通知。这样检查tg参数对不对。

package main

import (
    "encoding/json"
    "flag"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/url"
    "os"
    "strings"
    "time"
)

const apiURL = "https://ca.ovh.com/engine/apiv6/dedicated/server/datacenter/availabilities/?excludeDatacenters=false&planCode=24ska01&server=24ska01"

type Datacenter struct {
    Availability string `json:"availability"`
    Datacenter   string `json:"datacenter"`
}

type Server struct {
    Datacenters []Datacenter `json:"datacenters"`
}

func checkAvailability(testMode bool, telegramBotToken, chatID string) {
    log.Println("Starting availability check...")

    resp, err := http.Get(apiURL)
    if err != nil {
        log.Println("Failed to fetch data:", err)
        return
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Println("Failed to read response body:", err)
        return
    }

    log.Println("Received JSON response:", string(body))

    var servers []Server
    err = json.Unmarshal(body, &servers)
    if err != nil {
        log.Println("Failed to parse JSON:", err)
        return
    }

    // 如果是测试模式,强行设置 bhs 数据中心的可用性为 72H
    if testMode {
        log.Println("Test mode enabled. Forcing bhs datacenter availability to 72H.")
        for i, server := range servers {
            for j, dc := range server.Datacenters {
                if dc.Datacenter == "bhs" {
                    servers[i].Datacenters[j].Availability = "72H"
                }
            }
        }
    }

    for _, server := range servers {
        for _, dc := range server.Datacenters {
            log.Printf("Checking datacenter: %s, availability: %s\n", dc.Datacenter, dc.Availability)
            if dc.Availability != "unavailable" {
                log.Printf("Availability change detected: %s in datacenter: %s\n", dc.Availability, dc.Datacenter)
                sendTelegramNotification(dc.Datacenter, dc.Availability, telegramBotToken, chatID)
                return // 一旦发现可用的服务器,立即发送通知并停止进一步检查
            }
        }
    }

    log.Println("No availability changes detected.")
}

func sendTelegramNotification(datacenter, availability, telegramBotToken, chatID string) {
    msg := fmt.Sprintf("Server availability changed to: %s in datacenter: %s", availability, datacenter)
    telegramApi := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", telegramBotToken)

    log.Printf("Sending notification: %s\n", msg)

    form := url.Values{}
    form.Add("chat_id", chatID)
    form.Add("text", msg)

    resp, err := http.Post(telegramApi, "application/x-www-form-urlencoded", strings.NewReader(form.Encode()))
    if err != nil {
        log.Println("Failed to send telegram message:", err)
        return
    }
    defer resp.Body.Close()

    log.Println("Notification sent successfully.")
}

func main() {
    // 解析命令行参数
    testMode := flag.Bool("test", false, "Enable test mode to simulate availability change")
    telegramBotToken := flag.String("token", "", "Telegram bot token")
    chatID := flag.String("chatid", "", "Telegram chat ID")
    flag.Parse()

    // 检查是否提供了必要的参数
    if *telegramBotToken == "" || *chatID == "" {
        fmt.Println("Usage: ./exename -token=<telegramBotToken> -chatid=<chatID> [-test]")
        os.Exit(1)
    }

    for {
        checkAvailability(*testMode, *telegramBotToken, *chatID)
        time.Sleep(1 * time.Minute)
    }
}

这个脚本是与nginx和Cloudflare配套使用的。在一分钟内累计请求数达到1000时,进入under attack模式10分钟,然后解除。 当然,数值是可以根据情况修改的。
原理很简单,每30秒统计一下nginx的访问日志即可。脚本差不多90%是gpt完成的。
功能很简单,不过nginx和cloudflare居然都没有简单的方法实现这一点。cf的rate limit基本就是个废物。因为现在主流的cc都是多ip低访问量的方式。
因为每30秒钟要扫描一次日志文件,如果访问量很大,这脚本当然就不能用了,不然太消耗资源,一般小网站没问题的。

#!/bin/bash

# 日志文件路径
LOG_FILE="/var/log/nginx/access.log"
CHECK_LOG="/var/log/nginx/check.log"  # 输出日志文件路径

# Cloudflare API 相关信息
ZONE_ID="xxxxxxxxxxxxxxxx"  # Cloudflare Zone ID
EMAIL="xxxxxxxxxxx"  # Cloudflare 登录邮箱
API_KEY="xxxxxxxxxxxx"  # Cloudflare Global API Key

# 请求阈值和计时
THRESHOLD=1000
COOLDOWN_TIME=10 # Under Attack 模式保持的分钟数

while true; do
    # 统计过去 1 分钟的请求次数
    REQ_COUNT=$(grep "$(date +'%d/%b/%Y:%H:%M')" $LOG_FILE | wc -l)

    # 检查请求数是否超过阈值
    if [ "$REQ_COUNT" -gt "$THRESHOLD" ]; then
        echo "$(date) - Requests in last minute: $REQ_COUNT. Exceeded!" >> $CHECK_LOG
        echo "$(date) - Enabling 'Under Attack' mode." >> $CHECK_LOG
        
        # 启用 Cloudflare "Under Attack" 模式
        curl -s -o /dev/null -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/security_level" \
            -H "X-Auth-Email: $EMAIL" \
            -H "X-Auth-Key: $API_KEY" \
            -H "Content-Type: application/json" \
            --data '{"value":"under_attack"}'
        
        # 等待 10 分钟后关闭 "Under Attack" 模式
        sleep "${COOLDOWN_TIME}m"
        
        # 取消 Cloudflare "Under Attack" 模式
        curl -s -o /dev/null -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/security_level" \
            -H "X-Auth-Email: $EMAIL" \
            -H "X-Auth-Key: $API_KEY" \
            -H "Content-Type: application/json" \
            --data '{"value":"medium"}'
        
        echo "$(date) - 'Under Attack' mode disabled." >> $CHECK_LOG
    else
        echo "$(date) - Requests in last minute: $REQ_COUNT. No action needed." >> $CHECK_LOG
    fi

    # 等待 30s再检查
    sleep 30
done

刚在gcp上开通了一台机器并搭建了一个typecho网站,debian12,用的是lnmp,apt手搓的。然后再安装了哪吒探针(客户端)和vnstat。这就是这台机器上的所有操作。才1个小时的机器,还不至于健忘忘掉啥。
机器开通1个小时后就被gcp给暂停了,警告存在挖矿行为。
debian是gcp官方装的应该没问题,而且也apt upgrade过了,typecho应该没有0day的(有0day也不至于用到我身上),apt手搓的nginx mariadb php vnstat应该也不可能有问题,debian官方源来着的。机器防火墙只开放22和80(只允许cf),22只能密钥登录,我相信没人能在操作系统层面入侵。

福尔摩斯说,当你排除所有不可能的因素之后,无论剩下的多么难以置信,那就是真相。

我倒不是对国产软件有什么误解,我相信哪吒不会挖矿,我只是想,也许它频繁的向主控传送心跳信息符合了某个挖矿的行为模式?
把哪吒禁掉了,继续观察了,如果过了今晚还没问题的话,那肯定就是它了。

nz.jpg

wk.jpg

bing总是不收录这个博客,然后我进webmaster后台看了看,所有的链接,包括/都被excluded了,K掉了。 向bing投诉,得到的结果是人工审核下来,K得没问题,不能恢复。至于原因不能告诉我。
bing确实是人工审核过,不是网上说的只是套话,因为那天网页统计显示,有近60个微软的ip上来看过。他们人真够多。
再看了看以前的老域名,状态倒是蛮正常的,大概,只是猜的,bing觉得我的新域名是镜像/盗版的老域名站吧,它可不知道都是我的。不过奇怪的是我做了301的啊。想不通。
先不管了,恢复老的吧。 也许又来一次循环,认为我老域盗新域。咳咳。
随便改域名是大忌啊,理解一些了。

bing1.jpg
bing.png

老是看到有人送这卡,网上都是说可以免费的得到sim卡然后转换成esim。不过操作方法是用postman。。够折腾。
好奇之下,下载了giffgaff的app注册好帐号进去, 人家很扎眼的两大功能,申请实体卡,申请esim!哪需要实体卡再转换!google一下马上明白了,aff的力量啊,因为只有实体卡能得到aff。好吧。。
于是花了5分钟不到,顺利搞定giffgaff的esim,不就10磅嘛,这点钱还是有。顺带我运气不错,号码无4,格式是 我的户口所在地区号+4位数字+AAA,瞬间就把号码背下来了。
这卡确实神卡。0月租,半年发条短信即可保号(原理是180天内需要资金变动,我感觉开通下数据漫游然后马上关掉应该也可以),除了email需要验证其它所有信息都可以乱来。

*充值的是10英镑预存款。如果走漫游流量(0.2/M),可以保号25年,如果走短信(0.3),可以保号16.6年。16/25年后我们100%已经不用这个号了,所以,去找affman冒着被骗的风险以及自己折腾改esim而只是为了多5或者10英镑帐面上的余额,值得么?