DBで大規模アクセスに対応するメモ

RDBで大規模サービスをやるときにどう捌くか。

  • joinを減らす(DBに考えさせない)
  • あえて正規化を崩す
  • キャッシュサーバ使って、I/O減らす(memchachedとか)
  • レプリケーションしてマスタ/スレーブに分ける。データ読み取りはスレーブ、更新はマスタのDBマシンへ。

NAT越えについてメモ

switchの通信対戦なんかでNAT越えの問題がよくあるみたいですが、ここら辺なんでダメなのかよくわかっていなかったのでメモ。

  • local <-> grobalIPを変換するのがNAT
  • local側に複数端末を割り当てるときは一つのgrobal ipでは外側からの通信をどの端末に届けていいかわからないので、ポート番号も組み合わせる。これがNAPT
  • 割り当てはルータのNATテーブルに定義。これのフィルタリングがフルコーン(すべてok)・過去にlocalから通信した外部の端末のIPならok・過去にlocalから通信した外部の端末のIPとポートならok・シンメトリック型(LAN,WANのポートとIPで一組)の4つの形式がある
  • 普通のクライアントサーバ型のオンラインゲームなんかだとNAT越えは比較的簡単
  • というのもlocal側から外に向かって通信しているので、その段階でNATテーブルが定義されているから
  • なんでswitchとかでNATを超えられないのかというと、P2P通信だから、お互いに外側からどこに向けて通信すればいいのかわからない。
  • これを解決するためにSTUNサーバのような外側から自分がどう見えているかを通知するやり方がある。

パケットキャプチャしている端末を見つけ出す

f:id:canning:20190526164621p:plain:w600

ARPプロトコルのことを調べているときに、Wiresharkなんかでパケットを盗聴している端末を見つけ出す方法があることを知ったので、実際に試してみました。

github.com

普段の動作

パソコンがインターネットを通じて通信するとき、
送信するときは
「アプリが送るデータをソケットAPIでネットワークスタックに依頼」
->「OSが適時パケットの分割とヘッダの負荷」
->「NICから物理的な信号として送出」
受信するときは
NICがブロードキャストor自分宛の通信か判断」
->「OSが受け取ったパケットを組み立て」
->「組み立て終わったデータがアプリへ」

という流れ。
(のはず…)

なので、普通の動きでは自分宛以外のパケットを認識することはできない。
でもこのNICに対して、自分宛以外でもパケットを拾うように設定することもできる。
これをプロミスキャスモードといいます。

f:id:canning:20190526164536p:plain:w450

f:id:canning:20190526165718p:plain:w450

プロミスキャスモード

Wiresharkなどのパケットキャプチャソフトはこうした設定でネットワーク上のパケットの様子を調べることができます。

f:id:canning:20190526170219p:plain:w450

でも全部を取り込んでいる、という点を突いて、キャプチャしている端末を見つけることができます。

パケットキャプチャしている端末を見つける

NICでは宛先macアドレスを見てブロードキャストor自分宛?を判断していて、
似たような判断はOSでもやっているのですが、そのチェックの粒度には差があって、
NICでは厳密にmacアドレスの最初から最後を見ますが、OSでは最初の何バイトかを見て判断しています。

f:id:canning:20190526171930p:plain:w600

なので、このチェック粒度の差とプロミスキャスモードを組み合わせて、ARPパケットを送りつけてあげることで、キャプチャ端末を特定することができます。

どういうことかというと、ぱっと見ブロードキャストなパケットで、しかもARP要求を送ってあげると
そのパケットは無事APPの層まで到達して、ARP応答が戻ってくる、という仕組みです。

f:id:canning:20190526172858p:plain:w600

環境

パケットキャプチャ側をRaspberry Piで、
ARPパケットをVirtual BoxCent OSから送信します。

パケットの送信にはScapyというPythonのライブラリを使用いたしました。

まずキャプチャ側のNICをプロミスキャスモードにして、

f:id:canning:20190526180754p:plain:w600

ARP要求パケットを送出。

f:id:canning:20190526181048p:plain:w600

その様子をWiresharkで観察

f:id:canning:20190526181533p:plain:w600

ARPレスポンスが返ってくる。やったぜ。

参考

社内の盗聴者を見つけ出す---フリーツール「PromiScan」の使い方(中) | 日経 xTECH(クロステック)
ARPを利用してプロミスキャスモードの盗聴ホストを特定してみた - sonickun.log
盗聴者特定ツール
sniffer - How can I detect if someone is sniffing network packets on the LAN? - Information Security Stack Exchange

