社内プライベートポッドキャスト実現方法
所属している、ヘンリー社には、社内ラジオコンテンツがあり、Notion上に音声ファイルを置く形で実現されている。これを、ポッドキャスト化してポッドキャストクライアントで聞きたいというのが動機。ちゃんとしたオープンな規格としてのポッドキャストにしたい。
もちろん、公開はせずプライベートなものにしたい。ただ、ポッドキャストはオープンコンテンツ前提の規格になっているため完全な実現は難しい。認証のかかっていないRSSフィード及び、そのRSSフィードに埋め込まれたMP3等の音声ファイルにも認証がかかっていないことが前提となるからだ。
やるからには、あまりコストを掛けずに静的配信をベースにしたい。お手軽なプライベートポッドキャストサービスもあまりないようだ。
基本方針
それに対する現実的な妥当解を考え、その実現のために、まずポッドキャストサイトを生成するpodbardというOSSを作った。そして、それを使って、簡単にプライベートポッドキャストを開始できる、podbard-private-podcast-starterというテンプレートリポジトリも公開した。これは、コンテンツをCloudflare Pagesに、音声ファイルをR2にdeployする仕組みになっている。外部サービスを使わず、自前でポッドキャストサイトを生成するものだ。
podbardやこのCloudflareを利用したこのテンプレートに関して別途解説するが、ここでは、実験結果も踏まえ、プライベートポッドキャストの実現方法を解説する。完全にプライベートにするのは難しいが、多重に防御することで実現しようとしている。具体的には以下。ちなみに、上記のテンプレートはこれら対策がすべて盛り込まれている。
- サイトコンテンツ (ポッドキャストサイト及びRSSフィード)
- 推測しづらいURLにする
- Basic認証をかける
- robots.txtやHTTPヘッダ、メタタグで不要なクローリングやインデックス登録を防ぐ
- HTTPヘッダやメタタグでリファラを送らないように
- 音声ファイル
- 推測しづらいURLにする
- robots.txtは置く
- 認証はかけずURL直打ちでアクセスできてしまうことは許容する
これで、よっぽどの機密情報が話されているとかではなければ、実用上は十分プライベートと言えるのではないだろうか。代表的な動画配信サイトのプライベート動画であっても、実は生の動画URLを入手できればダウンロード可能だったりする。ちなみに、GitHubのアップロード画像は、ちゃんと認証がかかるようになりましたね。
Spotifyにもプライベートポッドキャストの機能があるようだが、「プライベートRSSフィード」という言葉があるので、概ね似たような仕組みになっているのではないかと思う。Basic認証は使ってない気はするが。
さて、防御方法についてそれぞれ解説していく。
推測しづらいURLにする
例えば、以下のような具合。
- サイトURL:
https://mypodcast.example.com/{random-path}/
- RSSフィード:
https://mypodcast.example.com/{random-path}/feed.xml
FQDN(ホスト名)は平文DNSから漏れる可能性があるが、パスをランダム文字列にすればhttpsであればテクニカルにはURLが判明する可能性は低い。
Basic認証をかける
冒頭に「認証はかけられない」と書いたが、HTTPに備わっているステートレスな認証方式であるBasic認証はかけられる。これによって、URLが漏洩しても直ちに影響はないし、ユーザー毎に異なるパスワードも設定できるので退職時等の失効も可能。
ちなみに、Basic認証は以下のように認証情報をURLに含められる。この文字列が漏洩してしまうと、クリック一発でコンテンツにアクセスできてしまうので注意。
https://username:p4ssw0rd@mypodcast.example.com/{random-path}/feed.xml
この完全なフィードURLをポッドキャストアプリに登録してやれば、ポッドキャストの購読ができる。もしくは、認証情報を含まないURLであっても、認証情報を聞かれるダイアログが開いたのでそれに入力すれば購読できる。iPhoneのポッドキャストアプリや、私が使っているOvercast では、いずれの方法でも購読が確認できた。
クローラーを避ける
検索エンジンのクローラーを避け、余計なインデックス登録をブロックする。robots.txt
を配置する。HTMLにはmetaタグを記述すればよいが、HTML以外のコンテンツのインデックス登録を防ぐために、HTTPヘッダも付与できると良い。
robots.txt
User-Agent: *
Disallow: /
- メタタグ:
<meta name="robots" content="noindex, nofollow" />
- HTTPヘッダ:
X-Robots-Tag: noindex, nofollow
参考:
リファラでのURL漏洩を防ぐ
Show Note上のリンクなど、外部サイト遷移時のリファラによるURL漏洩は避けたい。とは言え、現代のブラウザのリファラポリシーは基本的にはstrict-origin-when-cross-origin
になっており、外部遷移時の漏洩は実はそこまで気にする必要はない。URLのパスは漏洩せず、FQDNが渡るだけである。平文DNSがまだ多い現時点では、FQDNは漏れうるものだという前提に立った方が良い。
とは言え、要らぬ情報が外部に渡ることは避けたいだろうので、その場合はクローラー避け同様に、メタタグ及び可能ならHTTPヘッダにリファラポリシーを設定すると良い。
- メタタグ:
<meta name="referrer" content="same-origin">
- HTTPヘッダ:
Referrer-Policy: same-origin
ポリシーはno-referrer
でもよいが、同一オリジン内であれば、リファラがわたっても問題ないし、寧ろ遷移元情報が分かったほうが良いという話もあるので、same-origin
が良いのではないでしょうか。
参考:
音声ファイルに認証をかけないことについて
そもそも、サイトコンテンツは静的に書き出してBasic認証をかぶせる、音声は何らかのオブジェクトストレージにアップロードする、というのがお手軽なのでそうしたかった。
音声ファイルにもBasic認証をかけ、RSS内の音声ファイルのURLを https://username:p4ssw0rd@audiobucket.mypodcast.example.com/{random-path}/foo.mp3
のように、認証情報を含めた記述にするというのも機能するのかも知れないが(未検証)、その場合、RSSフィードをユーザーごとに動的配信したり、全ユーザー分書き出すなどの対応が必要になるので、やらないことにした。
何にせよ、せいぜいBasic認証しかかけられないし、それでも結局、完全なURL文字列が漏れたら、一発でアクセス可能なので、あまりリスク軽減になっていないというのもある。なので、オブジェクトストレージのバケットのルートにrobots.txt
を置いておくくらいの対策に留めた。
まとめ
ということで、プライベートポッドキャスト実現方法について書いてみた。ご意見あればフィードバックいただけると嬉しいです。
また、podbard及び、podbard-private-podcast-starterは一応使い始められるようになっている。テンプレートリポジトリについては、そこから新たにリポジトリを作れば、すぐにこのページで解説した方法でのプライベートポッドキャストが実現できるようになっている。
使い方などは追って解説エントリを書きますが、是非試してみてほしいし、わからないことがあれば聞いてくれればできる限り回答したいので、ぜひお試しください。