Slide 1

Slide 1 text

WireGuardとOpenID Connectの連携を Goで実装してみた 株式会社サイバーエージェント AI事業本部 黒崎 優太 (@kuro_m )

Slide 2

Slide 2 text

黒崎 優太 • 株式会社サイバーエージェント AI事業本部 アプリ運⽤センター • ⼩売業界 x DXの事業をやっています • バックエンドエンジニア 直近はAWSとかGCPとかセキュリティまわりの 仕事をしていました @kuro_m @kurochan #times_kurochan

Slide 3

Slide 3 text

VPNを作ってみました

Slide 4

Slide 4 text

VPNサーバが欲しくなった経緯 • AI事業本部内のDX本部に異動しました • 詳しくはこれを⾒てください • https://speakerdeck.com/kurochan/retail-dx-project

Slide 5

Slide 5 text

聞こえてくる会話 • 🧑💻「xxxのシステムにアクセスするために出社しないといけないんですよね…」

Slide 6

Slide 6 text

聞こえてくる会話 • 🧑💻「xxxのシステムにアクセスするために出社しないといけないんですよね…」 • 👩💻「固定IPじゃないといけないらしくて、⾃宅のIPはすぐ変わっちゃうし…」

Slide 7

Slide 7 text

聞こえてくる会話 • 🧑💻「xxxのシステムにアクセスするために出社しないといけないんですよね…」 • 👩💻「固定IPじゃないといけないらしくて、⾃宅のIPはすぐ変わっちゃうし…」 • 🧑💻「xxxのスマホアプリの検証にもIPアドレス制限が…」

Slide 8

Slide 8 text

VPNサーバの需要があるらしい • 様々な企業やシステムと連携しつつ開発する業態 • 何かしらの認証/暗号化 + IPアドレス制限という仕組みはよく出てくる • 個⼈的にはIPアドレス制限に頼りすぎずゼロトラストな環境は作っていきたい

Slide 9

Slide 9 text

VPNサーバを作ってみる • VPNサーバの実現⽅法は⾊々ありそう • OSSもあるし、商⽤VPNもありそう • アカウントの棚卸し業務をやりたくない • サイバーエージェントには内製の認証基盤がある • OpenID Connectもあるよ • アプリ運⽤センターに異動してきてGo⾔語を書く必要が • 直近広告事業で6年半くらいScalaを書いていた • Go⾔語よく知らない… • Go⾔語の勉強がてら作ってみる

Slide 10

Slide 10 text

作ったものの概要

Slide 11

Slide 11 text

WireGuard + OpenID Connect • 簡単に構築ができて、社内のID基盤とも連携できるのを⽬指す • 固定IP + 通信の暗号化のためにWireGuard VPN • 社内のID基盤を使った認証をするためにOpenID Connect • https://github.com/kurochan/oidc-wireguard-vpn/

Slide 12

Slide 12 text

WireGuard • [CB ] WireGuard:次世代耐乱⽤性カーネルネットワークトンネル by Jason Donenfeld • https://www.slideshare.net/codeblue_jp/cb -donenfeld-ja

Slide 13

Slide 13 text

WireGuard • https://www.slideshare.net/codeblue_jp/cb -donenfeld-ja

Slide 14

Slide 14 text

WireGuard • Linux, Windows, iOS, Androidで動くOSSのVPN • 最近のLinuxだとカーネルに組み込まれています • 構築, 設定も簡単 • 単体で使うのももちろんおすすめ

Slide 15

Slide 15 text

OpenID Connect • OAuth . (認可) + 認証のしくみ • WEBサイトの間でのIDを連携するのに特化 • シングルサインオンが実現できます

Slide 16

Slide 16 text

OpenID Connect CIBA Flow • OpenID Connectは「Webサイト」に特化している • WireGuardのように、ブラウザアプリケーションではないアプリも認証したい • CIBA = Client Initiated Backchannel Authentication • クライアント側から認証を開始して、裏側(何かしらの⽅法)で認証/認可をする • VPN接続しようとしたらSlack経由で認証/認可のリクエストが⾶んでくるなど