Windows Terminalをビルドしてインストールする

f:id:canning:20190526085415p:plain:w600

絵文字に対応したsshクライアントソフトを探していたら、
Windows Terminalなるソフトを見つけました。

[速報]マイクロソフト、「Windows Terminal」発表。タブ機能、コマンドプロンプト、PowerShell、SSHなどを統合、オープンソースで開発中。Microsoft Build 2019 - Publickey

冬には配信されるとのことだったけど、githubの方見たらビルドしてインストールはできるみたいなので、やってみました。

自分の環境ではこうだったよ、的な記事なので実際やるときは公式の方見ながら、自己責任でお願いします。

用意するもの

自分はVisual Studio 2017でやったので、githubを参考に以下を用意しました。
Guide for build and installation · Issue #489 · microsoft/terminal · GitHub

Git for Windowsgitコマンドが使えるツールならなんでもいいです。

Windows 10 SDK (10.0.18362)は以下から
Windows 10 SDK – Windows アプリ開発

Nuget.exeは以下から「nuget.exe」を
NuGet クライアント ツールのインストール | Microsoft Docs

Windows 10 Version 1903は以下から「Windows 10 May 2019 Update」を
Windows 10 のダウンロード

Visual Studio側の準備

必要なものをVisual Studio Installerから入れていきます。
C++によるデスクトップ開発」
「ユニバーサルWindowsプラットフォーム開発」
にチェック。

f:id:canning:20190526090138p:plain:w600

さらに、「インストールの詳細」->「ユニバーサルWindowsプラットフォーム開発」から 「C++ユニバーサルWindowsプラットフォーム開発」が未チェックならチェックする。

f:id:canning:20190526090545p:plain:w600

他に足りないものがあれば、あとでプロジェクトを開いた際に

f:id:canning:20190526092317p:plain:w600

こんな感じに足りないよ!って言われるので、適宜入れてあげてください。

プロジェクトの準備

以下のプロジェクトをcloneします。
GitHub - microsoft/terminal: The new Windows Terminal, and the original Windows console host -- all in the same place!

適当にディレクトリを作成して、そこで
git clone https://github.com/microsoft/terminal.gitします。

f:id:canning:20190526091726p:plain:w600

cd terminalして移動。
git submodule update --init --recursiveをします。

f:id:canning:20190526091829p:plain:w600

さらにNuget.exeを使って、nuget.exe restore OpenConsole.slnを打ってください。

f:id:canning:20190526092508p:plain:w600

プロジェクトを開いて、64bitマシンならx64に合わせて、Releaseでビルド。
おそらくたくさんエラーが出るので、それを修正していきます。

f:id:canning:20190526093510p:plain:w600

ちなみに以下に載せる修正の方法とかは、「準備するもの」に載せたIssuesBuild Stepsに丸々載っているので、英語とか得意ならそっちを直接見た方が早いです。

VtPipeTermmain.cppの修正。
TEST_LANGCYRILLIC,CHINESE,JAPANESE,KOREANの前にu8プレフィックスを追記。

f:id:canning:20190526094229p:plain:w600

C2220エラーが出ているファイルは、適当なエディタで開いて、 UTF-8BOM付きで保存してください。

f:id:canning:20190526094634p:plain:w600

Windows 10側の準備

以下をやっていきます。

  • Windows 10 1903へのアップデート
  • 開発者向け機能の設定

Windows 10 1903へのアップデートは画面に従って進めていけばオッケーです。
外付けのUSBとかくっつけてるとやり直しになっちゃうので、外しておきます。

f:id:canning:20190526095227p:plain:w600

それが終わったら「設定」->「更新とセキュリティ」->「開発者向け」から「開発者モード」を選択。

f:id:canning:20190526095624p:plain:w600

Windows Terminalのインストール

プロジェクトをVisual Studioで「ソリューションのビルド」。

ビルドが無事終わったら、Terminal->CascadiaPackageを右クリックして「配置」を選択。

f:id:canning:20190526095942p:plain:w600

もしDEP3321が出ているなら、

f:id:canning:20190526100354p:plain:w600

プロジェクトを一個一個右クリックして「プロパティ」から「ターゲットバージョン」「最小バージョン」を最新化してあげます。

f:id:canning:20190526100834p:plain:w600

これでインストール完了です。

f:id:canning:20190526100154p:plain:w600

絵文字もばっちりです。やったぜ!

f:id:canning:20190526100230p:plain:w600