收集 OpenTelemetry Netflow 接收器記錄

支援的國家/地區:

本文說明如何使用 Google Cloud Storage V2,將 OpenTelemetry Netflow Receiver 記錄檔擷取至 Google Security Operations。

OpenTelemetry Netflow 接收器是開放原始碼元件,可監聽 Netflow、sflow 和 IPFIX UDP 流量,並轉換為 OpenTelemetry 記錄。這項功能可監控及分析網路流量,包括識別通訊協定、分析流量、追蹤通訊埠使用情況,以及提供位元組/封包統計資料。

事前準備

請確認您符合下列必要條件:

  • Google SecOps 執行個體
  • 已啟用 Cloud Storage API 的 GCP 專案
  • 建立及管理 GCS bucket 的權限
  • 管理 Google Cloud Storage 值區 IAM 政策的權限
  • 建立 Cloud Run 服務、Pub/Sub 主題和 Cloud Scheduler 工作所需的權限
  • 可傳送 NetFlow、sFlow 或 IPFIX 資料的網路裝置
  • 有權設定網路裝置匯出設定

建立 Google Cloud Storage bucket

  1. 前往 Google Cloud 控制台。
  2. 選取專案或建立新專案。
  3. 在導覽選單中,依序前往「Cloud Storage」>「Bucket」。
  4. 按一下「建立值區」。
  5. 提供下列設定詳細資料:

    設定 值
    為 bucket 命名 輸入全域不重複的名稱 (例如 netflow-logs-bucket)
    位置類型 請根據需求選擇 (區域、雙區域、多區域)
    位置 選取位置 (例如 us-central1)
    儲存空間級別 標準 (建議用於經常存取的記錄)
    存取控管 統一 (建議)
    保護工具 選用:啟用物件版本管理或保留政策
  6. 點選「建立」。

為 Cloud Run 函式建立服務帳戶

Cloud Run 函式需要具備寫入 GCS bucket 權限,且可由 Pub/Sub 叫用的服務帳戶。

建立服務帳戶

  1. 在 GCP 控制台中,依序前往「IAM 與管理」>「服務帳戶」。
  2. 按一下「Create Service Account」(建立服務帳戶)。
  3. 請提供下列設定詳細資料:
    • 服務帳戶名稱:輸入 netflow-collector-sa
    • 服務帳戶說明:輸入 Service account for Cloud Run function to collect netflow logs
  4. 按一下「建立並繼續」。
  5. 在「將專案存取權授予這個服務帳戶」部分,新增下列角色:
    1. 按一下「請選擇角色」。
    2. 搜尋並選取「Storage 物件管理員」。
    3. 點選「+ 新增其他角色」。
    4. 搜尋並選取「Cloud Run 叫用者」。
    5. 點選「+ 新增其他角色」。
    6. 搜尋並選取「Cloud Functions Invoker」(Cloud Functions 叫用者)。
  6. 按一下「繼續」。
  7. 按一下「完成」。

這些角色適用於:

  • Storage 物件管理員:將記錄檔寫入 GCS bucket,並管理狀態檔案
  • Cloud Run 叫用者:允許 Pub/Sub 叫用函式
  • Cloud Functions 叫用者:允許叫用函式

授予 GCS bucket 的 IAM 權限

將 GCS bucket 的寫入權限授予服務帳戶:

  1. 依序前往「Cloud Storage」>「Buckets」。
  2. 點按 bucket 名稱 (例如 netflow-logs-bucket)。
  3. 前往「權限」分頁。
  4. 按一下「授予存取權」。
  5. 提供下列設定詳細資料:
    • 新增主體:輸入服務帳戶電子郵件地址 (例如 netflow-collector-sa@PROJECT_ID.iam.gserviceaccount.com)
    • 指派角色:選取「Storage 物件管理員」
  6. 按一下 [儲存]。

建立 Pub/Sub 主題

建立 Pub/Sub 主題,Cloud Scheduler 會發布至該主題,Cloud Run 函式則會訂閱該主題。

  1. 在 GCP 控制台中,依序前往「Pub/Sub」>「Topics」(主題)。
  2. 按一下「建立主題」。
  3. 請提供下列設定詳細資料:
    • 主題 ID:輸入 netflow-trigger
    • 其他設定保留預設值
  4. 點選「建立」。

