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言語でNetFlowを受信する方法

Posted at

はじめに

Go言語でNetFlowのパケットを受信して処理するためのパッケージ

の使い方を説明します。

サンプルプログラム

GiHUBのリポジトリにcmd/nf-dumpというサンプルプログラムがあります。
そのままです。


/*
Command nf-dump decodes NetFlow packets from UDP datagrams.

Usage:

	nf-dump [flags]

Flags:

	-addr string 	Listen address (default ":2055")
*/
package main

import (
	"bytes"
	"flag"
	"log"
	"net"

	"github.com/tehmaze/netflow"
	"github.com/tehmaze/netflow/ipfix"
	"github.com/tehmaze/netflow/netflow1"
	"github.com/tehmaze/netflow/netflow5"
	"github.com/tehmaze/netflow/netflow6"
	"github.com/tehmaze/netflow/netflow7"
	"github.com/tehmaze/netflow/netflow9"
	"github.com/tehmaze/netflow/session"
)

// Safe default
var readSize = 2 << 16

func main() {
	listen := flag.String("addr", ":2055", "Listen address")
	flag.Parse()

	var addr *net.UDPAddr
	var err error
	if addr, err = net.ResolveUDPAddr("udp", *listen); err != nil {
		log.Fatal(err)
	}

	var server *net.UDPConn
	if server, err = net.ListenUDP("udp", addr); err != nil {
		log.Fatal(err)
	}

	if err = server.SetReadBuffer(readSize); err != nil {
		log.Fatal(err)
	}

	decoders := make(map[string]*netflow.Decoder)
	for {
		buf := make([]byte, 8192)
		var remote *net.UDPAddr
		var octets int
		if octets, remote, err = server.ReadFromUDP(buf); err != nil {
			log.Printf("error reading from %s: %v\n", remote, err)
			continue
		}

		log.Printf("received %d bytes from %s\n", octets, remote)

		d, found := decoders[remote.String()]
		if !found {
			s := session.New()
			d = netflow.NewDecoder(s)
			decoders[remote.String()] = d
		}

		m, err := d.Read(bytes.NewBuffer(buf[:octets]))
		if err != nil {
			log.Println("decoder error:", err)
			continue
		}

		switch p := m.(type) {
		case *netflow1.Packet:
			netflow1.Dump(p)

		case *netflow5.Packet:
			netflow5.Dump(p)

		case *netflow6.Packet:
			netflow6.Dump(p)

		case *netflow7.Packet:
			netflow7.Dump(p)

		case *netflow9.Packet:
			netflow9.Dump(p)

		case *ipfix.Message:
			ipfix.Dump(p)
		}
	}
}

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

UDPのポートをオープンして受信状態にする

	listen := flag.String("addr", ":2055", "Listen address")
	flag.Parse()

	var addr *net.UDPAddr
	var err error
	if addr, err = net.ResolveUDPAddr("udp", *listen); err != nil {
		log.Fatal(err)
	}

	var server *net.UDPConn
	if server, err = net.ListenUDP("udp", addr); err != nil {
		log.Fatal(err)
	}

2055番ポートです。

送信元毎にデコーダーを作成する

		d, found := decoders[remote.String()]
		if !found {
			s := session.New()
			d = netflow.NewDecoder(s)
			decoders[remote.String()] = d
		}

NetFlowパケットをデコードする

		m, err := d.Read(bytes.NewBuffer(buf[:octets]))
		if err != nil {
			log.Println("decoder error:", err)
			continue
		}


NetFlowのバージョン毎にダンプする

		switch p := m.(type) {
		case *netflow1.Packet:
			netflow1.Dump(p)

		case *netflow5.Packet:
			netflow5.Dump(p)

		case *netflow6.Packet:
			netflow6.Dump(p)

		case *netflow7.Packet:
			netflow7.Dump(p)

		case *netflow9.Packet:
			netflow9.Dump(p)

		case *ipfix.Message:
			ipfix.Dump(p)
		}

よく使われるのは、v5,v9,ipfix(v10)です。

実行結果

