概要

7日間のインターンシップで,内容としてはeBPFを使ったOSSの強化を行うものでした.

ペパボではバイトをしていた経験もあり,楽しい会社だとわかっていたのと,eBPF及びGoのキャッチアップをしたかったので応募しました.

agenda

目的

eBPFとGoの理解を深めたかったのが大きな目標です.

実は私は最近の流行(?)である,ライブラリに対するサプライチェーンアタックの対策について考える事があります.

eBPFでビルド時の通信をフィルタリングするなどして対策が出来ないものかと前々から構想していて,その為にもeBPFを理解しようと応募してみたところ,まさにその用途で使えるbouhekiの改修が業務内容でした.うれしい.

bouhekiについて

github.com/mrtc0/bouheki

現在,bouhekiではeBPFを使ってconnect(2)の接続先をFilteringしています.

設定は以下のようなフォーマットのyamlで行います.

network:
  # Block or monitor the network.
  # If block is specified, communication that matches the policy will be blocked.
  mode: block # monitor or block. Default: monitor
  # Restriction to the whole host or to a container
  target: host # host or container. Default: host
  cidr:
    allow:
      - 0.0.0.0/0
      # - 10.0.1.1/24
      # - 127.0.0.1/24
    # Override "allow" list with exceptions. Default: []
    deny: # []
      - 10.0.1.71/32
  # Restrictions by command name (optional).
  command:
    # Default: empty. All command will be allowed.
    allow: []
    # - curl
    # Default: empty. All command will be allowed.
    deny: []
    #  - wget
    #  - nc
  # Restrictions by UID (optional).
  uid:
    allow:
      - 0 # Default []
    deny:
      - 1000 # Default []
  # Restrictions by GID (optional).
  gid:
    allow: []
      # - 0
    deny: []
      # 1000
log:
  # Log format(json or text). Default: json
  format: json
  # Specified log file location. Default: stdout
  # output: /var/log/bouheki.log.json
  # Maximum size to rotate (MB)
  # max_size: 100
  # Period for which logs are kept
  # max_age: 365

bouhekiは,ユーザ空間で動くプログラム(Go)と,カーネル空間で動くプログラム(eBPF)に分類され,それぞれ

ユーザ空間

カーネル空間

やったこと

IPv6対応DNS Lookupなどの機能追加を行いました.

を触るのはほぼ初めてだった上,Goのコードもかなり久しぶりだった為,結構手こずった点はありますが,サポーターのmrtc0さん,udzuraさんに助けてもらいながら実装しました.

IPv6対応

これはユーザ/カーネル空間共に改修が必要でした.

ユーザ空間

  1. configにIPv6のアドレスが書けるようにする
  2. eBPF mapにIPv6のkeyを挿入できるようにする

カーネル空間

  1. IPv6用のmapのkeyを定義する
  2. mapのIPv6アドレスと照合させる
  3. Ring Bufferに流すデータのフォーマットを修正する

ドメインによる指定

こちらはユーザ空間のプログラムの改修だけで対応できます.

必要なのは

  1. configに書かれたドメインからIPアドレスを取得する
  2. 取得したアドレスをmapに挿入する
  3. 古いアドレスをmapから削除する
  4. 上記の処理を定期的に行う

ドメインに紐付いたIPアドレスが変わることもあるため,定期的な更新も実装する必要がありました.

反省点

TDDっぽい実装ができなかった

まず第一に,ユーザ空間で動くGoの部分に関してはもう少し細かい粒度でテストを書くべきだったと思っています.

第二に,言い訳にはなりますがeBPFプログラムのテストが難しかったという点があります.

以下,言い訳を連ねます.

感想

実装については,そもそもコードが読みやすかった事,本質的な部分に集中できるようなサポートをして頂けた事もあり,思っていたよりも戦えた感覚があります.

それ以外の点では,アルバイトをしていた頃には話したことが無かったメンバーとランチや面談で趣味の話が出来て非常に楽しかったです.