AWSで2段階認証(MFA)を構成する(Android版: Google Authenticator使用)

AWSアカウントはGoogleアカウント、Amazonアカウントに次いで大事なアカウントです。
2段階認証、多要素認証、MFA(Multi-Factor Authentication)等々呼ばれ方は様々ですが、
AWSアカウントにも2段階認証を設定することができます。
AWSではMFA(Multi-Factor Authentication, 多要素認証)と呼ばれています。
今回はこれを設定します。

2段階認証を実行するプロセスにはSMSによるメッセージングもできるのですが、
ドコモとかだと海外からのSMSの受信制限とかがかかっていたりして、これを解除しないとうまく受け取れないことがあります。
最初GitHubから2段階認証のワンタイムパスワードを何度やってもSMSで受け取れなくて国コードが間違ってるんじゃないかとか、
先頭の0を取らないといけないじゃないかとか、GitHubのバグなんじゃないかと思いました。

ここではAndroidアプリのGoogle Authenticator(Google認証システム)を使用します。
Google AuthenticatorはGoogleの二段階認証にしか使えないのかと思っていたのですが、
他の2段階認証を採用しているシステムでも使えるようです。
便利ですねー。

MFAの設定を有効にする

  • Management Consoleにログイン後、右上のメニューから[Security Credentials]を選択します。

f:id:wnoguchi0727:20140812213056p:plain

  • あなたがアクセスしようとしているページはAWSアカウントのセキュリティクレデンシャルのページで、
    AWSアカウントのセキュリティクレデンシャルはAWSリソースへの無制限アクセスを提供するものだから
    AWSのベストプラクティスにならってIAMで制限されたユーザを作成してやったほうがいいよーと
    警告が表示されるので[Continue to Security Credentials]をクリックして先に進みます。

f:id:wnoguchi0727:20140812213051p:plain

  • 次に[Your Security Credentials]セクション内の[Multi-Factor Authentication(MFA)]を開いて
    [Activate MFA]ボタンをクリックします。

f:id:wnoguchi0727:20140812213054p:plain

  • [A virtual MFA device]を選択します。

f:id:wnoguchi0727:20140812213044p:plain

  • 要するに、Google Authenticatorを入れてねと書いてあります。

f:id:wnoguchi0727:20140812213045p:plain

  • QRコードが表示されました。
    この段階ではGoogle Authenticatorがインストール済みの前提で話を進めます。
    さらに厳重に認証コードを2連続で入力を促されます。
    そんなことできたんだ・・・。

f:id:wnoguchi0727:20140812213046p:plain

Google Authenticatorを起動する

さて、このQRコードを読み取るためにGoogle Authenticatorを起動します。
こんなアイコンのやつですね。

f:id:wnoguchi0727:20140812213053p:plain

  • [アカウントを設定]をタップします。

f:id:wnoguchi0727:20140812213052p:plain

f:id:wnoguchi0727:20140812213055p:plain

  • AWSアカウントのワンタイムパスワードを生成するところが現れたのがわかると思います。
    右側の円グラフのゲージがこの認証コードの有効な期間なので2回、この認証コードををさっきの認証コード入力欄に入力して[Next Step]をクリックします。

f:id:wnoguchi0727:20140812213050p:plain

  • これで2段階認証を行うためのGoogle AuthenticatorとAWSアカウントが紐付けられました。

f:id:wnoguchi0727:20140812213047p:plain

f:id:wnoguchi0727:20140812213048p:plain

実際にログインしてみる

実際に2段階認証が有効になったかサインアウトしてもう一度ログインしてみます。

  • ログインID、パスワードを入力します。

f:id:wnoguchi0727:20140812213057p:plain

  • 認証コードを求められるようになりました。
    ここでGoogle Authenticatorで生成される認証コードを期限内に入力してログインします。

f:id:wnoguchi0727:20140812213049p:plain

これでAWSアカウントに2段階認証を設定することができました。

デバイスが壊れた、紛失してログインできなくなってしまったら

GitHubやQiita等はリカバリコードが用意されていますが、AWSの場合は直接問合せする必要があるようです。
要注意。

Amazon Route53にレジストラとしての機能がついたのでさっそく使ってみた

帰ってきて何の気なしにAmazonからのメールをぼーっとみてると
「あーはいはい、またなんか機能追加したのね」ってそのまま即効でアーカイブしそうになったけど、

(2014-08-09追記 日本語ブログエントリ出てました)

Domain Name Registration

You can now purchase a new domain name or transfer the management of your existing domain name to Route 53. When you purchase new domains via Route 53, the service will automatically configure a Hosted Zone for each domain and ensure the privacy of your WHOIS record at no additional charge. In addition, you benefit from AWS‘s consolidated billing to manage your domain name expenses alongside all of your other AWS resources.

この文章見てもしかしてRoute53にレジストラとしての機能が実装されたのか?

って半信半疑で少しぐぐってみたけど日本語の情報全然ないから僕の英語力がおかしいのかと思ったんだけど、
ちょっと試してみました。

上の文章を要約すると

  1. Amazon Route53 でドメインのお買い物ができるようになりました(レジストラになりました)。
  2. ドメインの転送もできます。
  3. Route53 で購入したドメインは自動的に Hosted Zone が構成されます。
  4. 何もしなくてもWHOISレコードからプライバシーが保護されます。
  5. 支払いはAWSの他のサービスの利用料金と統合して請求されます。

ものは試しなのでやってみました

ドメイン買ってみる

  • Route53のダッシュボードでDomainsを選択

f:id:wnoguchi0727:20140802020330p:plain

foo-bar-blah.com はもう僕がお名前.comで取得しちゃっているので買えません。
foo-bar-blah.jp ドメインは $100 だそうです。ぼったくり価格w

f:id:wnoguchi0727:20140802020333p:plain

今回は foo-bar-blah.net を取得することにしました。
Continue をクリック。

f:id:wnoguchi0727:20140802020332p:plain

技術者情報を入力します。
WHOISで個人情報が大公開されないようにするために Privacy Protection を Yes とするのがポイント。

f:id:wnoguchi0727:20140802024714p:plain

最終的な確認画面。規約に同意したらチェックして購入を確定する。

f:id:wnoguchi0727:20140802020335p:plain

ドメインの登録リクエストが正常に送信されたことが確認できる。

f:id:wnoguchi0727:20140802020336p:plain

ダッシュボードに戻ってみると Domain Registration in Progress となっており、登録中であることがわかる。

f:id:wnoguchi0727:20140802020337p:plain

しばらくすると Domains のメニューで選択した時の一覧に先ほど購入したドメインがリストアップされた。

f:id:wnoguchi0727:20140802020339p:plain

Hosted Zoneも自動的に構成されており、すぐに A レコード等を追加して使いはじめることができるようになっていた。

f:id:wnoguchi0727:20140802023645p:plain

すごいな・・・。

ドメイン移管してみる

お名前.comで取得したちょうど期限が切れそうなドメインが合ったのでRoute53に転送しました。

まずは Transfer Domain をクリックする。

f:id:wnoguchi0727:20140802020338p:plain

移管したいドメインを検索する。
今回はもうすぐ有効期限が切れそうなドメイン cloud-clipboard.com を選択した。

f:id:wnoguchi0727:20140802020340p:plain

AuthCode 等を入力して確定。

f:id:wnoguchi0727:20140802020341p:plain

これで移管の申請は完了。

f:id:wnoguchi0727:20140802020342p:plain

たぶんもう少ししたら結果出ると思う(2014/08/01深夜)。

Domain transfer in progress となり、ドメイン移管の手続きが始まったようです(2014/08/02朝)。

f:id:wnoguchi0727:20140802085611p:plain

Geographic Routing with Geo DNS の項についてはよくわかりませんでしたが、
負荷分散的な話でしょうか。誰か教えてください。。。

Lower Prices for DNS Queries では 8/1 から Route53 へのクエリ問合せが20%安くなったよって言ってるんでしょうか。

うーん、英語は難しいですね。

「hbstudy#60 SerfとConsulでシステム運用を楽しくしよう!」に行ってきました&Serf試してみました

hbstudy#60

行ってまいりました!今回は実際にSerfを使ってみましたので、お手すきの方は是非ごらんください。

今回の勉強会のToggeterまとめはこちらになっています!前佛さんが作成されました。

参加前

繰り上がるつもり・・・!!

f:id:wnoguchi0727:20140721230832p:plain

繰り上がりきたああああああ!(7/17)

概要

hbstudyの趣旨についてですが、インフラエンジニアの勉強会です。

世の中のエンジニアは開発と運用とを掛け持ちされている方も多いかと思われます。
ネットワーク機器のコンフィグをいじることはなくてもLinux系、Windows Server系に限らずサーバの設定やアプリケーションのデプロイ作業等はやったことがある方は結構多いと思います。
Webエンジニアであるからこそ、密接に関わるインフラに対する興味も尽きないわけで、その理解を深めるためにも参加してまいりました。

会場到着(開始前)

会場に到着すると会場の設営はほとんど済んでいるようでした。
参加費1,000円を渡すと首から下げるIDカードを貰いました。

f:id:wnoguchi0727:20140721230850p:plain

さすがに百何十人収容できる会議室は広い。
Wi-Fiはこの段階ではつながらないようだったため、ちょっとテザリングで対応しました。
(のちほどつながるようになりました)

勉強会が始まる段になると、株式会社ハートビーツの馬場さんが司会をつとめてくださいました。

SerfとConsulで運用を楽しくしよう!

  • 最近注目されているSerfとConsulの話と、活用して運用を楽しくしたいね!という話をしていただきます
  • 前佛 雅人さん
  • @zembutsu

いろいろとパロディを交えて楽しく講演をしていただきました。
スライドはこちらです。

Serfについて

Serf

軽量なオーケストレーションツールとのことです。

スクリーンにはVirtualBoxインスタンスを3台動かしている様子が映され、Serfのクラスタが構成するデモをが行われました。

  • バイナリ1個あれば動く
  • コマンド1個叩くだけで動く

同期してserf membersで表示される情報は

  • ホスト名
  • IPアドレス
  • ポート
  • alive, left 等のステータス

情報がすぐに同期される のがポイントらしいです。

  • クラスタが10台でも100台でもすぐに同期できる。

ということがわかっていればもう 帰宅 寝ていても大丈夫とのことです。
(そんなことあない!)

資料を作るときは自動保存するようにしましょうねと注意が促されました。確かに、苦労して作成したデータが保存されていなかったということはよくあると思います。

最近は新しい技術をキャッチアップしていくのが結構大変ですね。Dockerとか流行っています。

Docker Meetup Tokyo行ってみたかったです。

