0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go言語でsFlowのパケットを受信する方法

Posted at

はじめに

Go言語でsFlowのパッケットを受信して処理する方法の紹介です。sFlowのサーバーを開発するGo言語のパッケージはありますが、うまく動かなかったので、sFlowのパケットをデコードするパッケージ

を使ってサーバーを作る方法を紹介します。

sFlowパケット受信プログラム

package main

import (
	"bytes"
	"log"
	"net"

	"github.com/Cistern/sflow"
)

func main() {
	sv, err := net.ListenPacket("udp", ":6343")
	if err != nil {
		log.Fatalln(err)
	}
	defer sv.Close()
	data := make([]byte, 8192)
	for {
		l, ra, err := sv.ReadFrom(data)
		if err != nil {
			log.Println(err)
			continue
		}
		r := bytes.NewReader(data[:l])
		d := sflow.NewDecoder(r)
		dg, err := d.Decode()
		if err != nil {
			log.Println(err)
			continue
		}
		raIP := ""
		switch a := ra.(type) {
		case *net.UDPAddr:
			raIP = a.IP.String()
		case *net.TCPAddr:
			raIP = a.IP.String()
		}
		for _, sample := range dg.Samples {
			switch s := sample.(type) {
			case *sflow.CounterSample:
				log.Printf("CounterSample from %s:", raIP)
				for _, record := range s.Records {
					log.Printf("%+v", record)
				}
			case *sflow.FlowSample:
				log.Printf("FlowSample from %s", raIP)
				for _, record := range s.Records {
					log.Printf("%+v", record)
				}
			case *sflow.EventDiscardedPacket:
				log.Printf("EventDiscardedPacket from %s", raIP)
				for _, record := range s.Records {
					log.Printf("%+v", record)
				}
			default:
				log.Printf("%v form %s", s, raIP)
			}
		}
	}
}

このプログラムのポイントは

UDPでsFlowのポートを受信できるようにする

	sv, err := net.ListenPacket("udp", ":6343")
	if err != nil {
		log.Fatalln(err)
	}
	defer sv.Close()

 受信したデータをsFlowパッケージでデコードする

		l, ra, err := sv.ReadFrom(data)
		if err != nil {
			log.Println(err)
			continue
		}
		r := bytes.NewReader(data[:l])
		d := sflow.NewDecoder(r)
		dg, err := d.Decode()
		if err != nil {
			log.Println(err)
			continue
		}

デコードしたデータに基づいて処理する

		for _, sample := range dg.Samples {
			switch s := sample.(type) {
			case *sflow.CounterSample:
				log.Printf("CounterSample from %s:", raIP)
				for _, record := range s.Records {
					log.Printf("%+v", record)
				}
			case *sflow.FlowSample:
				log.Printf("FlowSample from %s", raIP)
				for _, record := range s.Records {
					log.Printf("%+v", record)
				}
			case *sflow.EventDiscardedPacket:
				log.Printf("EventDiscardedPacket from %s", raIP)
				for _, record := range s.Records {
					log.Printf("%+v", record)
				}
			default:
				log.Printf("%v form %s", s, raIP)
			}
		}

デコードしたデータには、

  • CounterSample(CPUやメモリーの使用率)
  • FlowSample(パケットのサンプル)
  • EventDiscardedPacket(破棄したパケットのサンプル)

があります。

実行結果