建立 Cloud Run 函式來收集 Netflow 記錄

Cloud Run 函式會執行 OpenTelemetry 收集器,接收 NetFlow 資料並匯出至 GCS。

  1. 前往 GCP 控制台的「Cloud Run」。
  2. 按一下「Create service」(建立服務)。
  3. 選取「函式」 (使用內嵌編輯器建立函式)。
  4. 在「設定」部分,提供下列設定詳細資料:

    設定 值
    服務名稱 netflow-collector
    區域 選取與 GCS bucket 相符的區域 (例如 us-central1)
    執行階段 選取 Python 3.12 以上版本
  5. 在「觸發條件 (選用)」部分:

    1. 按一下「+ 新增觸發條件」。
    2. 選取「Cloud Pub/Sub」。
    3. 在「選取 Cloud Pub/Sub 主題」中,選擇 Pub/Sub 主題 netflow-trigger。
    4. 按一下 [儲存]。
  6. 在「Authentication」(驗證) 部分:

    1. 選取「需要驗證」。
    2. Identity and Access Management (IAM)。
  7. 向下捲動並展開「容器、網路、安全性」。

  8. 前往「安全性」分頁標籤:

    • 服務帳戶:選取服務帳戶 netflow-collector-sa
  9. 前往「容器」分頁:

    1. 按一下「變數與密鑰」。
    2. 針對每個環境變數,按一下「+ 新增變數」:
    變數名稱 範例值 說明
    GCS_BUCKET netflow-logs-bucket GCS bucket 名稱
    GCS_PREFIX netflow 記錄檔的前置字串
    NETFLOW_PORT 2055 Netflow 接收器的通訊埠
    NETFLOW_SCHEME netflow 架構類型:netflow、sflow 或 ipfix
    NETFLOW_SOCKETS 4 UDP 通訊端數量
    NETFLOW_WORKERS 8 解碼器工作站數量
  10. 在「變數與密鑰」部分,向下捲動至「要求」:

    • 要求逾時:輸入 600 秒 (10 分鐘)
  11. 前往「設定」分頁:

    • 在「資源」部分:
      • 記憶體:選取 1 GiB 以上
      • CPU:選取「2」
  12. 在「修訂版本資源調度」部分:

    • 執行個體數量下限:輸入 1
    • 執行個體數量上限:輸入 10
  13. 點選「建立」。

  14. 等待服務建立完成 (1 到 2 分鐘)。

  15. 服務建立後,內嵌程式碼編輯器會自動開啟。