Dockerの講演でも使用されたスライドだそうですが、今回はバージョン1.02だそうです。

頭の悪い資料を作成することで有名とのことですが、そんなことはありません。

ここで、農業の話になり、ラックのようなところでレタスが栽培されているスライドが映しだされました。

ここで、 ラックマウントレタス という造語を思いついた方は少なく無いと思います。

農業でやるとでやるとものすごい初期投資がかかるが、この業界でも監視自動化とかやろうと思えばすぐに試すことができる。

Docker

  • Docker control group
  • namespace
  • aufs

まずはオーケストレーションツールを使ってみる

  • Dockerはエコシステム
  • Eucalyptus Confでしゃべったことがあるそうです。

自動化は

を包含する物

Fun(楽しい)とEasy(楽)は近づけることができる。

制御的な意味合いかな、ミドルウェアの設定はChef等でやる必要があると。
ごめんなさい、間違っていたら指摘をお願いします。

Serf

  • ノードの同期が数秒単位
  • タグ機能(Web、開発)
  • 障害、フェイルオーバ情報の同期
  • wgetでバイナリ1個とってくるだけで動作
  • 多くのプラットフォームで動作
  • HoshiCorpの方が作ったOSSプロダクト

Serfには以下の機能があるそうです。

  • メンバ管理
  • 障害検知
  • カスタムイベント

  • イベントをトリガとして動作する

  • シェルで動くものならなんでも実行できる
  • クラスタ参加・離脱

  • 参加したら監視システムに設定を投入するとか

  • 離脱したらLBから切り離すとか

メンバ管理

タグごとにグループ処理できる

さて

AとBがある

AからBにserf joinで両方を認識する

これでクラスタが構成される。

Cが参加したいとき

  • CがAに参加した
  • AがCに応答する
  • BもMemberjoinを受け取る
  • 以降はランダムに死活監視
  • SPOFがない

Bが突然の死

  1. 死んだのを認識
  2. それでもA, Cは定期的にBをチェックするが
  3. こいつだめだと思われたら容赦なく外す

  4. 多数決論理ではない

  5. NICの死に方によってはフラッピングするかもしれない

イベントが同期される

  • 参加・離脱
  • 伝搬速度はSerfのサイトでシミュレーションできる
  • 理論値で1秒で95%が、2秒で100%(Convergence Simulator – Serf

運用例

  • WebとLB
  • ChefとPuppetとは違う。混同しないこと。
  • メンバーの管理、イベントの発行
  • serf agentコマンドだけで立ち上がる

イベントハンドラ

  • イベントに応じていろんなコマンドを実行する
  • 起動オプションをjsonファイルにまとめられる

→日々の運用管理を楽にしてくれる

LVSに応用する

  • 致命的な問題がある
  • ノード自身が停止は分かる
  • サービスの停止はわからない

そこでConsulですよ

  • サービス検出
  • 障害検知
  • Nagiosプラグインみたいな方法で検出する
  • HTTP APIまたはDNSで結果を返すことができる
  • Zabbixの監視項目を動的化とかね

これらを応用すると

AWSみたいにOpenStackの上でオートスケールとかできるんじゃないでしょうか(聞き取り間違ってたらゴメンナサイ)

  • Web UI
  • HTTP API
  • ローカルのDNSと連携することができる
  • .internal
  • Consulは開発途上です
  • Webサーバのダウンをトリガとして一斉にコマンドを実行するなど

質疑応答

Q. なんでノード指定してjoinしてるのですか?

  1. マルチキャストDNSに対応している環境であれば参加先のノード名を指定する必要はない。
    今回のデモもdiscoverオプションでやっています。

Consul

サービスが消えるとクライアント自身が検出してサーバに送りつける
envconsul
Helokuもどきをつくれる
Qiita上にもいくつか投稿したかも

  • 軽量でシンプル
  • こんな複雑じゃないツールってなかったよね!!

たしかにPacemakerやHeartbeatでHAクラスタ構成する実験しようとしてWebサーバのHAクラスタ構成するだけでものすごい苦労した記憶あります。
私のスキルセットが足りないのが大きな一因なのかもしれませんが・・・。

実践Zabbix

  • Zabbixの管理の自動化
  • 興味があったら見てね〜
  • ZabbixにはAPIがある

cactiはもうオワコンなのだろうか。
たしかにGUIめんどくさい。
グラフ系はZabbixよく聞くようになったなあ・・・。

楽しいと楽をつなげるようなことができればいいな。

Google Group
オーケストレーションの部屋

を用意しました(します)とのことです。

休憩入ります~15:10

130人以上が一斉につなぐとWi-Fi重っ!

「consulについて」

  • HashiCorpの新しいOSSプロダクトConsulの紹介と簡単な応用事例等。
  • Michael H. Oshitaさん
  • @ijin

Consul – HashiCorp

替わりましてijinさんの公演となりました。
スライドはこちらです。

Consulについてもっと詳しく

  • 10年ぐらい日本住んでらっしゃる
  • 本名マイケルさん
  • トラブル☆しゅーたーず という障害対応の勉強会をやります(8/9)

トラブル☆しゅーたーずへの参加はこちらから!

懇親会にも参加しましたがijinさんとよく呼ばれていらっしゃるのでしょうか。
懇親会でもお話を聞くとAWSにものすごく詳しいそうです。
うおおおすごい。

HashiCorpの4つめのプロダクト Consul

  1. Vagrant
  2. Packer
  3. Serf
  4. Consul

特徴

画期的なのは

  • DNSまたはHTTPでできること
  • 複数のデータセンタをまたぐ
  • KVS(動的な設定情報の置き場所として使っている)

構成要素は

  • Consensus Protocol
  • Gossip Protocol
  • Sessions(Chuby)
  • TLS Jespen Testing

アーキテクチャ

エージェントをそれぞれのサーバに入れてサーバモード、またはクライアントモードで動作させる。

サーバモード

CONSISTENCY

  • CAPの定理
  • raftというものを使用している
  • トランザクションのクエリはリーダノードにいってwrite
  • スレーブにレプリケート

  • 半分以上に行ったらコミット成功とみなす

  • quorumにならないとコミットとみなさない

  • ネットワークの分断テストはどうするのか

    • JEPSEN TESTINGでシミュレーションしている

Consul agent

  • foo
  • bar
  • baz

DNS, HTTPで設定

  • タグservice[redis]
  • タグservice[01.web]
  • タグservice[02.web]
dig @localhost -p8600 bar.node.consul
01.web.service.consul
  • serviceでグルーピングすると複数のIPがかえってくる
  • v0.2まではTTLはデフォルトで0
  • 以降はキャッシュできるようになった

key/value endpoint

/v1/kv/<key>
  • RESTful
  • GET, PUT, DESTROY

kv

  • ここでもjqコマンドが使われている
  • base64エンコード
  • 生表示は ?raw をつける

catalog

health

  • ヘルスチェック
  • このへんはjsonで定義する
  • exitコードはnagiosっぽく
  • 内部DNSとして使用できる

ここでデモ

こちらのデモはグッときました。
関連記事はこちら。

Ansibleの場合は

  • staticなhostsファイルに対してpingを打つなど
  • サーバの台数が増えてくるとつらい
  • Ansibleにはダイナミックインベントリという機能がある

  • MySQLレプリケーションしているとき

  • マスタが死んだとき
  • MHA
  • 一番バイナリログが進んでいる奴に対して

  • VIPを変える

  • DNSでカタログのDNSを変更する

  • Consulでうまく連携する方法思いついたのでデモ

DNS引いて得られるIPが変わってスレーブがマスタに昇格する様子が映し出されます。

ベンチマーク

GET

0.2.0→0.3.0のバージョンアップで

  • TTLキャッシュで5倍ぐらいに向上した
  • consistensy

PUTについても改善。

consul-apiはGo言語で書かれている。

consulイイよ!

おしらせ

  • 8/9とらぶるしゅーたずきてね
  • 今日この中にさくらのクラウドの横田さんがいます!
  • SerfとConsulをやった結果をブログでアップしてください!

とのことでした。

以前さくらのクラウドAPIcurlで叩いて操作して、結果をjqで整形して見るようなエントリを書いて、横田さんにリツイートしてもらったのですが、是非一度お目にかかりたかったのでご挨拶してまいりました。
恐れ多くもさくらのクラウドのクーポン券を頂戴いたしました。
大切に使わせていただこうと思います。
横田さんありがとうございます!

f:id:wnoguchi0727:20140721230957p:plain

懇親会

一次会、二次会にまで参加してまいりました。
一応以前はインフラもちょっとは触っていましたが、
私とは比較にならないほどすごくレベルの高いインフラエンジニアの方々ばかりでした。
私は現在、Web系のシステム開発寄りのお仕事をしているのですが、インフラエンジニアの方々の現場の生の声がいろいろ聞けてとても面白かったです。

f:id:wnoguchi0727:20140721231026p:plain

一人大反省会

ちょっといろんな運用自動化系の知識が曖昧だったので整理が必要だなと感じました。今日だけで言葉だけ聞いたことがあるミドルウェアやインフラ基盤用語がいくつもでてきました。

  1. Serf: オーケストレーションツール
  2. Consul: オーケストレーションツール
  3. Ansible: Pythonで書かれた構成管理ツール(Chefの親戚)
  4. Fabric: Python製のデプロイツールCapistranoでやっとピンときた。
  5. Sensu: Nagiosを現代化した版。みんなSensu, Sensuって言ってたのでなんだろうと思ってたら、監視ツールのトレンドはNagiosではなくSensuなのか!Icingaは前に検討したことあったけど、あんまりはやってないのかな。
  6. SoftLayer: 懇親会の席ではデータセンターのクラウド版と言われて理解できなかったのですが、調べてみたら物理サーバーやネットワークの引き回しのレベルでいじれるようにしたクラウドプラットフォームなんだろうか?

  7. 監視ソフトをNagiosからSensuに切り替えて2ヶ月経ったのでまとめた – Glide Note – グライドノート

  8. chef – 次世代監視ツール Sensu リファレンス – Qiita
  9. Home – Icinga: Open Source Monitoring
  10. IBMの新しい高性能クラウド「SoftLayer」を使ってみた ~アカウント開設からインスタンス立ち上げまで (1/4):CodeZine

やってみた(次の日)

「SerfとConsulをやってみた結果をブログでアップしてくださいねー!」とのことでしたので、やってみました。
今回は自分のデスクトップマシンで実験してみようと思います。

僕のデスクトップPCは無駄に性能がいいです。
Core i7に実装メモリ32GB。
ディスプレイは最低2枚ないと生きていけないですね・・・。
最近グラボの調子が悪くて、引っ越してきてから上手く動かないんです。
これがあればディスプレイ4台まではいけるんだけど・・・。
電源の容量足りないのかな・・・?
しかたないからオンボードでデュアルしてます。

という話は置いておいて、こういうことやってるから私はあまりお金がないので、
この無駄に性能のいいマシンで serf のクラスタを構成してみたいと思います。

数の暴力

とりあえず、私はそこまで頭が良くないので Serf のクラスタリングのさわりだけやってみます。

32GBの実装メモリがあるので、これを可能な限り活用してみようと思います。
とりあえず必要最小限のアプリだけ立ち上げてメモリの使用量を減らしまくります。

f:id:wnoguchi0727:20140721231045p:plain

1インスタンス512MBの割り当てとして立ち上げた場合

(29 - 2) * 1000 / 512 = 52

52台分の仮想マシンが構成できます。

もっと頑張れば

(29 - 0.5) * 1000 / 512 ≒ 56

いける。

まずは2台でやってみた

50台近くも立てる予定なので、こんなのVagrant使わないとやってられないのでこの段階からVagrantを使います。
まずは2台。

C:\Users\wnoguchi\Documents\vagrant\serf>vagrant init chef/centos-6.5
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

Vagrantfile抜粋

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "chef/centos-6.5"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "512"]
end
config.vm.define "web_1" do |instance|
instance.vm.network :private_network, ip: "192.168.33.10"
end
config.vm.define "web_2" do |instance|
instance.vm.network :private_network, ip: "192.168.33.11"
end
end

