优化白名单
This commit is contained in:
@@ -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
|
||||
|
2
curl.go
2
curl.go
@@ -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"`)
|
||||
|
10
go.mod
10
go.mod
@@ -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
15
go.sum
@@ -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=
|
||||
|
29
ipset.go
29
ipset.go
@@ -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
74
main.go
@@ -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
50
whitelist.go
Normal 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
2
whitelist.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
127.0.0.1
|
||||
158.101.117.243
|
Reference in New Issue
Block a user