GO实现基于命令行的简单IPS程序代码

 更新时间:2024年12月28日 11:21:03   作者:星星猫  
本文介绍了入侵防御系统IPS的工作原理和实现,IPS通过网络流量监控和实时响应,防止网络攻击,通过使用Go语言实现一个简单的IPS示例程序,展示了如何获取本地IP地址和探测网络中其他设备的IP地址,包括如何定义和加载规则文件,以及如何检测IP对相应端口的访问是否达到规定阈值

入侵防御系统

IPS(Intrusion Prevention System)即入侵防御系统,主要用于实时检查和阻止网络入侵。与入侵检测系统(IDS)不同,IPS通常部署在网络的关键路径上,实时监控网络流量,并在发现攻击时立即采取响应措施,如丢弃恶意数据包、封锁攻击源IP地址等。

IPS的工作原理

IPS通过直接嵌入到网络流量中实现主动防御。它通过一个网络端口接收来自外部系统的流量,经过检查确认其中不包含异常活动或可疑内容后,再通过另一个端口传送到内部系统中。有问题的数据包以及所有来自同一数据流的后续数据包都会在IPS设备中被清除掉。

GO实现IPS

下面我们用 Go 语言编写,一个可以在命令行中获取并打印本地 IP 地址(基于常见网络接口)的示例程序,这里主要是获取 IPv4 地址进行展示,示例代码使用了标准库中的 net 包:

获取本地网络接口上绑定的 IP 

package main

import (
    "fmt"
    "net"
)

func main() {
    addrs, err := net.InterfaceAddrs()
    if err!= nil {
        fmt.Printf("获取网络接口地址失败: %v\n", err)
        return
    }

    for _, addr := range addrs {
        ipNet, ok := addr.(*net.IPNet)
        if ok &&!ipNet.IP.IsLoopback() && ipNet.IP.To4()!= nil {
            fmt.Println("IP地址:", ipNet.IP.String())
        }
    }
}

运行

  1. 确保已经安装了 Go 环境(Go 1.10 及以上版本)。
  2. 将上述代码保存到一个以 .go 为后缀的文件中,比如 ips.go。
  3. 打开命令行,切换到该文件所在的目录。
  4. 运行命令 go run ips.go,程序就会执行并输出找到的本地非回环的 IPv4 地址信息。

也可编译后运行

go build ips.go

然后运行生成的可执行文件(在 Windows 上是 .exe 后缀的文件,在 Linux、macOS 等系统上就是普通的二进制文件)也能看到相应的 IP 地址输出。

请注意:这里只是简单获取本地网络接口上绑定的 IP 示例

 对于IPS而言,他要检测的是网络中的流量(比如探测网络中其他设备 IP 等)这需要进一步扩展代码,例如利用 net.Dial 等去做网络连接测试、IP 扫描等操作。

探测网络中其他设备 IP

这里只是通过简单的 ICMP 即 ping 操作概念类似的简单探测

package main

import (
    "fmt"
    "net"
    "os"
    "sync"
    "time"
)

func PingIP(ip string, wg *sync.WaitGroup, result chan<- string) {
    defer wg.Done()
    conn, err := net.DialTimeout("ip4:icmp", ip, time.Second*2)
    if err == nil {
        conn.Close()
        result <- ip
    }
}

func main() {
    if len(os.Args)!= 2 {
        fmt.Println("请输入要扫描的网段,例如 192.168.1.0/24")
        return
    }
    _, ipnet, err := net.ParseCIDR(os.Args[1])
    if err!= nil {
        fmt.Printf("解析网段失败: %v\n", err)
        return
    }

    var wg sync.WaitGroup
    result := make(chan string)

    for ip := ipnet.IP.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
        wg.Add(1)
        go PingIP(ip.String(), &wg, result)
    }

    go func() {
        wg.Wait()
        close(result)
    }()

    for aliveIP := range result {
        fmt.Println("存活IP:", aliveIP)
    }
}

func inc(ip net.IP) {
    for j := len(ip) - 1; j >= 0; j-- {
        ip[j]++
        if ip[j] > 0 {
            break
        }
    }
}

在命令行中使用这个扩展版本时,可以像这样运行(假设编译后的可执行文件名为 ips):

./ips 192.168.1.0/24

上述命令会尝试去探测指定网段 192.168.1.0/24 内的 IP 地址哪些是存活的(可以响应 ICMP 请求的,类似 ping 通的概念),并打印出存活的 IP 地址。

增加规则文件(rules.json)

首先我们设定一个规则文件,用json的方式来保存规则