仮想マシン2台立ち上げ

C:\Users\wnoguchi\Documents\vagrant\serf_minimum>vagrant up
Bringing machine 'web_1' up with 'virtualbox' provider...
Bringing machine 'web_2' up with 'virtualbox' provider...
==> web_1: Box 'chef/centos-6.5' could not be found. Attempting to find and install...
web_1: Box Provider: virtualbox
web_1: Box Version: >= 0
==> web_1: Loading metadata for box 'chef/centos-6.5'
web_1: URL: https://vagrantcloud.com/chef/centos-6.5
==> web_1: Adding box 'chef/centos-6.5' (v1.0.0) for provider: virtualbox
web_1: Downloading: https://vagrantcloud.com/chef/centos-6.5/version/1/provider/virtualbox.box
web_1: Progress: 100% (Rate: 5908k/s, Estimated time remaining: --:--:--)
==> web_1: Successfully added box 'chef/centos-6.5' (v1.0.0) for 'virtualbox'!
==> web_1: Importing base box 'chef/centos-6.5'...
==> web_1: Matching MAC address for NAT networking...
==> web_1: Checking if box 'chef/centos-6.5' is up to date...
==> web_1: Setting the name of the VM: serf_minimum_web_1_1405924483325_20292
==> web_1: Clearing any previously set network interfaces...
==> web_1: Preparing network interfaces based on configuration...
web_1: Adapter 1: nat
web_1: Adapter 2: hostonly
==> web_1: Forwarding ports...
web_1: 22 => 2222 (adapter 1)
==> web_1: Running 'pre-boot' VM customizations...
==> web_1: Booting VM...
==> web_1: Waiting for machine to boot. This may take a few minutes...
web_1: SSH address: 127.0.0.1:2222
web_1: SSH username: vagrant
web_1: SSH auth method: private key
web_1: Warning: Connection timeout. Retrying...
==> web_1: Machine booted and ready!
==> web_1: Checking for guest additions in VM...
==> web_1: Configuring and enabling network interfaces...
==> web_1: Mounting shared folders...
web_1: /vagrant => C:/Users/wnoguchi/Documents/vagrant/serf_minimum
==> web_2: Box 'chef/centos-6.5' could not be found. Attempting to find and install...
web_2: Box Provider: virtualbox
web_2: Box Version: >= 0
==> web_2: Loading metadata for box 'chef/centos-6.5'
web_2: URL: https://vagrantcloud.com/chef/centos-6.5
==> web_2: Adding box 'chef/centos-6.5' (v1.0.0) for provider: virtualbox
==> web_2: Importing base box 'chef/centos-6.5'...
==> web_2: Matching MAC address for NAT networking...
==> web_2: Checking if box 'chef/centos-6.5' is up to date...
==> web_2: Setting the name of the VM: serf_minimum_web_2_1405924553780_11101
==> web_2: Fixed port collision for 22 => 2222. Now on port 2200.
==> web_2: Clearing any previously set network interfaces...
==> web_2: Preparing network interfaces based on configuration...
web_2: Adapter 1: nat
web_2: Adapter 2: hostonly
==> web_2: Forwarding ports...
web_2: 22 => 2200 (adapter 1)
==> web_2: Running 'pre-boot' VM customizations...
==> web_2: Booting VM...
==> web_2: Waiting for machine to boot. This may take a few minutes...
web_2: SSH address: 127.0.0.1:2200
web_2: SSH username: vagrant
web_2: SSH auth method: private key
web_2: Warning: Connection timeout. Retrying...
==> web_2: Machine booted and ready!
==> web_2: Checking for guest additions in VM...
==> web_2: Configuring and enabling network interfaces...
==> web_2: Mounting shared folders...
web_2: /vagrant => C:/Users/wnoguchi/Documents/vagrant/serf_minimum

Serfのインストール

$ wget https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
Cannot write to “(snip)” (File name too long).

名前長すぎ!!って怒られてしまった。
また、このboxイメージだとunzipコマンドが入っていないっぽいのでインストール。

sudo yum -y install unzip

もとい、

wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
unzip 0.6.3_linux_amd64.zip
sudo mv serf /usr/local/bin/

バージョンを確認する。

[vagrant@localhost ~]$ serf version
Serf v0.6.3
Agent Protocol: 4 (Understands back to: 2)

Serfエージェントを立ち上げる

& バックグランドジョブにしないとプロンプトが帰ってこないから注意。

  • host1にて
serf agent -node=host1 &
  • host2にて
serf agent -node=host2 &

クラスタに加わる

mDNS(Multicast DNS)が有効かどうかはわからないので(このへん初心者)、serf join コマンドからとりあえず入門してみることにした。

  • host1にて
[vagrant@localhost ~]$ serf members
2014/07/21 07:04:28 [INFO] agent.ipc: Accepted client: 127.0.0.1:56604
host1  10.0.2.15:7946  alive

メンバは自分のみ。

  • host2に加える
[vagrant@localhost ~]$ serf join host2
2014/07/21 07:04:37 [INFO] agent.ipc: Accepted client: 127.0.0.1:56605
2014/07/21 07:04:37 [INFO] agent: joining: [host2] replay: false
2014/07/21 07:04:37 [WARN] memberlist: Failed to resolve host2: lookup host2: no such host
2014/07/21 07:04:37 [WARN] agent: error joining: lookup host2: no such host
Error joining the cluster: lookup host2: no such host

あれ、エラー・・・。
そうだよね、host1がhost2のIPアドレス知ってるわけないもんね・・・。

  • IP直指定でhost2に加える。
[vagrant@localhost ~]$ serf join 192.168.33.11
2014/07/21 07:11:39 [INFO] agent.ipc: Accepted client: 127.0.0.1:56606
2014/07/21 07:11:39 [INFO] agent: joining: [192.168.33.11] replay: false
2014/07/21 07:11:39 [INFO] serf: EventMemberJoin: host2 10.0.2.15
2014/07/21 07:11:39 [INFO] agent: joined: 1 nodes
Successfully joined cluster by contacting 1 nodes.
[vagrant@localhost ~]$     2014/07/21 07:11:40 [INFO] agent: Received event: member-join
2014/07/21 07:11:41 [WARN] memberlist: Got ping for unexpected node 'host2'
2014/07/21 07:11:42 [INFO] memberlist: Suspect host2 has failed, no acks received
2014/07/21 07:11:43 [WARN] memberlist: Got ping for unexpected node 'host2'
2014/07/21 07:11:44 [INFO] memberlist: Suspect host2 has failed, no acks received
2014/07/21 07:11:44 [WARN] memberlist: Got ping for unexpected node 'host2'
2014/07/21 07:11:45 [INFO] memberlist: Suspect host2 has failed, no acks received
2014/07/21 07:11:46 [WARN] memberlist: Got ping for unexpected node 'host2'
2014/07/21 07:11:47 [INFO] memberlist: Suspect host2 has failed, no acks received
2014/07/21 07:11:47 [INFO] memberlist: Marking host2 as failed, suspect timeout reached
2014/07/21 07:11:47 [INFO] serf: EventMemberFailed: host2 10.0.2.15
2014/07/21 07:11:48 [INFO] agent: Received event: member-failed

うまくい・・・ったようにみえて最終的に失敗している。

  • serf members の結果

host2との通信が失敗してる(failed となっている)。
いったんハンドシェイクが成功して繋がらなくなったような感じ。

[vagrant@localhost ~]$ serf members
2014/07/21 07:12:03 [INFO] agent.ipc: Accepted client: 127.0.0.1:56608
host1  10.0.2.15:7946  alive
host2  10.0.2.15:7946  failed

まてよ、と思い直す。
Vagrantfileでプライベートネットワークを構成するためにNIC追加してたんだ。
どのNICでリッスンしてるかわかんないと通信を確立していいIPアドレスもわからないんじゃないか。

改めてhost1, host2それぞれのNICの当たり方を確認してみる。

  • host1
[vagrant@localhost ~]$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:ce:08:3d brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
inet6 fe80::a00:27ff:fece:83d/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:5e:6e:58 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.10/24 brd 192.168.33.255 scope global eth1
inet6 fe80::a00:27ff:fe5e:6e58/64 scope link
valid_lft forever preferred_lft forever
  • host2
[vagrant@localhost ~]$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:ce:08:3d brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
inet6 fe80::a00:27ff:fece:83d/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:ba:62:c3 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.11/24 brd 192.168.33.255 scope global eth1
inet6 fe80::a00:27ff:feba:62c3/64 scope link
valid_lft forever preferred_lft forever

NIC3つついてるから eth0 のアドレスで通信を確立したらいいかどうか分かんなくて失敗したのかな。

NICを指定してSerfエージェントを立ち上げる

さて、仕切り直し。
fg してCtrl-C でプロセス殺して以下の設定でエージェント再度起動。

  • host1にて
serf agent -iface=eth1 -node=host1 &
  • host2にて
serf agent -iface=eth1 -node=host2 &

serf joinしてみる