go run main.go
2024/09/29 17:10:15 CounterSample from 192.168.1.32:
2024/09/29 17:10:15 HostDiskCounters: {Total:10196652032 Free:8712331264 MaxUsedPercent:2.039e-42 Reads:49837 BytesRead:1260391424 ReadTime:136338 Writes:3332846 BytesWritten:15576254464 WriteTime:3325584}
2024/09/29 17:10:15 HostMemoryCounters: {Total:498462720 Free:73256960 Shared:0 Buffers:524288 Cached:179838976 SwapTotal:0 SwapFree:0 PageIn:814353 PageOut:7605593 SwapIn:0 SwapOut:0}
2024/09/29 17:10:15 HostCPUCounters: {Load1m:0.08 Load5m:0.08 Load15m:0.02 ProcessesRunning:0 ProcessesTotal:153 NumCPU:1 SpeedCPU:3392 Uptime:2028012 CPUUser:2308970 CPUNice:14820 CPUSys:2891590 CPUIdle:2015687000 CPUWio:214730 CPUIntr:0 CPUSoftIntr:338560 Interrupts:107210281 ContextSwitches:117161266 CPUSteal:56590 CPUGuest:0 CPUGuestNice:0}
2024/09/29 17:10:15 HostNetCounters: {BytesIn:107098 PacketsIn:976 ErrorsIn:23 DropsIn:0 BytesOut:182648 PacketsOut:835 ErrorsOut:0 DropsOut:0}
2024/09/29 17:10:17 FlowSample from 192.168.1.32
2024/09/29 17:10:17 RawPacketFlow: {Protocol:1 FrameLength:370 Stripped:4 HeaderSize:128 Header:[80 0 0 4 0 1 80 0 0 6 0 0 8 0 69 0 1 96 161 216 0 0 64 17 9 233 10 30 1 12 192 168 1 250 12 213 8 8 1 76 31 4 0 9 0 4 120 226 28 166 102 249 11 104 0 5 1 16 0 0 0 1 1 2 0 76 0 0 0 0 0 0 0 222 0 0 0 0 0 0 0 222 0 0 0 3 0 0 0 3 120 223 70 212 120 223 70 212 0 161 233 159 0 0 0 1 17 0 0 0 20 0 0 48 68 0 0 0 0 0 0 0 0 14 4 195 0 10]}
2024/09/29 17:10:17 FlowSample from 192.168.1.32
2024/09/29 17:10:17 RawPacketFlow: {Protocol:1 FrameLength:74 Stripped:4 HeaderSize:70 Header:[80 0 0 4 0 0 0 37 54 171 119 83 8 0 69 0 0 56 204 75 0 0 63 1 225 173 192 168 1 250 10 30 1 12 3 3 230 211 0 0 0 0 69 0 1 96 161 216 0 0 63 17 10 233 10 30 1 12 192 168 1 250 12 213 8 8 1 76 0 0]}
2024/09/29 17:10:18 FlowSample from 192.168.1.32
2024/09/29 17:10:18 RawPacketFlow: {Protocol:1 FrameLength:64 Stripped:4 HeaderSize:60 Header:[1 128 194 0 0 0 108 205 214 195 36 97 0 39 66 66 3 0 0 2 2 124 128 0 108 205 214 195 36 95 0 0 0 0 128 0 108 205 214 195 36 95 128 4 0 0 20 0 2 0 15 0 0 0 0 0 0 0 0 0]}
2024/09/29 17:10:18 FlowSample from 192.168.1.32
2024/09/29 17:10:18 ExtendedSwitchFlow: {SourceVlan:0 SourcePriority:0 DestinationVlan:0 DestinationPriority:0}
2024/09/29 17:10:18 RawPacketFlow: {Protocol:1 FrameLength:146 Stripped:4 HeaderSize:128 Header:[80 0 0 4 0 0 0 37 54 171 119 83 8 0 69 0 3 29 103 109 0 0 57 17 143 109 198 41 0 4 192 168 1 32 0 53 136 185 3 9 83 11 156 87 128 0 0 1 0 0 0 8 0 13 3 111 114 103 0 0 1 0 1 192 12 0 2 0 1 0 2 163 0 0 25 2 97 50 3 111 114 103 11 97 102 105 108 105 97 115 45 110 115 116 4 105 110 102 111 0 192 12 0 2 0 1 0 2 163 0 0 21 2 98 50 3 111 114 103 11 97 102 105 108 105 97 115 45]}

のような感じになります。

余談

私の開発したTWSNMP FC/FKでは、この方法でsFlowのパケットを処理しています。
このsFlowのパケットをデコードするパッケージを使っている理由は

に詳しく書いています。

このパッケージ開発をちょっとだけお手伝いしました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?