Files
DenyIP-go/ipset.go
2025-07-09 16:15:04 +08:00

211 lines
5.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"bytes"
"fmt"
"log"
"os/exec"
"strconv"
"strings"
)
func createIPSet(setName string) error {
cmd := exec.Command("ipset", "create", setName, "hash:ip")
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
// 记录错误信息,但不退出
log.Printf("failed to execute command: %v, stderr: %s", err, stderr.String())
}
return err // 返回错误以便调用者处理
}
func AddIPSet(setName string, ip string) error {
cmd := exec.Command("ipset", "add", setName, ip)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
// 记录错误信息,但不退出
log.Printf("failed to add IP to set: %v, stderr: %s", err, stderr.String())
}
return err // 返回错误以便调用者处理
}
// NumIPSet returns the number of entries in the specified ipset set.
func NumIPSet(setName string) (int, error) {
cmd := exec.Command("sh", "-c", fmt.Sprintf("ipset list %s | grep \"Number of entries\" | cut -d ':' -f 2 | sed 's/ //g'", setName))
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
log.Printf("cmd.Run() failed with %v, stderr: %s\n", err, stderr.String())
return 0, fmt.Errorf("failed to execute command: %w, stderr: %s", err, stderr.String())
}
output := strings.TrimSpace(stdout.String())
numEntries, err := strconv.Atoi(output)
if err != nil {
log.Printf("failed to parse output as integer: %v, output: %s\n", err, output)
return 0, fmt.Errorf("failed to parse output as integer: %w, output: %s", err, output)
}
return numEntries, nil
}
// IsIpset 检查名为 setName 的 ipset 是否存在,通过返回 0 表示存在,非零表示不存在或其他错误。
func Is_Name_Ipset(setName string) int {
cmd := exec.Command("ipset", "list", setName)
err := cmd.Run()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
// The program has exited with an exit code != 0
return exitError.ExitCode()
} else {
// Another error occurred (e.g., command not found)
return -1 // 或者你可以选择其他方式来标识这种情况
}
}
// Command executed successfully, the set exists
return 0
}
func Is_Ip_Ipset(ip string) int {
cmd := exec.Command("sh", "-c", fmt.Sprintf("ipset list | grep \"%s\"", ip))
err := cmd.Run()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
// The program has exited with an exit code != 0
return exitError.ExitCode()
} else {
// Another error occurred (e.g., command not found)
return -1 // 或者你可以选择其他方式来标识这种情况
}
}
// Command executed successfully, the set exists
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 {
cmd := exec.Command("sh", "-c", fmt.Sprintf("iptables -A INPUT -p tcp -m set --match-set %s src -j DROP", setName))
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
//log.Printf("cmd.Run() failed with %v, stderr: %s\n", err, stderr.String())
//err = fmt.Errorf("failed to execute command: %w, stderr: %s", err, stderr.String())
}
return err
}
// 删除 Iptables 规则
func iptables_del(setName string) error {
cmd := exec.Command("sh", "-c", fmt.Sprintf("iptables -D INPUT -p tcp -m set --match-set %s src -j DROP", setName))
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
//log.Printf("cmd.Run() failed with %v, stderr: %s\n", err, stderr.String())
//err = fmt.Errorf("failed to execute command: %w, stderr: %s", err, stderr.String())
}
return err
}
// 打印 Iptables 规则
func iptables_list() error {
cmd := exec.Command("sh", "-c", "iptables -L -v -n --line-numbers")
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
log.Printf("cmd.Run() failed with %v, stderr: %s\n", err, stderr.String())
err = fmt.Errorf("failed to execute command: %w, stderr: %s", err, stderr.String())
}
fmt.Print(stdout.String())
return err
}
/*
func main() {
// 创建 IPSet但即使出错也继续执行
err := createIPSet("root0")
if err != nil {
log.Println("创建 IPSet 出错:", err)
} else {
fmt.Println("IPSet 创建成功!")
}
// 添加 IP 到 IPSet出错时继续执行
err = AddIPSet("root0", "1.1.1.1")
if err != nil {
log.Println("添加 IP 到 IPSet 出错:", err)
}
// 获取 IPSet 条目数,出错时继续执行
num, err := NumIPSet("root0")
if err != nil {
log.Println("获取 IPSet 条目数出错:", err)
} else {
fmt.Printf("IPSet 条目数: %d\n", num)
}
iptables("root0")
}
*/