[vagrant@localhost ~]$ serf join 192.168.33.11
2014/07/21 07:48:37 [INFO] agent.ipc: Accepted client: 127.0.0.1:56634
2014/07/21 07:48:37 [INFO] agent: joining: [192.168.33.11] replay: false
2014/07/21 07:48:37 [INFO] serf: EventMemberJoin: host2 192.168.33.11
2014/07/21 07:48:37 [INFO] agent: joined: 1 nodes
Successfully joined cluster by contacting 1 nodes.
[vagrant@localhost ~]$     2014/07/21 07:48:38 [INFO] agent: Received event: member-join

今度は成功したみたいだ。

serf membersの結果

どっちもaliveと表示された。

[vagrant@localhost ~]$ serf members
2014/07/21 07:48:44 [INFO] agent.ipc: Accepted client: 127.0.0.1:56636
host1  192.168.33.10:7946  alive
host2  192.168.33.11:7946  alive
  • 試しにhost2 のSerfエージェントを殺す。

上品な方法でシャットダウンするようです。

[vagrant@localhost ~]$ fg
serf agent -iface=eth1 -node=host2
^C==> Caught signal: interrupt
==> Gracefully shutting down agent...
2014/07/21 07:51:04 [INFO] agent: requesting graceful leave from Serf
2014/07/21 07:51:05 [INFO] serf: EventMemberLeave: host2 192.168.33.11
2014/07/21 07:51:05 [INFO] agent: requesting serf shutdown
2014/07/21 07:51:05 [INFO] agent: shutdown complete
  • host1側でメンバの一覧を確認。

failed ではなく left となっているところがポイントですね。

[vagrant@localhost ~]$ serf members
2014/07/21 07:51:12 [INFO] agent.ipc: Accepted client: 127.0.0.1:56642
host2  192.168.33.11:7946  left
host1  192.168.33.10:7946  alive

Serfエージェントを立ち上げる(マルチキャストDNS

50何台すべてにserf joinしてたらたまらないのでマルチキャストDNS版もためす。

  • host1にて
serf agent -iface=eth1 -node=host1 -discover=webapp &
  • host2にて
serf agent -iface=eth1 -node=host2 -discover=webapp &

ログの流れは次のような感じ

host1にてエージェントを立ち上げると

[vagrant@localhost ~]$ serf agent -iface=eth1 -node=host1 -discover=webapp &
[1] 2308
[vagrant@localhost ~]$ ==> Using interface 'eth1' address '192.168.33.10'
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
Node name: 'host1'
Bind addr: '192.168.33.10:7946'
RPC addr: '127.0.0.1:7373'
Encrypted: false
Snapshot: false
Profile: lan
mDNS cluster: webapp
==> Log data will now stream in as it occurs:
2014/07/21 08:06:13 [INFO] agent: Serf agent starting
2014/07/21 08:06:13 [INFO] serf: EventMemberJoin: host1 192.168.33.10
2014/07/21 08:06:13 [INFO] agent: joining: [192.168.33.10:7946] replay: false
2014/07/21 08:06:13 [INFO] agent: joined: 1 nodes
2014/07/21 08:06:13 [INFO] agent.mdns: Joined 1 hosts
2014/07/21 08:06:14 [INFO] agent: Received event: member-join

ついでhost2で立ち上げるとhost2側では以下の様なログが流れ、

[vagrant@localhost ~]$ ==> Using interface 'eth1' address '192.168.33.11'
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
Node name: 'host2'
Bind addr: '192.168.33.11:7946'
RPC addr: '127.0.0.1:7373'
Encrypted: false
Snapshot: false
Profile: lan
mDNS cluster: webapp
==> Log data will now stream in as it occurs:
2014/07/21 08:07:11 [INFO] agent: Serf agent starting
2014/07/21 08:07:11 [INFO] serf: EventMemberJoin: host2 192.168.33.11
2014/07/21 08:07:11 [INFO] agent: joining: [192.168.33.11:7946 192.168.33.10:7946] replay: false
2014/07/21 08:07:11 [INFO] serf: EventMemberJoin: host1 192.168.33.10
2014/07/21 08:07:11 [INFO] agent: joined: 2 nodes
2014/07/21 08:07:11 [INFO] agent.mdns: Joined 2 hosts
2014/07/21 08:07:12 [INFO] agent: Received event: member-join
  • host1側でも
    2014/07/21 08:07:11 [INFO] serf: EventMemberJoin: host2 192.168.33.11
2014/07/21 08:07:12 [INFO] agent: Received event: member-join
2014/07/21 08:07:13 [INFO] agent: joining: [192.168.33.11:7946] replay: false
2014/07/21 08:07:13 [INFO] agent: joined: 1 nodes
2014/07/21 08:07:13 [INFO] agent.mdns: Joined 1 hosts

という追加のログが流れる。

serf members の結果は

OK。

[vagrant@localhost ~]$ serf members
2014/07/21 08:09:33 [INFO] agent.ipc: Accepted client: 127.0.0.1:35347
host2  192.168.33.11:7946  alive
host1  192.168.33.10:7946  alive

ここまででVMは要らなくなったので一括削除。

vagrant destroy -f

ここまでのSerfの使い方で参考にしたのは前佛さんの以下の記事です。

  1. Serf設定オプションまとめ | Pocketstudio.jp log3
  2. 【Serf】v0.2.0 へのバージョンアップと、変わった所を確認してみた | Pocketstudio.jp log3
  3. ご注文は監視自動化ですか?

Vagrant複数インスタンスを立ち上げるのに参考にしたのは以下、

  1. vagrantの複数インスタンスをたてて遊んでみる – わすれっぽいきみえ
  2. study-vagrant/study4 at master · tmknom/study-vagrant

今度は予めプロビジョニングした状態のSerfクラスタを構成する

これができるようになるまで何回も vagrant destroy -f でぶっこわしまくりました。

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "chef/centos-6.5"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "512"]
end
config.vm.define "web_1" do |instance|
instance.vm.network :private_network, ip: "192.168.33.10"
instance.vm.provision :shell do |shell|
shell.inline = <<-EOS
        if [ ! `which unzip` ]; then sudo yum -y install unzip ;fi
        if [ ! `which serf` ]; then
          cd /tmp/
          wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
          unzip 0.6.3_linux_amd64.zip
          sudo mv serf /usr/local/bin/
          nohup /usr/local/bin/serf agent -iface=eth1 -node=host1 -discover=webapp 0<&- &>/dev/null&
          cat <<EOF >>/etc/rc.d/rc.local
          /usr/local/bin/serf agent -iface=eth1 -node=host1 -discover=webapp &
EOF
        fi
      EOS
end
end
config.vm.define "web_2" do |instance|
instance.vm.network :private_network, ip: "192.168.33.11"
instance.vm.provision :shell do |shell|
shell.inline = <<-EOS
        if [ ! `which unzip` ]; then sudo yum -y install unzip ;fi
        if [ ! `which serf` ]; then
          cd /tmp/
          wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
          unzip 0.6.3_linux_amd64.zip
          sudo mv serf /usr/local/bin/
          nohup /usr/local/bin/serf agent -iface=eth1 -node=host2 -discover=webapp 0<&- &>/dev/null&
          cat <<EOF >>/etc/rc.d/rc.local
          /usr/local/bin/serf agent -iface=eth1 -node=host2 -discover=webapp &
EOF
        fi
      EOS
end
end
end
  1. Linuxでのプロセスの管理(bg,fg,disown) – longicornの日記
  2. Linuxコマンド集 – 【 nohup 】 ログアウトした後もコマンドを実行し続ける:ITpro
  3. Shell provisioning fails to exit · Issue #1553 · mitchellh/vagrant

Serfクラスタ10台を構成する

いきなり50台はなんかうまくいかなそうな気がするので、10台からやってみる。
このままじゃプロビジョニングが美しくないのでRuby力を発揮する。

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "chef/centos-6.5"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "512"]
end
# Number of Virtual Machines
NUMBER_OF_VMS = 10
ip_addr_base = 10
(1..NUMBER_OF_VMS).each do |host_index|
define_name = "web_#{host_index}"
hostname = "host#{host_index}"
octet4 = ip_addr_base + host_index - 1
config.vm.define define_name do |instance|
instance.vm.network :private_network, ip: "192.168.33.#{octet4}"
instance.vm.provision :shell do |shell|
shell.inline = <<-EOS
          if [ ! `which unzip` ]; then sudo yum -y install unzip ;fi
          if [ ! `which serf` ]; then
            cd /tmp/
            wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
            unzip 0.6.3_linux_amd64.zip
            sudo mv serf /usr/local/bin/
            nohup /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp 0<&- &>/dev/null&
            cat <<EOF >>/etc/rc.d/rc.local
            /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp &
EOF
          fi
        EOS
end
end
end
end

このあたりになってくるとvagrant upコマンドがなかなか終わらないが、
始めのころのVMは既にアクセス可能になっているはずなので、
そのノードに接続してwatchコマンドとかでserf membersの変化とかを確認すると
出来上がったインスタンスから次々にSerfのクラスタwebappクラスタに加わっていって結構面白いことになってる。

watch -n 1 serf members

f:id:wnoguchi0727:20140721231247p:plain

冪等性も保証しているので、ひと通りメンバに加わったことがわかったらここで

vagrant reload

してみるのも面白い。

リロード中のVMはfailedのステータスになる。
さらに特定のVMだけを停止してみたり、

C:\Users\wnoguchi\Documents\vagrant\serf_minimum>vagrant halt web_3
==> web_3: Attempting graceful shutdown of VM...

f:id:wnoguchi0727:20140721231311p:plain

一斉にとめて一斉に再起動するのもfailedがどんどん増えていくのでなかなかおつなものです。
ただし接続している自分自身がシャットダウンされたら元も粉もないですけど。

C:\Users\wnoguchi\Documents\vagrant\serf_minimum>vagrant halt
==> web_10: Attempting graceful shutdown of VM...
==> web_9: Attempting graceful shutdown of VM...
==> web_8: Attempting graceful shutdown of VM...
==> web_7: Attempting graceful shutdown of VM...
==> web_6: Attempting graceful shutdown of VM...
==> web_5: Attempting graceful shutdown of VM...
==> web_4: Attempting graceful shutdown of VM...
==> web_2: Attempting graceful shutdown of VM...
==> web_1: Attempting graceful shutdown of VM...
C:\Users\wnoguchi\Documents\vagrant\serf_minimum>vagrant up
Bringing machine 'web_1' up with 'virtualbox' provider...
Bringing machine 'web_2' up with 'virtualbox' provider...
Bringing machine 'web_3' up with 'virtualbox' provider...
Bringing machine 'web_4' up with 'virtualbox' provider...
Bringing machine 'web_5' up with 'virtualbox' provider...
Bringing machine 'web_6' up with 'virtualbox' provider...
Bringing machine 'web_7' up with 'virtualbox' provider...
Bringing machine 'web_8' up with 'virtualbox' provider...
Bringing machine 'web_9' up with 'virtualbox' provider...
Bringing machine 'web_10' up with 'virtualbox' provider...
==> web_1: Checking if box 'chef/centos-6.5' is up to date...
==> web_1: Clearing any previously set forwarded ports...

