WebSocketでリアルタイム通信
stmkza (ストーム)
WebSocketとは?
• サーバからデータを送る方法
• ブラウザプラグインがいらない
• 軽い
• HTTP使えるならポート解放などは不要
• サーバもファイアウォールの設定不要
通信の中身
• HTTPで接続する
• Upgrade: WebSocket と Connection: upgrade でプロトコル切り替え
• 使うポートは80番ポート(SSLだと443)と、変わらない
• ↑にあるようにSSL使えます
• 実際の通信を見せようと思ったけれど、うまくできませんでした。。。
今から話すこと
• C++でサーバを実装してみる には時間が足りませんでした。。。。
• 時間がなくなったのは、今週ずっと夜はプライムビデオでアニメ観てたか
らです。。。すみません m(_ _)m
• さっきのような感じで宣伝?を続ける のもネタが尽きる。。。
• 実際に使う方法を説明することにします。Socket.io使います。
• バーチャル学生LT用に作ったチャットで使っているサーバを紹介します
普通のページに使ってるもの
Socket.ioで一番基本的な構成
Socket.io
Socket.ioで一番基本的な構成
Socket.io
問題点
そのままだと同一生成元ポリシーに引っかかる
サーバの生IPを知らせる必要がある
ファイアウォールに引っかかることがある
SSL対応するにはnodeでHTTPサーバ建てる必要ある
こうすれば解決する
Socket.io
ただし、このままだと
うまく動かないので、
nginxの設定を変える
nginxの設定
• Socket.ioが使うのは /socket.io/
• HTTPバージョンを1.1に限定する
• Upgradeヘッダを通す
• Connectionヘッダに "upgrade"を設定する
upstream socketio {
server 127.0.0.1:8080;
}
server {
server_name example.com;
root /path/to/webroot;
listen 80;
index index.php;
location ^~ /socket.io/ {
proxy_pass http://socketio;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
サンプルはGistにも書きました
ln.stmkza.net/socketio
CloudFlareの対応について
• 実は結構前(2014年くらい)からWebSocketに対応していたらしいです
• Networkから設定できる(デフォルトでON?)
サンプルはGistにも書きました
ln.stmkza.net/socketio
ご静聴ありがとうございました
サンプルはGistにも書きました
ln.stmkza.net/socketio
おまけ
• GDPR関係の事情でEUからのアクセスを拒否したいときにもCloudFlareが
便利です
• Network > IP Geolocation をONにするだけで HTTPヘッダに国コードが入
ってきます。
• これを使ってnginxでアクセス拒否するようにしました
設定内容
http {
map $http_cf_ipcountry $is_eu_access {
default no;
AT yes;
BE yes;
BG yes;
HR yes;
CY yes;
CZ yes;
DK yes;
EE yes;
FI yes;
FR yes;
DE yes;
GR yes;
HU yes;
IE yes;
IT yes;
LV yes;
LT yes;
LU yes;
MT yes;
NL yes;
PL yes;
PT yes;
RO yes;
SK yes;
SI yes;
ES yes;
SE yes;
}
}
server {
# 略
if($is_eu_access = yes) {
return 403;
}
}
ln.stmkza.net/cfeu
とても長いので、Gistをご覧ください
↓にURLが書いてあります

WebSocketでリアルタイム通信 (第13回学生LT資料)

Editor's Notes

  • #2 みなさん初めまして、stmkza(ストーム)です。この前の多数決?で読み方が決まったので、アイコンを"あれ"っぽくしてみました(笑) LTとかの発表をするのは初めてなんですけども、いろいろ軽く今から発表させていただきます。 よろしくお願いします。 まず、今回発表する内容なんですけれども、バーチャル学生LTの視聴ページでは実はリアルタイム通信を使ってチャットとかプレイヤー操作とかをリモートでできるようにしてあるんですけど、その時にWebSocketを使ってみたんです。 その時に色々わかったこと とかをここで話させていただければなと思います。
  • #3 じゃあ、まずWebSocketの特徴をざっくりと説明させていただきます。 まず、WebSocketを一言で説明すると、「サーバからデータを送る方法」です。 今まではそういうリアルタイム通信がしたかったら、ネイティブアプリ作ったりFlashとかJavaApplet使っていましたが、WebSocketはJavaScriptから直接使えるので、プラグインがいらないんです。だから、スマホとかにも対応できます。 また、サーバもクライアントも軽いんです。今まで無理やりJavaScriptで実装するとなると、1秒ごとにサーバにリクエストを送ったり、Commet使って実装していたんですが、通信量的にも、最大コネクション数とか負荷的にも全くよろしくなかったんですが、WebSocketは専用のプロトコル作っちゃったので、負荷的がかなり小さいです。 また、ブラウザがする普通の通信と同じHTTPを使っているので、普通のページが開けるのであればWebSocketも使えます。ただ、プロクシとかが対応してないこともあるので、それだけは注意です。 サーバ側も新しくポートを開ける必要はないです。Webサーバの設定をいろいろ弄るだけですぐ使えるようにできます。
  • #4 具体的な通信について軽く説明しようと思うのですが、通信の手順としては、 ・まず、HTTPで普通に接続して、 ・HTTPステータスコードの101番、Switching Protocolsと、Upgradeヘッダを使ってWebSocketプロトコルに切り替えます。 ・この時でもあくまでHTTPの中でプロトコル変えているので、HTTP1.0とHTTP1.1を切り替えているのと大して違いはありません。だから使うポートは変わりません。これがさっき「ポート開放がいらない」って言った理由です。 ・また、SSLはHTTPよりも下のレイヤーで動いているので、WebSocketだからSSLが使えないってことはありません。 ・本当はここで実際の通信を見せたかったのですが、Wiresharkがちゃんと働いてくれなかったので見せることができません、すみませんでした。。。
  • #5 それでは今から話すことについてですが、いろいろ考えましたが、 ・C++で実際にサーバを作ろうかと思っていましたが、時間がいつの間にか無くなってて諦めました。。。 ・今週、ずっとプライムビデオでアニメ見てたからです。あれ、結構危険ですよ。やめられなくなる ・だからと言って、さっきみたいなWebSocketの宣伝?を続けるほど詳しいわけではないから、 ・実際に使う方法を説明します。Socket.io使うといい感じにできそうだったので、今回はsocket.ioを使います ・ちなみにこれはバーチャル学生LTのチャットとかで使った技術なので、何か脆弱性見つけるヒントになるかもしれません。正直怖いです。。。。
  • #6 普通のPHPで作ったページはこんな感じになってます。 php-fpmで動かしたのをnginxを通して、それをさらにCloudFlareでリバースプロキシします。
  • #7 そして、Socket.io使うときの一番基本的な構成は、node.jsでサーバ建てて、それに直接アクセスするっていう構成です。 開発時とかに使うと手軽でいいです。 ただ、もちろん問題点があって、
  • #8 そのままだとポートが違うので同一性制限ポリシーに引っかかります。node.jsでプレイヤーページも動かせばいいはずですが、同時アクセスとか負荷的に耐えれるか自信がないので、正直CloudFlareとnginxを通したいです。。。あ、でもこれは全く調べてないので、もしかしたら大丈夫かもしれません。ここにいるnoderの皆さんすみません m(_ _)m あとは、サーバの生IPでアクセスするとなると、SSHポートへのアタックとかDDoSが怖いのであまりやりたくないです。一応SSHポート変えて公開鍵認証にしてるけど怖いですw あとは、すでに80番ポート使ってるので他のポート使う必要あるんですが、そしたらファイアウォールに引っかかる環境からアクセスしてる時に使えないので、そこもまずい気がします。 さらに、SSLに対応させるにはSocket.io単体だと無理で、HTTPモジュール使ってサーバ作ってそれに紐づける必要があるらしいです。
  • #9 自分的にはこのような感じで、さっきのPHPをnode.jsに変えたような構成にしたいので、これを目指して設定します。
  • #10 ただ、実際に試してみたらうまく動かなかったので、nginxの設定を変えました。
  • #11 こんな感じに設定したのですが、右のサンプルはGistにもあげたのでそちらを見てくれたらいいかと思います。QRコードはちょっとしばらく表示しておきます。 設定の大体の内容としては、 ・Socket.ioが使う /socket.io/に対して、 ・HTTP1.1を使わせて、 ・Upgradeヘッダをつけて、 ・Connection: upgradeを設定する っていうことをしました。Upgradeヘッダがnginxを通ると消えてしまうっぽかったので、このような設定が必要です。
  • #12 ちなみにCloudFlareはWebSocketに2014年くらいから対応していて、設定画面からWebSocketをONにできますが、デフォルトでONな気がして、この設定の必要性がよくわかりません。。。 Networkから設定できますが、プランによって最大接続数が違うっぽいです。 Freeプランだと"Hobby or demonstration site"って書いてあるんですが、具体的な制限値は見つけれませんでした。
  • #13 ということで、ご静聴ありがとうございました。
  • #14 おまけで、CloudFlareを使っているなら国の判別が簡単にできて、HTTPヘッダに CF-IPCountryとして国コードが追加されます。 これを使って、EUからのアクセスを拒否できます。「IP/Country Block」っていうアクセス元(もと)の国を拒否する設定は、月20ドルのProプラン以上じゃないと使えませんが、この機能を使うことでFreeプランでもそのような設定ができます。
  • #15 具体的な設定内容ですが、EUに加盟してる国が多すぎるので、これもまたGistにあげました。ぜひご覧ください。 それではご静聴ありがとうございました。