<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Technology</title>
<link>https://www.klab.com/jp/blog/tech/</link>
<description></description>
<item>
<title>『ゼロからのTCP/IPプロトコルスタック自作入門』を出版しました</title>
<link>https://www.klab.com/jp/blog/tech/2025/tcpip.html</link>
<description>この記事は KLab Engineer Advent Calendar 2025、23日目の記事です。
ご無沙汰しております、いつのまにか自分がオーナーのOSSの脆弱性を調査した結果がトップカンファレンスで公開されるという貴重な体験をしました、@pandax381 です。
この度、長年ライフワークとして取り組んでいる「プロトコルスタック自作」の集大成として、『ゼロからのTCP/IPプロトコルスタック自作入門』を執筆し、11月21日にマイナビ出版さまから発売されました。
2022年5月にマイナビ出版の編集さんからメールを頂いたのがきっかけで、KLab Expert Campの公開資料をベースに書籍化の話がスタートしました。なお、今回お世話になった編集さんは &quot;みかん本&quot; でお馴染みの『ゼロからのOS自作入門』も担当されており、MikanOSに自作プロトコルスタックを移植してTCP/IPを喋らせるようにした件で「面白いことしてる人」として認知いただいたそうです。20年ほど昔になりますが過去に単著の執筆の経験があったことに加えて、今回はベースとなる資料があってプログラムのコードもある程度固まっていたことから「1年で書き上げる」というスケジュールで動きはじめたのですが、見込みが甘すぎて最終的に3年も掛かってしまいました。。執筆の遅れによって何度もリスケが発生し、編集さんをはじめ制作陣のみなさまに大変なご迷惑をお掛けしてしまったことを改めてお詫びいたします。
当初の想定からページ数が膨らんでいたこともあり、途中で「上下巻に分けて出版することもできますよ」という提案もいただいたのですが、「この熱い思いを伝えるには厚い重い本でなければ」という僕のわがままで、608ページ／約900グラムのチョット厚くて重い本として出版させていただきました。
目次
Step 0　はじめに
Step 1　ネットワークデバイスの管理
Step 2　デバイスドライバ
Step 3　プロトコルの管理
Step 4　IP：パケットの入力と検証
Step 5　論理インタフェースの管理
Step 6　IP：パケットの送信
Step 7　IP：上位プロトコルの管理
Step 8　ICMP：メッセージの入力と検証
Step 9　ICMP：メッセージの送信
Step 10　Ethernet：フレームの入力
Step 11　Ethernet：デバイスドライバの実装
Step 12　ARP：メッセージの入力と応答
Step 13　ARP：キャッシュの実装
Step 14　ARP：要求メッセージの送信
Step 15　受信パケットの遅延処理
Step 16　IP：ルーティング機能の追加
Step 17　UDP：データグラムの入力と検証
Step 18　UDP：制御ブロックとユーザコマンド
Step 19　UDP：データの送受信
Step 20　TCP：セグメントの入力
Step 21　TCP：制御ブロック
Step 22　TCP：コネクション確立（その1）
Step 23　TCP：データ転送
Step 24　TCP：セグメントの再送
Step 25　TCP：コネクション確立（その2）
Step 26　TCP：コネクション切断（その1）
Step 27　TCP：コネクション切断（その2）
Step 28　TCP：落ち穂拾い
Step 29　TCP：ソケット互換のユーザコマンド
Step 30　ソケットAPI
Appendix 1　割り込み処理
Appendix 2　タイマー処理
Appendix 3　タスク管理
これまで、KLab Expert Campやセキュリティ・キャンプ ネクストを通じて、延べ100名以上の学生に向けてプロトコルスタック自作の講義を行ってきました。その経験をもとに、読者の皆さんが「作る」ことを通じてTCP/IPの奥深い世界を肌で体感し、本質的な理解を得られるよう構成したつもりです。1日1ステップ進めれば1ヶ月でプロトコルスタックを自作できるので是非チャレンジしてみてください！
表紙のデザインについて
執筆を終えて制作が始まった段階で表紙のデザインについての意向確認があるのですが、世界一美しいコンピュータをオマージュした配色にして欲しいとお願いしました。妙なオーダーにも関わらずデザイナーさんが素晴らしい表紙を作成してくれ、個人的に満点の仕上がりです。
技術書典での先行販売
本書の発売日は11月21日だったのですが、都内の大型書店では1週間ほど早く先行販売が行われ、11月15日に池袋で開催された「技術書典19」においても同様に先行販売が実施されました。技術書典は技術同人誌の即売会なのですが、前回から商業出版された書籍を扱う特設ブース「技術書店」が設置され、そちらに本書も並べていただけることになりました。こちらが「技術書店」ブースの様子なのですが、本書だけ明らかに多く積まれており、売り子さんからも「マイナビ出版さん、気合入ってるみたいですよ！」というお言葉をいただきました。スペースに限りがあるなかで20冊ほど並べていただいたのは大変光栄なのですが、正直なところ「これだけ並べてもらってさっぱり売れなかったらどうしよう...」という不安な気持ちでいっぱいでした。
お目当てのブースを回りながらも、こちらのブースの様子が気になって仕方なく何度も立ち寄る不審者になっていたのですが、売り子さんが気を利かせて「あちらに著者さんいるのでサインもらえますよ！」と声がけをしてくれたことにより突発的にサイン会（？）のような事象が発生しました。こんなこともあろうかと夜中にこっそりサインを考えておいて本当に良かったです。そんなこんなで、当初の不安をよそに閉場を前にして完売を見届けることができました。最後の一冊をお迎えいただいた際に、技術書店ブース内の皆さんから拍手をいただくという大変エモい体験もさせていただきました。本当にありがとうございました。
カテゴリランキングの強敵
Amazonではカテゴリ毎に売れ筋ランキングを集計しており、そのカテゴリで1位になると「ベストセラー」のタグが付与されます。欲しいです、ベストセラーの称号。Xにて出版を告知したタイミングでたくさんの反応をいただいたことから、好調なスタートを切ることができ発売直後から「UNIXオペレーティングシステム」のカテゴリで上位にランクインしていました。ベストセラーの称号まであと一歩というところなのですが、実はこの「UNIXオペレーティングシステム」のカテゴリにはとんでもない強敵が潜んでいるのでした。
書籍の「UNIXオペレーティングシステム」カテゴリのトップに君臨している軟式野球ボール。人気商品のようでなかなか追い抜くことができません。どうやらこのカテゴリの宿命のようで、同じようにこの軟式野球ボールによってベストセラーを阻まれた著者が他にもいらっしゃるようでした。
なお、皮肉にもこれを嘆いたポストが拡散されたことにより本書の売上が伸び、1位の座を奪ってベストセラーの称号を獲得することができたのでした（翌日には首位を奪還されてしまったため儚い夢でした）。
重版出来！
なんと、大変ありがたいことに先行販売から2週間経過した時点で重版決定の連絡を頂きました。20年前に書いた1冊目の本は重版をまたずに絶版になってしまったのですが、今回はこんなにも早く重版が決まったことに驚きました。大喜びで再度校正を行い、初版で見逃してしまっていた誤字脱字など修正してあります。
おわりに
本書をお迎えいただいた皆様、ありがとうございます。また、この記事をきっかけに少しでも興味を持っていただけた方には、ぜひ書店でお手にとってみていただけると嬉しいです。
OS自作やプログラミング言語自作のように、「プロトコルスタック自作」が新たな技術の楽しみとして盛り上がっていくことを心から期待しています。本書が、読者のみなさんのチャレンジ精神や好奇心を満たす一助となれば幸いです。</description>
<pubDate>Tue, 23 Dec 2025 13:00:00 +0900</pubDate>
<category>書籍紹介</category>
</item>
<item>
<title>技術書典19で同人誌を頒布します &amp; 既刊PDFダウンロードページ</title>
<link>https://www.klab.com/jp/blog/tech/2025/tbf19.html</link>
<description>こんにちは。 技術書典活動の代表のUMEです。
11/15(土) ~ 11/30(日) の期間、技術書の即売会 技術書典19 が開催されます。 期間中はオンラインにて書籍を購入することができ、 さらに 11/16(日) にはオフラインでも開催されます。 (入場券の発行など、詳しくは公式サイトをご覧ください)
KLabは例年新刊を発行しながら参加しており、今回も社内の有志のエンジニアが各自好きな内容で記事を執筆し、最新刊「KLabTechBook Vol.16」を発行します。 既刊のVol.3~15とあわせてオンラインマーケットで頒布します。
技術書典では他にも様々な方が執筆された技術書が多数発行されていますので、ぜひ技術書典オンラインマーケットにお越しください。
頒布内容
新刊/既刊を問わず、物理本+電子版は500円、電子版のみは無料で頒布します。
最新刊
KLab Tech Book Vol. 16 - 技術書典マーケット
今回収録しているのは以下の3記事です。 内容は章ごとに独立しているので、気になる記事が一つでもあればぜひご一読ください。
1. Python の抽象基底クラスの紹介
Python ではダックタイピングに基づいて書かれたクラスにも isinstance による型チェックができることがあります。これを支えている仕組み、抽象基底クラスについて紹介します。
2. SQLによるDBマイグレーションの再設計
SQLでマイグレーションを書く合理性について、あらためて整理してみました。 その実践の中で生まれたツール「migy」も、想像以上に便利に働いてくれています。
3. TypeScript + GitHub Actions + Grafana Cloudで実現する現代的GAS開発環境
Google App Scriptの開発環境改善について書きました。特にGASのステージング環境を運用する話と、Grafana Lokiによるオブザーバビリティの話は他であまり見ない内容かと思います。
既刊
既刊の物理本は在庫の少ないものもあるため、開催期間中に売り切れとなる可能性があります。ご容赦ください。
KLab Tech Book Vol. 15 - 技術書典マーケット
KLab Tech Book Vol. 14 - 技術書典マーケット(電子版のみ)
KLab Tech Book Vol. 13 - 技術書典マーケット
KLab Tech Book Vol. 12 - 技術書典マーケット
KLab Tech Book Vol. 11 - 技術書典マーケット
KLab Tech Book Vol. 10 - 技術書典マーケット
KLab Tech Book Vol. 9 - 技術書典マーケット(電子版のみ)
KLab Tech Book Vol. 8 - 技術書典マーケット
KLab Tech Book Vol. 7 - 技術書典マーケット(電子版のみ)
KLab Tech Book Vol. 6 - 技術書典マーケット
KLab Tech Book Vol. 5 - 技術書典マーケット
KLab Tech Book Vol. 4 - 技術書典マーケット
KLab Tech Book Vol. 3 - 技術書典マーケット
既刊PDFダウンロード
既刊の電子版PDFです（物理本とは一部異なる場合があります）。
KLab Tech Book Vol.1
KLab Tech Book Vol.2
KLab Tech Book Vol.3
KLab Tech Book Vol.4
KLab Tech Book Vol.5
KLab Tech Book Vol.6
KLab Tech Book Vol.7
KLab Tech Book Vol.8
KLab Tech Book Vol.9
KLab Tech Book Vol.10
KLab Tech Book Vol.11
KLab Tech Book Vol.12
KLab Tech Book Vol.13
KLab Tech Book Vol.14
KLab Tech Book Vol.15
</description>
<pubDate>Fri, 14 Nov 2025 19:00:00 +0900</pubDate>
<category>GAS</category>
<category>Python</category>
<category>SQL</category>
<category>イベント</category>
<category>技術書典</category>
</item>
<item>
<title>CEDEC 2025 「最少変更でPC/CS版リリース！モバイル専用タイトルだった『BLEACH Brave Souls』のマルチプラットフォーム事例」登壇報告</title>
<link>https://www.klab.com/jp/blog/tech/2025/cedec2025-bleach.html</link>
<description>技術広報グループのyamaguchi-daです。 2025年7月22日～7月24日に開催された、CEDEC 2025にKLabの常深 健太と鈴木 隼平が登壇しました。
本稿では、「最少変更でPC/CS版リリース！モバイル専用タイトルだった『BLEACH Brave Souls』のマルチプラットフォーム事例」のセッションの紹介と資料を公開します。
セッション紹介
セッションタイトル
「最少変更でPC/CS版リリース！モバイル専用タイトルだった『BLEACH Brave Souls』のマルチプラットフォーム事例」
講演時間
7月24日(木) 18:00 〜 19:00(第1会場)
講演内容
昨今では、モバイル端末の高スペック化に伴い、モバイルゲームがPC/CS版をリリースすることが増えています。 『BLEACH Brave Souls』ではモバイルを主体に最小での並行運用をコンセプトにプラットフォームの拡大を進め、2015年にiOS/Androidでサービス開始してから10年間でPC(Steam)/PS4/Xbox/Switchにサービスを拡大しました。
PC/コンソール版をリリースすることで高価なモバイル端末を購入できない人やPC/コンソール主体でプレイしている人など、普段アプローチできないユーザー層にアプローチできるなど多くのメリットがあります。 しかしPC/コンソールはルールも文化も違うため、何から始めたらいいか、どんな作業をしたらいいかわからないという人も多いと思います。
本セッションでは、『BLEACH Brave Souls』でこれらのプラットフォームをサポートするにあたって何をしたか、どんな問題が起こったかをインゲーム・アウトゲームの実例を交えて紹介・解説します。
資料
スライドへのリンク（Google Slides）
CEDEC 2025セッションページ CEDiL
</description>
<pubDate>Fri, 08 Aug 2025 16:58:44 +0900</pubDate>
<category>CEDEC</category>
<category>Unity</category>
<category>イベント</category>
</item>
<item>
<title>CEDEC 2025 「全世界ユーザーのDL体験向上を目指して！マルチCDNの仕組みと統一的な評価手法」登壇報告</title>
<link>https://www.klab.com/jp/blog/tech/2025/cedec-2025-dlcdn.html</link>
<description>技術広報グループのyamaguchi-daです。 2025年7月22日～7月24日に開催された、CEDEC 2025にKLabの山口 大祐と赤岡 武が登壇しました。
本稿では、「全世界ユーザーのDL体験向上を目指して！マルチCDNの仕組みと統一的な評価手法」のセッションの紹介と資料を公開します。
セッション紹介
セッションタイトル
「全世界ユーザーのDL体験向上を目指して！マルチCDNの仕組みと統一的な評価手法」
講演時間
7月23日(水) 10:50 〜 11:50(第8会場)
講演内容
モバイルオンラインゲームにおいて、アセットダウンロードはユーザー体験の重要なKPIであるチュートリアル突破率に大きな影響を与えます。 その配信インフラであるCDNは、欠かせない要素です。
しかし、CDNプロバイダーごとに公開されているパフォーマンス情報には各社違いがあるため、比較は困難です。
本講演では、実際にゲームで使用している環境にて各プロバイダーを比較評価するために、「同条件で複数CDNプロバイダを利用する仕組み」および「統一的に測定可視化する仕組み」について解説します。 また、この活動から得られた知見についてもご紹介します。
資料
スライドへのリンク（Google Slides）
CEDEC 2025セッションページ
CEDiL</description>
<pubDate>Fri, 08 Aug 2025 16:57:47 +0900</pubDate>
<category>Android</category>
<category>CEDEC</category>
<category>iOS</category>
<category>イベント</category>
<category>インフラ</category>
<category>ネットワーク</category>
</item>
<item>
<title>技術書典18で同人誌を頒布します &amp; 既刊PDFダウンロードページ</title>
<link>https://www.klab.com/jp/blog/tech/2025/tbf18.html</link>
<description>こんにちは。 技術書典活動の代表のUMEです。
5/31(土) ~ 6/15(日) の期間、技術書の即売会 技術書典18 が開催されます。 期間中はオンラインにて書籍を購入することができ、 さらに 6/1(日) にはオフラインでも開催されます。 (入場券の発行など、詳しくは公式サイトをご覧ください)
KLabは例年新刊を発行しながら参加しており、今回も社内の有志のエンジニアが各自好きな内容で記事を執筆し、最新刊「KLabTechBook Vol.15」を発行します。 既刊のVol.3~14とあわせてオンラインマーケットで頒布します。
技術書典では他にも様々な方が執筆された技術書が多数発行されていますので、ぜひ技術書典オンラインマーケットにお越しください。
頒布内容
新刊/既刊を問わず、物理本+電子版は500円、電子版のみは無料で頒布します。
最新刊
KLab Tech Book Vol. 15 - 技術書典マーケット
今回収録しているのは以下の4記事です。 内容は章ごとに独立しているので、気になる記事が一つでもあればぜひご一読ください。
1. 生成AIの力を借りて世界の祝日カレンダーを作った話
世界の祝日カレンダーの制作を題材に、生成AIの活用と限界についての体験談を紹介します。
2. Cython 再訪
PythonコードをPython拡張ライブラリを表すCコードに変換してしまう古のツール、Cythonの今について紹介します。
3. GopherJSからWebAssemblyへ: Go-TypeScript連携の再構築
GoとTypeScriptの連携方法をGopherJSからWasmに刷新しました。 このとき直面したCommonJSとESModulesの違いとそれに伴う困難を紹介します。
4. git log から branch history を構築できるかについての考察
Gitの典型的な履歴情報からブランチ操作履歴が得られたら嬉しいなと思いました。考察の結果不可能と気づき、悪あがきを試みるも失敗した、そんな考察の結果をお伝えします。
既刊
既刊の物理本は在庫の少ないものもあるため、開催期間中に売り切れとなる可能性があります。ご容赦ください。
KLab Tech Book Vol. 14 - 技術書典マーケット
KLab Tech Book Vol. 13 - 技術書典マーケット
KLab Tech Book Vol. 12 - 技術書典マーケット
KLab Tech Book Vol. 11 - 技術書典マーケット
KLab Tech Book Vol. 10 - 技術書典マーケット
KLab Tech Book Vol. 9 - 技術書典マーケット(電子版のみ)
KLab Tech Book Vol. 8 - 技術書典マーケット
KLab Tech Book Vol. 7 - 技術書典マーケット(電子版のみ)
KLab Tech Book Vol. 6 - 技術書典マーケット
KLab Tech Book Vol. 5 - 技術書典マーケット
KLab Tech Book Vol. 4 - 技術書典マーケット
KLab Tech Book Vol. 3 - 技術書典マーケット
既刊PDFダウンロード
既刊の電子版PDFです（物理本とは一部異なる場合があります）。
KLab Tech Book Vol.1
KLab Tech Book Vol.2
KLab Tech Book Vol.3
KLab Tech Book Vol.4
KLab Tech Book Vol.5
KLab Tech Book Vol.6
KLab Tech Book Vol.7
KLab Tech Book Vol.8
KLab Tech Book Vol.9
KLab Tech Book Vol.10
KLab Tech Book Vol.11
KLab Tech Book Vol.12
KLab Tech Book Vol.13
KLab Tech Book Vol.14
</description>
<pubDate>Fri, 30 May 2025 18:50:00 +0900</pubDate>
<category>AI</category>
<category>Python</category>
<category>TypeScript</category>
<category>イベント</category>
<category>技術書典</category>
</item>
<item>
<title>CEDEC＋KYUSHU 2024「モバイルオンラインゲーム開発を支える早く、安く、使いやすいサーバインフラ構築」登壇報告</title>
<link>https://www.klab.com/jp/blog/tech/2024/cedec-plus-kyushu.html</link>
<description>技術広報グループのyamada-masaです。 2024年11月23日に開催された、CEDEC＋KYUSHU 2024に、KLabのエンジニア山田 雅人と髙橋 慶充が登壇しました
本稿では、「モバイルオンラインゲーム開発を支える早く、安く、使いやすいサーバインフラ構築」のセッションの紹介と資料を公開します。
セッション紹介
セッションタイトル
「モバイルオンラインゲーム開発を支える早く、安く、使いやすいサーバインフラ構築」
講演時間
11月23日（土）17:00 〜 18:00
講演内容
本セッションでは、現在開発中のモバイルオンラインゲームにおける最新の開発用サーバインフラとその成果について紹介します。
KLabのサーバアプリケーションはクライアントと密接に関連しており、開発期でも重要な要素です。
ゲーム開発のペースが年々速まり、開発用サーバインフラにはデプロイとサーバアプリケーション動作の高速性、コスト効率、利便性が求められています。
これらを実現するために開発用サーバインフラは開発に特化しており、Docker Composeによる共用サーバ形式となっています。
本セッションでは、このサーバインフラがどのようにニーズを実現しているかをエピソードを交えながら詳しくお話しします。
資料
スライドへのリンク（Google Slide）
スライドへのリンク（SlideShare）
CEDECセッション情報ページ</description>
<pubDate>Thu, 12 Dec 2024 19:49:24 +0900</pubDate>
<category>AWS</category>
<category>イベント</category>
<category>クラウド</category>
</item>
<item>
<title>技術書典17で同人誌を頒布します &amp; 既刊PDFダウンロードページ</title>
<link>https://www.klab.com/jp/blog/tech/2024/tbf17.html</link>
<description>こんにちは。 技術書典活動の代表のUMEです。
11/2(土) ~ 11/17(日) の期間、技術書の即売会 技術書典17 が開催されます。 期間中はオンラインにて書籍を購入することができ、 さらに 11/3(日) にはオフラインでも開催されます。 (入場券の発行など、詳しくは公式サイトをご覧ください)
KLabは例年新刊を発行しながら参加しており、今回も社内の有志のエンジニアが各自好きな内容で記事を執筆し、最新刊「KLabTechBook Vol.14」を発行します。 既刊のVol.3~13とあわせてオンラインマーケットで頒布します。
技術書典では他にも様々な方が執筆された技術書が多数発行されていますので、ぜひ技術書典オンラインマーケットにお越しください。
頒布内容
新刊/既刊を問わず、物理本+電子版は500円、電子版のみは無料で頒布します。
最新刊
KLab Tech Book Vol. 14 - 技術書典マーケット
今回収録しているのは以下の6記事です。 内容は章ごとに独立しているので、気になる記事が一つでもあればぜひご一読ください。
1. GitHub ActionsでカジュアルにOpenAIを利用する
Github Actionsから簡単に Open AI API を利用できる物を作りました。 自然言語に対して行いたいことを自然言語でコーディングするようで、アイディア次第で何でもできそうです。
2. mypy 再訪
型ヒントの付け方をPython3.12時代に追いつくべく学び直しました。その知識をもとに、これから型ヒントをつけてmypyを使っていこうとしている方へ向けて過去のしがらみ無しの入門記事を書きました。
3. 2D Shader 試験場
2Dエフェクトの方へ。【解像度：256x256px】60fpsで旗が揺らめくアニメーションのデータサイズは240KBでした。
4. shader graph で水表現
shader graph にて水の表現をどう行うか試行した内容について書きました。
5. XMLプログラミング言語「XSLT」の可能性
XSLTをご存知ですか？XMLを変換するためのテンプレート言語ですが、なんとチューリング完全だそうです。であればやることは決まっています！Brainfuckのインタプリタを実装してみました！
6. 好きなC++のコア機能発表ドラゴン
C++好きな発表ドラゴンが　好きな (C++の) コア機能を発表します
既刊
既刊の物理本は在庫の少ないものもあるため、開催期間中に売り切れとなる可能性があります。ご容赦ください。
KLab Tech Book Vol. 13 - 技術書典マーケット
KLab Tech Book Vol. 12 - 技術書典マーケット
KLab Tech Book Vol. 12 - 技術書典マーケット
KLab Tech Book Vol. 11 - 技術書典マーケット
KLab Tech Book Vol. 10 - 技術書典マーケット
KLab Tech Book Vol. 9 - 技術書典マーケット
KLab Tech Book Vol. 8 - 技術書典マーケット
KLab Tech Book Vol. 7 - 技術書典マーケット(電子版のみ)
KLab Tech Book Vol. 6 - 技術書典マーケット
KLab Tech Book Vol. 5 - 技術書典マーケット
KLab Tech Book Vol. 4 - 技術書典マーケット
KLab Tech Book Vol. 3 - 技術書典マーケット
既刊PDFダウンロード
既刊の電子版PDFです（物理本とは一部異なる場合があります）。
KLab Tech Book Vol.1
KLab Tech Book Vol.2
KLab Tech Book Vol.3
KLab Tech Book Vol.4
KLab Tech Book Vol.5
KLab Tech Book Vol.6
KLab Tech Book Vol.7
KLab Tech Book Vol.8
KLab Tech Book Vol.9
KLab Tech Book Vol.10
KLab Tech Book Vol.11
KLab Tech Book Vol.12
KLab Tech Book Vol.13
</description>
<pubDate>Fri, 01 Nov 2024 18:00:00 +0900</pubDate>
<category>AI</category>
<category>Python</category>
<category>Shader</category>
<category>イベント</category>
<category>技術書典</category>
</item>
<item>
<title>CEDEC 2024 「モバイルオンラインゲームのアプリ外課金の導入と運用方法について」登壇報告</title>
<link>https://www.klab.com/jp/blog/tech/2024/cedec-2024-outappbilling.html</link>
<description>技術広報グループのyamada-masaです。 2024年8月21日～8月23日に開催された、CEDEC 2024にKLabの西岡 修一郎が登壇しました。
本稿では、「モバイルオンラインゲームのアプリ外課金の導入と運用方法について」のセッションの紹介と資料を公開します。
セッション紹介
セッションタイトル
「モバイルオンラインゲームのアプリ外課金の導入と運用方法について」
講演時間
8月21日(水) 18:00 〜 19:00(第6会場)
講演内容
モバイルオンラインゲームにおいて、プラットフォームを介さずにユーザーに課金機能を提供する、いわゆるアプリ外課金の導入事例が増えてきております。 本セッションでは、アプリ外課金の日本・海外での導入実績を元に、まずはアプリ外課金の概要について紹介し、その実現方法についてお話します。また、リリースまでに注意すべき事項や運用に入ってから発生した問題などを事例も交えつつお話しさせて頂きます。
資料
スライドへのリンク（Google Slides）
スライドへのリンク（SlideShare）
CEDEC 2024セッションページ</description>
<pubDate>Mon, 30 Sep 2024 20:00:00 +0900</pubDate>
<category>イベント</category>
<category>課金</category>
</item>
<item>
<title>CEDEC 2024 「デバイスファーム 「AirLab」 による 自動QAテストの実績と機械学習が拓く次世代QAの可能性」登壇報告</title>
<link>https://www.klab.com/jp/blog/tech/2024/cedec-2024-airlab.html</link>
<description>技術広報グループのyamada-masaです。 2024年8月21日～8月23日に開催された、CEDEC 2024にKLabの許 信勇と加納 基晴が登壇しました。
本稿では、「デバイスファーム 「AirLab」 による 自動QAテストの実績と機械学習が拓く次世代QAの可能性」のセッションの紹介と資料を公開します。
セッション紹介
セッションタイトル
「デバイスファーム 「AirLab」 による 自動QAテストの実績と機械学習が拓く次世代QAの可能性」
講演時間
8月21日(水) 11:10 〜 12:10(第5会場)
講演内容
スマートフォンゲームアプリの開発規模が拡大している現在、多くの企業が多様な端末への品質管理を、限られた開発期間内で対処するという課題に直面しています。
この発表では、昨年に続き、自動テストの基盤となるAirLabの進化について語ります。全社のプロジェクトで、自動テストを実施しつつ定点観測もできる実例を紹介します。 さらに、AirtestとPocoSDKを用いて、仕様変更に対応しやすく、低コストでメンテナンスできる自動テストスクリプトの作法、自動テストによるQAテストの効率化、コストパフォーマンス等、品質管理の現場での実績を共有します。 また、自社で開発した機械学習による「テストスクリプトなしでスクリーンショットからUIを発見し、アプリを操作するテストツール『ゴリラテスト』」について、開発から実戦投入までのエピソードも共有します。
資料
スライドへのリンク（Google Slides）
スライドへのリンク（SlideShare）
CEDEC 2024セッションページ</description>
<pubDate>Mon, 30 Sep 2024 20:00:00 +0900</pubDate>
<category>Python</category>
<category>その他</category>
<category>イベント</category>
<category>機械学習</category>
</item>
<item>
<title>CEDEC 2024 「「EA SPORTS FC™ Tactical」におけるAWS Global Accelerator を活用したグローバル配信基盤の整備とユーザ体験向上に関する取り組み 」登壇報告</title>
<link>https://www.klab.com/jp/blog/tech/2024/cedec2024ga.html</link>
<description>エンジニアリング本部ゲームコアテクノロジーグループの牧内とインフラグループの松下が CEDEC2024 に登壇しました。
本稿では、セッションの紹介とアーカイブ動画、資料が公開されているURLについてお知らせします。
セッション紹介
セッションタイトル
「EA SPORTS FC™ Tactical」におけるAWS Global Accelerator を活用したグローバル配信基盤の整備とユーザ体験向上に関する取り組み 」
講演時間
8月23日(金) 17:10 〜 17:35(第12会場)
講演内容
新規グローバルタイトルである「EA SPORTS FC™ Tactical」において AWS Global Accelerator を導入したことで、オンライン対戦のレイテンシーを約40〜80ms改善し、顧客体験を向上しました。この発表では、単一リージョンにおけるグローバル配信基盤についてのTipsをお届けします。
登壇を終えての感想など
登壇者のお二人に、登壇後に感想を頂戴しましたのでここにて紹介したいと思います。
牧内
AWS Global Acceleratorを導入してみて想像以上に効果があり驚いていたところ、AWSさんから登壇のお誘いをいただきました。
このセッションでは、実際にどれくらいレイテンシが改善するのかをお伝えできたのではないかと思います。
また発表の準備にあたり、AWSさんと技術的な部分の議論もでき、とても勉強になりました。
このような機会をいただき、ありがとうございました。
松下
こういった場での発表経験はほぼなく、緊張しっぱなしの時間でしたが、とてもよい経験をさせていただきました。
AWSさんにはこのような機会をいただけたことをとても感謝しています。
今回使ってみてGlobal Acceleratorが手軽に導入できてレイテンシ改善の効果も高いということがわかったので、今後もどんどん活用していけたらなと思っています。
アーカイブ動画
資料
発表資料はCEDiLにてダウンロードが可能となっています。
https://cedil.cesa.or.jp/cedil_sessions/view/2937
</description>
<pubDate>Mon, 30 Sep 2024 20:00:00 +0900</pubDate>
<category>AWS</category>
<category>イベント</category>
<category>インフラ</category>
</item>
<item>
<title>LLMを活用してシンボリックGame AIを構築する研究の紹介 (2024年度人工知能学会全国大会)</title>
<link>https://www.klab.com/jp/blog/tech/2024/jsai2024-llm-ai.html</link>
<description><![CDATA[こんにちは、機械学習Gの加納です。
KLabでは、ゲームエンジニアと機械学習エンジニアが協力し、新しいゲームAIの研究を進めています。 その成果の一つとして、2024年度人工知能学会全国大会（第38回）にて、「LLMを活用したシンボリックGame AIの構築」という研究を発表しました。
この記事では、その研究内容を詳しくご紹介いたします。
研究の背景
エンターテイメントゲームでは、ユーザーが楽しめるようなゲーム体験を提供することが大きな目標となっています。そのため、ゲーム内のノンプレイヤーキャラクター（NPC）もゲームデザイナーの意図を反映したキャラクター性を持つことが求められます。本研究では、NPCがデザイナーの意図に従うことを「アライメント」と呼んでいます。
現在、ゲームAIの開発には「シンボリックAI」という手法が広く使われています。この手法では、ルールベースの処理を組み合わせてNPCの行動を制御し、開発者が直感的にNPCの振る舞いを設定することができます。しかし、全ての行動パターンを手作業で実装する必要があるため、多数のNPCを作成する際には大変な労力がかかります。
一方、深層強化学習を用いたゲームAIの研究も進んでいます。この手法を用いると、NPCが自ら学習し、より汎用的で柔軟な振る舞いを身につけることができます。
例えば、先行研究「Reward design with language models(Kwon, Minae, et al.)」では、エージェントの行動ログを自然言語に変換し、LLM（大規模言語モデル）で「エージェントが個性を表現できているか？」をYes/Noで評価し報酬を決定するという手法が提案されました。この研究により、LLMの一般的な知識を活用して、個性や役割のアライメントが可能であるという結果が得られています。
しかし、深層強化学習を実際の開発現場に応用するには以下のような課題があります。
学習結果の制御が難しい：意図しない振る舞いをすることがあり、開発者が望む結果を得るのが難しい。
計算リソースの必要性：深層モデルを動かすには十分な計算リソースが必要であり、コストが高い。
環境整備のコスト：AIの学習環境を整える必要があり、開発フローへの導入コストが高い。
提案手法の概要
そこで今回は、LLM（大規模言語モデル）を活用してキャラクターの行動を再現する評価関数を作成し、シンボリックAIの上で動作させる手法を提案しました。
この手法により、従来のゲームAI開発ではエンジニアがAIの仕様書から手作業で行動を設計していた作業を自動化できます。 その結果、エンジニアはより細かい挙動の制御に集中でき、ゲーム開発の効率が向上することを目指しています。
シンボリックAI
提案手法の詳細を説明する前に、今回の研究で使用したシンボリックAIについて説明します。
NPCの状態表現
NPCの行動を機械学習で扱えるようにするためには、人間が理解し設計できる状態の表現が必要です。
そこで、NPCの状態を複数の「条件」の真偽を並べた２値ベクトルで表現することにしました。
ここでの「条件」とは、シンボリックAIにおける記号のことを指します。例えば、「剣を持っている」、「アイテムを持っている」、「HPが50%以上」などTrue/Falseで評価できるものが条件となります。
2値ベクトルを使用することで計算の高速化が可能となり、リアルタイムでのゲームプレイがよりスムーズになるというメリットも得られます。
NPCの行動定義
NPCの行動は「前提（満たすべき条件）」と「結果（達成される条件）」で定義されます。例えば、「剣で攻撃する」という行動は、以下のように定義できます。
「前提」:「剣を持っている」かつ「敵が近い」
「結果」: Not「敵が近い」
NPCの状態が「前提」を満たしている場合、その行動を実行することができます。
また、「行動後の状態」は「現在の状態」が「行動の結果」を満たす状態に遷移するように表現できます。 つまり、「現在の状態」と「行動の結果」によって、「行動後の状態」が一意に定まります。 「剣で攻撃する」の例では、「行動後の状態」は「現在の状態」の「敵が近い」がFalse(0)になった状態に遷移しています。
このようなシンボリックAIを使用することで、ゲーム内で実際に行動を行わずに、行動による状態遷移データを擬似的に作成することが可能です。
ゲーム実行時における条件の真偽評価や剣で攻撃するプログラムは人間が開発します。これらを人間が作成・制御することによって、開発者が自由にNPCの見た目上の動きなどを調整できるように設計しています。
この提案手法はNPCの設計図があれば適用可能なので、ゲーム内でデータを収集する必要がなく、プログラムの実装にも依存しないため、開発の初期段階から適用することができます。 ゲーム開発と共にNPCの調整やアップデートが行なえることは産業応用上重要ですが、この提案手法はその点をカバーしています。
提案手法
LLMを活用してキャラクターを再現するような行動評価関数を作成して、 先に説明したシンボリックAIの上で動作させる手法を提案しました。提案手法の要素は3つに分けられます。
LLMを用いたデータセットの作成
1. 状態遷移データの生成
状態遷移データをランダムに生成します。具体的には、「現在の状態、行動、行動後の状態」を生成しています。 まず、ランダムに01ベクトルを生成することで「現在の状態」を表現します。 次に、生成した「現在の状態」から実行可能な「行動」をランダムに選択します。 「行動後の状態」は「現在の状態」と「行動」から計算します。
2. NPCの仕様文書
NPC仕様文書のテキストデータをLLMに入力するテキストとして使用します。 NPC仕様文書とは、ゲームデザイナーが定義したNPCのキャラクター性や行動ルールを記述した文書です。
3. 行動をLLMで複数観点で3段階評価
1と2で生成したデータを元に、LLMに入力するプロンプトを作成します。 このプロンプトによって、現在の状態における行動を複数の観点で3段階で評価します。
評価は良いもの順に、Excellent, Average, Poorと設定しています。プロンプト間での評価の一貫性を保つために、１００点満点ではなく、3段階評価にしています。
評価観点は例えば、キャラ再現度、敵への効果、味方との協力などです。1つ1つの評価は３段階ですが、複数の観点を用意して最後に合算することで、最終的な評価の粒度を上げるように工夫しています。
最終的には、以下の情報を持つデータセットを作成します。
現在の状態と行動後の状態の01ベクトル
各観点の評価値(Excellent、Average、Poor)
このようにして、さまざまな状態における行動の評価データを大量に生成することで、NPCの行動評価関数を学習するためのデータセットを作成します。
意思決定関数の蒸留
作成したデータセットを使用して、線形回帰モデルを構築します。このモデルは、「状態遷移」から「行動の評価値」を推定するために使用されます。
説明変数: 現在と行動後の状態の01ベクトルを連結したベクトル
目的変数: 行動の評価値(Excellent、Average、Poor)を数値にマッピングし、各観点を重み付けして合算した値
キャラ再現度の重みを大きくすることで、キャラクター性を重視した行動を選択するようにします。
シンボリックAI上での意思決定
シンボリックAI上では、以下の手順で行動のキャラ再現度を評価し、最高評価の行動を実行します。
行動評価のモデルは線形モデルという小さい機械学習モデルを使用しているため、計算コストが低く、リアルタイムでの意思決定が可能です。
「条件」を評価して、現在の状態を取得します。
前提を満たしている(つまり実行可能な)行動の評価値をモデルで推定します。行動後の状態は現在の状態と行動の結果から計算されます。
推定評価値が最も高い行動を選択します。
実験の設定
実験環境
Unityで作成されたドッジボールゲームの環境を使用しました
ゲームルール:
各チームは4体のキャラクターで構成されています。
フィールドに落ちているボールを拾い、相手に向かって投げます。
キャラクターはボールが2回当たるとゲームオーバーになります。
相手チームを全滅させると勝利となります。
検証キャラクター
今回の研究では、実験として以下の3つのキャラクターを用意しました。この３キャラクターの再現を提案手法で実現できるかを検証しました。
攻撃型 (近接攻撃型)
詳細
敵が多い場所に入っていって、積極的に攻撃に参加する攻撃型キャラクター。
ボールを積極的に拾いながら、敵に近距離攻撃を与える。
敵に攻撃ができる時は、ボールを積極的に投げていく。
危険な時は攻撃を回避する。
バランス型 (近接遠距離両方)
詳細
攻撃もしつつ、危険な時は攻撃を回避し、味方のサポートも行うバランス型のキャラクター。
できるだけチームの勝利に貢献するために、いろんな動きを柔軟に行う。
攻撃ができそうな時は攻撃する。
サポート型 (遠距離攻撃型)
詳細
危険な味方の攻撃をサポートするキャラクター。
敵が多い場所にはあまり近付かず、できるだけ離れたところからボールを拾って、敵を攻撃する。
危険な時は攻撃を回避する。敵が居て、攻撃ができる時は攻撃する。
修正版 * サポート型はプロンプトを修正して実験をやり直しています。(後述)
危険な味方の攻撃をサポートするキャラクター。
敵が多い場所には極力近づかず、ボールを拾い、できるだけ遠くから敵を攻撃しましょう。
危険なときは攻撃を回避します。
このNPCは敵を探索し発見した場合、近づかずその場で攻撃するだけです。
条件・行動
今回は26種類の条件と19種類の行動を用意しました。
条件の例としては、「敵/味方が近くにいる」「ボールを持っている」、「敵の方向を向いている」、「最寄りの味方のHPが低い」などがあります。近くにいるやHPが低いなどの定義は、実際のゲームに合わせて定義しました。
行動の例としては、「ボールを投げる/避ける」，「味方/敵の近くに移動する」，「最寄り/２番目に最寄りのボールを取りに移動する」などを定義しました。ボールや敵までのルートはUnityのNavMeshAgentというルート探索ライブラリを使用して計算しています。
データセットについて
LLMはGPT-3.5-turboを使用しています。
各キャラクターについて、約1170の学習用データサンプルを生成しました。
データの作成が完了するには約20分ほどかかりました。
作成時に使用した行動評価用のプロンプトは以下の通りです。
プロンプト詳細  実験では英語で記述していますが、日本語訳しています。プロンプトはシステムプロンプトとユーザプロンプトの2つを使用しています。
（システムプロンプトはLLMの振る舞いを定義する文章、ユーザプロンプトは人間が入力する文章です。）
システムプロンプト
# これは_非常に重要なタスクですので、集中して解決してください。
あなたはアクションゲームのゲームデザイナーであり、特定のNPCの行動の質を評価し、協力、仕様への忠実度、自己利益、味方への利益、敵への影響、自身の安全、味方の安全の各側面において適切な行動をNPCに割り当てます。
NPCは、味方、自身のヒットポイント、位置、仕様条件などの状況に応じて適切な行動をとる必要があります。
与えられた状況に基づいて自己判断をせずに、厳密な評価と決定を行ってください。
まずNPC、ゲーム状況、NPCが目指している状態、そして次に取るべき行動が提示されます。
回答では、目標と仕様に基づいて焦点を当てるべき条件をまず決定してください。その後、条件を確認し、次の行動が適切かどうかを検証します。
評価の理由を考え、深呼吸してから評価を検証し、最終的な評価を行ってください。
評価指標を3段階の[Excellent, Average, Poor]で評価してください。各評価指標に対してこの3つの評価値のいずれかを必ず割り当ててください。空欄やNaNフィールドは許可されません。
# 出力フォーマット（&lt;EVALUATION&gt;部分を3段階の[Excellent, Average, Poor]で評価します。できるだけこの3段階で評価してください。もし不明な場合は、一般的なアクションゲームに基づいて推測してください。）
1. 理由: &lt;各評価視点で確認する必要がある状況を考慮し、与えられた条件を確認します。その後、評価の理由を説明します。&gt;
2. 検証: &lt;先に考えた理由を検証し、修正が必要な点があれば修正します。&gt;
3. 評価: # 評価のみを回答します。評価を空欄にしたり飛ばしたりすることは許可されません！
味方との協力: &lt;EVALUATION&gt;
NPC仕様への忠実度: &lt;EVALUATION&gt;
自己利益: &lt;EVALUATION&gt;
味方の利益: &lt;EVALUATION&gt;
敵への影響: &lt;EVALUATION&gt;
自身の安全: &lt;EVALUATION&gt;
味方の安全: &lt;EVALUATION&gt;
# ゲームの説明
&lt;ゲームの説明&gt;
ユーザープロンプト
# NPC仕様
{npc_specification}
# 現在の状況
{state_prompt}
# 次に取るべき行動
{next_action}
# 出力形式 (3段階で&lt;EVALUATION&gt;パートを評価します：[Excellent, Average, Poor]。できるだけこの3段階で評価してください。不明な場合は、一般的なアクションゲームに基づいて推測してください。)
1. 理由: &lt;各評価視点で確認する必要がある状況を考慮し、与えられた条件を確認します。その後、評価の理由を説明します。&gt;
2. 検証: &lt;先に考えた理由を確認し、修正が必要な点があれば修正します。&gt;
3. 評価: # 評価のみを回答します。評価を4つの選択肢で必ず記入してください。評価の飛ばしや空白は許可されません！
味方との協力: &lt;EVALUATION&gt;
NPC仕様への忠実度: &lt;EVALUATION&gt;
自己利益: &lt;EVALUATION&gt;
味方への利益: &lt;EVALUATION&gt;
敵への効果: &lt;EVALUATION&gt;
自身の安全性: &lt;EVALUATION&gt;
味方の安全性: &lt;EVALUATION&gt;
結果
実験では、以下の点について検証を行いました。
Q1. 状況に応じた適切な意思決定が可能か
学習済みの強化学習エージェントとシンボリックAIとの間で300回の対戦を行いました。
勝率を比較することで、キャラの再現度に意思決定が偏ってしまう(ボールを避けるべきなのに他の行動を取る・明らかにボールを投げるべきなのに投げないなど)ことなく、基本的に状況に応じて適切な意思決定ができているかを検証しました。
比較対象のシンボリックAI
提案手法を使用した3つのキャラクター
実行可能な行動からランダムに選択するシンボリックAI
結果
提案手法の勝率はランダムな手法よりも高かった。（統計的に有意性あり）
モデルがゲームルールを理解し、基本的に状況に応じた意思決定ができることが確認できました。
Q2. キャラクター仕様を再現した意思決定が可能となるか
この検証では、被験者5名にNPCの動作動画を提示し、動作NPCがどのキャラらしいかを予測してもらいました。
結果
攻撃型とバランス型については、被験者の予測したキャラクター型と実際のキャラクター型が一致する割合が高く、キャラクターの再現に成功したという結果が得られました。
一方で、サポート型に対して、サポート型らしいと予測した割合は低い結果となりました(20%)。
サポート側はより攻撃型らしく見えてしまっていたようでした。
下の図は、それぞれのキャラクターに対する被験者の予測割合を示しています。 
サポート型のキャラクターの再現に失敗した理由を考察しました。 その結果、サポート型のキャラクターは、ある特定の状態下で、攻撃型よりも敵の近くに移動する傾向があることがわかりました。(下図の赤字部分注目)
キャラクタータイプ
攻撃可能な敵まで
攻撃型
バランス型
サポート型
サポート型(修正後)
中距離
63
0
150
0
長距離
119
0
0
0
この挙動のせいで、サポート型のキャラクターが攻撃型のように見えてしまった可能性があります。
サポート型のキャラクターの仕様文書を調べると、意図に合わない表現が含まれていたことも判明しました。
具体的には、"If there is an enemy and you can attack, attack."と命令形で攻撃を促すような表現がありました。
このサポート型のキャラクターの仕様文書を修正したところ問題が解消しました。 今手法では、プロンプトに本来の意図とのズレが生じないように注意する必要があると考えられます。
最後に実際に各キャラクターのプレイ動画を共有します。 青いキャタクターが提案手法によって動いていて、1試合で4対のキャラクターがすべて同じキャラクター型となっています。
紫色のキャラクターが強化学習エージェントによって動いています。
まとめ
今手法では、シンボリックAIとLLMを活用して、NPCの性格や役割を再現した行動の評価関数を作成する研究を紹介しました。 この手法では、人手でのアノテーションやゲーム内でのデータ収集は必要なく、プロンプトを使用してキャラクターの性格を再現することができます。 また、シンボリックAI上で動かすことができるため、開発現場での応用も容易です。
最近のLLMによる汎用的な知識を活用することにより、産業応用が行いやすいAIの開発が今後も模索できると考えています。 具体的には、LLMを他のシンボリックAI（例：ビヘイビアツリー）への活用や、キャラクター仕様とのアライメント精度を向上させるためのモデル学習や調整方法の開発が可能ではないかと思っています。 今後も、新しいAI技術を活用したゲームAIの研究を進めていきます！]]></description>
<pubDate>Wed, 31 Jul 2024 18:25:00 +0900</pubDate>
<category>機械学習</category>
</item>
<item>
<title>技術書典16で同人誌を頒布します &amp; 既刊PDFダウンロードページ</title>
<link>https://www.klab.com/jp/blog/tech/2024/tbf16.html</link>
<description>こんにちは。 技術書典活動の代表のUMEです。
5/25(土) ~ 6/9(日) の期間、技術書の即売会 技術書典16 が開催されます。 期間中はオンラインにて書籍を購入することができ、 さらに 5/26(日) にはオフラインでも開催されます。 (入場券の発行など、詳しくは公式サイトをご覧ください)
KLabは例年新刊を発行しながら参加しており、今回も社内の有志のエンジニアが各自好きな内容で記事を執筆し、最新刊「KLabTechBook Vol.13」を発行します。 既刊のVol.3~12とあわせてオンラインマーケットで頒布します。
技術書典では他にも様々な方が執筆された技術書が多数発行されていますので、ぜひ技術書典オンラインマーケットにお越しください。
頒布内容
新刊/既刊を問わず、物理本+電子版は500円、電子版のみは無料で頒布します。
最新刊
KLab Tech Book Vol. 13 - 技術書典マーケット
今回収録しているのは以下の4記事です。 内容は章ごとに独立しているので、気になる記事が一つでもあればぜひご一読ください。
1. TCP_NODELAYの効果を確かめる
名前だけは知っていたTCP_NODELAYについてちゃんと調べてみました。DockerはLinuxなのでネットワーク系の動作確認がしやすいですね。ホストマシンもLinuxにすると特に便利ですよ！
2. 2024 年から始める Python asyncio 入門
Python の asyncio ライブラリまわりを学び直し。まずはこれだけを知っていれば Python で非同期プログラミングを始められる、公式ドキュメントを読み進められるという内容を目指して紹介記事を書きました。
3. 欲しい釣具の入荷状況を生成AIで監視してみた
いつも品切れな釣り道具を購入するために、AIにECサイトを監視してもらいました。早くAIから在庫発見の報告が来ないかな。
4. Cloudflare WARP経由で自宅の透過Proxyを使う話
スマホアプリの通信に開発者用proxyを差し込んで通信内容を編集できる環境を常用する話を書きました。
既刊
既刊の物理本は在庫の少ないものもあるため、開催期間中に売り切れとなる可能性があります。ご容赦ください。
KLab Tech Book Vol. 12 - 技術書典マーケット
KLab Tech Book Vol. 11 - 技術書典マーケット
KLab Tech Book Vol. 10 - 技術書典マーケット
KLab Tech Book Vol. 9 - 技術書典マーケット
KLab Tech Book Vol. 8 - 技術書典マーケット
KLab Tech Book Vol. 7 - 技術書典マーケット(電子版のみ)
KLab Tech Book Vol. 6 - 技術書典マーケット
KLab Tech Book Vol. 5 - 技術書典マーケット
KLab Tech Book Vol. 4 - 技術書典マーケット
KLab Tech Book Vol. 3 - 技術書典マーケット
既刊PDFダウンロード
既刊の電子版PDFです（物理本とは一部異なる場合があります）。
KLab Tech Book Vol.1
KLab Tech Book Vol.2
KLab Tech Book Vol.3
KLab Tech Book Vol.4
KLab Tech Book Vol.5
KLab Tech Book Vol.6
KLab Tech Book Vol.7
KLab Tech Book Vol.8
KLab Tech Book Vol.9
KLab Tech Book Vol.10
KLab Tech Book Vol.11
KLab Tech Book Vol.12
</description>
<pubDate>Fri, 24 May 2024 22:00:00 +0900</pubDate>
<category>AI</category>
<category>Python</category>
<category>TCP/IP</category>
<category>イベント</category>
<category>技術書典</category>
</item>
<item>
<title>「IC-Light」画像の照明効果を自在に変更できる生成AI</title>
<link>https://www.klab.com/jp/blog/tech/2024/IC-Light.html</link>
<description>機械学習グループの吉田と申します。
今回は画像の照明を自在に変更することができる生成AI「IC-Light」が最近公開されましたので、使ってみました。
元画像
sunset over sea
neon light, city
natural lighting
IC-Lightとは
IC-Lightとは、画像の照明効果をテキストや、背景画像を使って自在にコントロールすることができる生成AIです。
IC-LightはControlNetの開発者が最近公開したもので、かなり注目を集めています。
実際に公式から公開されている画像がこちらです。
一番左の画像が元画像で、その画像に対して以下のプロンプトを設定しています。
beautiful woman, detailed face, warm atmosphere, at home, bedroom
そして生成結果が一番右の画像となっています。(真ん中の画像は中間画像のため無視して大丈夫です)
元画像では外で花に囲まれていた画像でしたが、生成された画像はプロンプト通りに家のベッドルームの写真になっています。 それに合わせて被写体の女の子に対する光加減が元画像より暗くなっていることがわかるかと思います。 家の中は外よりは暗いため、それに合わせてAIが自動的に照明を調節してくれています。
IC-Lightを使うと、このような画像の背景や照明を容易にコントロールすることが可能となります。
IC-Lightを使ってみる
実際にIC-Lightを使ってみようと思います。
IC-Lightはオープンソースとなっており、コードはこちら で公開されています。
環境構築
IC-Lightを使うためには実行環境の構築を行う必要があります。
詳細な手順はReadMEに記載されていますが、手軽に試せるように Google Colaboratory ノートブックを用意しました。
Google Colaboratory とは無料で手軽に機械学習環境がブラウザで試せるサービスです。(利用時間に制限はあります)
colabの使い方
1. こちら のノートブックを開きます
2. メニューのファイル → ドライブにコピーして保存　を押し、自分のドライブにコピーします。
3. メニューのランタイム → ランタイムのタイプを変更 → T4 GPUを選択し保存を押して、GPUを使うように設定します。
4. メニューのランタイム → すべてのセルを実行を押す。実行に数分かかるので待つ。
5. このようなポップアップが表示された場合、キャンセルを押してそのままにするか、再起動しもう一度4から実行する。
6. 実行が完了するとこのようにリンクがでるのでそのリンクを開く
7. リンクを開くとIC-Lightが使えるWebUIが立ち上がります。
テキストでの変換
実際に自分の方で生成してみた結果がこちらです。
生成はWebUIから画像とプロンプトを入れて、出力画像のサイズ等を指定しRelightを押すだけで簡単にできます。
出力してみた結果が以下となります。 プロンプトには以下の接頭辞に各項目の文字を付け加えています。
beautiful woman, detailed face
元画像
sunset over sea
neon light, city
natural lighting
背景画像を用意しての変換
続いて背景画像を用いた変換です。
このように背景画像を用意してあげることで、それに合わせた画像生成をしてくれます。
実際に生成してみた結果がこちらになります。
元画像
背景画像
変換後
次に光源を4隅に用意して比較してみました。 光源の方向に対して、うまく照明効果を適用してくれています。
元画像
背景画像
変換後
まとめ
IC-Lightを簡単に触ってみましたが、かなり性能も良さそうで色々と用途がありそうです。
生成AI技術は日々進化しており、私たちはこれからも新たな技術を追求していきたいと思っています!
</description>
<pubDate>Wed, 15 May 2024 20:30:00 +0900</pubDate>
<category>Python</category>
<category>グラフィック</category>
<category>機械学習</category>
</item>
<item>
<title>Falcoホワイトリスト型カスタムルールの検討</title>
<link>https://www.klab.com/jp/blog/tech/2024/202402falco.html</link>
<description><![CDATA[はじめに
FalcoはLinux OS向けのランタイムセキュリティツールであり、システム上での異常なアクティビティや潜在的なセキュリティリスクをリアルタイムで検知し、警告するように設計されています。 Kubernetesとシームレスに統合できるため、クラウド上のWebアプリケーションのセキュリティモニタリングに非常に適しています。 前回の記事で、Falcoの概要、デプロイ方法、実際の検出例について詳しく紹介しました。 Falcoプロジェクトでは、異常検知のためのデフォルトルールセットが提供されており、開発者によってメンテナンスされています。ユーザーは必要に応じてこれらのルールを選択し、利用することが可能です。
Falcoのデフォルトルールセットは強力ですが、前回の記事で指摘した通り、未知のセキュリティリスクを検知できないケースが存在します。 攻撃者は既知の攻撃パターンに加え、常に新たな方法で脆弱性を探り、侵入を試みます。 この記事では、そうした脅威に対抗するために、ホワイトリスト型カスタムルールの活用を検討しましたので、それについて紹介したいと思います。
前回記事のおさらい
Falcoの仕組みと特徴
FalcoはLinux OS向けのランタイムセキュリティツールで、 システム上で発生する異常なアクティビティや潜在的なセキュリティリスクをリアルタイムで検知し、警告するよう設計されています。 このツールの核となるのは、カーネルレベルでのシステムコールを監視するモジュール、異常なイベントを検知するための監視ルールに基づくエージェント、そして外部に通知を行うFalcosidekickエージェントです。
Falcoシステム構成
Falcoの監視ルールは、開発元が提供するデフォルトセットを利用することも、組織のセキュリティポリシーに合わせてカスタマイズすることも可能です。
Falcoインシデント検知の例
前回の記事では、シンプルなnginx podを起動し、以下の3つの操作を実施した際のFalcoによる検知能力を検証しました。検知結果はWeb UIで確認し、さらにjsonログファイルをダウンロードして詳細に分析しました。
試したケース
bashシェル実行: kubectl execコマンドでコンテナに接続し、bashシェルを起動します。
viインストール実行: kubectl execコマンドでコンテナに接続し、viエディタをインストールして実行します。
外部ssh接続: kubectl execコマンドでコンテナに接続し、443ポートを介して外部サーバにssh接続します。
それぞれのログ検出結果
bashシェル実行: Terminal shell in containerルールにマッチし、対応するログが生成されました。
viインストール実行: Drop and execute new binary in containerルールにマッチし、対応するログが生成されました。
外部ssh接続: Disallowed SSH Connection Non Standard Portルールにマッチし、対応するログが生成されました。
これらの結果は、Falcoが予定されたイベントを正確に検知できる能力を有していることを示しています。しかし、侵入者が工夫を凝らすことで検知を回避する可能性があることも明らかになりました。
なぜホワイトリスト型カスタムルールなのか
問題点
前述の例で、Falcoが特定の異常行動を検知できることを示しましたが、侵入者がFalcoの監視を回避するために工夫を凝らす可能性があります。 ここでは、検証した3つのケースでの潜在的な回避方法と、それに対抗するためのホワイトリスト型カスタムルールの必要性について考察します。
1. bashシェル実行:
bashコマンドを/dev/hogeにコピーし、それを実行することで、Terminal shell in containerルールの検知を回避することが可能です。このルールは特定のバイナリ名(ash, bash, csh, ksh, sh, tcsh, zsh, dash)を検出対象としていますが、ファイル名が変更されると検知できなくなります。
root@v130:~# kubectl exec -it nginx -- cp /bin/bash /dev/hoge
root@v130:~# kubectl exec -it nginx -- /dev/hoge
root@nginx:/# 
exit
2. viインストール実行:
viを/dev/viにコピーし、実行することで、Drop and execute new binary in containerルールの検知を回避できます。このルールはoverlayfsの最上位層に新規作成されたファイルの実行を検知しますが、/devディレクトリはtmpfsがマウントされており、検知条件から外れてしまいます。
root@nginx:/# apt install vim
root@nginx:/# cp /usr/bin/vi /dev/vi
root@nginx:/# /dev/vi test
3. 外部ssh接続:
実行ファイル名を偽装したり、標準以外のポートを使用してSSH接続することで、Disallowed SSH Connection Non Standard Portルールを回避できます。このルールは特定のポート(80, 8080, 88, 443, 8443, 53, 4444)への接続を検知するため、条件に合致しなければ検知されません。
これらのケースは、Falcoのデフォルトルールセットでは検知しきれないシナリオを示しています。攻撃者はFalcoのルールを分析し、これらを回避する新たな手法を常に模索しています。
Falcoのデフォルトルールセットは、セキュリティ脆弱性に関する広範な情報を提供するMITRE ATT&amp;CK データベースを基に作られており、既知のリスクを広くカバーしています。 しかし、実行バイナリファイル名、ファイルの置き場所、ポート番号などを検知条件にしたルールも多く、常に新たな攻撃パターンにさらされ、どうしても監視ルールの作成がいたちごっこになってしまいます。
そこで、すべてのアクティビティを網羅できるようなルールファイルを作成し、出力されたログを元に無害なものを逐次、検知の除外条件に加えていく、ホワイトリスト型のルールセットが作成可能か検討してみました。
ホワイトリスト型カスタムルールの考え方
ホワイトリスト型カスタムルールでは、システムで許可されるアクティビティのみを明確に定義し、それ以外の全てを潜在的な脅威として扱います。 このアプローチにより、未知の攻撃手法に対しても、もれなく対応することが可能になります。 以下では、この考え方を具体的なルール作成の例を通じて説明します。
Falcoで検出可能なイベントの種類は大まかに次の三種類に分類できます。
TCP、UDPなどのネットワークに関するイベント
コマンド実行などプロセス生成に関するイベント
ファイルの改変、新規作成などの、ファイル操作に関するイベント
それぞれについて、ホワイトリスト型カスタムルールを考えてみました。
ネットワーク
例えば、80、443ポートを除くすべてのTCPのインバウンドコネクションを検出するカスタムルールは次のようなものになります。
- macro: inbound
condition: >
(((evt.type in (accept,listen) and evt.dir== 0 or evt.res = EINPROGRESS))
- list: expected_tcp_ports
items: [80, 443]
- macro: expected_tcp_traffic
condition: fd.port in (expected_tcp_ports)
- rule: Inbound TCP Traffic
condition: inbound and fd.l4proto=tcp and not expected_tcp_traffic
output: ...
priority: WARNING
tags: [catch_all, inbound, container]
macro: inboundでは、インバウンドのtcpコネクションに関する条件を定義しています。
macro: expected_tcp_trafficで除外条件を定義しています。除外条件を追加する場合には、ここに追加します。
rule: Inbound TCP Trafficがルール本体で、condition:が検出条件、output:には検出条件がマッチした場合の出力ログをテンプレート形式で定義します。 not expected_tcp_trafficとあるように、マクロで定義した条件の頭にnotをつけて、除外条件としていることがポイントです。
プロセス生成
全てのコマンド実行、プロセス生成を検出するルールは次の様になります。
- macro: spawned_process
condition: (evt.type in (execve, execveat) and evt.dir=- macro: proc_trusted
condition: (...)
- rule: Process Creation
condition: spawned_process and not proc_trusted
output: ...
priority: WARNING
tags: [catch_all, process]
macro: spawned_processはプロセス生成イベントをキャッチするためのマクロです。
macro: proc_trustedに信頼するプロセス、すなわち除外条件の定義を追加していきます。
rule: Process Creationがルール本体です。信頼するプロセス以外のすべてのプロセス生成イベントに対し、output:に定義したログを出力します。 not proc_trustedとあるように、マクロで定義した条件の頭にnotをつけて、除外条件としていることがポイントです。
ファイル操作
ファイル操作の内、書き込みモードでのファイルオープンを全て検知するルールは次の様になります。
- macro: open_write
condition: (evt.type in (open,openat,openat2) and evt.is_open_write=true and fd.typechar='f' and fd.num>=0)
- macro: file_write_exempt
condition: (...)
- rule: Unexpected File Write
condition: open_write and not file_write_exempt
output: ...
priority: WARNING
tags: [catch_all, file_write]
macro: open_write は、書き込みモードでのファイルオープンをキャッチするためのマクロです。
macro: file_write_exemptには、ログファイルへの書き込みなど、通常のアクティビティで想定される条件を追加していきます。
rule: Unexpected File Writeがルール本体です。condition:にマッチしたイベントに対してoutput:に定義された形式でログ出力することを設定しています。 not file_write_exemptとあるように、マクロで定義した条件の頭にnotをつけて、除外条件としていることがポイントです。
以上で、TCPのインバウンドコネクション、プロセス生成、書き込みモードのファイルオープンを検知するルールを例に、キャッチオール形式でルールを作成し、除外条件をホワイトリストとして追加していくやり方を説明しました。
実際には、TCPのアウトバウンドコネクション、UDPインバウンド・アウトバンド通信、ファイル操作に関しては、renameやdelete、symlink、hardlinkに関する条件などにも対応する必要があり、上に掲げた例の他にいくつかルールを作成する必要があります。 しかし、おおまかな考え方については上記で説明した通りになります。
カスタムルールの書き方、適用方法
Falcoでカスタムルールを作成し適用する方法を簡潔に説明します。
カスタムルールの書き方
Falcoをhelmでインストールする場合には、helm chartのカスタマイズファイルにカスタムルールを記述することができます。
custom-rules.yaml
customRules:
custom-rules.yaml: |-
- rule: Example rule 1
desc: ...
...
- rule: Example rule 2
...
ここで注意点として、最初の"customRules:"と2行目の"custom-rules.yaml: |-"が必要で、ルール自体のインデントも二段分深くする必要があるようです。(参考)
helm chartのカスタマイズファイルは複数読み込むことができますので、カスタムルールが長くなる場合には、それぞれ専用のカスタマイズファイルに書くと良いでしょう。 Falcoのカスタムルールをさらに別のcustom-rules2.yamlファイルから読み込むには、同様のフォーマットで記述します。
custom-rules2.yaml
customRules:
custom-rules2.yaml: |-
- rule: Example rule 3
desc: ...
...
- rule: Example rule 4
...
ここでの注意点としては、"custom-rules2.yaml: |-"や"- rule: Example rule 3"等の行が同じファイルの別部分や他のファイルと重複しないようにする必要があります。
カスタムルールのデプロイ方法
デフォルトルールセットに加えて、カスタムルールを利用する場合には、次のコマンドラインでhelmを実行します。
helm install falco falcosecurity/falco --namespace falco --create-namespace \
-f myvalues.yaml -f custom-rules1.yaml -f custom-rules2.yaml
デフォルトルールセットを利用せずに、カスタムルールのみを利用したい場合には、myvalues.yamlファイルの中身を次の様にし、上記のコマンドでhelmを実行します。(参考)
falcoctl:
config:
artifact:
install:
enabled: false
follow:
enabled: false
falco: rules_file: - /etc/falco/falco_rules.local.yaml - /etc/falco/rules.d  
カスタムルールは改ざんされないのか
Helmにより適用されたFalcoのルールはKubernetesのConfigMapに格納されます。この設定ファイルへの不正な改ざんを試みる行為は、Falcoによって検出可能です。攻撃者がFalcoのルールファイルを書き換えるためには、コンテナ内からKubernetesのAPIを介してConfigMapにアクセスする必要があります。このようなアクセスは、Falcoの監視ルールによって検知され警告されます。
ホワイトリスト形式カスタムルールの実際
それでは実際のホワイトリスト形式カスタムルールはどのように作成すれば良いでしょうか。ここではインバウンドのTCPコネクションのケースを例に手順を説明します。
Kubernetesのコントロールプレーンが使用するポートはこのページにまとまっています。これを元に初期バージョンのカスタムルールファイルを作成します。
いったんある程度のものができたら、Falcoに適用します。
検出されるログを収集、解析します。
さらに、除外ルールを追加していきます。
検知不要なイベントに対するログが出なくなるまで、ステップ2と3を繰り返します。
初期バージョンの作成
カスタムルールの初期バージョンとして、Kubernetesのコントロールプレーンのトラフィックを除外するルールファイルを作成しました。
custom-rules-inboud-tcp0.yaml
customRules:
custom-rules-inboud-tcp0.yaml: |-
- macro: container
condition: (container.id != host)
- macro: inbound_tcp
condition: &gt;
((evt.type in (accept,accept4,listen) and evt.dir=&lt;) and
(fd.typechar = 4 or fd.typechar = 6) and
(fd.ip != &quot;0.0.0.0&quot; and fd.net != &quot;127.0.0.0/8&quot;) and
(evt.rawres &gt;= 0 or evt.res = EINPROGRESS))
- macro: k8s_kubelet
condition: &gt;
proc.name = &quot;kubelet&quot; and (
(evt.type in (accept4) and fd.sport = 10250)
)
- macro: k8s_apiserver
condition: &gt;
k8s.ns.name = &quot;kube-system&quot; and
k8s.pod.name startswith kube-apiserver- and (
(evt.type = accept4 and fd.sport = 6443)
)
- macro: k8s_etcd
condition: &gt;
k8s.ns.name = &quot;kube-system&quot; and
k8s.pod.name startswith etcd- and (
(evt.type = accept4 and fd.sport = 2380)
)
- macro: expected_tcp_traffic
condition: (
k8s_kubelet or
k8s_apiserver or
k8s_etcd
)
- rule: TCP Inbound
desc: Detect unexpected Inbound TCP connection
enabled: true
condition: inbound_tcp and fd.l4proto=tcp and not expected_tcp_traffic
output: &gt;
Unexpected Inbound TCP Traffic
(evt_type=%evt.type host=%evt.hostname
connection=%fd.name fd_proto=%fd.l4proto
cIP=%fd.cip sIP=%fd.sip cPort=%fd.cport sPort=%fd.sport
process=%proc.name command=%proc.cmdline proc_exepath=%proc.exepath parent=%proc.pname
user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid terminal=%proc.tty
exe_flags=%evt.arg.flags %container.info)
priority: WARNING
tags: [catch_all, tcp_inbound, network, ktaka]
Falcoのデプロイ
以下のコマンドでFalcoをデプロイします。
helm install falco falcosecurity/falco --namespace falco --create-namespace \
-f myvalues.yaml -f custom-rules-inboud-tcp0.yaml
ログ収集と解析
Falcoのデプロイ後しばらくすると、WebUIに大量のログが記録されます。全体を見通すために、json形式のログファイルをExportし、jqを駆使してどのようなログが記録されているのか解析します。
次の例は、一件の検出イベントに対するjsonログです。
ktaka@bulls:~/Downloads$ jq .[2] falco_events.json 
{
"uuid": "0effbce1-6012-4e16-84ee-1f7ec2012a1a",
"output": "04:21:50.762917673: Warning Unexpected Inbound TCP Traffic (evt_type=accept4 host=v136 connection=10.244.5.1:45754->10.244.5.226:2801 fd_proto=tcp cIP=10.244.5.1 sIP=10.244.5.226 cPort=45754 sPort=2801 process=falcosidekick command=falcosidekick proc_exepath=/app/falcosidekick parent=containerd-shim user=falcosidekick user_uid=1234 user_loginuid=-1 terminal=0 exe_flags= container_id=d38b28bb9ab9 container_image=docker.io/falcosecurity/falcosidekick container_image_tag=2.28.0 container_name=falcosidekick k8s_ns=falco k8s_pod_name=falco-falcosidekick-749d77d5c7-22jph)",
"priority": "Warning",
"rule": "TCP Inbound",
"time": "2023-12-22T04:21:50.762917673Z",
"source": "syscall",
"output_fields": {
"container.id": "d38b28bb9ab9",
"container.image.repository": "docker.io/falcosecurity/falcosidekick",
"container.image.tag": "2.28.0",
"container.name": "falcosidekick",
"evt.arg.flags": null,
"evt.hostname": "v136",
"evt.time": 1703218910762917600,
"evt.type": "accept4",
"fd.cip": "10.244.5.1",
"fd.cport": 45754,
"fd.l4proto": "tcp",
"fd.name": "10.244.5.1:45754->10.244.5.226:2801",
"fd.sip": "10.244.5.226",
"fd.sport": 2801,
"k8s.ns.name": "falco",
"k8s.pod.name": "falco-falcosidekick-749d77d5c7-22jph",
"proc.cmdline": "falcosidekick",
"proc.exepath": "/app/falcosidekick",
"proc.name": "falcosidekick",
"proc.pname": "containerd-shim",
"proc.tty": 0,
"user.loginuid": -1,
"user.name": "falcosidekick",
"user.uid": 1234
},
"hostname": "v136",
"tags": [
"catch_all",
"ktaka",
"network",
&quot;tcp_inbound&quot;
]
}  
今回の例ではこのようなログが、1分25秒間の間に8308件と大量に記録されていました。
$ jq .[].time falco_events.json |wc -l 
8308
$ jq .[0].time falco_events.json
"2023-12-22T04:21:51.067533099Z"
$ jq .[8307].time falco_events.json
"2023-12-22T04:20:26.389131383Z"
このログを、jqを使って見やすい形式に整形します。 今回の例では、元のログファイルから必要そうなフィールドのみを拾い出し、重複行を一行にまとめることで見やすい形になりました。
$ jq '.[].output_fields' falco_events.json|jq  -r '[."fd.sport", ."evt.type",　."k8s.pod.name"]|@csv' | sort  -u -t, -k 1 
2801,"accept4","falco-falcosidekick-749d77d5c7-22jph"
2801,"accept4","falco-falcosidekick-749d77d5c7-9g2lq"
2802,"accept4","falco-falcosidekick-ui-6885c6cffd-dslgc"
2802,"accept4","falco-falcosidekick-ui-6885c6cffd-hsb4j"
6379,"accept","falco-falcosidekick-ui-redis-0"
8080,"accept4","coredns-5dd5756b68-48lkl"
8080,"accept4","coredns-5dd5756b68-759kd"
8181,"accept4","coredns-5dd5756b68-48lkl"
8181,"accept4","coredns-5dd5756b68-759kd"
8765,"accept","falco-6tcd5"
8765,"accept","falco-ch66w"
8765,"accept","falco-dbcf4"
8765,"accept","falco-dqphh"
8765,"accept","falco-wpt8n"
8765,"accept","falco-wt662"
この内容をみると、どうやらログ出力の原因となった通信は、falco関連のプロセスと、corednsに起因するもので、いずれも無害なものと判断して良さそうです。
そこで、この結果を元に以下のようなマクロを作成しました。 これらをホワイトリストとして除外条件に加ることで、1分25秒間の間に8308件出力されていたfalcoの関連プロセス間通信によるの大量のログは全く出力されなくなります。
- macro: k8s_coredns
condition: >
k8s.ns.name = "kube-system" and
k8s.pod.name startswith coredns- and ( 
evt.type = accept4 and fd.sport in (8080,8181)
)
- macro: falco
condition: &gt;
k8s.ns.name = &quot;falco&quot; and
k8s.pod.name startswith falco- and (
(evt.type = accept and fd.sport = 8765)
)
- macro: falco_falcosidekick
condition: &gt;
k8s.ns.name = &quot;falco&quot; and
k8s.pod.name startswith falco-falcosidekick- and (
(evt.type = accept4 and fd.sport = 2801)
)
- macro: falco_falcosidekick_ui
condition: &gt;
k8s.ns.name = &quot;falco&quot; and
k8s.pod.name startswith falco-falcosidekick-ui- and (
(evt.type = accept4 and fd.sport = 2802)
)
- macro: falco_redis
condition: &gt;
k8s.ns.name = &quot;falco&quot; and
k8s.pod.name startswith falco-falcosidekick-ui-redis- and (
(evt.type = accept and fd.sport = 6379)
)
また、しばらく運用していると違う条件で通信イベントのログが出力されますが、同じ要領で順次除外条件をホワイトリストに加えていきます。
最終的なカスタムルールファイル
最終的なカスタムルールファイルは次の様になりました。 このルールファイルでFalcoを起動し直すと、無害な通信に起因するログが出力されなくなりました。
custom-rules-inboud-tcp1.yaml
customRules:
custom-rules-inboud-tcp0.yaml: |-
- macro: container
condition: (container.id != host)
- macro: inbound_tcp
condition: &gt;
((evt.type in (accept,accept4,listen) and evt.dir=&lt;) and
(fd.typechar = 4 or fd.typechar = 6) and
(fd.ip != &quot;0.0.0.0&quot; and fd.net != &quot;127.0.0.0/8&quot;) and
(evt.rawres &gt;= 0 or evt.res = EINPROGRESS))
- macro: k8s_kubelet
condition: &gt;
proc.name = &quot;kubelet&quot; and (
(evt.type in (accept4) and fd.sport = 10250)
)
- macro: k8s_apiserver
condition: &gt;
k8s.ns.name = &quot;kube-system&quot; and
k8s.pod.name startswith kube-apiserver- and (
(evt.type = accept4 and fd.sport = 6443)
)
- macro: k8s_etcd
condition: &gt;
k8s.ns.name = &quot;kube-system&quot; and
k8s.pod.name startswith etcd- and (
(evt.type = accept4 and fd.sport = 2380)
)
- macro: k8s_coredns
condition: &gt;
k8s.ns.name = &quot;kube-system&quot; and
k8s.pod.name startswith coredns- and ( 
evt.type = accept4 and fd.sport in (8080,8181)
)
- macro: falco
condition: &gt;
k8s.ns.name = &quot;falco&quot; and
k8s.pod.name startswith falco- and (
(evt.type = accept and fd.sport = 8765)
)
- macro: falco_falcosidekick
condition: &gt;
k8s.ns.name = &quot;falco&quot; and
k8s.pod.name startswith falco-falcosidekick- and (
(evt.type = accept4 and fd.sport = 2801)
)
- macro: falco_falcosidekick_ui
condition: &gt;
k8s.ns.name = &quot;falco&quot; and
k8s.pod.name startswith falco-falcosidekick-ui- and (
(evt.type = accept4 and fd.sport = 2802)
)
- macro: falco_redis
condition: &gt;
k8s.ns.name = &quot;falco&quot; and
k8s.pod.name startswith falco-falcosidekick-ui-redis- and (
(evt.type = accept and fd.sport = 6379)
)
- macro: expected_tcp_traffic
condition: (
k8s_kubelet or
k8s_apiserver or
k8s_etcd or
k8s_coredns or
falco or
falco_falcosidekick or
falco_falcosidekick_ui or
falco_redis
)
- rule: TCP Inbound
desc: Detect unexpected Inbound TCP connection
enabled: true
condition: inbound_tcp and fd.l4proto=tcp and not expected_tcp_traffic
output: &gt;
Unexpected Inbound TCP Traffic
(evt_type=%evt.type host=%evt.hostname
connection=%fd.name fd_proto=%fd.l4proto
cIP=%fd.cip sIP=%fd.sip cPort=%fd.cport sPort=%fd.sport
process=%proc.name command=%proc.cmdline proc_exepath=%proc.exepath parent=%proc.pname
user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid terminal=%proc.tty
exe_flags=%evt.arg.flags %container.info)
priority: WARNING
tags: [catch_all, tcp_inbound, network, ktaka]
その他のカスタムルール
前節でTCPのインバウンド通信を例に、ホワイトリスト形式のカスタムルールの作成方法について説明しました。
その他に、作成すべきカスタムルールとしては、以下のようなものが考えられます。
ネットワーク通信の残り、すなわち、TCPアウトバウンド、UDPインバウンド、UDPアウトバウンド通信に関するもの
プロセス生成に関するもの
ファイル操作に関するもの
1.のネットワーク通信の残りについては、前節と同じようにホワイトリストを作成していけば問題ありません。 2.、3.に関しては、基本的に同じ手順でホワイトリストの作成ができますが、ルールの記述方法に関して、難しさがあることがわかりました。
プロセス生成
プロセス生成のホワイトリストに関しては、ルールの記述が比較的容易なものと、どう書くべきか難しい部分が存在しています。
簡単な部分の例
簡単な部分は、kubernetesのコントロールプレーンなど、目的がはっきりしているプロセス達です。以下は、大量に出力されるログから作成した、除外条件マクロの一部です。
- macro: proc_kube_proxy
condition: k8s.ns.name = kube-system and k8s.pod.name startswith kube-proxy- and (
proc.exepath = /usr/sbin/xtables-nft-multi
)
ログファイルの中に/usr/sbin/xtables-nft-multiの起動に関するログが大量にありました。その中でkube-proxy-xxxxという名前のポッド内で起動されるものであれば、問題ないであろうと判断し、このマクロを作成しました。 kube-proxy-xxxxはリナックスカーネルのiptablesを操作してproxyを実現しており、/usr/sbin/xtables-nft-multiはiptablesコマンドのバイナリ実体であるからです。
- macro: proc_falco
condition: k8s.ns.name = falco and k8s.pod.name startswith falco-falcosidekick-ui- and (
proc.exepath = /app/falcosidekick-ui
)
ログファイルの中に/app/falcosidekick-uiの実行に関するログが大量にありました。これもfalco-falcosidekick-ui-xxxxという名前のポッド内で起動されていたので、問題ないと判断し、このマクロを作成しました。
- macro: proc_kubelet
condition: container.id = host and proc.pname = kubelet and (
proc.exepath = /sbin/xtables-nft-multi
or proc.exepath = /usr/sbin/xtables-nft-multi
or proc.exepath = /usr/bin/mount
or proc.exepath = /usr/bin/umount
)
ログファイルの中には、他にもxtables-nft-multi、mount、umountに関するものがありました。その中でも、proc.pname = kubeletすなわち親プロセスがkubeletであるものは問題ないであろうと判断し、このマクロを作成しました。
難しい部分
一方で、プロセス起動に関するログとして、cp、mv、rm、cmp、dirname、tar、date、apt-compat、dpkgなど、それだけでは一見、問題があるかどうか判断がつかないものも大量に存在していました。
その多くは、ホストのOS上で、cronやsystemdにより定期的に実行されるスクリプトの中から呼び出されるものでした。
一例としてcronジョブに関係していそうなログに対して、それを除外するためのマクロを以下に示します。
- macro: proc_cron
condition: container.id = host and (
(proc.name in (apt-compat, aptitude, dpkg, logrotate, sysstat, debian-sa1) and (proc.aname[2] = cron or proc.aname[3] = cron or proc.aname[4] = cron))     
or (proc.name = sh and proc.pname = cron)
or proc.exepath = /usr/bin/run-parts
or proc.exepath = /usr/bin/cmp
or proc.exepath = /usr/bin/basename
or proc.exepath = /usr/bin/dirname
or (proc.exepath = /usr/bin/cp and proc.cmdline = "cp -p /var/lib/aptitude/pkgstates aptitude.pkgstates")
or (proc.exepath = /usr/bin/dash and proc.cmdline = "savelog /bin/savelog -c 7 aptitude.pkgstates")
or (proc.exepath = /usr/bin/rm and proc.cmdline = "rm -f -- .//aptitude.pkgstates.6 .//aptitude.pkgstates.6.gz")
or (proc.exepath = /usr/bin/gzip and proc.cmdline = "gzip -f -9 .//aptitude.pkgstates.0")
)
このマクロは、以下の条件にマッチするものです。
(apt-compat, aptitude, dpkg, logrotate, sysstat, debian-sa1)については、祖先のいずれかがcronであるもの
shは、親プロセスがcronであるもの
cmp、basename、dirname、run-partsはそれ自体（書き込みが無いため無害とみなす）
cp, dash, rm, gzipについては、コマンドラインが完全一致するもの
それぞれのログに対してアドホックに条件を書いているので指定の仕方が統一されていないことなどから、今後も検討、改善を続けることが必要だと考えています。
ファイル操作
ファイル操作のホワイトリストに関しては、実際にやってみると、稼働中のシステムではたいへん多くのファイル読み書きのイベントが発生していることがわかり、それを整理してホワイトリストを作成するのは大変でした。
ファイル書き込み操作に関するホワイトリストマクロの一部を以下に紹介します。
- macro: file_trusted_process
condition: (
proc.exepath = /usr/sbin/runc
or proc.exepath = /usr/bin/kubelet
or proc.exepath = /usr/bin/apt-config
or proc.exepath = /usr/bin/apt-get
or proc.exepath = /usr/lib/apt/apt-helper
or proc.exepath = /usr/bin/dpkg
or proc.exepath = /usr/local/bin/containerd
or proc.exepath = /usr/local/bin/containerd-shim-runc-v2
or proc.exepath = /usr/bin/systemctl
or proc.exepath = /usr/bin/systemd-tmpfiles
or proc.exepath = /usr/lib/systemd/systemd
or proc.exepath = /usr/lib/systemd/systemd-journald
or proc.exepath = /usr/sbin/logrotate
or proc.exepath = /usr/lib/sysstat/sadc
or proc.exepath = /usr/bin/kmod
or proc.exepath = /usr/sbin/xtables-nft-multi
or proc.exepath = /usr/bin/dbus-daemon
or proc.exepath = /usr/bin/udevadm
or proc.exepath = /usr/bin/umount
or proc.exepath = /opt/cni/bin/bridge
or proc.exepath = /opt/cni/bin/flannel
or proc.exepath = /opt/cni/bin/host-local
or proc.exepath = /opt/cni/bin/loopback
or proc.exepath = /usr/bin/cmp
or proc.exepath = /usr/bin/sar.sysstat
or (k8s.ns.name = kube-system and (
(k8s.pod.name startswith etcd- and proc.exepath = /usr/local/bin/etcd)
or (k8s.pod.name startswith kube-apiserver- and proc.exepath = /usr/local/bin/kube-apiserver)
or (k8s.pod.name startswith kube-proxy- and proc.exepath = /usr/local/bin/kube-proxy)
or (k8s.pod.name startswith kube-proxy- and proc.exepath = /usr/sbin/xtables-nft-multi)
or (k8s.pod.name startswith coredns- and proc.exepath = /coredns)
))
or (k8s.ns.name = falco and (
(k8s.pod.name startswith falco- and proc.exepath = /usr/bin/falco)
or (k8s.pod.name startswith falco- and proc.exepath = /usr/bin/falcoctl)
or (k8s.pod.name startswith falco-falcosidekick- and proc.exepath = /app/falcosidekick)
or (k8s.pod.name startswith falco-falcosidekick-ui- and proc.exepath = /app/falcosidekick-ui)
or (k8s.pod.name startswith falco-falcosidekick-ui-redis- and proc.exepath = /opt/redis-stack/bin/redis-server)
))
or (k8s.ns.name = kube-flannel and (
(k8s.pod.name startswith kube-flannel and proc.exepath = /opt/bin/flanneld)
or (k8s.pod.name startswith kube-flannel and proc.exepath = /sbin/xtables-nft-multi)
))
)
- macro: file_write
condition: (
(container.id = host and (
fd.name in (/dev/null)
or (proc.exepath = /usr/bin/dash and fd.name in (/run/motd.dynamic.new, /var/lib/apt/daily_lock))
or (proc.exepath = /usr/bin/bash and fd.name in (/dev/tty, /root/.bash_history))
or (proc.exepath = /usr/bin/bash and proc.name = sa2 and fd.name pmatch (/var/log/sysstat/))
or (proc.exepath = /usr/bin/bash and proc.name = sa2 and proc.pname = systemd and fd.name = /usr/lib/sysstat/sa2 and proc.cmdline = &quot;sa2 /usr/lib/sysstat/sa2 -A&quot;)
or (proc.exepath = /usr/sbin/sshd and fd.name in (/dev/null, /dev/ptmx, /dev/pts/0, /dev/tty, /proc/self/oom_score_adj, /var/log/lastlog, /var/log/wtmp, /var/run/utmp))
or (proc.exepath = /usr/bin/cp and proc.cmdline = &quot;cp -p /var/lib/aptitude/pkgstates aptitude.pkgstates&quot; and fd.name = &quot;/var/backups/aptitude.pkgstates&quot;)
or (proc.exepath = /usr/bin/gzip and proc.cmdline = &quot;gzip -f -9 .//aptitude.pkgstates.0&quot; and fd.name = &quot;/var/backups/aptitude.pkgstates.0.gz&quot;)
or (proc.cmdline = &quot;6 init&quot; and proc.name = 6 and proc.pname = runc and fd.name startswith /proc/self/oom_score_adj)
))
or (k8s.ns.name = falco and (
(k8s.pod.name startswith falco-falcosidekick-ui-redis- and proc.exepath = /opt/redis-stack/nodejs/bin/node and fd.name startswith /redisinsight/content/)
))
)
- macro: file_write_exempt
condition: (
file_write
or file_trusted_process
or user_apps_file_write
)
このマクロのポイントは次の通りです。
macro: file_trusted_processでは、信頼できるプロセスを定義しています。これらのプロセスによるファイル書き込みは問題ないと判断しました。
macro: file_writeでは、dash、bash、cp、gzipなど、有害無害の判断が難しい汎用的なユーティリティプログラムによるファイル書き込みを、コマンドラインの完全一致や、対象ファイル名のディレクトリ名の一致など、より厳しい条件で絞り込んでいます。
macro: file_write_exemptは、上記二つを組み合わせたものです。
汎用的なユーティリティプログラムによるファイル書き込みに関して、安全なものを識別するためにどのような条件が適切なのか、ホワイトリスト全体としての管理のし易さなどに関して、今後の改善が必要であると考えております。
まとめ
FalcoはLinux OSに特化したランタイムセキュリティツールで、 システム上で発生する異常なアクティビティや潜在的なセキュリティリスクをリアルタイムで検知し、警告します。 前回の記事では、Falcoプロジェクトで用意されているデフォルトルールセットだけでは、未知の脅威に対して必ずしも万全ではないということを指摘しました。 この課題に対処するため、本記事ではホワイトリスト型のカスタムルールを用いるアプローチを探求しました。
ホワイトリスト型カスタムルールの導入により、ネットワーク通信、プロセス生成、ファイル操作など、各種イベントに対して全インシデントを検知可能なルールセットを構築することができます。 Falcoの運用中に記録される大量のログデータを分析することで、これらのルールを継続的に調整し、検知の除外条件を追加していくことが可能です。
実際にやってみると、ネットワーク通信に関しては、比較的容易にルールファイルの作成が可能であることがわかりました。 一方で、プロセス生成やファイル操作に関するルール作成に関しては、ルールの精度を高め、誤検知を減らすためにルールの書き方の細部について改善検討を続けていく必要があることがわかりました。
Falcoのホワイトリスト型カスタムルールは、未知の脅威に対しても高いレベルの保護を提供する強力なツールです。継続的な監視、分析、およびルールの微調整を通じて、Falcoはクラウド上のWebアプリケーションのセキュリティ強化に重要な役割を果たし続けるでしょう。
]]></description>
<pubDate>Thu, 29 Feb 2024 17:16:00 +0900</pubDate>
<category>Kubernetes</category>
<category>セキュリティ</category>
<category>連載：Falco</category>
</item>
<item>
<title>FalcoでKubernetesのセキュリティモニタリング</title>
<link>https://www.klab.com/jp/blog/tech/2023/falcokuberenetes.html</link>
<description><![CDATA[はじめに
最近のWEBアプリケーションは、クラウド環境上にLinuxコンテナクラスタとしてデプロイすることが多くなってきました。 Linuxコンテナクラスタを管理するツールとして、Kubernetesが大変人気があります。 Kubernetesを使うと、設定ファイルの記述通りにコンテナクラスタが生成され、その状態が維持されるので、WEBアプリケーションの管理が容易になります。 その一方で、このような環境では数多くのコンテナが動的に生成、破棄されるので、セキュリティのモニタリングやインシデント検知が非常に難しくなってしまいます。
オープンソースのセキュリティ監視ツールであるFalcoは、Kubernetesとシームレスに統合できるため、クラウド上のWEBアプリケーションのセキュリティモニタリングに非常に適しています。 FalcoはLinuxカーネルのシステムコールを監視し、あらかじめ定義したルールに基づき、不正なアクティビティを検知します。 Falcoの監視と通知は、リアルタイムで行われるため、セキュリティインシデントに対する迅速な対応が可能となり、攻撃や侵入の検出に役立ちます。
今回、Falcoの仕組みやデプロイ方法、どのようなアクティビティが検出可能かなどについて調査を行いましたので、このブログで紹介したいと思います。
Falcoの概要
Falcoの仕組みと特徴
FalcoはLinux OS向けのランタイムセキュリティツールです。 システム上での異常なアクティビティや潜在的なセキュリティリスクをリアルタイムで検知し、警告するように設計されています。 その中核は、カーネル内でのシステムコール監視モジュールと、監視ルールに基づいて異常なイベントを検知するエージェント、さらに外部への通知を行うFalcosidekickエージェントからなっています。
以下がその仕組みと特徴です。
Falcoは、Linuxカーネルモジュールまたはebpfモジュールを用い、カーネル内でシステムコール監視します。
Falcoエージェントプログラムは、事前に定義された監視ルールに一致するアクティビティを検知します。
Falcosidekickエージェントは、事前に設定した方法（ログ出力、電子メール通知、Slack通知など）でリアルタイムに通知を行います。
Falcoの監視ルールは開発元が用意したものをそのまま利用しても良いですし、組織のセキュリティポリシーに合わせてカスタマイズすることも可能です。 最新のFalcoではシステムコールのモニタリング機能に加え、プラグインを介してより多くのデータソースからセキュリティイベントを取り込むことも可能です。
Falcoで検出できるもの
Falcoでは以下に示したようなイベントを検出できるので、セキュリティリスクの早期検知に役立ちます。
特権コンテナを利用したPrivilege escalation
setnsなどを使ったNamespaceからの脱出
/etc、/usr/bin、/usr/sbinなどへの読み書き監視
symlink、hardlink作成
ファイルオーナー、モードの変更
execveによるプロセス生成
shellやsshの実行
重要なファイルの置き換え
Falcoのデプロイ
デプロイされるもの
Falcoの主要コンポーネントは、以下の通りです。
Linuxカーネルモジュール又はebpfモジュール: Kubernetesの各ノード上でLinuxカーネルのシステムコールを監視します。
Falcoエージェント: Kubernetesの各ノード上で動作し、ルールにマッチしたイベントを検知します。
Falcosidekick : Falcoエージェントで検知したイベントを収集し、設定した方法（ログ収集基盤へ出力、電子メール通知、Slack通知など）で通知します。
Falcosidekick-ui: Falcoに付いてくるWeb UI。NodePortやIngress、Port Forward経由でアクセス可能です。
Kubernetes環境では、Falco podはdaemonsetとしてすべてのノード上にデプロイされます。 Falco podは、Linuxカーネルモジュール又はebpfのモジュールローダ、Falcoエージェント、監視ルールの自動アップデーターなどの複数コンテナで構成されます。 モジュールローダは、リポジトリからコンパイル済みのLinuxカーネルモジュール、ebpfモジュール等を自動的にダウンロードし、カーネルにロードします。 リポジトリに適切なバージョンのモジュールが存在しない場合には、コンテナ内でソースからモジュールをコンパイルしカーネルにロードします。
Linuxカーネルモジュール、ebpfモジュールどちらを使うのか
FalcoではLinuxカーネルモジュールまたはebpfモジュールをカーネルにロードし、システムコールの監視を行いますが、カーネルにモジュールをロードする行為自体がセキュリティリスクとみなされることもあるため、クラウド環境などではモジュールのロード自体が許されていない場合があります。 したがって現実的には、インフラ環境によって推奨されるモジュールを利用することになると思います。
Falcoのブログには、環境ごとの推奨モジュール、インストール方法がまとめられています。 本ブログの執筆時点では、AWS EKSではカーネルモジュールが推奨され、GKEではebpfモジュールが推奨されるようです。
Helm Chartによるデプロイ
Falcoプロジェクトでは、FalcoをKubernetes環境上にデプロイする方法として、kustomization.yamlによる方法とHelm Chartによる方法を用意しているようです。 本稿ではHelm Chartによるデプロイ方法について説明します。
HelmはKubernetes用のアプリケーションをパッケージ化し、簡単にデプロイおよび管理するためのツールです。次のような手順でHelmをセットアップし、falcoをデプロイすることができます。
Helmのインストール
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh 
Helm Chartリポジトリの追加
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
Falcoのデプロイ
helm install falco falcosecurity/falco -f myvalues.yaml --namespace falco --create-namespace
ここでのオプションの内容は以下の通りです。
--namespace falco : デプロイ先として falco ネームスペースを指定。
--create-namespace : 指定したネームスペースが存在しなければ作成する。
-f myvalues.yaml : Helm Chartのカスタマイズ内容を myvalues.yaml ファイルから読み込む指定です。
Helm Chartカスタマイズ
Helm Chartのデフォルト設定は、次のレポジトリの values.yaml に定義されています。このデフォルト設定をオーバーライドしたい場合に、myvalues.yamlを利用します。
https://github.com/falcosecurity/charts/blob/master/charts/falco/values.yaml
https://github.com/falcosecurity/charts/blob/master/charts/falcosidekick/values.yaml
myvalues.yamlの内容は、例えば以下のように記述します。
driver:
loader:
enabled: true
falcosidekick:
enabled: true
webui:
enabled: true
redis:
storageClass: "local-storage"
service:
type: "NodePort"
上記の設定では、次のようなカスタマイズを行っています。
FalcoのLinuxカーネルモジュールの自動ロード
Falcosidekick及びWeb UIの有効化
Web UIのredis用ストレージに"local-storage"を指定
Web UIのNodePortサービス有効化
動作確認
Falcoが正しくデプロイできたかどうかは、helm list コマンド、kubectl get pods コマンドなどで確認できます。
helm list コマンドでは、Chartのデプロイ状況が確認できます。
# helm list -n falco
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
falco   falco           1               2023-11-20 17:49:41.962917835 +0900 JST deployed        falco-3.7.1     0.36.0
kubectl get pods コマンドでは、Kubernetes上にデプロイされた各podの状態が確認できます。 次の例では、falco podがv131-v136の各ノードで一つずつデプロイされていること、falco-falcosidekick、falco-falcosidekick-ui podは全体二つずつ、falco-falcosidekick-ui-redis podは全体で一つだけデプロイされていること等が分かります。
# kubectl get pods -n falco -o wide
NAME                                      READY   STATUS    RESTARTS        AGE     IP             NODE   NOMINATED NODE   READINESS GATES
falco-4dfjc                               2/2     Running   0               9m46s   10.244.4.204   v135              
falco-659kn                               2/2     Running   0               9m46s   10.244.1.195   v132              
falco-7scxs                               2/2     Running   0               9m46s   10.244.5.206   v136              
falco-falcosidekick-749d77d5c7-bsp5f      1/1     Running   0               9m46s   10.244.5.204   v136              
falco-falcosidekick-749d77d5c7-lzdwd      1/1     Running   0               9m46s   10.244.3.252   v134              
falco-falcosidekick-ui-6885c6cffd-k4bt8   1/1     Running   2 (9m44s ago)   9m46s   10.244.5.205   v136              
falco-falcosidekick-ui-6885c6cffd-zhrbn   1/1     Running   2 (9m45s ago)   9m46s   10.244.4.203   v135              
falco-falcosidekick-ui-redis-0            1/1     Running   0               9m46s   10.244.3.253   v134              
falco-h9s99                               2/2     Running   0               9m46s   10.244.0.211   v131              
falco-n25zx                               2/2     Running   0               9m46s   10.244.2.194   v133              
falco-zshln                               2/2     Running   0               9m46s   10.244.3.254   v134              
Falco Web UI
Falcoには次の図のような簡易的なWeb UIが容易されています。
このページ右上の EXPORT ボタンを押すと、json形式のログファイルをダウンロードすることもでき、非常に便利です。
Web UIにはNodePort、Port Forward、ingressなどを通してアクセスすることができます。 ここでは、NodePortを通してのアクセスと、Port Forwardを利用する方法についてまとめます。
kubectl get svc でKubernetesのサービスの確認が可能です。 次の例では、falco-falcosidekick-uiにクラスターIP:10.109.212.176、Port:2802がアサインされ、さらにNodePort:30282で外部からアクセス可能であることが分かります。
# kubectl get svc -n falco
NAME                           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
falco-falcosidekick            ClusterIP   10.109.145.202           2801/TCP         2m17s
falco-falcosidekick-ui         NodePort    10.109.212.176           2802:30282/TCP   2m17s
falco-falcosidekick-ui-redis   ClusterIP   10.97.33.253             6379/TCP         2m17s
NodePort
WEBブラウザを開きKubernetesのNodeのひとつで30282番ポート(例えばhttp://10.0.0.131:30282)にアクセスすることで、Web UIを開くことが可能です。
NodeのIPアドレスは kubectl get nodes -o wide で確認可能です。
root@v130:~# kubectl get nodes -o wide
NAME   STATUS   ROLES           AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION    CONTAINER-RUNTIME
v131   Ready    control-plane   54d   v1.28.2   10.0.0.131            Debian GNU/Linux 12 (bookworm)   6.4.11-64kvmg01   containerd://1.7.6
v132   Ready    control-plane   54d   v1.28.2   10.0.0.132            Debian GNU/Linux 12 (bookworm)   6.4.11-64kvmg01   containerd://1.7.6
v133   Ready    control-plane   54d   v1.28.2   10.0.0.133            Debian GNU/Linux 12 (bookworm)   6.4.11-64kvmg01   containerd://1.7.6
v134   Ready              54d   v1.28.2   10.0.0.134            Debian GNU/Linux 12 (bookworm)   6.4.11-64kvmg01   containerd://1.7.6
v135   Ready              54d   v1.28.2   10.0.0.135            Debian GNU/Linux 12 (bookworm)   6.4.11-64kvmg01   containerd://1.7.6
v136   Ready              54d   v1.28.2   10.0.0.136            Debian GNU/Linux 12 (bookworm)   6.4.11-64kvmg01   containerd://1.7.6
Port Forward
まず、次のコマンドでPort Forwardをセットアップします。WEBブラウザを開き、kubectl port-forward を実行しているホストの1234番ポート(例えばhttp://127.0.0.1:1234)にアクセスすれば、Web UIを開くことが可能です。
kubectl port-forward svc/falco-falcosidekick-ui -n falco --address 0.0.0.0 1234:2802
Falcoのルールファイル
デフォルトルールセット
Falcoのリポジトリには、デフォルトのルールセットが用意されており、ユーザーはそれらのルールを必要に応じて有効化したり、修正したり、独自のルールを追加したりすることができます。 デフォルトルールセットを全く使わずに、独自のルールのみでFalcoを運用することも可能です。
このブログ記事の執筆時点で、Falcoプロジェクトでは88個のデフォルトルールセットが用意されており、重要度に応じて次の4つのファイルに分けられています。
falco_rules.yaml
falco-incubating_rules.yaml
falco-sandbox_rules.yaml
falco-deprecated_rules.yaml
Helmのコマンドラインで特に何も指定しない場合は、falco_rules.yaml のみがロードされます。 falco_rules.yaml には次の25個のルールが定義されています。
Directory traversal monitored file read
Read sensitive file trusted after startup
Read sensitive file untrusted
Run shell untrusted
System user interactive
Terminal shell in container
Contact K8S API Server From Container
Netcat Remote Code Execution in Container
Search Private Keys or Passwords
Clear Log Activities
Remove Bulk Data from Disk
Create Symlink Over Sensitive Files
Create Hardlink Over Sensitive Files
Packet socket created in container
Redirect STDOUT/STDIN to Network Connection in Container
Linux Kernel Module Injection Detected
Debugfs Launched in Privileged Container
Detect release_agent File Container Escapes
PTRACE attached to process
PTRACE anti-debug attempt
Find AWS Credentials
Execution from /dev/shm
Drop and execute new binary in container
Disallowed SSH Connection Non Standard Port
Fileless execution via memfd_create
Falcoの公式サイトには、各ファイルのルールの内容、デフォルトで有効かどうかなどについて、わかりやすくまとめられたページが用意されています。
falco_rules.yaml の他に、falco-incubating_rules.yaml falco-sandbox_rules.yaml をロードしたい場合には、helmコマンド実行時に明示的に指定する必要があります。
helm install falco falcosecurity/falco \
--set "falcoctl.config.artifact.install.refs={falco-rules:2,falco-incubating-rules:2,falco-sandbox-rules:2}" \
--set "falcoctl.config.artifact.follow.refs={falco-rules:2,falco-incubating-rules:2,falco-sandbox-rules:2}" \
--set "falco.rules_file={/etc/falco/k8s_audit_rules.yaml,/etc/falco/rules.d,/etc/falco/falco_rules.yaml,/etc/falco/falco-incubating_rules.yaml,/etc/falco/falco-sandbox_rules.yaml}"
あるいは、上記のようにコマンドラインに引数として指定する代わりに、myvalues.yamlで次のような設定を行うと、helmコマンドのオプションを簡略化することができます。
falcoctl:
config:
artifact:
install:
refs:
- falco-rules:2
- falco-incubating-rules:2
- falco-sandbox-rules:2
follow:
refs:
- falco-rules:2
- falco-incubating-rules:2
- falco-sandbox-rules:2
falco:
rules_file:
- /etc/falco/k8s_audit_rules.yaml
- /etc/falco/rules.d
- /etc/falco/falco_rules.yaml
- /etc/falco/falco-incubating_rules.yaml
- /etc/falco/falco-sandbox_rules.yaml
その場合、helmのコマンドラインは次のようになります。
helm install falco falcosecurity/falco -f myvalues.yaml --namespace falco --create-namespace
Falcoプロジェクトで用意されているデフォルトルールセットには、すべてMITRE ATT&amp;CK のタグ付けがされていて、既知の攻撃パターンを幅広く網羅していると言えます。しかしながらその逆に、未知の攻撃パターンに対しては必ずしも万全とは言えないかもしれません。
未知の攻撃パターンを検知するには、ホワイトリスト形式のカスタムルールを作成すると良いかもしれません。 現在、ホワイトリスト形式のカスタムルールの検討も行っていますが、それについては別の機会にまとめたいと思います。
Falcoルールの例
Falcoルールファイルは、List、Macro、Ruleの三種類の要素からなっています。
List: ルールやマクロ、その他のリストに含めることができるアイテムのコレクション。
Macro: ルールや他のマクロの中で再利用できるルール条件のスニペット。
Rule： アラートを発生させる条件とアラートの出力文字列の定義。
以下は、Disallowed SSH Connection Non Standard Port というルールの例です。
"macro: outbound": TCP、UDPのアウトバウンド通信にマッチするマクロです。
"list: ssh_non_standard_ports": sshの標準ポートが塞がれている場合に、抜け道としてよく使われるポート番号のリスト。
"macro: ssh_non_standard_ports_network": sshの抜け道ポート番号リストへのマッチを判定するマクロです。
これらのマクロを利用して、"rule: Disallowed SSH Connection Non Standard Port"のconditionが書かれています。
- macro: outbound
condition: >
(((evt.type = connect and evt.dir== 0 or evt.res = EINPROGRESS))
- list: ssh_non_standard_ports
items: [80, 8080, 88, 443, 8443, 53, 4444]
- macro: ssh_non_standard_ports_network
condition: (fd.sport in (ssh_non_standard_ports))
- rule: Disallowed SSH Connection Non Standard Port
desc: > 
Detect any new outbound SSH connection from the host or container using a non-standard port. This rule holds the potential 
to detect a family of reverse shells that cause the victim machine to connect back out over SSH, with STDIN piped from 
the SSH connection to a shell's STDIN, and STDOUT of the shell piped back over SSH. Such an attack can be launched against 
any app that is vulnerable to command injection. The upstream rule only covers a limited selection of non-standard ports. 
We suggest adding more ports, potentially incorporating ranges based on your environment's knowledge and custom SSH port 
configurations. This rule can complement the "Redirect STDOUT/STDIN to Network Connection in Container" or 
"Disallowed SSH Connection" rule.
condition: > 
outbound 
and proc.exe endswith ssh 
and fd.l4proto=tcp 
and ssh_non_standard_ports_network
output: >-
Disallowed SSH Connection (connection=%fd.name lport=%fd.lport rport=%fd.rport 
fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid 
user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname 
command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
priority: NOTICE
tags: [maturity_stable, host, container, network, process, mitre_execution, T1059]
Falcoのデフォルトルールの自動アップデート
Falcoをhelmでデプロイした場合には、デフォルトのルールセットは定期的にアップデートされます。 定期アップデートはFalco pod内の falcoctl-artifact-follow コンテナにより行われます。
If you install the Helm chart, at least version 3.0.0 with:
helm install falco
Falco, by default, will load the latest rules file that is compatible with your Falco version and 
keep it up to date automatically via falcoctl. These are published on GitHub Packages.
- https://falco.org/docs/rules/default-custom/#rules-installed-via-the-helm-chart
Falcoのインシデント検知の例
シンプルなnginx podを起動し、次の３つの操作を実行し、falcoで検知可能かどうか確認しました。
kubectl execコマンドでコンテナに接続し、bashシェルを実行します。
コンテナ内でviをインストールし、実行します。
コンテナ内から外部サーバの443ポートにssh接続します。
Falcoでの検知結果はWeb UIで確認し、そこからダウンロードしたjsonログファイルの該当部分を記載しました。
nginx podの起動
kubectl apply -f simple-pod.yaml
simple-pod.yamlの内容
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
nginxコンテナにアタッチ
実行コマンド
# kubectl exec -it nginx -- /bin/bash 
root@nginx:/# 
検出されるログ
{
"uuid": "4b1a818b-7cd0-4985-ba95-a6f2fa897f4e",
"output": "09:10:51.667430058: Notice A shell was spawned in a container with an attached terminal ...",
"priority": "Notice",
"rule": "Terminal shell in container",
"time": "2023-11-27T09:10:51.667430058Z",
"source": "syscall",
"output_fields": {
"container.id": "e6f8a1e1dd97",
"container.image.repository": "docker.io/library/nginx",
"container.image.tag": "latest",
"container.name": "nginx",
"evt.arg.flags": "EXE_WRITABLE",
"evt.time": 1701076251667430100,
"evt.type": "execve",
"k8s.ns.name": "default",
"k8s.pod.name": "nginx",
"proc.cmdline": "bash",
"proc.exepath": "/usr/bin/bash",
"proc.name": "bash",
"proc.pname": "runc",
"proc.tty": 34817,
"user.loginuid": -1,
"user.name": "root",
"user.uid": 0
},
"hostname": "v136",
"tags": [
"T1059",
"container",
"maturity_stable",
"mitre_execution",
"shell"
]
}
"Terminal shell in container"ルールにマッチしてインシデントが検知されていることが分かります。 このルールは、コンテナ内でシェルプロセスが実行されたことを検知します。
viでファイルを編集
実行コマンド
apt install vim
vi test
検出されるログ
{
"uuid": "4485356c-4899-4b52-acc7-75308454a04c",
"output": "09:14:04.692611115: Critical Executing binary not part of base image ... ",
"priority": "Critical",
"rule": "Drop and execute new binary in container",
"time": "2023-11-27T09:14:04.692611115Z",
"source": "syscall",
"output_fields": {
"container.id": "e6f8a1e1dd97",
"container.image.repository": "docker.io/library/nginx",
"container.image.tag": "latest",
"container.name": "nginx",
"container.start_ts": 1701069045261889000,
"evt.arg.flags": "EXE_WRITABLE|EXE_UPPER_LAYER",
"evt.time": 1701076444692611000,
"evt.type": "execve",
"k8s.ns.name": "default",
"k8s.pod.name": "nginx",
"proc.aname[2]": "containerd-shim",
"proc.cmdline": "vi test",
"proc.cwd": "/",
"proc.exe": "vi",
"proc.exe_ino.ctime": 1701076429805272800,
"proc.exe_ino.ctime_duration_proc_start": 14886864198,
"proc.exe_ino.mtime": 1683195884000000000,
"proc.exepath": "/usr/bin/vim.basic",
"proc.name": "vi",
"proc.pname": "bash",
"proc.sname": "bash",
"proc.tty": 34816,
"user.loginuid": -1,
"user.name": "root",
"user.uid": 0
},
"hostname": "v136",
"tags": [
"PCI_DSS_11.5.1",
"TA0003",
"container",
"maturity_stable",
"mitre_persistence",
"process"
]
}
"Drop and execute new binary in container"ルールにマッチしてインシデントが検知されていることが分かります。 このルールはoverlayfsの最上位層に新規に作成されたファイルの実行を検知します。 なぜなら最上位層のファイルはもともとコンテナのベースイメージに存在していたものではなく、あとから侵入者が作成したものである可能性を排除できないからです。 このルールにより、侵入者がクラッキングツールをダウンロードし実行した場合などに、それを逃さずに検知することができます。
443番ポートへのssh接続
実行コマンド
root@nginx:/# ssh example.com -p 443
kex_exchange_identification: read: Connection reset by peer
Connection reset by 93.184.216.34 port 443
検出されるログ
{
"uuid": "303636ae-93cd-4474-b796-3d87aa28c089",
"output": "03:29:15.493403233: Notice Disallowed SSH Connection ... ", 
"priority": "Notice",
"rule": "Disallowed SSH Connection Non Standard Port",
"time": "2023-11-28T03:29:15.493403233Z",
"source": "syscall",
"output_fields": {
"container.id": "e6f8a1e1dd97",
"container.image.repository": "docker.io/library/nginx",
"container.image.tag": "latest",
"container.name": "nginx",
"evt.arg.flags": null,
"evt.time": 1701142155493403100,
"evt.type": "connect",
"fd.lport": 36820,
"fd.name": "10.244.5.218:36820->93.184.216.34:443",
"fd.rport": 443,
"fd.type": "ipv4",
"k8s.ns.name": "default",
"k8s.pod.name": "nginx",
"proc.cmdline": "ssh example.com -p 443",
"proc.exepath": "/usr/bin/ssh",
"proc.name": "ssh",
"proc.pname": "bash",
"proc.tty": 34816,
"user.loginuid": -1,
"user.name": "root",
"user.uid": 0
},
"hostname": "v136",
"tags": [
"T1059",
"container",
"host",
"maturity_stable",
"mitre_execution",
"network",
"process"
]
}
"Disallowed SSH Connection Non Standard Port"ルールにマッチしてインシデントが検知されていることが分かります。 このルールでは、ポート番号"80, 8080, 88, 443, 8443, 53, 4444"へのSSH接続を検知します。 これらのポートはHTTPやHTTPS、DNSなどで使われるポートなので経路上のファイアーウォールなどで塞がれることが少なく、22番ポートでの外部通信が禁止されている場合などに、SSHの代替ポートとして利用することが可能だからです。
デフォルトルールセットの問題点
Falcoのデフォルトルールセットは、既知の攻撃パターンを幅広く網羅していて非常に強力です。 しかしながら、未知の攻撃パターンに対しては必ずしも万全とは言えないかもしれません。
例えば、Falcoのインシデント検知の例で示したケースのうち次の二つについても、抜け穴が考えられます。
viでファイルを編集
443番ポートへのssh接続
viでファイルを編集
この例では、overlayfsの最上位層に新規に作成されたファイルの実行を検知しました。 しかし、コンテナにはtmpfsがマウントされていることも多く、そこに置かれたファイルの実行は検知しません。 この例のnginxコンテナの場合、/devにtmpfsがマウントされていました。 そこで、viを/devにコピーし/dev/viを実行してみましたが、Falcoで検知することはできませんでした。
root@nginx:/# cp /usr/bin/vi /dev/
root@nginx:/# /dev/vi test
443番ポートへのssh接続
この例では、ポート番号"80, 8080, 88, 443, 8443, 53, 4444"へのSSH接続を検知していました。 この場合ポートを限定しているため、その他の任意のポート番号で外部接続が可能であった場合に、それを利用したSSH接続を検知することができません。
この様に、Falcoのデフォルトルールセットで検知できないエッジケースは他に数多く存在すると予想されます。 未知の攻撃パターンを検知するには、ホワイトリスト形式のカスタムルールを作成すると良いかもしれません。 その試みについては別の機会にまとめたいと思います。
まとめ
Falcoの概要、デプロイ方法、インシデント検出の例などについてまとめました。 Falcoは、Kubernetes上ではHelm Chart等により簡単にデプロイ可能です。 また、Falcoのレポジトリには、デフォルトのルールセットが用意されています。 ユーザーはこれをそのまま利用したり、各ルールを状況に応じて有効・無効を切り替えて使うことができます。 Falcoのデフォルトルールセットは強力ではありますが、デフォルトルールセットの問題点に記載しているような未知のセキュリティリスクを検知できない場合があります。 次回以降の記事でホワイトリスト形式のカスタムルールの書き方、適用方法などについてまとめたいと思います。
]]></description>
<pubDate>Thu, 28 Dec 2023 11:50:00 +0900</pubDate>
<category>Kubernetes</category>
<category>セキュリティ</category>
<category>連載：Falco</category>
</item>
</channel>
</rss>