52ノードクラスタへの挑戦

もはや定数定義を52にしてマシンパワーの限界に挑戦するような感じになってきました。

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "chef/centos-6.5"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "512"]
end
# Number of Virtual Machines
NUMBER_OF_VMS = 52
ip_addr_base = 10
(1..NUMBER_OF_VMS).each do |host_index|
define_name = "web_#{host_index}"
hostname = "host#{host_index}"
octet4 = ip_addr_base + host_index - 1
config.vm.define define_name do |instance|
instance.vm.network :private_network, ip: "192.168.33.#{octet4}"
instance.vm.provision :shell do |shell|
shell.inline = <<-EOS
          if [ ! `which unzip` ]; then sudo yum -y install unzip ;fi
          if [ ! `which serf` ]; then
            cd /tmp/
            wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
            unzip 0.6.3_linux_amd64.zip
            sudo mv serf /usr/local/bin/
            nohup /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp 0<&- &>/dev/null&
            cat <<EOF >>/etc/rc.d/rc.local
            /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp &
EOF
          fi
        EOS
end
end
end
end

あともうひと息だったのですが、フォワーディングするポートが衝突してしまい、息絶えました。

f:id:wnoguchi0727:20140721232212p:plain

==> web_51:   inflating: serf
==> web_52: Importing base box 'chef/centos-6.5'...
==> web_52: Matching MAC address for NAT networking...
==> web_52: Checking if box 'chef/centos-6.5' is up to date...
==> web_52: Setting the name of the VM: serf_minimum_web_52_1405943316239_88578
Vagrant found a port collision for the specified port and virtual machine.
While this port was marked to be auto-corrected, the ports in the
auto-correction range are all also used.
VM: web_52
Forwarded port: 22 => 2222

少し書きなおしてみる。

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "chef/centos-6.5"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "512"]
end
# Number of Virtual Machines
NUMBER_OF_VMS = 52
ip_addr_base = 10
(1..NUMBER_OF_VMS).each do |host_index|
define_name = "web_#{host_index}"
hostname = "host#{host_index}"
octet4 = ip_addr_base + host_index - 1
forwarding_port = 8080 + host_index - 1
config.vm.define define_name do |instance|
instance.vm.network :private_network, ip: "192.168.33.#{octet4}"
instance.vm.network "forwarded_port", guest: 22, host: forwarding_port
instance.vm.provision :shell do |shell|
shell.inline = <<-EOS
          if [ ! `which unzip` ]; then sudo yum -y install unzip ;fi
          if [ ! `which serf` ]; then
            cd /tmp/
            wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
            unzip 0.6.3_linux_amd64.zip
            sudo mv serf /usr/local/bin/
            nohup /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp 0<&- &>/dev/null&
            cat <<EOF >>/etc/rc.d/rc.local
            /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp &
EOF
          fi
        EOS
end
end
end
end

今度はどうだろう。
ダメだった。

んー時間切れ。51ノードまでは確認できました。
ポートフォワーディングのコンフリクトが直せればもっといけそうな感じ。

f:id:wnoguchi0727:20140721232129p:plain

以上のVagrantfileは以下のGistからも取得可能です。

第60回: SerfとConsulでシステム運用を楽しくしよう!http://connpass.com/event/7322/ : 今回の実験使用したVagrantfileの一覧

Consulは?

Consulについてはサービス管理の機能がDNS, HTTP APIでシンプルに提供されいてることが分かったのですが、私の理解力が追いついていないため、今回は検証までには至りませんでした・・・。

以上です、ありがとうございました!

「夏のDNS祭り 2014 ~入門セミナ&ハンズオン~」に行ってきました

先週の7/5に開催されました「夏のDNS祭り 2014 ~入門セミナ&ハンズオン~」に行ってまいりました!

f:id:wnoguchi0727:20140705132347j:plain

概要

【自宅ラック勉強会 8.0】 この夏「ワタシハディエヌエスチョットデキル」ことを目標とします。

講師の方

滝澤 隆史 氏(@ttkzw)

インフラで有名な株式会社ハートビーツの方です。

Ustream

http://ustre.am/IWlq

ハッシュタグ

#自宅DNS #自宅ラック勉強会

質問ハッシュタグ

#自宅DNS-Q

会場到着

最近はだいぶ東京の電車にも慣れてきたので、あまり緊張すること無くいけました。
午前中は土曜日でもやってる区民事務所に行って、疲れていたので、時間が空いたらスタバで一杯飲もうかと思っていましたが、今度は会場が渋谷なので慣れないこともあり、場所の確認も兼ねて渋谷駅に行ったらおおむね時間通りになってしまいました。
いい時間なので、ココイチでカレーを食べました。
カレーはいつ食べても美味しいです。
前は車も持ってなくて、気軽にファミレスに行くこともなかったので、便利になったなと思います。

受付

セルリアンタワーのビジネスフロアに行くと警備員の方が立ってました。
駅の改札みたいなところで結構厳重に警備されていました。
さすがGMO
13:00ちょうどに受付の方がいらっしゃいました。
名刺を渡してチェックゲストカードを受け取るとSuicaと同じ要領で通過しました。
そして11Fへ。

GMOの華やかなフロアが見えてきました。
奥に行くとDNS祭り開場が。

準備

ちょっとスタッフの方に質問して、人以外なら撮影の許可が降りましたので、いくつか撮影させてもらいました。

着席するととてもかわいらしいConoHa関連のパンフレットやシールが置いてありました。

f:id:wnoguchi0727:20140705132618j:plain

f:id:wnoguchi0727:20140713221628j:plain

ひとまずConoHaへのSSH接続試験。
事前にconfigとキーペアの取得は済んでいたので一発でした。

ssh conoha-dns

ここで、Ustreamを会場で見るのはご勘弁ください!と会場に注意が促されました。
たしかに帯域を圧迫しそうですからね・・・。

開始

司会進行役は 鮭の切り身 さんです。

注意点

GMO様の会議室をご利用させていただくのでいろいろと注意。
UStream配信されています等々。

DNSの基本的な知識はとりあえず知ってるし、BINDの使い方も少しは知ってるから補欠の人には悪かったかな・・・と思ったのが大間違いでした。
ついていくのがやっとでした・・・。
自分がどれだけ知らないことがあるか思い知らされたセッションでした。

開始

GMOインターネット タカノ様 が登壇されました。

こういった勉強会に対する会場の提供といったサポートをされているようです。

ここでConoHaのサービス紹介。

  • ConoHaはCompute Nodes With Hi-flexible Architectureの略。
  • OpenStack+KVMで実装されたサービス。
  • スナップショット機能もついてる。

OpenStackはAmazon Web ServicesのEC2のオープンソース版に近いものです。

OpenStackはオールインワン構成でインストールしたことはありますが、
複数のコンピュートノードをぶら下げて実装できなかった悔しい思い出があります。

色々なコンポーネントで構成されているのでこのインフラをメンテナンスするのは大変だろうなあと思います。

ところで、ConoHaのコントロールパネルは

で実装されているそうです。Python(Django)で実装されているやつとは別なんですね・・・。とても好感が持てます。

ここで、このはモードにしたことはありますか?との投げかけがありましたが何のことやらわからなかったのですが、
言語を 日本語 から このは 言語

f:id:wnoguchi0727:20140709222517p:plain

に変更すると

f:id:wnoguchi0727:20140709222519p:plain

三雲このはちゃんが背景にお目見えしました。
とてもかわいいですね。
会場のみなさんも知らなかったようで驚いてましたw

ぜひ、美雲このは ちゃんをフォローして下さいねとのことでした。

  • ConoHaちゃーじが増えた
  • Suicaっぽいデザイン

ご清聴ありがとうございました。

ちなみに、近いうちに同じフロアで

TechOYAJI~ドキッ!おやじだらけのLT大会!ポロリもあるよ – ConoHa | Doorkeeper
のご案内

といったイベントも開催されるそうです。ポロリはどうかわかりませんが・・・。

講演開始

いよいよ滝澤氏による講演が始まりました。
資料は以下を参照とのことです。

夏のDNS祭り 2014 ~入門セミナ&ハンズオン~ – 資料一覧 – connpass

まずはDNSのポートを開けるところから

資料はこちら。

rootユーザでやるのが気持ち悪い人は一般ユーザを作ってからやってくださいと言われました。
私もずっとrootで作業するのは気持ち悪いたちなので空き時間を見つけてやりました。
言われた時点でやるのは難しかったですね・・・。

iptables(FW)の設定

基本的な流れは次の様な感じですね。

  1. iptablesのルールを確認
  2. InboundのTCP, UDPの53番ポートの穴を開ける
  3. iptablesのルールが変わったことを確認
  4. ルールを保存

IPv4のFWを開ける

sudo iptables -nvL INPUT --line-numbers
sudo iptables -I INPUT 5 -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT
sudo iptables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 53 -j ACCEPT
sudo iptables -nvL INPUT --line-numbers
sudo service iptables save

IPv6のFWを開ける

sudo ip6tables -nvL INPUT --line-numbers
sudo ip6tables -I INPUT 5 -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT
sudo ip6tables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 53 -j ACCEPT
sudo service ip6tables save

digコマンドが使えることを確認。

[root@v157-7-234-198 ~]# dig +short . soa
a.root-servers.net. nstld.verisign-grs.com. 2014070401 1800 900 604800 86400

で、用意ができたらGoogleDocsのスプレッドシートを案内されました。
ここに自分のConoHa VPSIPv4アドレスと好きなラベル名を設定するようです。
Google Docsのリアルタイムコラボレーション機能を遺憾なく使った良い例だと思います。

最初は ifconfig やっちゃったけど、本当は ip addr が本式。obsolete ですから。

# ip addr | head
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether fa:16:3e:01:b2:d0 brd ff:ff:ff:ff:ff:ff
inet 157.7.234.198/23 brd 157.7.235.255 scope global eth0
inet6 2400:8500:1301:813:a157:7:234:198f/64 scope global
valid_lft forever preferred_lft forever

ところで、ConoHaのVPSIPv6アドレスが豊富に割り当てられていますねー。
使い方がわからなかったので使わなかったですが・・・。

もりだくさんでした・・・。

ここでDNSに関する基本的な説明

ホスト名をIPアドレスに解決するものをリゾルバと呼ぶ

/etc/hosts で見つからなかったらリゾルバはDNSにアクセスに行く。