新增函式程式碼

  1. 在「進入點」欄位中輸入 main。
  2. 在內嵌程式碼編輯器中,建立三個檔案:

    • main.py:
    import functions_framework
    from google.cloud import storage
    import json
    import os
    import subprocess
    import tempfile
    import signal
    import time
    from datetime import datetime, timezone
    
    # Initialize Storage client
    storage_client = storage.Client()
    
    # Environment variables
    GCS_BUCKET = os.environ.get('GCS_BUCKET')
    GCS_PREFIX = os.environ.get('GCS_PREFIX', 'netflow')
    NETFLOW_PORT = os.environ.get('NETFLOW_PORT', '2055')
    NETFLOW_SCHEME = os.environ.get('NETFLOW_SCHEME', 'netflow')
    NETFLOW_SOCKETS = os.environ.get('NETFLOW_SOCKETS', '4')
    NETFLOW_WORKERS = os.environ.get('NETFLOW_WORKERS', '8')
    
    # Global process handle
    collector_process = None
    
    def create_collector_config():
      """Create OpenTelemetry Collector configuration."""
      timestamp = datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')
      file_path = f"/tmp/netflow_{timestamp}.ndjson"
    
      config = {
        'receivers': {
          'netflow': {
            'scheme': NETFLOW_SCHEME,
            'hostname': '0.0.0.0',
            'port': int(NETFLOW_PORT),
            'sockets': int(NETFLOW_SOCKETS),
            'workers': int(NETFLOW_WORKERS),
            'queue_size': 5000
          }
        },
        'processors': {
          'batch': {
            'timeout': '10s',
            'send_batch_size': 1000
          }
        },
        'exporters': {
          'file': {
            'path': file_path,
            'format': 'json'
          }
        },
        'service': {
          'pipelines': {
            'logs': {
              'receivers': ['netflow'],
              'processors': ['batch'],
              'exporters': ['file']
            }
          },
          'telemetry': {
            'logs': {
              'level': 'info'
            }
          }
        }
      }
    
      config_path = '/tmp/otel-config.yaml'
      with open(config_path, 'w') as f:
        import yaml
        yaml.dump(config, f)
    
      return config_path, file_path
    
    def upload_to_gcs(file_path):
      """Upload netflow logs to GCS."""
      if not os.path.exists(file_path) or os.path.getsize(file_path) == 0:
        print(f"No data to upload from {file_path}")
        return
    
      bucket = storage_client.bucket(GCS_BUCKET)
      timestamp = datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')
      object_key = f"{GCS_PREFIX}/netflow_{timestamp}.ndjson"
      blob = bucket.blob(object_key)
    
      blob.upload_from_filename(file_path, content_type='application/x-ndjson')
      print(f"Uploaded {os.path.getsize(file_path)} bytes to gs://{GCS_BUCKET}/{object_key}")
    
    def signal_handler(signum, frame):
      """Handle shutdown signals."""
      global collector_process
      if collector_process:
        print("Shutting down collector...")
        collector_process.terminate()
        collector_process.wait(timeout=10)
    
    @functions_framework.cloud_event
    def main(cloud_event):
      """
      Cloud Run function to run OpenTelemetry Collector for netflow collection.
    
      Args:
        cloud_event: CloudEvent object containing Pub/Sub message
      """
      global collector_process
    
      if not GCS_BUCKET:
        print('Error: GCS_BUCKET environment variable not set')
        return
    
      try:
        # Set up signal handlers
        signal.signal(signal.SIGTERM, signal_handler)
        signal.signal(signal.SIGINT, signal_handler)
    
        # Create collector configuration
        config_path, file_path = create_collector_config()
        print(f"Created collector config at {config_path}")
        print(f"Netflow receiver listening on {NETFLOW_SCHEME}://0.0.0.0:{NETFLOW_PORT}")
    
        # Start OpenTelemetry Collector
        collector_process = subprocess.Popen(
          ['/otelcol-contrib', '--config', config_path],
          stdout=subprocess.PIPE,
          stderr=subprocess.PIPE,
          text=True
        )
    
        print(f"Started OpenTelemetry Collector (PID: {collector_process.pid})")
    
        # Run for collection period (e.g., 5 minutes)
        collection_time = 300
        print(f"Collecting netflow data for {collection_time} seconds...")
    
        start_time = time.time()
        while time.time() - start_time < collection_time:
          if collector_process.poll() is not None:
            stdout, stderr = collector_process.communicate()
            print(f"Collector exited unexpectedly")
            print(f"STDOUT: {stdout}")
            print(f"STDERR: {stderr}")
            break
          time.sleep(10)
    
        # Stop collector
        if collector_process.poll() is None:
          print("Stopping collector...")
          collector_process.terminate()
          collector_process.wait(timeout=10)
    
        # Upload collected data
        upload_to_gcs(file_path)
    
        # Cleanup
        if os.path.exists(file_path):
          os.remove(file_path)
        if os.path.exists(config_path):
          os.remove(config_path)
    
        print("Netflow collection completed successfully")
    
      except Exception as e:
        print(f'Error during netflow collection: {str(e)}')
        if collector_process and collector_process.poll() is None:
          collector_process.terminate()
        raise
    
    • requirements.txt:
    functions-framework==3.*
    google-cloud-storage==2.*
    PyYAML==6.*
    
    • Dockerfile:
    FROM python:3.12-slim
    
    # Install OpenTelemetry Collector Contrib
    RUN apt-get update && apt-get install -y wget && \
      wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.144.0/otelcol-contrib_0.144.0_linux_amd64.deb && \
      dpkg -i otelcol-contrib_0.144.0_linux_amd64.deb && \
      rm otelcol-contrib_0.144.0_linux_amd64.deb && \
      apt-get clean
    
    # Set working directory
    WORKDIR /app
    
    # Copy requirements and install
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt
    
    # Copy function code
    COPY main.py .
    
    # Expose netflow port
    EXPOSE 2055/udp
    
    # Run function
    CMD ["functions-framework", "--target=main", "--port=8080"]
    
  3. 按一下「部署」,即可儲存並部署函式。

  4. 等待部署作業完成 (3 到 5 分鐘)。