[
    {
        "id": "1001",
        "description": "SSH暴力破解检测",
        "protocol": "tcp",
        "dst_port": 22,
        "action": "block",
        "threshold": 5,
        "time_window": 60
    },
    {
        "id": "1002",
        "description": "RDP暴力破解检测",
        "protocol": "tcp",
        "dst_port": 3389,
        "action": "block",
        "threshold": 5,
        "time_window": 60
    },
    {
        "id": "1003",
        "description": "MySQL暴力破解检测",
        "protocol": "tcp",
        "dst_port": 3306,
        "action": "block",
        "threshold": 5,
        "time_window": 60
    }
]

然后我们写一个go文件,来检测 IP 对相应端口的访问是否达到规则中定义的暴力破解阈值情况

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net"
    "os"
    "path/filepath"
    "sync"
    "time"
)

// Rule结构体表示一条安全规则
type Rule struct {
    ID          string  `json:"id"`
    Description string  `json:"description"`
    Protocol    string  `json:"protocol"`
    DstPort     int     `json:"dst_port"`
    Action      string  `json:"action"`
    Threshold   int     `json:"threshold"`
    TimeWindow  int     `json:"time_window"`
}

// LoadRules从文件加载安全规则
func LoadRules(filePath string) ([]*Rule, error) {
    content, err := ioutil.ReadFile(filePath)
    if err!= nil {
        return nil, fmt.Errorf("读取规则文件失败: %v", err)
    }
    var rules []*Rule
    err = json.Unmarshal(content, &rules)
    if err!= nil {
        return nil, fmt.Errorf("解析规则文件失败: %v", err)
    }
    return rules, nil
}

// ConnectionRecord记录IP的连接记录(简化示例,仅记录次数)
type ConnectionRecord struct {
    mu         sync.Mutex
    connections map[string]int
}

func NewConnectionRecord() *ConnectionRecord {
    return &ConnectionRecord{
        connections: make(map[string]int),
    }
}

func (cr *ConnectionRecord) Record(ip net.IP, port int) {
    cr.mu.Lock()
    key := fmt.Sprintf("%s:%d", ip.String(), port)
    cr.connections[key]++
    cr.mu.Unlock()
}

func (cr *ConnectionRecord) CheckViolation(rules []*Rule) []*Rule {
    var violatedRules []*Rule
    cr.mu.Lock()
    now := time.Now()
    for _, rule := range rules {
        for key, count := range cr.connections {
            parts := strings.Split(key, ":")
            ip := net.ParseIP(parts[0])
            port := atoi(parts[1])
            if port == rule.DstPort && count >= rule.Threshold {
                // 这里简单判断次数达到阈值就算违规,实际可能需考虑时间窗口等更复杂逻辑细化
                violatedRules = append(violatedRules, rule)
            }
        }
    }
    cr.mu.Unlock()
    return violatedRules
}

func atoi(s string) int {
    n, _ := fmt.Sscanf(s, "%d", &n)
    return n
}

func main() {
    // 获取当前目录下的rules.json作为配置文件路径(可根据实际调整)
    currentDir, err := os.Getwd()
    if err!= nil {
        fmt.Printf("获取当前目录失败: %v\n", err)
        return
    }
    configFilePath := filepath.Join(currentDir, "rules.json")

    rules, err := LoadRules(configFilePath)
    if err!= nil {
        fmt.Printf("加载规则失败: %v\n", err)
        return
    }

    targetIPNet := &net.IPNet{}
    _, targetIPNet, err = net.ParseCIDR("192.168.1.0/24")
    if err!= nil {
        fmt.Printf("解析目标IP网段失败: %v\n", err)
        return
    }

    record := NewConnectionRecord()

    // 模拟IP对内网端口的连接访问(这里简单循环增加连接次数示例)
    for i := 0; i < 10; i++ {
        for ip := targetIPNet.IP.Mask(targetIPNet.Mask); targetIPNet.Contains(ip); inc(ip) {
            // 简单模拟多次访问各规则关注的端口,实际场景会根据真实网络连接情况记录
            for _, rule := range rules {
                record.Record(ip, rule.DstPort)
            }
        }
    }

    violatedRules := record.CheckViolation(rules)
    for _, violatedRule := range violatedRules {
        fmt.Printf("IP段内存在疑似违反规则 %s 的情况,规则描述:%s\n", violatedRule.ID, violatedRule.Description)
    }
}