実行結果
$go run main.go
2024/09/27 17:48:57 received 172 bytes from 10.30.1.12:3285
NetFlow version 9 packet
2024/09/27 17:49:05 received 472 bytes from 192.168.1.32:36573
IPFIX message
2024/09/27 17:49:05 received 472 bytes from 192.168.1.32:36573
IPFIX message
2024/09/27 17:49:05 received 472 bytes from 192.168.1.32:36573
IPFIX message
2024/09/27 17:49:05 received 96 bytes from 192.168.1.32:36573
IPFIX message
2024/09/27 17:49:05 received 352 bytes from 192.168.1.32:36573
IPFIX message
2024/09/27 17:49:07 received 172 bytes from 10.30.1.12:3285
NetFlow version 9 packet
2024/09/27 17:49:07 received 60 bytes from 10.30.1.12:3285
NetFlow version 9 packet
2024/09/27 17:49:22 received 172 bytes from 10.30.1.12:3285
NetFlow version 9 packet
2024/09/27 17:49:22 received 60 bytes from 10.30.1.12:3285
NetFlow version 9 packet
2024/09/27 17:49:27 received 400 bytes from 10.30.1.12:3285
NetFlow version 9 packet
2024/09/27 17:49:37 received 60 bytes from 10.30.1.12:3285
NetFlow version 9 packet
2024/09/27 17:49:43 received 1236 bytes from 10.30.1.12:3285
NetFlow version 9 packet
2024/09/27 17:49:48 received 400 bytes from 10.30.1.12:3285
NetFlow version 9 packet
  data set template 258, length: 76
    1 records:
      record 0:
        octetDeltaCount: 3534
        postOctetDeltaCount: 3534
        packetDeltaCount: 6
        postPacketDeltaCount: 6
        flowStartSysUpTime: 1857598410
        flowEndSysUpTime: 1857658690
        ingressInterface: 1416
        egressInterface: 514
        icmpTypeCodeIPv4: 0
        protocolIdentifier: 0
        ipClassOfService: 1
        postIpClassOfService: 17
        applicationId: [0 0 0 20 0 0 48 68 0]
        66: [0 0 0 0]
        65: [0 0]
        forwardingStatus: 0
        flowEndReason: 12
        sourceIPv6Address: 540:20a:1e01:a0a:1e01:900::
  data set template 258, length: 76
    1 records:
      record 0:
        octetDeltaCount: 222
        postOctetDeltaCount: 222
        packetDeltaCount: 3
        postPacketDeltaCount: 3
        flowStartSysUpTime: 1857477520
        flowEndSysUpTime: 1857477520
        ingressInterface: 161
        egressInterface: 61598
        icmpTypeCodeIPv4: 0
        protocolIdentifier: 0
        ipClassOfService: 1
        postIpClassOfService: 17
        applicationId: [0 0 0 20 0 0 48 68 0]
        66: [0 0 0 0]
        65: [0 0]
        forwardingStatus: 0
        flowEndReason: 14
        sourceIPv6Address: 4c3:a:1e01:ac0:a801:fa00::
  data set template 258, length: 76
    1 records:
      record 0:
        octetDeltaCount: 219
        postOctetDeltaCount: 219
        packetDeltaCount: 3
        postPacketDeltaCount: 3
        flowStartSysUpTime: 1857477520
        flowEndSysUpTime: 1857477520
        ingressInterface: 61598
        egressInterface: 161
        icmpTypeCodeIPv4: 1
        protocolIdentifier: 0
        ipClassOfService: 0
        postIpClassOfService: 17
        applicationId: [0 0 0 20 0 0 48 68 0]
        66: [0 0 0 0]
        65: [0 0]
        forwardingStatus: 0
        flowEndReason: 14
        sourceIPv6Address: 4c3:c0:a801:fa0a:1e01:a00::
  data set template 258, length: 76
    1 records:
      record 0:
        octetDeltaCount: 296
        postOctetDeltaCount: 296
        packetDeltaCount: 1
        postPacketDeltaCount: 1
        flowStartSysUpTime: 1857579750
        flowEndSysUpTime: 1857654850
        ingressInterface: 53
        egressInterface: 4004
        icmpTypeCodeIPv4: 1
        protocolIdentifier: 0
        ipClassOfService: 0
        postIpClassOfService: 17
        applicationId: [0 0 0 20 0 0 48 68 0]
        66: [0 0 0 0]
        65: [0 0]
        forwardingStatus: 0
        flowEndReason: 12
        sourceIPv6Address: 540:20a:1e01:fe0a:1e01:a00::
  data set template 258, length: 76
    1 records:
      record 0:
        octetDeltaCount: 63
        postOctetDeltaCount: 63
        packetDeltaCount: 1
        postPacketDeltaCount: 1
        flowStartSysUpTime: 1857579750
        flowEndSysUpTime: 1857654850
        ingressInterface: 4004
        egressInterface: 53
        icmpTypeCodeIPv4: 0
        protocolIdentifier: 0
        ipClassOfService: 1
        postIpClassOfService: 17
        applicationId: [0 0 0 20 0 0 48 68 0]
        66: [0 0 0 0]
        65: [0 0]
        forwardingStatus: 0
        flowEndReason: 12
        sourceIPv6Address: 540:20a:1e01:a0a:1e01:fe00::

余談

このパッケージもTWSNMP FC/FKで使用しています。

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?