設定網路裝置,傳送 NetFlow 資料

設定網路裝置 (路由器、交換器、防火牆),將 NetFlow、sFlow 或 IPFIX 資料匯出至 Cloud Run 函式。

取得 Cloud Run 函式的外部 IP

  1. 在 GCP 控制台中,依序前往「Cloud Run」>「服務」。
  2. 按一下函式名稱 netflow-collector。
  3. 複製頂端顯示的 網址 (例如 https://netflow-collector-xxxxx-uc.a.run.app)。
  4. 從網址中擷取主機名稱。
  5. 使用 nslookup 或 dig 解析 IP 位址:

    nslookup netflow-collector-xxxxx-uc.a.run.app
    
  • 範例:Cisco 路由器 NetFlow 設定

      ! Configure netflow exporter
      flow exporter OTEL-EXPORTER
      destination <CLOUD_RUN_IP>
      transport udp 2055
      source <INTERFACE>
      export-protocol netflow-v9
    
      ! Configure flow monitor
      flow monitor OTEL-MONITOR
      exporter OTEL-EXPORTER
      record netflow ipv4 original-input
    
      ! Apply to interface
      interface GigabitEthernet0/0
      ip flow monitor OTEL-MONITOR input
      ip flow monitor OTEL-MONITOR output
    
  • 範例:一般 NetFlow 設定

    對於大多數網路裝置,請設定下列項目:

    • Netflow 版本:NetFlow v5、v9 或 IPFIX
    • 收集器 IP:Cloud Run 函式 IP 位址
    • 收集器通訊埠:2055 (或已設定的通訊埠)
    • 通訊協定:UDP
    • 有效逾時:60 秒 (建議)
    • 閒置逾時:15 秒 (建議)

建立 Cloud Scheduler 工作

Cloud Scheduler 會定期將訊息發布至 Pub/Sub 主題,觸發 Cloud Run 函式。

  1. 前往 GCP 控制台中的「Cloud Scheduler」。
  2. 點選「建立工作」。
  3. 提供下列設定詳細資料:

    設定 值
    名稱 netflow-collector-hourly
    區域 選取與 Cloud Run 函式相同的區域
    頻率 0 * * * * (每小時整點)
    時區 選取時區 (建議使用世界標準時間)
    目標類型 Pub/Sub
    主題 選取 Pub/Sub 主題 netflow-trigger
    郵件內文 {} (空白 JSON 物件)
  4. 點選「建立」。

排程頻率選項

根據記錄檔量和延遲時間需求選擇頻率:

頻率 Cron 運算式 用途
每 5 分鐘 */5 * * * * 高容量、低延遲
每 15 分鐘 */15 * * * * 中等音量
每小時 0 * * * * 標準 (建議)
每 6 小時 0 */6 * * * 低量、批次處理

測試整合項目

  1. 在 Cloud Scheduler 控制台中,找到工作 netflow-collector-hourly。
  2. 按一下「強制執行」,手動觸發工作。
  3. 稍等幾秒鐘。
  4. 前往「Cloud Run」>「服務」。
  5. 按一下函式名稱 netflow-collector。
  6. 點選「記錄」分頁標籤。
  7. 確認函式是否執行成功。尋找:

    Started OpenTelemetry Collector (PID: ...)
    Netflow receiver listening on netflow://0.0.0.0:2055
    Collecting netflow data for 300 seconds...
    Uploaded ... bytes to gs://netflow-logs-bucket/netflow/netflow_YYYYMMDD_HHMMSS.ndjson
    Netflow collection completed successfully
    
  8. 依序前往「Cloud Storage」>「Buckets」。

  9. 按一下 bucket 名稱 netflow-logs-bucket。

  10. 前往前置字元資料夾 netflow/。

  11. 確認系統已建立新的 .ndjson 檔案,並加上目前的時間戳記。

如果記錄中顯示錯誤:

  • 收集器意外結束:檢查 NetFlow 接收器設定
  • 沒有可上傳的資料:確認網路裝置是否將 NetFlow 資料傳送至正確的 IP 和通訊埠
  • 權限遭拒:確認服務帳戶是否具備「儲存空間物件管理員」角色
  • 通訊埠繫結錯誤:確認通訊埠 2055 未在使用中

擷取 Google SecOps 服務帳戶

Google SecOps 會使用專屬服務帳戶,從 GCS bucket 讀取資料。您必須授予這個服務帳戶值區存取權。

取得服務帳戶電子郵件地址

  1. 依序前往「SIEM 設定」>「動態饋給」。
  2. 按一下「新增動態饋給」。
  3. 按一下「設定單一動態饋給」。
  4. 在「動態饋給名稱」欄位中輸入動態饋給名稱 (例如 OpenTelemetry Netflow Logs)。
  5. 選取「Google Cloud Storage V2」做為「來源類型」。
  6. 選取「NETFLOW_OTEL」做為「記錄類型」。
  7. 按一下「取得服務帳戶」。系統會顯示專屬的服務帳戶電子郵件地址。例如:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  8. 複製這個電子郵件地址,以便在下一步中使用。

  9. 點選「下一步」。

  10. 指定下列輸入參數的值:

    • Storage bucket URL:輸入 GCS bucket URI,並加上前置字元路徑:

      gs://netflow-logs-bucket/netflow/
      
    • 來源刪除選項:根據偏好設定選取刪除選項:

      • 永不:一律不會在轉移後刪除任何檔案 (建議用於測試)。
      • 刪除已轉移的檔案:成功轉移檔案後刪除檔案。
      • 刪除已轉移的檔案和空白目錄:成功轉移檔案後,刪除檔案和空白目錄。

    • 檔案存在時間上限:納入在過去天數內修改的檔案 (預設為 180 天)

    • 資產命名空間:資產命名空間

    • 擷取標籤:要套用至這個動態饋給事件的標籤

  11. 點選「下一步」。

  12. 在「Finalize」(完成) 畫面中檢查新的動態饋給設定,然後按一下「Submit」(提交)。

將 IAM 權限授予 Google SecOps 服務帳戶

Google SecOps 服務帳戶必須具備 GCS bucket 的 Storage 物件檢視者角色。

  1. 依序前往「Cloud Storage」 > 「Bucket」。
  2. 按一下 bucket 名稱 netflow-logs-bucket。
  3. 前往「權限」分頁標籤。
  4. 按一下「授予存取權」。
  5. 提供下列設定詳細資料:
    • 新增主體:貼上 Google SecOps 服務帳戶電子郵件地址
    • 指派角色:選取「Storage 物件檢視者」
  6. 按一下 [儲存]。

UDM 對應表

下表顯示 OpenTelemetry Netflow Receiver 記錄檔欄位如何對應至 Google SecOps UDM 欄位:

OpenTelemetry 欄位 UDM 欄位 說明
source.address principal.ip 來源 IP 位址
source.port principal.port 來源通訊埠編號
destination.address target.ip 目的地 IP 位址
destination.port target.port 目的地通訊埠編號
network.transport network.ip_protocol 傳輸通訊協定 (tcp、udp)
network.type network.ip_version IP 版本 (ipv4、ipv6)
flow.io.bytes network.sent_bytes 傳輸的位元組總數
flow.io.packets network.sent_packets 傳輸的封包總數
flow.type metadata.product_log_id 流量類型 (NETFLOW_V5、NETFLOW_V9、SFLOW_5、IPFIX)
flow.start metadata.event_timestamp 流程開始時間
flow.end network.session_duration 流程結束時間
flow.sampler_address intermediary.ip Netflow 匯出工具 IP 位址
flow.tcp_flags network.tcp_flags TCP 標記
flow.io.bytes event.idm.read_only_udm.network.sent_bytes 從變更記錄對應
source.port event.idm.read_only_udm.principal.port 從變更記錄對應
destination.port event.idm.read_only_udm.target.port 從變更記錄對應
network.transport event.idm.read_only_udm.network.ip_protocol 從變更記錄對應
network.type event.idm.read_only_udm.security_result.detection_fields 從變更記錄對應
flow.sequence_num event.idm.read_only_udm.network.session_id 從變更記錄對應
flow.sampler_address event.idm.read_only_udm.observer.ip 從變更記錄對應
flow.type event.idm.read_only_udm.metadata.product_event_type 從變更記錄對應

變更記錄

查看這個剖析器的變更記錄

還有其他問題嗎?向社群成員和 Google SecOps 專業人員尋求解答。