{"id":37103352,"url":"https://github.com/flswld/halo","last_synced_at":"2026-01-14T12:30:59.068Z","repository":{"id":189317166,"uuid":"680458506","full_name":"flswld/halo","owner":"flswld","description":"Golang网络包收发框架,以太网帧,简单协议栈,软路由,IP包过滤与修改","archived":false,"fork":false,"pushed_at":"2025-07-12T03:48:41.000Z","size":234,"stargazers_count":33,"open_issues_count":0,"forks_count":7,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-12T05:35:52.417Z","etag":null,"topics":["ddos","dpdk","golang","kcp","nat","network","router"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/flswld.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-08-19T10:00:28.000Z","updated_at":"2025-07-12T03:47:14.000Z","dependencies_parsed_at":"2023-08-19T11:41:14.571Z","dependency_job_id":"656a3ca5-766b-4e5c-95bd-22ece6d935c5","html_url":"https://github.com/flswld/halo","commit_stats":null,"previous_names":["flswld/halo"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/flswld/halo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flswld%2Fhalo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flswld%2Fhalo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flswld%2Fhalo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flswld%2Fhalo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/flswld","download_url":"https://codeload.github.com/flswld/halo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flswld%2Fhalo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28420773,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ddos","dpdk","golang","kcp","nat","network","router"],"created_at":"2026-01-14T12:30:58.732Z","updated_at":"2026-01-14T12:30:59.047Z","avatar_url":"https://github.com/flswld.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# halo\n\n[English](README-EN.md)\n***\n\n## Golang高性能轻量级网络包收发框架\n\n* 网卡单个队列发包性能可超过10Mpps\n* 完整的路由器协议栈实现\n* 全平台开箱即用的工具包：`logger(日志)`、`cpu(协程绑核/自旋锁)`、`mem(内存分配器/环状缓冲区)`、`hashmap/list(自定义内存分配器)`\n\n### dpdk环境搭建\n\n```shell\n# 建议使用Ubuntu20.04\n\n# 安装dpdk\ncd /root\nwget https://fast.dpdk.org/rel/dpdk-20.11.10.tar.gz\ntar -zxvf dpdk-20.11.10.tar.gz\ncd dpdk-stable-20.11.10\n# 添加环境变量\nexport RTE_SDK=\"/root/dpdk-stable-20.11.10\"\n# 编译DPDK\nmeson build\ncd build\nmeson configure -Denable_kmods=true\nninja\nninja install\nldconfig\n\n# UIO\nmodprobe uio\ninsmod $RTE_SDK/build/kernel/linux/igb_uio/igb_uio.ko\nifconfig eth0 down\n$RTE_SDK/usertools/dpdk-devbind.py --bind=igb_uio eth0\n\n# VFIO\nvim /etc/default/grub\n# \"GRUB_CMDLINE_LINUX\" 追加 \"intel_iommu=on\"\nupdate-grub2\nreboot\nmodprobe vfio \u0026\u0026 modprobe vfio-pci\necho 1 \u003e/sys/module/vfio/parameters/enable_unsafe_noiommu_mode\n# 查看要绑定网卡的pcie设备号\n$RTE_SDK/usertools/dpdk-devbind.py --status\nifconfig eth0 down\n$RTE_SDK/usertools/dpdk-devbind.py -b vfio-pci 0000:00:05.0\n\n# KNI\ninsmod $RTE_SDK/build/kernel/linux/kni/rte_kni.ko carrier=on\n\n# 内存大页\necho 1024 \u003e/sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages\nmkdir -p /mnt/huge_2M\nmount -t hugetlbfs none /mnt/huge_2M -o pagesize=2M\necho 0 \u003e/sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages\nmkdir -p /mnt/huge_1G\nmount -t hugetlbfs none /mnt/huge_1G -o pagesize=1G\n\n```\n\n### 如何使用\n\n```shell\ngo get github.com/flswld/halo\n\n```\n\n### 使用示例\n\n```go\n// 详见example/example.go\n\n// DirectDpdk 直接使用dpdk收发网络报文\nfunc DirectDpdk() {\n\t// 启动dpdk\n\tdpdk.Run(\u0026dpdk.Config{\n\t\tDpdkCpuCoreList: []int{0, 1, 2, 3, 4, 5, 6, 7, 8}, // dpdk使用的核心编号列表 主线程第一个核心 每个网卡队列一个核心\n\t\tDpdkMemChanNum:  4,                                // dpdk内存通道数\n\t\tPortIdList:      []int{0, 1},                      // 使用的网卡id列表\n\t\tQueueNum:        2,                                // 启用的网卡队列数\n\t\tRingBufferSize:  128 * mem.MB,                     // 环状缓冲区大小\n\t\tAfPacketDevList: nil,                              // 使用的af_packet虚拟网卡列表\n\t\tStatsLog:        true,                             // 收发包统计日志\n\t\tDebugLog:        false,                            // 收发包调试日志\n\t\tIdleSleep:       false,                            // 空闲睡眠 降低cpu占用\n\t\tSingleCore:      false,                            // 单核模式 只使用cpu0\n\t\tKniEnable:       false,                            // 开启kni内核网卡\n\t})\n\n\t// 通过EthQueueRxPkt和EthQueueTxPkt方法发送接收原始以太网报文\n\tvar exit atomic.Bool\n\tgo func() {\n\t\tcpu.BindCpuCore(9)\n\t\tfor {\n\t\t\tif exit.Load() {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tpkt := dpdk.EthQueueRxPkt(0, 0)\n\t\t\tif pkt == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdpdk.EthQueueTxPkt(1, 0, pkt)\n\t\t}\n\t}()\n\tgo func() {\n\t\tcpu.BindCpuCore(10)\n\t\tfor {\n\t\t\tif exit.Load() {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tpkt := dpdk.EthQueueRxPkt(0, 1)\n\t\t\tif pkt == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdpdk.EthQueueTxPkt(1, 1, pkt)\n\t\t}\n\t}()\n\tgo func() {\n\t\tcpu.BindCpuCore(11)\n\t\tfor {\n\t\t\tif exit.Load() {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tpkt := dpdk.EthQueueRxPkt(1, 0)\n\t\t\tif pkt == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdpdk.EthQueueTxPkt(0, 0, pkt)\n\t\t}\n\t}()\n\tgo func() {\n\t\tcpu.BindCpuCore(12)\n\t\tfor {\n\t\t\tif exit.Load() {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tpkt := dpdk.EthQueueRxPkt(1, 1)\n\t\t\tif pkt == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdpdk.EthQueueTxPkt(0, 1, pkt)\n\t\t}\n\t}()\n\ttime.Sleep(time.Minute)\n\texit.Store(true)\n\ttime.Sleep(time.Second)\n\n\t// 停止dpdk\n\tdpdk.Exit()\n}\n\n// EthernetRouter 以太网路由器\nfunc EthernetRouter() {\n\tlogger.InitLogger(nil)\n\tdefer logger.CloseLogger()\n\n\t// 启动dpdk\n\tdpdk.DefaultLogWriter = new(logger.LogWriter)\n\tdpdk.Run(\u0026dpdk.Config{\n\t\tDpdkCpuCoreList: nil,\n\t\tDpdkMemChanNum:  1,\n\t\tPortIdList:      []int{0, 1},\n\t\tQueueNum:        1,\n\t\tRingBufferSize:  128 * mem.MB,\n\t\tAfPacketDevList: []string{\"eth0\", \"wlan0\"},\n\t\tStatsLog:        true,\n\t\tDebugLog:        false,\n\t\tIdleSleep:       true,\n\t\tSingleCore:      true,\n\t\tKniEnable:       true,\n\t})\n\n\t// 初始化路由器\n\tengine.DefaultLogWriter = new(logger.LogWriter)\n\tr, err := engine.InitRouter(\u0026engine.RouterConfig{\n\t\tDebugLog: false, // 调试日志\n\t\t// 网卡列表\n\t\tNetIfList: []*engine.NetIfConfig{\n\t\t\t{\n\t\t\t\tName:        \"wan0\",                 // 网卡名\n\t\t\t\tMacAddr:     \"AA:AA:AA:AA:AA:AA\",    // mac地址\n\t\t\t\tIpAddr:      \"192.168.100.100\",      // ip地址\n\t\t\t\tNetworkMask: \"255.255.255.0\",        // 子网掩码\n\t\t\t\tNatEnable:   true,                   // 开启网络地址转换\n\t\t\t\tNatType:     engine.NatTypeFullCone, // 网络地址转换类型\n\t\t\t\t// 网络地址转换端口映射表\n\t\t\t\tNatPortMappingList: []*engine.NatPortMappingEntryConfig{\n\t\t\t\t\t{\n\t\t\t\t\t\tWanPort:       22,                     // wan口端口\n\t\t\t\t\t\tLanHostIpAddr: \"192.168.111.222\",      // lan口主机ip地址\n\t\t\t\t\t\tLanHostPort:   22,                     // lan口主机端口\n\t\t\t\t\t\tIpv4HeadProto: protocol.IPH_PROTO_TCP, // ip头部协议\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tDnsServerAddr:    \"\",                                              // dns服务器地址\n\t\t\t\tDhcpServerEnable: false,                                           // 开启dhcp服务器\n\t\t\t\tDhcpClientEnable: false,                                           // 开启dhcp客户端\n\t\t\t\tEthRxFunc:        func() (pkt []byte) { return dpdk.EthRxPkt(0) }, // 网卡收包方法\n\t\t\t\tEthTxFunc:        func(pkt []byte) { dpdk.EthTxPkt(0, pkt) },      // 网卡发包方法\n\t\t\t\tBindCpuCore:      0,                                               // 绑定的cpu核心\n\t\t\t\tStaticHeapSize:   8 * mem.MB,                                      // 静态堆内存大小\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:             \"wan1\",\n\t\t\t\tMacAddr:          \"AA:AA:AA:AA:AA:BB\",\n\t\t\t\tNatEnable:        true,\n\t\t\t\tNatType:          engine.NatTypeFullCone,\n\t\t\t\tDhcpClientEnable: true,\n\t\t\t\tEthRxFunc: func() (pkt []byte) {\n\t\t\t\t\treturn dpdk.EthRxPkt(1)\n\t\t\t\t},\n\t\t\t\tEthTxFunc: func(pkt []byte) {\n\t\t\t\t\tdpdk.EthTxPkt(1, pkt)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:             \"lan0\",\n\t\t\t\tMacAddr:          \"AA:AA:AA:AA:AA:CC\",\n\t\t\t\tIpAddr:           \"192.168.111.1\",\n\t\t\t\tNetworkMask:      \"255.255.255.0\",\n\t\t\t\tDnsServerAddr:    \"223.5.5.5\",\n\t\t\t\tDhcpServerEnable: true,\n\t\t\t\tEthRxFunc: func() (pkt []byte) {\n\t\t\t\t\treturn dpdk.KniRxPkt()\n\t\t\t\t},\n\t\t\t\tEthTxFunc: func(pkt []byte) {\n\t\t\t\t\tdpdk.KniTxPkt(pkt)\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t// 静态路由列表\n\t\tRouteList: []*engine.RouteEntryConfig{\n\t\t\t{\n\t\t\t\tDstIpAddr:   \"114.114.114.114\", // 目的ip地址\n\t\t\t\tNetworkMask: \"255.255.255.255\", // 网络掩码\n\t\t\t\tNextHop:     \"192.168.100.1\",   // 下一跳\n\t\t\t\tNetIf:       \"wan0\",            // 出接口\n\t\t\t},\n\t\t},\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// 启动路由器\n\tr.RunRouter()\n\n\tr.Ipv4PktFwdHook = func(raw []byte, dir int) (drop bool, mod []byte) {\n\t\tpayload, _, srcAddr, dstAddr, err := protocol.ParseIpv4Pkt(raw)\n\t\tif err == nil {\n\t\t\tlogger.Debug(\"[IPV4 ROUTE FWD] src: %v -\u003e dst: %v, len: %v\", srcAddr, dstAddr, len(payload))\n\t\t}\n\t\treturn false, raw\n\t}\n\n\ttime.Sleep(time.Minute)\n\n\t// 停止路由器\n\tr.StopRouter()\n\n\t// 停止dpdk\n\tdpdk.Exit()\n}\n\n// EthernetSwitch 以太网交换机\nfunc EthernetSwitch() {\n\t// 启动dpdk\n\tdpdk.Run(\u0026dpdk.Config{\n\t\tPortIdList: []int{0, 1, 2, 3},\n\t\tStatsLog:   true,\n\t\tIdleSleep:  true,\n\t\tSingleCore: true,\n\t})\n\n\t// 初始化交换机\n\ts, err := engine.InitSwitch(\u0026engine.SwitchConfig{\n\t\t// 端口列表\n\t\tSwitchPortList: []*engine.SwitchPortConfig{\n\t\t\t{\n\t\t\t\tName:        \"port0\",                                         // 端口名\n\t\t\t\tEthRxFunc:   func() (pkt []byte) { return dpdk.EthRxPkt(0) }, // 端口收包方法\n\t\t\t\tEthTxFunc:   func(pkt []byte) { dpdk.EthTxPkt(0, pkt) },      // 端口发包方法\n\t\t\t\tVlanId:      1,                                               // vlan号\n\t\t\t\tBindCpuCore: 0,                                               // 绑定的cpu核心\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:      \"port1\",\n\t\t\t\tEthRxFunc: func() (pkt []byte) { return dpdk.EthRxPkt(1) },\n\t\t\t\tEthTxFunc: func(pkt []byte) { dpdk.EthTxPkt(1, pkt) },\n\t\t\t\tVlanId:    1,\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:      \"port2\",\n\t\t\t\tEthRxFunc: func() (pkt []byte) { return dpdk.EthRxPkt(2) },\n\t\t\t\tEthTxFunc: func(pkt []byte) { dpdk.EthTxPkt(2, pkt) },\n\t\t\t\tVlanId:    2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:      \"port3\",\n\t\t\t\tEthRxFunc: func() (pkt []byte) { return dpdk.EthRxPkt(3) },\n\t\t\t\tEthTxFunc: func(pkt []byte) { dpdk.EthTxPkt(3, pkt) },\n\t\t\t\tVlanId:    2,\n\t\t\t},\n\t\t},\n\t\tStaticHeapSize: 8 * mem.MB, // 静态堆内存大小\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// 启动交换机\n\ts.RunSwitch()\n\n\ttime.Sleep(time.Minute)\n\n\t// 停止交换机\n\ts.StopSwitch()\n\n\t// 停止dpdk\n\tdpdk.Exit()\n}\n\n```\n\n### TODO\n\n- [X] 简易ARP+IPV4+ICMP协议栈\n- [X] KCP协议栈\n- [X] 多网卡支持\n- [X] 路由转发功能\n- [X] NAT功能\n- [X] 网卡多队列支持\n- [X] DHCP功能\n- [ ] PPPOE功能\n- [ ] IPV6支持\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflswld%2Fhalo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflswld%2Fhalo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflswld%2Fhalo/lists"}