Slide 17

Slide 17 text

WireGuardに追加の認証を挟む • WireGuardは⾮常にシンプルなVPNなので、 処理をフックするような仕組みはありません!💥 • WireGuardで認証したあと、VPNの接続は確⽴したが、通信はブロックすると いう状態を作る • OpenID Connectで認証認可が成功したら通信を通す 認証認可前

Slide 18

Slide 18 text

WireGuardに追加の認証を挟む • WireGuardは⾮常にシンプルなVPNなので、 処理をフックするような仕組みはありません!💥 • WireGuardで認証したあと、VPNの接続は確⽴したが、通信はブロックすると いう状態を作る • OpenID Connectで認証認可が成功したら通信を通す 認証認可後

Slide 19

Slide 19 text

nftables • Linuxのネットワークファイアウォールであるnetfliterを管理する • iptablesを置き換えるフレームワーク • iptablesも裏側でnetfliterを使っている場合も

Slide 20

Slide 20 text

WireGuard + OpenID Connect + nftables • なんかいけそう! • WireGuardのVPNが通ったとしても、退職や部署異動するとOpenID Connect で認可されなくなる • WireGuardのサーバ側の設定は定期棚卸しくらいでよくなる

Slide 21

Slide 21 text

使い⽅(ユーザ向け) • クライアントの設定する • PCもスマホもだいたい⼀緒

Slide 22

Slide 22 text

使い⽅(ユーザ向け) • VPN接続する

Slide 23

Slide 23 text

使い⽅(ユーザ向け) • Slackに通知がくるので認可する

Slide 24

Slide 24 text

VPN経由で通信ができる

Slide 25

Slide 25 text

実装の紹介

Slide 26

Slide 26 text

netlink • github.com/vishvananda/netlink • Linuxのネットワークインターフェイスを作ったり設定をいじる仕組み

Slide 27

Slide 27 text

WireGuard • github.com/WireGuard/wgctrl-go • WireGuardのインターフェイスの詳細設定をする • 秘密鍵やVPNクライアントの公開鍵のペアなど

Slide 28

Slide 28 text

WireGuardで新規接続を検知する • 最後にセッション(鍵交換など)を更新した時間がわかるので、その時刻の⽐較 をすると新規接続を検知できそう

Slide 29

Slide 29 text

追加認証をしていない⼈の通信をブロックする • github.com/google/nftables • nftablesでフィルタルールを動的に制御する

Slide 30

Slide 30 text

nftables • ルールの追加の例

Slide 31

Slide 31 text

nftables • ルールの追加の例

Slide 32

Slide 32 text

OpenID Connect CIBA Flow • github.com/okzk/go-ciba • OIDC CIBA Flowを簡単に実現できる • 社内IdPとここで連携しています

Slide 33

Slide 33 text

OpenID Connect CIBA Flow • github.com/okzk/go-ciba • OIDC CIBA Flowを簡単に実現できる • 社内IdPとここで連携しています

Slide 34

Slide 34 text

追加認証をしていない⼈の通信を許可する • nftablesのセットを操作する

Slide 35

Slide 35 text

追加認証をしていない⼈の通信を許可する • nftablesのセットを操作する

Slide 36

Slide 36 text

追加認証をしていない⼈の通信を許可する • nftablesのセットを操作する

Slide 37

Slide 37 text

gracefulなシャットダウン • プロセスを停⽌させた時に余計なネットワークの設定などが残っていてほしく ない • プロセス停⽌のシグナルをフックする • シグナルもチャネルとして扱える • シグナルを何かしら受け取るまで無限にブロックさせておいて、 シグナルを受け取ったらシャットダウン処理をする

Slide 38

Slide 38 text

作ってみた感想 • 便利そうな気がするので育てていきたい • yamlファイルで設定しないでDBを使うとweb UIとかから設定投⼊ができそう • Linuxと連携させる部分はScalaよりだいぶ書きやすかった • テストの書き⽅や⾒通しのいい設計はプロダクト開発をやりつつ 勉強していきたい

Slide 39

Slide 39 text

No content