新架构

This commit is contained in:
2025-12-23 13:14:53 +08:00
parent 7c783f7bdf
commit 340509fd9f
9 changed files with 464 additions and 494 deletions

668
main.go
View File

@@ -1,7 +1,6 @@
package main
import (
"container/list"
"encoding/json"
"flag"
"fmt"
@@ -13,11 +12,12 @@ import (
"runtime"
"strings"
"sync"
"sync/atomic"
"syscall"
"time"
)
var BuildDate = "unknown" // 由编译时注入
var BuildDate = "unknown"
func init() {
// 强制使用 Go 的纯用户态 DNS 解析器
@@ -28,34 +28,311 @@ func init() {
var (
daemon = flag.Bool("d", false, "守护进程模式")
child = flag.Bool("child", false, "子进程模式, (不要使用!!!)")
child = flag.Bool("child", false, "子进程模式")
)
// 全局变量
// 全局配置变量
var (
InterfacesList bool // 是否列出网络接口
InterfaceName *string // 网络接口名称
PcapFile *string // 输出文件名
Protocol *string // BPF 过滤器
InterfacesList bool
InterfaceName *string
PcapFile *string
Protocol *string
IPSET_NUMBER int // 当前使用的 ipset 集合编号
MAX_IPSET_NAME = 100 // 最大 ipset 集合数量
IPSET_NAME string // 当前使用的 ipset 集合名称
IPSET_NUMBER int
MAX_IPSET_NAME = 100
IPSET_NAME string
IpList = list.New() // 存储 IPv4 地址的链表
IpMutex sync.Mutex // 保护 ipList 的互斥锁
// --- 优化部分开始 ---
ProcessedIPMap = map[string]time.Time{} // 使用 map 存储已处理的 IP
ProcessedMutex sync.Mutex // 互斥锁保护 ProcessedIPMap
// 替换 List 为带缓冲的 Channel
// 容量设为 5000足以应对大多数突发流量
IpChannel = make(chan string, 5000)
// 用于入队去重的 Map防止同一个 IP 在处理中时重复入队
// key: IP string, value: struct{}
PendingIPs sync.Map
PendingCount int64
// --- 优化部分结束 ---
ProcessedIPMap = map[string]time.Time{}
ProcessedMutex sync.Mutex
local_ipv4_addr string
)
// 启动子进程
// --- 核心逻辑优化:生产者 (入队) ---
// PushIPToQueue 安全地将 IP 放入队列
// 该函数应由 startPacketCapture 调用
func PushIPToQueue(ipStr string) {
// 0. 基础校验
if ipStr == "" {
return
}
// 1. 快速检查:如果已经在 ProcessedIPMap (已知的国内IP或白名单),直接忽略
ProcessedMutex.Lock()
_, processed := ProcessedIPMap[ipStr]
ProcessedMutex.Unlock()
if processed {
return
}
// 2. 去重检查:如果已经在 PendingIPs (队列中或正在处理),跳过
// LoadOrStore: 如果 key 存在,返回 true否则写入并返回 false
if _, loaded := PendingIPs.LoadOrStore(ipStr, struct{}{}); loaded {
return
}
// 【计数增加】只有确定要入队时才增加
atomic.AddInt64(&PendingCount, 1)
// 3. 非阻塞入队
select {
case IpChannel <- ipStr:
// 成功入队
default:
// 队列已满,丢弃该包
// 【回滚状态】从 Map 删除,并减少计数
PendingIPs.Delete(ipStr)
atomic.AddInt64(&PendingCount, -1)
// 可选log.Println("警告:处理队列已满,丢弃 IP:", ipStr)
}
}
// --- 核心逻辑优化:消费者 (处理 IP) ---
func processIP(ipStr string) {
// PushIPToQueue 已经拦截了空字符串,这里其实不需要再判断
// 但为了代码健壮性如果必须判断defer 必须在 return 之前定义
// 确保函数结束时从 Pending 状态移除并减少计数
defer func() {
PendingIPs.Delete(ipStr)
atomic.AddInt64(&PendingCount, -1)
}()
if ipStr == "" {
return
}
// 再次检查 ProcessedIPMap (防止排队期间被其他协程处理了)
ProcessedMutex.Lock()
_, processed := ProcessedIPMap[ipStr]
ProcessedMutex.Unlock()
if processed {
return
}
// 检查白名单
// --- 修改开始:使用读写锁检查白名单 ---
whiteListLock.RLock() // 加读锁
_, isWhitelisted := whiteList[ipStr] // 检查是否存在
whiteListLock.RUnlock() // 解读锁
if isWhitelisted {
log.Printf("\033[33m %s 在白名单中, 跳过 \033[0m\n", ipStr)
// 尝试从 ipset 移除
RemoveIPIfInSets("root", MAX_IPSET_NAME, ipStr)
return
}
// --- 修改结束 ---
REGION := "中国 内网"
// 如果 IP 已经在 ipset 中,通常无需处理
if Is_Ip_Ipset(ipStr) == 1 {
//log.Printf("\033[31m %s 已在 ipset 集合中 \033[0m\n", ipStr)
return
}
// 1. 离线库判断 (快速)
region, _ := ip2region(ipStr)
// 如果不包含 "中国" 也不包含 "内网",则判定为疑似国外
if !ContainsPart(region, REGION) {
log.Printf("\033[33m [%s %s] 离线库为国外, 进一步API判断\033[0m\n", ipStr, region)
// 2. 在线 API 判断 (慢速)
position, err := curl_(ipStr)
if err != nil {
log.Printf("获取IP地域出错: %v", err)
return // API 失败暂时跳过,等待下次重试
}
log.Printf("\033[31m [%s %s]\033[0m\n", ipStr, position)
if !ContainsPart(position, REGION) {
// --- 确认为国外 ---
AddIPSet(IPSET_NAME, ipStr)
log.Printf("\033[31m [封禁] 已添加国外 IP: %s \033[0m\n", ipStr)
} else {
// --- 确认为国内 ---
log.Printf("\033[32m %s API 修正为国内, 标记放行\033[0m\n", ipStr)
ProcessedMutex.Lock()
ProcessedIPMap[ipStr] = time.Now()
ProcessedMutex.Unlock()
}
} else {
// 离线库确认为国内,标记放行
ProcessedMutex.Lock()
ProcessedIPMap[ipStr] = time.Now()
ProcessedMutex.Unlock()
}
}
func RunMainProcess() {
log.Println(" 主进程启动...")
WriteLocalAddr()
cmd, err := StartChildProcess()
if err != nil {
log.Fatalf("子进程启动失败: %v", err)
}
IPSET_NUMBER = 0
IPSET_NAME = fmt.Sprintf("root%d", IPSET_NUMBER)
if Is_Name_Ipset(IPSET_NAME) == 0 { // 假设 0 表示不存在
createIPSet(IPSET_NAME)
}
// 1. 启动抓包 (生产者)
go startPacketCapture()
// 2. 启动 Worker Pool (消费者)
// 根据机器性能调整 worker 数量,建议 20-50
numWorkers := 40
log.Printf(" 启动 %d 个并发 Worker 处理 IP...", numWorkers)
for i := 0; i < numWorkers; i++ {
go func(id int) {
for ip := range IpChannel {
processIP(ip)
}
}(i)
}
// 定期保存 Map 数据 (替代原来在循环里保存)
go func() {
ticker := time.NewTicker(1 * time.Minute)
for range ticker.C {
if err := saveMapToFile("cn.json"); err != nil {
log.Printf(" 自动保存 Map 失败: %v", err)
}
}
}()
// 过期清理 ProcessedIPMap
go func() {
ticker := time.NewTicker(1 * time.Minute)
for range ticker.C {
now := time.Now()
ProcessedMutex.Lock()
count := 0
for ip, t := range ProcessedIPMap {
if t.Year() == 1971 {
continue
}
if now.Sub(t) > 30*time.Minute {
delete(ProcessedIPMap, ip)
count++
}
}
ProcessedMutex.Unlock()
if count > 0 {
log.Printf(" 已清理 %d 个过期 ProcessedIPMap 项", count)
}
}
}()
// 白名单刷新
go func() {
for {
time.Sleep(10 * time.Minute)
if err := LoadWhiteList("whitelist.txt"); err != nil {
log.Printf(" 刷新白名单失败: %v", err)
}
}
}()
// 防火墙扩容管理
// 防火墙扩容管理
go func() {
for {
time.Sleep(1 * time.Second)
// 1. 获取当前集合长度,必须处理错误
ipset_len, err := NumIPSet(IPSET_NAME)
if err != nil {
// 如果是因为集合不存在导致的错误,尝试创建它
if Is_Name_Ipset(IPSET_NAME) != 0 {
log.Printf("检测到集合 %s 不存在,正在初始化...", IPSET_NAME)
createIPSet(IPSET_NAME)
iptables_add(IPSET_NAME) // 重点:创建后必须同步添加 iptables 规则
}
continue
}
// 2. 检查是否需要扩容
// 注意ipset 默认 maxelem 是 65536达到这个值 add 操作就会失败
if ipset_len >= 65530 {
log.Printf("\033[31m ipset %s 列表已满 %d准备扩容... \033[0m\n", IPSET_NAME, ipset_len)
IPSET_NUMBER++
if IPSET_NUMBER >= MAX_IPSET_NAME {
log.Printf("\033[31m 警告:已达到最大集合数量限制!!! \033[0m\n")
// 这里可以根据需求决定是否 return 或采取其他措施
}
newSetName := fmt.Sprintf("root%d", IPSET_NUMBER)
// 3. 只有不存在时才创建 (注意判断逻辑: != 0 表示不存在)
if Is_Name_Ipset(newSetName) != 0 {
log.Printf("\033[32m 正在创建并应用新集合: %s \033[0m\n", newSetName)
if err := createIPSet(newSetName); err == nil {
// 4. 关键:创建新集合后,必须立刻将其加入 iptables 拦截规则
iptables_add(newSetName)
// 5. 切换全局变量
IPSET_NAME = newSetName
} else {
log.Printf("创建集合失败: %v", err)
}
} else {
// 如果集合已经存在(可能是上次运行留下的),直接切换过去
IPSET_NAME = newSetName
iptables_add(newSetName) // 确保规则存在
}
}
}
}()
// 打印日志
go func() {
for {
time.Sleep(7 * time.Second)
// 获取 ipset 数量
ipset_len, _ := NumIPSet(IPSET_NAME)
// 安全地获取 ProcessedIPMap 的长度(不要打印内容,不要在无锁状态下读取!)
ProcessedMutex.Lock()
processedLen := len(ProcessedIPMap)
ProcessedMutex.Unlock()
// 获取 Pending 数量
pendingCount := atomic.LoadInt64(&PendingCount)
log.Printf("\033[32m [状态监控] IPSet(%s): %d | 已处理缓存: %d | 待处理积压: %d \033[0m\n",
IPSET_NAME, ipset_len, processedLen, pendingCount)
}
}()
waitForSignalAndCleanUp(cmd)
}
func StartChildProcess() (*exec.Cmd, error) {
args := []string{}
for _, arg := range os.Args[1:] {
if !strings.HasPrefix(arg, "-child") { // 只过滤 -child 标志
if !strings.HasPrefix(arg, "-child") {
args = append(args, arg)
}
}
@@ -71,374 +348,88 @@ func StartChildProcess() (*exec.Cmd, error) {
return cmd, nil
}
// 停止子进程
func StopChildProcess(cmd *exec.Cmd) error {
if cmd == nil || cmd.Process == nil {
return fmt.Errorf("子进程无效")
}
// 尝试优雅地停止子进程
if err := cmd.Process.Signal(syscall.SIGTERM); err != nil {
return fmt.Errorf("发送 SIGTERM 信号失败: %w", err)
return fmt.Errorf("SIGTERM 失败: %w", err)
}
done := make(chan error, 1)
go func() {
done <- cmd.Wait()
}()
go func() { done <- cmd.Wait() }()
select {
case err := <-done:
if err != nil {
return fmt.Errorf("等待子进程退出时出错: %w", err)
}
case <-time.After(5 * time.Second): // 超时时间调整为5秒
fmt.Println("子进程未在规定时间内退出,尝试强制终止...")
if err := cmd.Process.Kill(); err != nil {
return fmt.Errorf("强制终止子进程失败: %w", err)
}
return err
case <-time.After(2 * time.Second):
_ = cmd.Process.Kill()
}
fmt.Printf("子进程已停止, PID: %d\n", cmd.Process.Pid)
return nil
}
// 等待信号并优雅退出
func waitForSignalAndCleanUp(cmd *exec.Cmd) {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
for sig := range sigChan {
fmt.Printf("主进程收到信号: %v\n", sig)
if cmd != nil && cmd.Process != nil {
_ = cmd.Process.Signal(sig) // 转发信号到子进程
}
if sig == syscall.SIGINT || sig == syscall.SIGTERM {
break
}
sig := <-sigChan
fmt.Printf("主进程收到信号: %v\n", sig)
if cmd != nil && cmd.Process != nil {
_ = cmd.Process.Signal(sig)
}
if err := StopChildProcess(cmd); err != nil {
log.Fatalf("清理子进程时遇到错误: %v", err)
}
fmt.Println("主进程退出")
StopChildProcess(cmd)
saveMapToFile("cn.json")
}
// 守护进程模式
func StartDaemon() {
// 创建一个新的实例并让当前进程退出。注意这并不是守护进程的标准实现。
args := []string{}
for _, arg := range os.Args[1:] {
if !strings.HasPrefix(arg, "-d") && !strings.HasPrefix(arg, "-child") { // 过滤掉 -d 和 -child 标志
if !strings.HasPrefix(arg, "-d") && !strings.HasPrefix(arg, "-child") {
args = append(args, arg)
}
}
args = append(args, "-d=false", "-child=false")
cmd := exec.Command(os.Args[0], args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
log.Fatalf("无法启动新实例: %v", err)
}
fmt.Println("新实例已启动,当前进程将退出")
cmd.Start()
os.Exit(0)
}
// 子进程逻辑
func RunChildProcess() {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for {
select {
case sig := <-sigChan:
fmt.Printf("子进程收到信号: %v, 准备退出...\n", sig)
return
case <-ticker.C:
}
}
signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
}
// 保存ProcessedIPMap到文件
func saveMapToFile(filePath string) error {
ProcessedMutex.Lock()
defer ProcessedMutex.Unlock()
file, err := os.Create(filePath)
if err != nil {
return fmt.Errorf("创建文件失败: %w", err)
return err
}
defer file.Close()
encoder := json.NewEncoder(file)
if err := encoder.Encode(ProcessedIPMap); err != nil {
return fmt.Errorf("编码 ProcessedIPMap 失败: %w", err)
}
//log.Println("ProcessedIPMap 已成功保存到文件")
return nil
return json.NewEncoder(file).Encode(ProcessedIPMap)
}
func loadFromFile(filePath string, logMessage string) error {
func loadFromFile(filePath string) error {
ProcessedMutex.Lock()
defer ProcessedMutex.Unlock()
file, err := os.Open(filePath)
if err != nil {
if os.IsNotExist(err) {
log.Println("文件不存在,跳过加载 Map")
return nil
}
return fmt.Errorf("打开文件失败: %w", err)
return nil
}
defer file.Close()
// 尝试用新格式解码
decoder := json.NewDecoder(file)
temp := make(map[string]time.Time)
if err := decoder.Decode(&temp); err == nil {
ProcessedIPMap = temp
log.Println(logMessage)
return nil
}
// 如果失败,尝试旧格式
file.Seek(0, 0) // 重置读取位置
decoder = json.NewDecoder(file)
oldTemp := make(map[string]string)
if err := decoder.Decode(&oldTemp); err == nil {
for ip := range oldTemp {
//ProcessedIPMap[ip] = time.Now() // 给旧 IP 打个当前时间戳
ProcessedIPMap[ip] = time.Date(1971, 1, 1, 0, 0, 0, 0, time.UTC) // 标记为永不过期
}
log.Println(logMessage + "(从旧格式转换)")
return nil
}
return fmt.Errorf("解码 Map 失败: %w", err)
return json.NewDecoder(file).Decode(&ProcessedIPMap)
}
func InitMap() {
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)
}
}()
loadFromFile("cn.json")
}
func WriteLocalAddr() {
local_ipv4_addr = GetLocalIpv4Addr() // 本机地址
// 将本机外网地址加入到已处理集合中
local_ipv4_addr = GetLocalIpv4Addr()
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.Date(1971, 1, 1, 0, 0, 0, 0, time.UTC) // 标记为永不过期
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)
}
}
func RunMainProcess() { // 主进程逻辑
log.Println(" 主进程启动...")
WriteLocalAddr() // 将本机外网地址加入到已处理集合中
cmd, err := StartChildProcess()
if err != nil {
log.Fatalf("子进程启动失败: %v", err)
}
IPSET_NUMBER = 0
IPSET_NAME = fmt.Sprintf("root%d", IPSET_NUMBER)
if return_value := Is_Name_Ipset(IPSET_NAME); return_value == 1 {
createIPSet(IPSET_NAME)
}
// 启动抓包
go startPacketCapture()
// 启动IP地域判断管理
go func() {
for {
IpMutex.Lock() // 锁定互斥锁
if IpList.Len() > 0 { // 链表不为空
e1 := IpList.Front() // 获取链表第一个元素
ipStr := e1.Value.(net.IP).String()
region, _ := ip2region(ipStr) // 离线库初步判断地域
ProcessedMutex.Lock()
_, processed := ProcessedIPMap[ipStr] // 检查是否已处理
ProcessedMutex.Unlock()
if processed { // 如果尚未处理
log.Printf("\033[33m %s 已经标记为国内,跳过!!! \033[0m\n", ipStr)
IpList.Remove(e1)
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
}
REGION := "中国 内网" // 默认地域
if Is_Ip_Ipset(ipStr) != 0 { // IP 不在 ipset 集合中
//if !strings.Contains(region, "中国") && !strings.Contains(region, "内网") { // 离线库判断不在中国内
if !ContainsPart(region, REGION) {
log.Printf("\033[33m [%s %s] 离线库为国外, 进一步API判断\033[0m\n", ipStr, region)
if position, err := curl_(ipStr); err != nil { // 使用 API 判断地域
log.Printf("获取IP地域出错: %v", err)
} else {
log.Printf("\033[31m [%s %s]\033[0m\n\n", ipStr, position) // 打印地域
//if !strings.Contains(position, "中国") && !strings.Contains(position, "内网") { // API 判断为国外
if !ContainsPart(region, REGION) {
AddIPSet(IPSET_NAME, ipStr) // 添加 IP 到 ipset 集合
// 钉钉告警,废弃!钉钉可能限制文本长度,和发送次数!
// warning_ding(ipStr, position) // 警告 IP 地域
} else {
log.Printf("\033[33m %s 离线库为国外, API 判断为国内, 标记为已处理\033[0m\n", ipStr)
// 将 IP 标记为已处理,国内地址
ProcessedMutex.Lock()
ProcessedIPMap[ipStr] = time.Now()
ProcessedMutex.Unlock()
// 写入json文件
if err := saveMapToFile("cn.json"); err != nil {
log.Printf(" 实时保存 Map 失败: %v", err)
}
}
}
}
} else { // IP 已在 ipset 集合中
log.Printf("\033[31m %s 在 ipset 集合中 \033[0m\n", ipStr)
}
// 无论是否已处理,都移除该 IP
IpList.Remove(e1)
}
next:
IpMutex.Unlock() // 解锁互斥锁
// 打印当前info
log.Printf(" 当前Ip链表长度:%d, Ipset名:%s, 长:%d, ProcessedIPMap:[%s]当前长度:%d\n", IpList.Len(), IPSET_NAME, func() int { // 打印 当前 Ipset 链长度
_len, _err := NumIPSet(IPSET_NAME)
if _err == nil {
return _len
}
return 0
}(), ProcessedIPMap, len(ProcessedIPMap))
time.Sleep(1 * time.Second) // 防止高频运行
}
}()
// 启动一个 goroutine后台任务用于定期清理 ProcessedIPMap 中过期的 IP 条目
go func() {
for {
time.Sleep(1 * time.Minute)
// 获取当前时间,用于与 map 中的时间戳进行比较
now := time.Now()
// 加锁,确保并发安全地访问全局变量 ProcessedIPMap
ProcessedMutex.Lock()
// 遍历 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)
}
}
// 解锁,允许其他 goroutine 访问 ProcessedIPMap
ProcessedMutex.Unlock()
// 打印日志,表示本次清理已完成
log.Println(" 已清理过期 ProcessedIPMap 项")
}
}()
// 定时重新加载白名单
go func() {
for {
time.Sleep(1 * time.Minute) // 每 10 分钟自动刷新
if err := LoadWhiteList("whitelist.txt"); err != nil {
log.Printf(" 刷新白名单失败: %v", err)
}
}
}()
// 启动防火墙管理
go func() {
for {
if ipset_len, _ := NumIPSet(IPSET_NAME); ipset_len >= 65535 {
log.Printf("\033[31m ipset %s 列表已满 %d \033[0m\n", IPSET_NAME, ipset_len)
// 创建新的 ipset 集合
IPSET_NUMBER++
if IPSET_NUMBER >= MAX_IPSET_NAME {
//log.Printf("已创建 %d 个集合!!!", MAX_IPSET_NAME)
log.Printf("\033[31m 已创建 %d 个集合!!! \033[0m\n", MAX_IPSET_NAME)
}
IPSET_NAME = fmt.Sprintf("root%d", IPSET_NUMBER)
if return_value := Is_Name_Ipset(IPSET_NAME); return_value == 1 {
createIPSet(IPSET_NAME)
}
}
time.Sleep(3 * time.Second)
}
}()
// 等待信号并清理
waitForSignalAndCleanUp(cmd)
}
func HandleCmd() {
@@ -449,7 +440,11 @@ func HandleCmd() {
flag.BoolVar(&InterfacesList, "l", false, "列出可用的网络接口")
Protocol = flag.String("f", "'tcp' or 'udp' or 'tcp or udp'", "指定 BPF 过滤器")
PcapFile = flag.String("o", "", "保存捕获数据的输出文件(可选)")
flag.StringVar(&instruction, "s", "", "-s start 启动 Iptables 规则\n-s stop 停止 Iptables 规则\n-s list 打印 Iptables 规则\n-s reload 重启 Iptables 规则")
flag.StringVar(&instruction, "s", "",
"-s start 启动 Iptables 规则\n"+
"-s stop 停止 Iptables 规则\n"+
"-s list 打印 Iptables 规则\n"+
"-s reload 重启 Iptables 规则")
flag.BoolVar(&help, "h", false, "")
flag.BoolVar(&help, "help", false, "帮助信息")
flag.Parse()
@@ -519,34 +514,21 @@ func HandleCmd() {
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) // 设置最大CPU核数
runtime.GOMAXPROCS(runtime.NumCPU())
HandleCmd()
CheckCommandExists("iptables")
CheckCommandExists("ipset")
embed_ip2region()
// 加载白名单
err := LoadWhiteList("whitelist.txt")
if err != nil {
log.Fatalf(" whiteList Map 加载白名单失败: %v", err)
} else {
log.Println(" whiteList Map 白名单加载成功")
}
// 守护进程模式
if *daemon {
StartDaemon()
}
// 子进程逻辑
if *child {
RunChildProcess() // 子进程逻辑
RunChildProcess()
return
}
InitMap()
RunMainProcess() // 主进程逻辑
RunMainProcess()
}