优化白名单

This commit is contained in:
2025-07-09 16:15:04 +08:00
parent 851b643374
commit de72ee1100
9 changed files with 155 additions and 32 deletions

View File

@@ -1,12 +1,15 @@
#!/bin/bash
set -x
DATE=$(date "+%Y-%m-%dT%H:%M:%S")
libcap=$(pkg-config --libs --static libcap)
libpcap=$(pkg-config --libs --static libpcap)
dbus=$(pkg-config --libs --static dbus-1)
a="'"
eval "CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -a -ldflags ${a}-extldflags \"-static ${libpcap} ${dbus} ${libcap} -lc\"${a}"
eval "CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -a -ldflags ${a}-X main.BuildDate=${DATE} -extldflags \"-static ${libpcap} ${dbus} ${libcap} -lc\"${a}"
if test -f denyip; then
upx -9 denyip

View File

@@ -95,7 +95,7 @@ func curl_(IP_ADDR string) (string, error) {
HTTP_Request.Header.Set("Cache-Control", "max-age=0")
HTTP_Request.Header.Set("Connection", "keep-alive")
HTTP_Request.Header.Set("Cookie", "BIDUPSID=04922F7E0DDC6A5B7E0BA15C33FD2176; PSTM=1722408897; BAIDUID=8313999060289847CAE0A6F34A9C4206:FG=1; Hm_lvt_edc762f9f8f5f525fad4770a32b5edda=1724987641; Hm_lvt_28a17f66627d87f1d046eae152a1c93d=1724987645; AGL_USER_ID=186badbd-dd36-4d39-89f4-8d2aa7a01414; BDUSS=1pvWmdhYThIelRSS1NuQkJESHNYV0REcG9teXMxOW9VaURTU2tyRlZTZ3Z4dmhtRVFBQUFBJCQAAAAAAAAAAAEAAADGRkRexaPT8cHrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC850WYvOdFmM")
HTTP_Request.Header.Set("Host", "qifu.baidu.com")
HTTP_Request.Header.Set("Host", "qifu-api.baidubce.com")
HTTP_Request.Header.Set("Sec-Ch-Ua", `"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"`)
HTTP_Request.Header.Set("Sec-Ch-Ua-Mobile", "?1")
HTTP_Request.Header.Set("Sec-Ch-Ua-Platform", `"Android"`)

BIN
denyip

Binary file not shown.

10
go.mod
View File

@@ -2,10 +2,12 @@ module denyip
go 1.23.4
require github.com/google/gopacket v1.1.19
require (
github.com/google/gopacket v1.1.19
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20250630080345-f9402614f6ba
)
require (
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20241220152942-06eb5c6e8230
golang.org/x/net v0.34.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/sys v0.33.0 // indirect
)

15
go.sum
View File

@@ -1,24 +1,19 @@
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20241220152942-06eb5c6e8230 h1:B0oaMTAQKDZd8cwYT0qsAI7+c3KbFeBNA8GhgoBMXWw=
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20241220152942-06eb5c6e8230/go.mod h1:C5LA5UO2ZXJrLaPLYtE1wUJMiyd/nwWaCO5cw/2pSHs=
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20250630080345-f9402614f6ba h1:t6xeYtXFnvu+GsvgEYyAK5zFnJARSG1fyGzBRZzuOhA=
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20250630080345-f9402614f6ba/go.mod h1:C5LA5UO2ZXJrLaPLYtE1wUJMiyd/nwWaCO5cw/2pSHs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=

View File

@@ -98,6 +98,35 @@ func Is_Ip_Ipset(ip string) int {
return 0
}
// RemoveIPIfInSets 在多个 ipset 中查找并删除某个 IP成功删除则返回集合名
func RemoveIPIfInSets(prefix string, max int, ip string) (string, error) {
for i := 0; i < max; i++ {
setName := fmt.Sprintf("%s%d", prefix, i)
// 检查 IP 是否在当前集合中
cmd := exec.Command("ipset", "test", setName, ip)
output, err := cmd.CombinedOutput()
if err != nil {
if strings.Contains(string(output), "is NOT in set") {
continue // 不在该集合中,尝试下一个
}
return "", fmt.Errorf("检测 %s 时出错: %v (%s)", setName, err, output)
}
// 存在,执行删除
cmd = exec.Command("ipset", "del", setName, ip)
output, err = cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("从 %s 删除 %s 时出错: %v (%s)", setName, ip, err, output)
}
return setName, nil // 删除成功,返回集合名
}
return "", nil // 所有集合都没有该 IP无需删除
}
// 添加 Iptables 规则
func iptables_add(setName string) error {

74
main.go
View File

@@ -17,6 +17,8 @@ import (
"time"
)
var BuildDate = "unknown" // 由编译时注入
func init() {
// 强制使用 Go 的纯用户态 DNS 解析器
net.DefaultResolver = &net.Resolver{
@@ -45,6 +47,7 @@ var (
ProcessedIPMap = map[string]time.Time{} // 使用 map 存储已处理的 IP
ProcessedMutex sync.Mutex // 互斥锁保护 ProcessedIPMap
)
// 启动子进程
@@ -209,7 +212,8 @@ func loadFromFile(filePath string, logMessage string) error {
oldTemp := make(map[string]string)
if err := decoder.Decode(&oldTemp); err == nil {
for ip := range oldTemp {
ProcessedIPMap[ip] = time.Now() // 给旧 IP 打个当前时间戳
//ProcessedIPMap[ip] = time.Now() // 给旧 IP 打个当前时间戳
ProcessedIPMap[ip] = time.Date(1971, 1, 1, 0, 0, 0, 0, time.UTC) // 标记为永不过期
}
log.Println(logMessage + "(从旧格式转换)")
return nil
@@ -219,18 +223,14 @@ func loadFromFile(filePath string, logMessage string) error {
}
func InitMap() {
if err := loadFromFile("cn.json", "Map 已成功从文件加载"); err != nil {
log.Fatalf("加载 Map 失败: %v", err)
}
if err := loadFromFile("white.json", "白名单 Map 已成功从文件加载!!!"); err != nil {
log.Fatalf("加载 Map 失败: %v", err)
if err := loadFromFile("cn.json", " Map 已成功从文件加载"); err != nil {
log.Fatalf(" 加载 Map 失败: %v", err)
}
defer func() {
// 程序退出时保存数据
if err := saveMapToFile("cn.json"); err != nil {
log.Printf("保存 Map 失败: %v", err)
log.Printf(" 保存 Map 失败: %v", err)
}
}()
@@ -242,9 +242,11 @@ func WriteLocalAddr() {
if local_ipv4_addr != "NULL" {
//log.Printf("\033[33m %s 本机地址 \033[0m\n", ipStr)
ProcessedMutex.Lock()
ProcessedIPMap[local_ipv4_addr] = time.Now()
//ProcessedIPMap[local_ipv4_addr] = time.Now()
ProcessedIPMap[local_ipv4_addr] = time.Date(1971, 1, 1, 0, 0, 0, 0, time.UTC) // 标记为永不过期
ProcessedMutex.Unlock()
}
// 写入json文件
if err := saveMapToFile("cn.json"); err != nil {
log.Printf("实时保存 Map 失败: %v", err)
@@ -256,6 +258,8 @@ func RunMainProcess() { // 主进程逻辑
fmt.Println("主进程启动...")
WriteLocalAddr() // 将本机外网地址加入到已处理集合中
cmd, err := StartChildProcess()
if err != nil {
log.Fatalf("子进程启动失败: %v", err)
@@ -280,8 +284,6 @@ func RunMainProcess() { // 主进程逻辑
ipStr := e1.Value.(net.IP).String()
region, _ := ip2region(ipStr) // 离线库初步判断地域
WriteLocalAddr() // 将本机外网地址加入到已处理集合中
ProcessedMutex.Lock()
_, processed := ProcessedIPMap[ipStr] // 检查是否已处理
ProcessedMutex.Unlock()
@@ -292,6 +294,23 @@ func RunMainProcess() { // 主进程逻辑
goto next
}
// 检查是否在白名单中
if _, ip_ := whiteList[ipStr]; ip_ {
log.Printf("\033[33m %s 跳过白名单, 跳过!!! \033[0m\n", ipStr)
IpList.Remove(e1)
setName, err := RemoveIPIfInSets("root", MAX_IPSET_NAME, ipStr)
if err != nil {
log.Printf(" %s 删除 IP 出错: %v\n", ipStr, err)
} else if setName != "" {
log.Printf(" %s 已从 %s 中移除 \n", ipStr, setName)
} else {
log.Printf(" %s 不在任何 IPSet 中,无需移除\n", ipStr)
}
goto next
}
if Is_Ip_Ipset(ipStr) != 0 { // IP 不在 ipset 集合中
if !strings.Contains(region, "中国") && !strings.Contains(region, "内网") { // 离线库判断不在中国内
@@ -356,6 +375,11 @@ func RunMainProcess() { // 主进程逻辑
// 遍历 ProcessedIPMap检查每个 IP 的记录是否已超过 24 小时
for ip, t := range ProcessedIPMap {
if t.Year() == 1971 {
continue // 不清理标记为“永不过期”的 IP
}
// 如果当前时间减去记录时间大于 1 小时,则删除该条目
if now.Sub(t) > 30*time.Minute {
delete(ProcessedIPMap, ip)
@@ -366,7 +390,17 @@ func RunMainProcess() { // 主进程逻辑
ProcessedMutex.Unlock()
// 打印日志,表示本次清理已完成
log.Println("已清理过期 ProcessedIPMap 项")
log.Println(" 已清理过期 ProcessedIPMap 项")
}
}()
// 定时重新加载白名单
go func() {
for {
time.Sleep(1 * time.Minute) // 每 10 分钟自动刷新
if err := LoadWhiteList("whitelist.txt"); err != nil {
log.Printf(" 刷新白名单失败: %v", err)
}
}
}()
@@ -414,10 +448,10 @@ func HandleCmd() {
if help {
fmt.Printf(
"\t\tDenyip firewall\n" +
"\tVersion 0.2\n" +
"\tE-mail: aixiao@aixiao.me\n" +
"\tDate: 20250102\n")
"\t\tDenyip firewall\n"+
"\tVersion 0.2\n"+
"\tE-mail: aixiao@aixiao.me\n"+
"\tBuild Date: %s\n", BuildDate)
flag.Usage()
fmt.Printf("\n")
@@ -465,6 +499,14 @@ func main() {
embed_ip2region()
// 加载白名单
err := LoadWhiteList("whitelist.txt")
if err != nil {
log.Fatalf(" whiteList Map 加载白名单失败: %v", err)
} else {
log.Println(" whiteList Map 白名单加载成功")
}
// 守护进程模式
if *daemon {
StartDaemon()

50
whitelist.go Normal file
View File

@@ -0,0 +1,50 @@
package main
import (
"bufio"
"log"
"os"
"strings"
"sync"
)
var (
whiteList = make(map[string]struct{})
whiteListLock = sync.RWMutex{}
)
func LoadWhiteList(filename string) error {
// 如果文件不存在,直接返回 nil 表示无需加载
if _, err := os.Stat(filename); os.IsNotExist(err) {
log.Printf(" 白名单文件 %s 不存在,跳过加载。", filename)
return nil
}
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
tempList := make(map[string]struct{})
for scanner.Scan() {
ip := strings.TrimSpace(scanner.Text())
if ip != "" {
tempList[ip] = struct{}{}
}
}
if err := scanner.Err(); err != nil {
return err
}
// 用写锁更新全局白名单
whiteListLock.Lock()
whiteList = tempList
whiteListLock.Unlock()
log.Println("白名单已加载完成")
return nil
}

2
whitelist.txt Normal file
View File

@@ -0,0 +1,2 @@
127.0.0.1
158.101.117.243