func inc(ip net.IP) {
    for j := len(ip) - 1; j >= 0; j-- {
        ip[j]++
        if ip[j] > 0 {
            break
        }
    }
}
  1. 定义规则结构体和相关操作函数:
  • 首先定义了 Rule 结构体,其字段与 JSON 格式的规则文件中的各个属性相对应,用于表示一条安全规则。
  • LoadRules 函数用于读取指定路径的 JSON 规则文件,并将其解析为 Rule 结构体的切片,若读取或解析过程出现错误则返回相应的错误信息。
  1. 定义连接记录结构体及相关方法:
  • ConnectionRecord 结构体用于记录 IP 地址对不同端口的连接情况,内部使用一个互斥锁(sync.Mutex)来保证并发安全,通过 Record 方法记录每个 IP 和端口的连接次数,使用 CheckViolation 方法来检查当前的连接记录是否违反了给定的规则(这里只是简单根据连接次数是否达到阈值判断,实际可进一步完善考虑时间窗口等更多细节)。
  1. 主函数逻辑:
  • 先获取当前目录下规则配置文件(rules.json)的路径(可按需修改为其他路径),调用 LoadRules 函数加载规则列表。
  • 接着解析要检测的目标 IP 网段(示例中为 192.168.1.0/24,可以根据实际情况更改),创建一个 ConnectionRecord 实例来记录连接情况。
  • 然后通过循环模拟 IP 对内网各端口的访问(这里只是简单循环增加访问次数示意,实际需要结合真实的网络连接情况来记录),并调用 ConnectionRecord 的 Record 方法记录每次的访问情况。
  • 最后调用 ConnectionRecord 的 CheckViolation 方法检查是否有违反规则的情况,若有则打印出相应的违规规则信息。

注意

这里的代码仅是抛砖引玉,其中的规则检查逻辑,尤其是针对时间窗口的处理比较简化,在实际应用场景中,你可能需要精确地记录每个连接的时间戳,并按照时间窗口准确判断是否在指定时间段内达到了阈值等情况,以实现更符合实际需求的检测逻辑。

模拟的 IP 访问场景也非常简单,只是为了演示功能而进行的简单循环增加访问次数,实际需要对接真实的网络流量监控等相关机制来准确记录 IP 的访问情况。

到此这篇关于GO实现基于命令行的简单IPS程序代码的文章就介绍到这了,更多相关GO实现基于命令行的简单IPS内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • GoLang编程必备:GoFrame GoLand插件介绍

    GoLang编程必备:GoFrame GoLand插件介绍

    掌握GoLang编程必备工具,我们来深入了解GoFrame GoLand插件,这个小巧但强大的插件将极大提升你的开发效率,让代码流畅如行云流水,一起跟随本指南,解锁更智能的编程之旅!
    2023-12-12
  • Go语言中interface语法与使用详解

    Go语言中interface语法与使用详解

    Go语言里面设计最精妙的应该算interface,它让面向对象,内容组织实现非常的方便,下面这篇文章主要给大家介绍了关于Go语言中interface语法与使用的相关资料,需要的朋友可以参考下
    2022-07-07
  • Go语言CSP并发模型实现MPG

    Go语言CSP并发模型实现MPG

    这篇文章主要为大家介绍了Go语言CSP并发模型实现MPG图文详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Redis BloomFilter布隆过滤器原理与实现

    Redis BloomFilter布隆过滤器原理与实现

    你在开发或者面试过程中,有没有遇到过 海量数据需要查重,缓存穿透怎么避免等等这样的问题呢?下面这个东西超棒,好好了解下,面试过关斩将,凸显你的不一样
    2022-10-10
  • golang等待触发事件的实例

    golang等待触发事件的实例

    这篇文章主要介绍了golang等待触发事件的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 基于go+vue实现的golang每日新闻数据浏览与检索平台(推荐)

    基于go+vue实现的golang每日新闻数据浏览与检索平台(推荐)

    gonews是基于 go+vue 实现的golang每日新闻浏览与检索平台,本文通过实例代码给大家讲解,介绍的非常详细,具有参考借鉴价值,需要的朋友参考下吧
    2018-01-01
  • goland把go项目打包进docker镜像的全过程记录

    goland把go项目打包进docker镜像的全过程记录

    golang编译的应用是不需要依赖其他运行环境的,下面这篇文章主要给大家介绍了关于goland把go项目打包进docker镜像的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • Golang实现程序优雅退出的方法详解

    Golang实现程序优雅退出的方法详解

    项目开发过程中,随着需求的迭代,代码的发布会频繁进行,在发布过程中,Golang如何让程序做到优雅的退出?本文就来详细为大家讲讲
    2022-06-06
  • 详解Go语言中数组,切片和映射的使用

    详解Go语言中数组,切片和映射的使用

    Arrays (数组), Slices (切片) 和 Maps (映射) 是常见的一类数据结构。这篇文章将为大家详细介绍一下Go语言中数组,切片和映射的使用,感兴趣的可以学习一下
    2022-07-07
  • Go语言中的map扩容机制

    Go语言中的map扩容机制

    Go语言中的map是一种高效的数据结构,其扩容机制确保了在大数据量情况下的性能,本文介绍了包括扩容触发条件、扩容过程和渐进式扩容,感兴趣的可以了解一下
    2024-12-12

最新评论