DNSのプレイヤー

  • スタブリゾルバ(このPC)
  • フルサービスリゾルバ(リカーシブサーバ、DNSキャッシュサーバとも)/etc/resolv.conf に指定するサーバ
  • 権威ネームサーバ(Authoritative Name Server)

ここから本番

RFC1034/RFC1035 が基本的な使用。
それ以外は拡張仕様。

RFC2181 が曖昧な部分を明確にしようとしたもの

ルートのためにはnullラベルが用意されている。
ノードの

www.example.jp.

最後がドットで終わるのは空のラベルがあるから。

っていう理由があるのはかなり腑に落ちました。

  • マスターファイルは絶対ドメイン名で記述される
  • 最後にドットがついていないと相対ドメインとして扱われる。
  • digでも絶対ドメイン名で使用する
  • 0オクテットは空のラベルで予約されている
  • プロトコル上は8bitコードも許容されている

  • ケースインセンシティブ

  • 可能な限り大文字小文字を維持する
  • 興味のある方はRFC4343を参照。

ようやく休憩となりました。けっこうもりだくさんです。

一般ユーザーを作成する暇がなかったのでここで作成 visudo でパス無しで sudo できるように ec2-user を作成。
ここでも ec2-user を使いたくなるのはAWSに毒されている・・・。

休憩中によく聞こえてきたのはEC2のときはセキュリティグループでフィルタリングしちゃうからiptables忘れちゃったというお話でした。
あーなるほどなーと思いました。
僕の場合は自鯖で参考にするiptablesの自動生成スクリプトばっかり使ってたから戸別のルールを確認するのが疎かになってなってたのが仇になった感じです。

ちなみにiptablesの設定ファイルは以下のファイルで定義されています。(IPv4)

# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.4.7 on Sun Jul 13 08:30:43 2014
*filter
:INPUT ACCEPT [4278:5161614]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1971:96049]
-A INPUT -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 53 -j ACCEPT
COMMIT
# Completed on Sun Jul 13 08:30:43 2014
.tokyo
.nagoya

これもgTLD。最初、私はエイプリルフールのネタかと思いました。

予約済みTLD

  • test
  • examle
  • invalid
  • localhost
  • local

  • .local は使っちゃダメ。とのことでした。

  • 理由はRFC6762を読んでくださいだそうです。

こんなところに理由が書いてありました。

どさにっき

  • ARPAドメイン
  • ip6.arpa
  • リソースレコード(RR)
  • ホスト名やIPアドレスとと言った資源に関するデータ
  • これらをまとめて
  • RRsetとする
OWNER TTL CLASS TYPE RDATA
  • TTL=0のときはキャッシュ禁止を表す

  • CLASS

  • IN(Internet)
  • CH
  • HS

CHはネームサーバの情報の取得に使われている

dig TXT CH…
  • TYPE
  • RRの種類
  • A, NS, CNAME, SOA
  • RDATA(資源データ)

  • SOA

  • ゾーンの権威の開始
  • ゾーン転送はこのRRの設定によって動作する

  • ネガティブキャッシュのTTLであるため、86400のような大きな値を設定しないように。

  • NSにはCNAMEを使用してはいけない

  • AAAA(クワッドエイと読む)
  • .in-addr.arpa.
  • 1つのアドレスに複数のPTRレコードを記述できる

  • TXT

  • SPF
  • DKIM
  • DNSBL

様々な目的で使用される

RRは1行で示される

複数行になる場合はカッコ ()で括るそうです。

$ORIGIN example.com.
  • @はオリジンを意味する
  • ゾーン頂点のドメイン

  • $TTL TTL

  • デフォルトのTTLを指定した値に変更する

  • クラスINは省略可能

  • $INCLUDE ファイル名のファイルを挿入する

  • DNSメッセージ
  • EDNS0を使うとUDPでも

ちょっとここで怒涛のハンズオンが展開されましたが、ページをの大半を割いてしまうため、省略します。

ハンズオン – dig編

ゾーン転送が成功しているか調べる(シリアル値)ときはセカンダリサーバのシリアル値がプライマリサーバのシリアル値と一致していることを確認するそうです。目からうろこですね。

[ec2-user@v157-7-234-198 ~]$ dig conoha.jp. +nssearch
SOA ns1.gmointernet.com. hostmaster.gmointernet.com. 2014012105 3600 300 3600000 7200 from server 157.7.32.254 in 2 ms.
SOA ns1.gmointernet.com. hostmaster.gmointernet.com. 2014012105 3600 300 3600000 7200 from server 157.7.33.254 in 1 ms.
SOA ns1.gmointernet.com. hostmaster.gmointernet.com. 2014012105 3600 300 3600000 7200 from server 2400:8500:3fff::254 in 2 ms.
SOA ns1.gmointernet.com. hostmaster.gmointernet.com. 2014012105 3600 300 3600000 7200 from server 2400:8500:3000::254 in 1 ms.

ちなみに +multiline オプションをつけると綺麗に整形されて表示されるそうです。
便利ですね。

[ec2-user@v157-7-234-198 ~]$ dig @8.8.8.8 jp. SOA +dnssec +multiline
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.23.rc1.el6_5.1 <<>> @8.8.8.8 jp. SOA +dnssec +multiline
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20695
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;jp.            IN SOA
;; ANSWER SECTION:
jp.         21592 IN SOA z.dns.jp. root.dns.jp. (
1404543604 ; serial
3600       ; refresh (1 hour)
900        ; retry (15 minutes)
1814400    ; expire (3 weeks)
900        ; minimum (15 minutes)
)
jp.         21592 IN RRSIG SOA 8 1 86400 20140728174502 (
20140628174502 33429 jp.
RX0UdYgW3YBVNfIjvuyB8t1G630o7x2XZgIAZ0Ab8jyZ
G7YTCh2kdfFodJKdJYC9Xi+k9ecydB7V1cNqKm4/u1io
ejmKPGoU8SqYX+W5iUpH8JRMtXhi9tPg2+f1roZocuhc
tsgdEj7GzZLJzaWvjfPCLnDwhPjy7j6idxp9kkA= )
;; Query time: 66 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sat Jul  5 16:10:52 2014
;; MSG SIZE  rcvd: 240

リゾルバについて

スタブリゾルバ

  • キャッシュはMAY

フルサービスリゾルバ

  • キャッシュはMUST

  • 全世界に公開するとオープンリゾルバになってしまう

前々から気になっていて、質疑応答の時にGoogle Public DNS(8.8.8.8, 8.8.4.4)はオープンリゾルバですかと確認したのですが、
オープンリゾルバだそうです。だけど受けるところと出すところを別にしていたりシてかなり工夫しているらしいです。
すごいなー。

  • セカンダリは複数OK
  • マスター、スレーブ
  • スレーブからゾーン転送要求を行う

  • AXFRにはTCP

  • IXFRにはUDP

  • 伝搬遅延

  • NOTIFYで解決

  • ゾーン転送(NOTIFY)についてはRFC1996

オープンリゾルバであることの何が悪いのか

  • UDPのソースIPは簡単に詐称できる
  • DNSリフレクション
  • 毒入れをしやすくなる

講師さんが前述のGoogleスプレッドシートの別のシートに転写した内容をコピペして makezone.sh で自動生成されました。
シェル芸職人・・・。

Unbound

今回はBINDを使わないそうです。
というかBINDはBIND10で開発が終了してしまったらしく、次のものも微妙?なのだそうです。

ここではフルサービスリゾルバにUnbound、権威サーバにNSDを使います。

日本Unboundユーザー会

滝澤氏が翻訳されたサイトとのことです。

Unbound

  • Unbound 1.4.14以降、この2年間は脆弱性はみつかっていない
  • RHEL7は標準でUnboundはインストールできる。
  • デフォルトの設定でローカル動作可能(オープンリゾルバとはならない)
  • NXDOMAIN

NSD

NSDの特徴

  • リゾルバ機能なし
  • 設定ファイルがシンプル
  • NSD 3.2.13以降は脆弱性は見つかっていない
  • 昨年NSD4がリリース
  • nsd-controlによる制御
  • パターン
    • 動的にゾーンの追加・削除が可能

ハンズオン – Unbound編

ConoHaのVPSでは標準でEPELのリポジトリが登録されているそうです。

sudo yum --enablerepo=epel install unbound
cd /etc/unbound
sudo cp -p unbound.conf{,.orig}
sed '/^.*#/ d;/^$/ d' unbound.conf

設定ファイルをコメント抜きで俯瞰すると以下のとおり。
なんだかYAMLっぽい。

server:
verbosity: 1
statistics-interval: 0
statistics-cumulative: yes
extended-statistics: yes
num-threads: 2
interface-automatic: no
outgoing-port-permit: 32768-65535
outgoing-port-avoid: 0-32767
max-udp-size: 3072
chroot: ""
username: "unbound"
directory: "/etc/unbound"
log-time-ascii: yes
pidfile: "/var/run/unbound/unbound.pid"
harden-glue: yes
harden-dnssec-stripped: yes
harden-below-nxdomain: yes
harden-referral-path: yes
use-caps-for-id: no
unwanted-reply-threshold: 10000000
prefetch: yes
prefetch-key: yes
rrset-roundrobin: yes
minimal-responses: yes
dlv-anchor-file: "/etc/unbound/dlv.isc.org.key"
trusted-keys-file: /etc/unbound/keys.d/*.key
auto-trust-anchor-file: "/var/lib/unbound/root.anchor"
val-clean-additional: yes
val-permissive-mode: no
val-log-level: 1
include: /etc/unbound/local.d/*.conf
remote-control:
control-enable: yes
server-key-file: "/etc/unbound/unbound_server.key"
server-cert-file: "/etc/unbound/unbound_server.pem"
control-key-file: "/etc/unbound/unbound_control.key"
control-cert-file: "/etc/unbound/unbound_control.pem"
include: /etc/unbound/conf.d/*.conf
  • 必要に応じて、interface, access-controlを
  • 設定
     - デフォルト値は⼩規模向けなので⼤規模向け
  • ⽤途の場合にはチューニングも⾏う。

このへんのハンズオンはかなり複雑なので省略します。

NSD

ハンズオン – NSD編

NSD 4のRPMパッケージは提供されていない。ので滝澤氏自身がビルドされたRPMをインストールしました。

[ec2-user@v157-7-234-198 ~]$ wget http://www.sub.emaillab.jp/nsd-4.0.3-1.el6.x86_64.rpm
--2014-07-05 17:29:52--  http://www.sub.emaillab.jp/nsd-4.0.3-1.el6.x86_64.rpm
www.sub.emaillab.jp をDNSに問いあわせています... 2400:8500:1301:813:a157:7:234:430, 157.7.234.43
www.sub.emaillab.jp|2400:8500:1301:813:a157:7:234:430|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 404 Not Found
2014-07-05 17:29:52 エラー 404: Not Found。

おっと、IPv4でダウンロードしないといけなかったですか。

[ec2-user@v157-7-234-198 ~]$ wget --4 http://www.sub.emaillab.jp/nsd-4.0.3-1.el6.x86_64.rpm
wget: unrecognized option '--4'
使い方: wget [オプション]... [URL]...
詳しいオプションは `wget --help' を実行してください。
[ec2-user@v157-7-234-198 ~]$ wget -4 http://www.sub.emaillab.jp/nsd-4.0.3-1.el6.x86_64.rpm
--2014-07-05 17:30:47--  http://www.sub.emaillab.jp/nsd-4.0.3-1.el6.x86_64.rpm
www.sub.emaillab.jp をDNSに問いあわせています... 157.7.234.43
www.sub.emaillab.jp|157.7.234.43|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 792320 (774K) [application/x-redhat-package-manager]
`nsd-4.0.3-1.el6.x86_64.rpm' に保存中
100%[====================================================================================================================================>] 792,320     --.-K/s 時間 0.04s
2014-07-05 17:30:47 (19.8 MB/s) - `nsd-4.0.3-1.el6.x86_64.rpm' へ保存完了 [792320/792320]

インストール。

[ec2-user@v157-7-234-198 ~]$ sudo rpm -ivh nsd-4.0.3-1.el6.x86_64.rpm
準備中...                ########################################### [100%]
1:nsd                    ########################################### [100%]

これ以降のハンズオンもかなり複雑でしたので省略します。

怒涛のハンズオンが終了していよいよLTに突入です。

LT

@tukiyo3 さんによる「 Web系,社内インフラ担当向けTips紹介 」

LT資料 (夏のDNS祭り 2014 ~入門セミナ&ハンズオン~) – Qiita
Tips – MindMeister 思考マップ

  • メールの送り合戦になってしまった
  • nagiosが上がると電話がかかるようにした
  • whoisで所属する社員一覧をとってきたり
  • シェル芸職人。

@toshi__ya さんによる「 DNSキャッシュサーバのベンチマークテスト 」

@toshi__ya

スライドはこちら。

Dns 20140705 up_ver

  • dnsperfを用いてDNSサーバの負荷試験を実施する。
  • BIND10を起動しただけだと権威サーバにもならなければキャッシュサーバにもならない
  • unbound.confのチューニングが必要だ!!
  • キャッシュメモリの量とか増やせばいい?

@twovs さんによる「パケットが教えてくれたルートサーバが 13個の理由 」

@twovs

スライドはこちら。

パケットが教えてくれた ルートサーバが 13個の理由

512バイト中に13個入るか試してみたそうです。

だが、途中で13個も入らないんじゃないかという結論に達しそうになり、

I can compress RRs a little. ワタシハ アッシュク チョットデキル

という事実に気付いたそうです。

Message Compressionを頑張って頑張って収まることがわかりました。
14個目も入るか試してみたそうです。
収まったそうです・・・。

がんばればrootサーバ14個もいける。

DNS勉強会の開場ネットワークを作ってみた

LTではありませんが、最後にこの勉強会のインフラを構築してくれた方々よりご紹介がありました。

  • PyConのネットワークを構築する
  • 快適なネットワークを皆様に届けたい!!
  • splunk
  • VPN Gate
  • L2スイッチの下に

routerboard

  • syslogやSNMPの取得が可能
  • 持ち込んだスイッチのSpanning-treeが生きておりUplinkがShutdown

BuffaloのAP買ってこようかとした!

IPv6をどうやって構築したか

SoftEtherPacketiXで自宅にVPNしてIPv6貫通してた。
会場で驚きの声があがりました。

Splunk

リアルタイムにログを可視化できる。

まとめ

怒涛のハンズオンは終了いたしました・・・。
うーん、最後のNSDのハンズオンは苦戦してしまいうまくいきませんでした。

ただ、自分の知っているようで知らなかった事実が色々とあって、
BINDとか少し設定できるし、ちょっと復習的な感じになるのかなーと思っていましたが、
大違いで、いい感じで期待を裏切られました。

懇親会に参加しました

渋谷人多い!

その後は生まれ始めて勉強会の懇親会にも参加して色々な方とお話することができました。
自宅ラック勉強会の方々やハートビーツの講師滝澤さんともお話することができました。
ガチでインフラ系のエンジニアの方々の生の声が聞けてかなりネットワーク関係の自分の知識不足感を実感して
いい刺激を受けることができました。

どちらかというとWeb系のシステムエンジニアなので、異なった視点の話題を交わすことができてとても面白かったです。

以上、DNSがちょっとできるようになった体験記でした。

awscliでec2インスタンスを操作する

よく忘れるので基本的な操作方法のまとめ。

インスタンスの操作

インスタンスを作成

  • AMI IDを調べてメモる
  • 立ち上げたいインスタンス
  • インスタンスタイプ: 現状t2.microが最小(2014/7/8現在)
  • 使用するキーペア
  • 適用するセキュリティグループ
% aws ec2 run-instances --image-id ami-29dc9228 --count 1 --instance-type t2.micro --key-name default --security-groups hoge | jq '.'

AZを指定する

--placement AvailabilityZone=ap-northeast-1a をつけてやればいい。

aws ec2 run-instances --image-id ami-29dc9228 --count 1 --instance-type t2.micro --key-name default --security-groups web --placement AvailabilityZone=ap-northeast-1a | jq '.'

DeleteOnTerminationを避ける

今ではほとんどEBSから起動されるEC2インスタンスがほとんどだが、このままでは DeleteOnTermination=true となってしまっているので、インスタンスをterminateするとインスタンスに紐付けられているボリューム自体も削除されてしまう。

これを避けたいなら

% aws ec2 run-instances --image-id ami-29dc9228 --count 1 --instance-type t2.micro --key-name default --security-groups hoge \
--block-device-mappings "[{\"DeviceName\": \"/dev/xvda\",\"Ebs\":{\"DeleteOnTermination\": \"false\"}}]" | jq '.'

としなければならない。面倒だが。

既に作成されたインスタンスについて DeleteOnTermination=true としたい場合は

% aws ec2 modify-instance-attribute --instance-id i-dfff36d1 --block-device-mappings "[{\"DeviceName\": \"/dev/xvda\",\"Ebs\":{\"DeleteOnTermination\": \"false\"}}]" | jq '.'

とすればいい。

インスタンスを起動

% aws ec2 start-instances --instance-ids i-xxxxxxxx | jq '.'

インスタンスを停止

% aws ec2 stop-instances --instance-ids i-xxxxxxxx | jq '.'          

停まったかどうか確認。

% aws ec2 describe-instances --instance-ids i-xxxxxxxx | jq -r '.Reservations [] .Instances [] .State .Name'
stopped

インスタンスを削除(terminate)

% aws ec2 terminate-instances --instance-ids i-xxxxxxxx | jq '.'

jqで欲しい値をとってくる

インスタンスID

% aws ec2 describe-instances | jq -r '.Reservations [] .Instances [] .InstanceId'
i-xxxxxxxx

グローバルIPアドレス

% aws ec2 describe-instances | jq -r '.Reservations [] .Instances [] .PublicIpAddress'
xxx.xxx.xxx.xxx

PublicDNS名

% aws ec2 describe-instances | jq -r '.Reservations [] .Instances [] .PublicDnsName'
ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com

SSHで接続するとき

単なる覚え書き。

ssh ec2-user@xxx.xxx.xxx.xxx -i ~/.ssh/foobar.pem

References

  1. run-instances — AWS CLI 1.3.21 documentation
  2. start-instances — AWS CLI 1.3.21 documentation
  3. stop-instances — AWS CLI 1.3.21 documentation
  4. terminate-instances — AWS CLI 1.3.21 documentation
  5. describe-instances — AWS CLI 1.3.21 documentation

awscliでt1.microインスタンスをたちあげようとしたら怒られたでござる

t1.microインスタンスawscliから立ち上げようとAMI ID調べて立ち上げようとしたら失敗した。

% aws ec2 run-instances --image-id ami-29dc9228 --count 1 --instance-type t1.micro --key-name default --security-groups hoge | jq '.'
A client error (InvalidParameterCombination) occurred: Non-Windows instances with a virtualization type of 'hvm' are currently not supported for this instance type.

このインスタンスタイプはサポートしてないぞゴルァ!と怒られてしまいました。
しかたなくManagement Consoleからどんなタイプが選べるのか確認してみると t2.micro というインスタンスタイプが・・・。
「無料枠に最適!」って書いてあったのでこれで立ち上げてみました。

% aws ec2 run-instances --image-id ami-29dc9228 --count 1 --instance-type t2.micro --key-name default --security-groups hoge | jq '.'
{
"Instances": [
{
(snip)
}
],
"Groups": [],
"ReservationId": "r-ffffaaaa",
"OwnerId": "ffffffffffff"
}

うーん、今度からはt1.microインスタンスじゃなくてt2.microインスタンスっていう新しい最小のインスタンスタイプが追加された?変更された?みたいだ。
発表は2014/7/1とタイムリー。
T2インスタンスにはCPUクレジットという概念が追加されたみたい。
バーストするけど、クレジット消費してしまっても極端には性能は落ちませんよってことかな?

References

  1. dogmap.jp を t1.micro から t2.micro に変更してみました | dogmap.jp
  2. Amazon Web Services ブログ: 【AWS発表】バースト可能な性能を持つ新しい低コストEC2インスタンス

awscliでセキュリティグループを定義する

このへんは手でやったほうが早い気がしないでもない。
CloudFormationとかだといろいろよろしくやってくれるんだろうか。
まだその辺の境地にも達してないけど・・・。

セキュリティグループの作成

% aws ec2 create-security-group --group-name web --description "Web server role security group."
{
"return": "true",
"GroupId": "sg-ffffffff"
}

Inbound方向の規則を定義する

ping(ICMP)応答

aws ec2 authorize-security-group-ingress --group-name web --protocol icmp --port -1 --cidr "0.0.0.0/0" | jq '.'
{
"return": "true"
}

SSH

% aws ec2 authorize-security-group-ingress --group-name web --protocol tcp --port 22 --cidr "0.0.0.0/0" | jq '.'
{
"return": "true"
}

HTTP

% aws ec2 authorize-security-group-ingress --group-name web --protocol tcp --port 80 --cidr "0.0.0.0/0" | jq '.'
{
"return": "true"
}

Outbound方向

Outbound(authorize-security-group-egress)方向はデフォルトで全通過。

まとめると

aws ec2 create-security-group --group-name web --description "Web server role security group." | jq '.'
aws ec2 authorize-security-group-ingress --group-name web --protocol icmp --port -1 --cidr "0.0.0.0/0" | jq '.'
aws ec2 authorize-security-group-ingress --group-name web --protocol tcp --port 22 --cidr "0.0.0.0/0" | jq '.'
aws ec2 authorize-security-group-ingress --group-name web --protocol tcp --port 80 --cidr "0.0.0.0/0" | jq '.'

逆の操作

セキュリティグループに対して以下の様な操作を行うと22番ポートが封じられるのでSSH不能になる。
CIDRまできちんと記述しないといけないので注意。

aws ec2 revoke-security-group-ingress --group-name web --protocol tcp --port 22 --cidr "0.0.0.0/0" | jq '.'

ただし、ICMP規則を削除するときは

aws ec2 revoke-security-group-ingress --group-name web --protocol icmp --port -1 --cidr "0.0.0.0/0" | jq '.'

に関してはいったんpingを止めないとpingをずっと受け入れ続けてしまうみたいなので、いったん Ctrl+C でとめてからもう一回pingを打ってみると通らなくなることが確認できる。

References

  1. authorize-security-group-ingress — AWS CLI 1.3.21 documentation
  2. authorize-security-group-egress — AWS CLI 1.3.21 documentation

「Security Casual Talks 2014#2 (すみだセキュリティ勉強会)」に行ってきました

6/7に開催されたすみだセキュリティ勉強会に行ってきました!

f:id:wnoguchi0727:20140607120537j:plain

開催して3, 4日のうちには書くぞって思ってたのにこんなに時間が空いてしまいました。
いかんいかん・・・。

私の妄想がふんだんに盛り込まれている可能性が高いので雰囲気だけ味わってください。

現地まで

総武線で一本で亀戸駅までゆるりと・・・。
会場はすぐに見つかり、池袋よりは迷うことはありませんでした。
池袋は迷路ですわあ・・・。

現地についてから

9:30ころに到着。
ちょっと早めに着いてしまったので、会場の設営のお手伝いをさせていただきました。
椅子を前に移動する。ちょっともたついてしまった。(汗)

事前に買っておいたボイスレコーダーで録音してもいいですかと確認しましたが、
一部の方はOKですが、他の方は確認が必要とのことでした。残念。
でも、セキュリティの勉強会ですし、仕方ないですよね。

発表順スライド

  1. 無線LANデンパゆんゆん観察
  2. CRYPT+YOU, UNDERSTAND TODAY!
  3. Metasploitでペネトレーションテスト

開場

な、なんと

会場内に無線LANの設備はありません(すみません)

の文字が・・・。

とのことでしたので、テザリングで実況中継等してました。
ノートは適宜Evernote手書きノートで。
手書きノートは結局タイトルしか書かなかったな・・・。

と、ここで

「Metasploitやったことありますかー?」→ちらほら挙手

ぼくはやったことも聞いたこともなかったので挙手しませんでした。

簡単な自己紹介タイム

「wnoguchiと申します。
プログラマですが、インフラ全般に興味があります。」

終了。

人がいっぱいです!!

発表:無線LANデンパゆんゆん観察 (@ozuma5119)

  • ISP 4月転職
  • 理科っぽい写真をとってる

みんなWEPキーを破りたい!

その前に電波法

電波法とかやっとかないと逮捕者が出てしまいます。

セキュリティエンジニアやるには法律には気をつけて欲しい。

電波法59条

何人も法律に別段の定めがある場合を除くほか、特定の相手方に対して行われる無線通信
電気通信事業法第4条第1項又は第164条第2項の通信であるものを除く。
第109条並びに第109条の2第2項及び第3項において同じ。)を傍受して
その存在若しくは内容を漏らし、又はこれを窃用してはならない。

Wirsharkとかのパケットキャプチャについて
  • 傍受は大丈夫。
  • 公共の場で無線APのSSIDを公開したらかなり黒に近いグレー

f:id:wnoguchi0727:20140618224655p:plain

  • 航空無線も漏らしてはいけない!!
  • 羽田空港で聞いてる人がいる。でも内容は決して教えてくれないはずです。
  • 電車オタクも同様。
電波法59条まとめ
  • 傍受はいくらでもOK。
  • 漏らしちゃダメよ。

電波法60条

無線局には、正確な時計及び無線業務日誌その他総務省令で定める書類を備え付けておかなければならない。
ただし、総務省令で定める無線局については、これらの全部又は一部の備付けを省略することができる。

無線LANを運用していたら無線日誌をつけなきゃいけない?

自宅の無線LANは無線業務日誌は省略してかまわない。

電波法の注意点がわかったところでさっそくWEPをやぶってみよう

  • WPA2は一般的
  • WEPは超弱い

  • IV(initialization vector)キー

  • 暗号キー(WEPに設定するパスワード)
  • これらから鍵(擬似乱数列)になる

WEPの破りやすさ

  • IV初期化ベクトルが24bitで弱い
  • 認証と暗号の鍵が同一で鍵を変えない

Wireshark無線LANに慣れる

  • アイトリプルイーエイトオートぅ~どっとわんわん
  • IEEE802.11
wlan.bssid == 00:ff:ff:ff:ff:ff
  • 無線LANのフレームはBSSIDで絞り込むのがおすすめ

  • 無線LANフレームのサンプル:ビーコンを見てみたい

  • 無線LANの一覧はこのビーコンで拾ってる

  • 暗号化してもSSIDは見れる

  • WEPで暗号化されたパケット

  • IV(初期化ベクトル)は平文で送られてくる

Wireshark飽きた

  • aircrack-ngというツール
    Macだとインストールがめっちゃめんどくさい
  • Ubuntuという神の手によって作られたディストリなら一発
  • karilinuxというものがある

  • BSSID:ESSIDは違う

  • チャンネル番号をメモしとくと便利

あんちょこを用意してましたー

~10分程度でやぶれる

質疑応答

  • アダプタをモニタモードにしないといけない
  • 対応していないのもあるからNICを変えてみたら?

@inaz2 さん

  • マルチSSID
  • WEP
  • WPA2
  • 同じパスにしちゃだめだよ。

発表:CRYPT+YOU, UNDERSTAND TODAY! (@inaz2)

暗号大事

  • X.509とか802.11Xとかのキーワードが交じる
  • PEM, CSR, RADIUS

暗号という概念に限って言えばそれほど難しくない

  • 換字式暗号
  • 文字単位、あるいはブロック単位で置き換える

2014/05/05 NSA採用担当さんがなんか言った

全自動解読機あります。

解読後

want to know what it takes to work at nsa?
check back eachmong ad in mad as we explore careersessential to protect in your nation.

XORスクランブルの復元

RC4

  • 共通鍵暗号方式のうち、ストリーム暗号と呼ばれるもののひとつ
  • Winnyでもこれが使われている
  • RC4のバイアス問題

AES

  • 共通鍵暗号方式のうち、ブロック暗号と呼ばれる
  • いい感じにぐちゃぐちゃになる
  • でも鍵がわかれば元に戻せるよ

暗号利用モード

  • ADOBE PASSWORD BREACH
  • 暗号化されていたがECB Mode。使っちゃいけない

CBCモードが有効

RSA

openssl genrsa 192 | openssl rsa -modulus
  • 768ならまずむり
  • スパコンが本気だせば半年で終わる
  • 2048, 4096が一般的

RSAの使われ方

  • データそのものの暗号化にはほとんど用いられない
  • 鍵共有
  • デジタル署名

BIG BROTHER MIGHT BE WATCHING YOU

RSA秘密鍵を盗まれたら鍵共有で交換していた共通鍵がばれる。

DH(Diffie-Hellman)

鍵共有プロトコル

PERFECT FORWARD SECRECY

  • 通信のセッションごとに違う共通鍵を使って暗号化
  • セッションごとに鍵を変える場合を特にDHE(Ephemeral)と呼ぶ
  • 最近Twitterがこれを適用した

SSL/TLS’S CIPHERSUITE

  • デッキみたいなもの
  • SSL/TLSにて、使用する暗号の組み合わせを表したもの
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

基礎は大事!!

発表:Metasploitでペネトレーションテスト (@super_a1ice)

  • 大学院生
  • 池袋セキュリティ勉強会参加してた

Metasploit Framework基本

ここまでで聞いているのがやっとなくらいに難しい単語が並ぶ@@;

Webアプリケーションの脆弱性をついてみよう

代表的な例で「OSコマンドインジェクション」。

<?php
$cmd=‘whois ‘ . $_GET[‘ip’];
$result =

こういうのをやるときは周りに迷惑をかけないように仮想マシンでやるといい。
VirtualBoxならHostOnlyAdapterなどを使うなどして細心の注意を払ってやってください。

Exploitを使って電卓を起動してみよう

方法は2つある。

  1. exploit-dbから探す
  2. 自作する

.

  • Immunity Debugger
  • mona

WinXPにて・・・

さっきのpythonのコードを実行して、生成されたHTMLをメモ帳で開く。
閉じようとするとcalcが立ち上がる!
普通に動かせる。

すごい以外の言葉が見つからない。

質疑応答

このあたりのツールを前向きないいことに使う方法はありますか?

  • マルウェア検知に使えたり
  • 防御側として攻撃手法を知っていく必要があるため、実際にやってみるのは有益
  • 脆弱性検査をお願いされた場合はこういう確認の意味として使用することも有用である

まとめ

無線APのWEPキーを破るのとかとても興味深いテーマで、解読していく過程や、電波法に関する豆知識もとても勉強になりました。
試しに無線AP手に入ったらやってみたいです。あーでもやりたいこといっぱいある。

暗号化理論は難しくて私にはよくわからないけど、Diffie-Hellmanとか認証関係で頭悩まされた単語なので親しみ深かったです。

ペネトレーションテストツールである?Metasploit Frameworkをとても興味深いツールでした。
攻撃者の攻撃手法を身をもって体感してみるのもセキュリティエンジニアとしての努めかなと思ってみたり。
karilinuxは近いうちに触ってみたいディストリビューションですね。

とりあえず登壇された方はフォローさせていただきました。

残って食事会にでも参加してみたかったのですが、駅前でかき揚げ天玉そばを食べて帰りました。

また今度ご一緒したいです!

参考文献

  1. すみだセキュリティ勉強会
  2. Security Casual Talks 2014#2 (すみだセキュリティ勉強会) : ATND
  3. ももいろテクノロジー
  4. Metasploit – Wikipedia
  5. Security Casual Talks 2014#2(すみだセキュリティ勉強会)に参加してきました – 夜はいよいよ冴えたのだ。
  6. quippiuq – cryptoquip and cryptogram solver