2018年2月16日

RubyのCGIをGoogle Cloud Platformの無料枠で動かしたい ~(2)SELinuxの設定

SELinuxでCGIスクリプトが500エラーになる

RubyのCGIをGCP(Google Cloud Platform)の無料枠で動かしたい~(1)セットアップ の続きです。

CGIスクリプトをブラウザから実行しようとして 500 Internal Server Error が出る場合、SELinuxの設定変更が必要かもしれません。

対策として「SELinuxをオフにすれば動きます」という大胆なブログ記事も見かけますが、できることならセキュアな状態で使いたいものです。GCPは世界中から狙われやすそうですし。
SELinuxを有効にしたままCGIを動かせるよう設定します。

問題を切り分ける(本当にSELinuxのせい?)

SELinuxを一時的に停止して、本当にSELinuxのせいなのかを切り分けます。
# setenforce 0
# getenforce ←確認
Permissive
permissiveモードは完全無効化とは違い、アクセス制御は行ないませんがログを出力します。

まずは超簡単なシェルスクリプトを /var/www/cgi-bin/test.cgi あたりに配置してみます。
#!/bin/sh
echo Content-type:text/plain
echo
echo ok!
パーミッションは755にでもして、コマンドラインで実行できることを確認します。
# cd /var/www/cgi-bin
# ./test.cgi
Content-type:text/plain

ok!
シェル上では問題なく実行できるのに http://~/cgi-bin/test.cgi にブラウザでアクセスしてエラーが出るようなら、そもそもSELinuxとは別のところに問題がありそうです。
  • Apacheの設定は正しいですか? apachectl configtest の結果は?
  • httpd.conf編集後に systemctl reload httpd しました?
  • cgiファイルのパーミッションは適切ですか?(Apacheユーザに実行権限はあります?)

シェルスクリプトで問題なかったら、次はRubyのCGIスクリプトを /cgi-bin に置きます。
#!/usr/local/bin/ruby
puts "Content-type: text/plain"
puts
puts "Ruby!"
まずはコマンドラインで実行します。ここで動かないならRubyが正しく導入できていないことになります。
次にブラウザからアクセスしてみます。エラーになるなら、スペルミスやファイルパーミッションなどを確認します。

ここまで確認して問題がなかったなら、SELinuxを元に戻してみます。
# setenforce 1
# getenforce
Enforcing
これで再びエラーが出るようになったなら、さすがにSELinuxが原因と言えそうです。

SELinuxでCGIを動かすための基本設定 (httpd_enable_cgi)

そもそもCGIが無効になっていると動きません。
# getsebool httpd_enable_cgi
httpd_enable_cgi --> off
offになっていたらonにします。
# setsebool -P httpd_enable_cgi 1

SELinuxコンテキストの設定 (httpd_sys_script_exec_t)

SELinuxでは「コンテキスト」という概念があって、適切なコンテキストが設定されていないと動作が阻止されます。
CGIの場合、ファイルが httpd_sys_script_exec_t というタイプになっている必要があります。

コンテキストは ls コマンドの -Z オプションで表示できます。
# ls -aZ /var/www/cgi-bin
drwxr-xr-x. root root system_u:object_r:httpd_sys_script_exec_t:s0 .
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 ..
-rwxr-xr-x. root root unconfined_u:object_r:user_home_t:s0 test.cgi
末尾が _t となっている部分がタイプです。test.cgiファイルは user_home_t タイプになっており、これではSELinuxに止められます。

chcon コマンドでタイプを変更します。
# chcon -t httpd_sys_script_exec_t test.cgi
# ls -Z test.cgi
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_script_exec_t:s0 test.cgi

GCEのCentOS7なら、ここまですれば全く動かないということはないと思いますが、それでも動かない場合はログを見ながら原因を探ることになります。
# audit2allow -wa
ログの読み方と対処法はここでは説明しきれないので、ハマってしまったらがんばってください……。

/var/www/html 以下でもCGIスクリプトを動かしたい (httpd_sys_script_exec_t)

CGIファイルを /var/www/cgi-bin ではない場所に置きたい場合、先ほどと同じくCGIファイルのタイプを httpd_sys_script_exec_t にすればOKです。
# cd /var/www/html
# ls -Z test.cgi
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 test.cgi
# chcon -t httpd_sys_script_exec_t test.cgi
# ls -Z test.cgi
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_script_exec_t:s0 test.cgi

/var/www/cgi-bin では動作するのに /var/www/html では動かない、という場合はApacheの設定を見直します。Options に ExecCGI は入ってますか?

SELinuxコンテキスト設定の永続化と適用 (restorecon)

ひととおり動作することが確認できたら、デフォルトのタイプ設定として永続化することができます。
パスは正規表現で指定します。
# semanage fcontext -a -t httpd_sys_script_exec_t '/var/www/html/.*\.cgi'
# semanage fcontext -lC
SELinux fcontext                                   type               Context
/var/www/html/.*\.cgi                              all files          system_u:object_r:httpd_sys_script_exec_t:s0
これで /var/www/html/ 以下の(サブディレクトリも含む)拡張子.cgiのファイルのデフォルトタイプが httpd_sys_script_exec_t になりました。

デフォルト設定すればいちいち chcon しなくても済むのですが、残念ながらファイルを新しく作ると自動的にデフォルトタイプになるわけではありません。
初期タイプは、ファイルの属するディレクトリから受け継ぎます。
# touch /var/www/html/test2.cgi
# ls -aZ /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 .
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 ..
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 test2.cgi
ファイルのデフォルトタイプを適用するには restorecon を使います。
# restorecon -v test2.cgi
restorecon reset /var/www/html/test2.cgi context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:httpd_sys_script_exec_t:s0
# ls -Z test2.cgi
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_script_exec_t:s0 test2.cgi

結局ファイルを作るたびにタイプ変更のコマンドを叩く必要があるなら、デフォルト設定って何の役に立つの? という気持ちになるかもしれませんが、restorecon は chcon と違ってタイプを具体的に指定しなくて済むのはメリットです。

CGIスクリプトからファイルに書き込みたい (httpd_sys_rw_content_t)

CGIの実行は可能になったものの、CGIスクリプトからファイルに書き込もうとするとSELinuxによって阻止されます。
たとえ書き込み先のファイル権限が 666 であってもです。

書き込み先のファイルにはSELinuxのタイプ httpd_sys_rw_content_t が必要です。
ファイルをCGIスクリプトから作成したい場合は、書き込み先のディレクトリにも同タイプを設定します。

chcon で毎回設定してもいいですが、たとえば data という名前のディレクトリは一律でデータ用とするなら、デフォルト設定にしてもよいでしょう。
# semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/html(/.*)?/data(/.*)?'
これで /var/www/html 以下の data ディレクトリと、dataディレクトリ内のすべてのファイルやディレクトリのデフォルトタイプが httpd_sys_rw_content_t になります。

data ディレクトリを httpd_sys_rw_content_t タイプにしておくと、CGIスクリプトでデータファイルを新規に作成した場合、ファイルのタイプは自動的に httpd_sys_rw_content_t になります。新しく作ったファイルはディレクトリのタイプを受け継ぐためです。

CGIスクリプトから通信したい (httpd_can_network_connect)

CGIスクリプトからローカルファイルの読み書きは可能になりましたが、スクリプト内で通信をしようとするとSELinuxに阻止されます。
curlを呼んだりしたい場合は、通信の許可設定が必要です。
# setsebool -P httpd_can_network_connect 1

httpd関連だけSELinuxを止めたい(permissive_httpd_t)

とりあえず以上の設定でCGIスクリプトはひととおり動くはずですが、どうしてもエラーが解消しきれなくて時間がない場合、SELinuxを丸ごと permissive モードにするのではなく、httpd 関連のみ permissive にする方法もあります。
# semanage permissive -a httpd_t
# semodule -l | grep permissive
permissive_httpd_t      (null)
permissivedomains       (null)

問題が解決したら元に戻します。
# semanage permissive -d httpd_t

2018年2月2日

RubyのCGIをGoogle Cloud Platformの無料枠で動かしたい ~(1)セットアップ

RubyのCGIをGCPで(無料で)動かしたい

自分で使う用のこまごまとしたWebアプリを動かすために手頃なレンタルサーバーを借りていたのですが、年契約の更新時期が来ました。
ふと思い出したのが昨春Google Cloud Platform(GCP)の無料枠拡大の話。2年目以降も無料で使えるのはかなり限られた構成になりますが、自分しか使わないサーバーなのでスペックは足りそう。乗り換えてみることにしました。

GCP(の無料枠)でPHPやRuby on Railsを動かすための情報はいくつか見つかったのですが、CGIの話は見当たらなかったので、作業記録やひっかかりポイントを書き残しておきます。

無料トライアルに申し込む

無料枠内しか使わないつもりでも、クレジットカードの登録は必要です。

申込みから初期セットアップまでの手順はいろんな方がまとめてくれているので、ここでは改めて書きません。たとえば下記などを参考に。

OSはCentOS 7にしました。個人的にはDebianのほうが慣れていますが仕事だとCentOSが多いので、これを機に馴染んでおこうかと。

他、ポイントとしては:
  • ゾーンはus-westを選びます。usしか無料にならないので、せめて日本から一番近い西海岸を
  • ディスクサイズはせっかくなので無料枠の上限である30GBに上げます
  • 固定(静的な外部)IPアドレスを割り当てます(1つなら無料)

最低限の初期設定

GCE(Google Compute Engine)のVMインスタンスが起ち上がったら、Web上の管理画面からブラウザ上で動くSSHクライアントを起動できます。
最終的には手元のPC等のネイティブSSHクライアントから入ったほうが快適なのですが、とりあえずの作業はブラウザからでも事足ります。ちょっとレスポンスが遅いのが難点ですが。

ブラウザSSHだとbash上でCtrl+Wを叩くと、1語消えるかわりにブラウザが「このサイトを離れてもよろしいですか?」と訊いてくる問題もありますが、ChromeならSSH for Google Cloud Platform 拡張機能をインストールすればCtrl+WもCtrl+NもCtrl+Tも叩き放題です。

最低限、次のあたりを設定しておきます。
  • 22番ポートをファイアウォールで遮断。セキュリティ対策
  • 代わりに適当なポートでSSHで入れるように
  • タイムゾーンを日本に
    $ sudo timedatectl set-timezone Asia/Tokyo

ほかはお好みで。

Apacheをインストール

$ sudo yum install httpd
/etc/httpd/conf/httpd.conf などを適宜編集したら、
$ sudo systemctl enable httpd

DNSやSSLの設定は後回しにして、いったん手元のPC等から http://IPアドレス/ でwelcomeページを表示できることを確認します。
表示できない場合は、Apacheやファイアウォールなどの設定を見直します。

ところで CentOS 7 ではサービスの制御は systemctl を使いますが、httpd.conf を編集した後に反映させるのは graceful ではなく reload です。
$ sudo systemctl graceful httpd
Unknown operation 'graceful'.
$ sudo systemctl reload httpd
$ (反映された)

/usr/lib/systemd/system/httpd.service には次のように定義されており、ちゃんと graceful してくれます。
(略)
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
(略)



yumのRubyは古い

Rubyもyumで…と思いきや、バージョンがずいぶん古いのでした。
$ yum info ruby
(略)
Available Packages
Name        : ruby
Arch        : x86_64
Version     : 2.0.0.648
Release     : 30.el7
(略)
仕方ないのでrbenvを入れて自分でビルドします。
ちょっと重い作業になりますが、レンタルサーバーと違って新しいバージョンが使えるというのはうれしいものです。いまだに1.8しか使えないレンタルサーバーとかありますし……。

Rubyビルドの事前準備(パッケージ導入・スワップファイル作成)

ビルドに必要なパッケージを入れます。
$ sudo yum -y install git gcc openssl-devel readline-devel
(他にも何か入れたかも。ビルド中にエラーが出たら適宜yum installしてください)

最初、このままビルドに進んだら途中でメモリ不足になってしまいました。
無料枠のf1-microインスタンスのメモリは0.6GB。国民機PC-9801の1000倍ですが、それでも足りないようです。

スワップファイルを作ります。
$ sudo su -
# dd if=/dev/zero of=/swapfile bs=1M count=1024
# chmod 600 /swapfile
# mkswap /swapfile
# swapon /swapfile
# free -m
           total       used       free     shared buff/cache  available
Mem:         588        148        319          4        119        323
Swap:       1023          0       1023

1GBにしたのにはキリがいいからですが、推奨値はRAMの2倍なので1.2GBのがよかったのかもしれません。ただ、1GBでもRuby 2.5.0のビルドには問題ありませんでした。

今後もスワップファイルを常用したければ /etc/fstab に書きます。
/swapfile       swap    swap    defaults        0 0

rbenvをシステム全体で使えるようにインストール

rbenvの基本的な導入方法は https://github.com/rbenv/rbenv に書かれているとおりですが、~/.rbenv/ にインストールしてしまうとCGIで使うにはちょっと不便です。システム全体で使えるよう /opt/rbenv に導入することにします。

rbenvを /usr/local 以下に導入した話をよく見かけますが、FHS(Filesystem Hierarchy Standard)では /usr/local には任意のディレクトリを作ってはならないと規定されています。パッケージ名でディレクトリを作りたければ /opt を使うそうです。

.bash_profile に書く設定は代わりに /etc/profile.d/ 以下に置けば、自動的に全員にロードされます。
# git clone https://github.com/rbenv/rbenv.git /opt/rbenv
# echo 'export RBENV_ROOT="/opt/rbenv"' >> /etc/profile.d/rbenv.sh
# echo 'export PATH="${RBENV_ROOT}/bin:${PATH}"' >> /etc/profile.d/rbenv.sh
# echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh
# . /etc/profile.d/rbenv.sh

Rubyをビルド・symlink作成

Rubyのバージョンは事情に応じて選びます。
特に事情もないなら最新版(現時点では2.5.0)でよいかと。
# mkdir -p "$(rbenv root)"/plugins
# git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
# rbenv install 2.5.0
(20分くらいかかりました)
# rbenv global 2.5.0
# ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]

このままでもRubyは実行できますが、CGIスクリプトのファイル1行目を次のように書くことになります。
#!/opt/rbenv/shims/ruby
ちょっと見慣れなすぎて覚えられなさそうなので、見知ったパスにシンボリックリンクをはってしまいます。
# ln -s /opt/rbenv/shims/ruby /usr/local/bin/ruby

SELinuxの設定変更

この状態でももうCGIスクリプトは動作するのですが、cgi-bin ディレクトリ以外に置くと 500 Internal Server Error になってしまいます。
/var/www/html 以下でもCGIスクリプトは動かしたい場合、SELinuxの設定変更が必要です。

長くなってきたので次回の記事で。

2017年9月9日

ノートPCのDVDドライブをお安く換装したい(2)

前回のあらすじ

9.5mm厚の内蔵DVDドライブが欲しいのだけど、いちばん安かったのが外付けドライブ。
Qtop ポータブルドライブ 外付けプレイヤー USB3.0対応 CD-RW/DVD-RW タッチ制御 Superdrive搭載 Windows/Mac両対応-ブラック ¥2,188

うまいこと分解して中身を取り出せるでしょうか?

箱・同梱品・外観

最近は中国製品でもちゃんとした化粧箱に入っているものが多くなりました。

箱の裏面は英語と中国語。

開けるとDVDドライブ本体の他にケーブルが2本。
USB3.0ケーブルと、補助電源ケーブル。補助電源はUSBタイプA⇒DCプラグ。


本体外観

天面にあるのはイジェクトのタッチセンサー。

誤動作防止のためか、軽く触れただけでは反応せず、1秒くらい触れ続ける必要があります。
通常のイジェクトボタンよりも操作しやすい位置にあって、なかなか便利。このまま外付けで使いたいくらい。

端子はUSB3.0と補助電源。

裏側。


分解

ぱっと見、ネジ穴は見当たらず。
接着剤やツメで固定するタイプだとしたら、バラしづらいし再組立も難しくてガッカリですが……。

シールになっているゴム足を剥がすと、ネジが見つかりました。端子側の2ヶ所。(ベゼル側のもう2ヶ所にはネジは隠れていませんでした)


ネジ2本を外すだけ。接着剤は使われていませんでした。

ドライブのラベル。

型番は DA-8AESH、メーカーは PLDS(Philips & Lite-On Digital Solutions Corporation)。
無事9.5mmのSATAでした。

ちなみにWindowsからだと次のように認識されます。


話を戻して分解の続き。
とはいえドライブも基盤も固定されていないのでそのまま取り外せます。

基盤の枠で囲ったところは上からSATA端子、USB端子、タッチセンサー。

壊れた旧ドライブと比較。端子もネジ穴も位置が共通なのが分かります。


ベゼルのツメ

ベゼルは2ヶ所のツメで固定されています。

向かって右側は横長のツメ。外すには下に押し下げ。(四角枠はイジェクトスイッチ)

左側のツメを外すには内側に押します。(四角枠はイジェクトスイッチ)


まとめ

9.5mm/SATAのDVDスーパーマルチドライブの新品(たぶん)がこの値段で手に入るなら上々でしょう。

Qtop ポータブルドライブ 外付けプレイヤー USB3.0対応 CD-RW/DVD-RW タッチ制御 Superdrive搭載 Windows/Mac両対応-ブラック

新品価格
¥2,188から
(2017/9/9時点)



でもタッチセンサーのイジェクトスイッチが地味に便利で、外付けのまま使ったほうがオススメです。
ドライブ側のUSBは3.0ですが、DVDドライブは高々8倍速なので、PC側はUSB2.0でつないでも速度に変わりはなさそう。

2017年8月28日

ノートPCのDVDドライブをお安く換装したい(1)

DVDドライブがヘタった

ノートPC(Lenovo ThinkPad E440)の内蔵DVDドライブがディスクを読み取らなくなりました。
光学ドライブは消耗品なので仕方ありません。新しいのを買って取り替えることにします。

外付けドライブでよければUSB接続のものを買えば何でもつながるでしょうが、内蔵の場合はどういう規格の品を買えばいいのでしょう?
もちろんメーカー純正パーツを買えば間違いないでしょうが、手頃な価格で済ませられないか調べてみました。

確認するのは「厚さ」「接続方式」の2点

ノート用のスリム光学ドライブは、ここ10年くらいの機種なら共通規格になっているらしく、「厚さ」と「接続方式」の2点さえ合っていればどのメーカーのドライブでも使えるようです。
(たまに特殊なマシンもあるそうですが)

厚さ:
ノートPC向けの場合は「12.7mm」「9.5mm」の2種類。
接続方式:
「SATA」か「ATAPI(IDE)」の2種類。最近の機種はSATAで、ATAPIは古い機種に限られます。

ThinkPad E440 は 9.5mm/SATA でした。

ベゼル(イジェクトボタンなどがついている表側のパーツ)の形はPCによってまちまちですが、今まで使っていたドライブのベゼルに問題がなければ、取り外して新しいドライブで再利用できます。新しく調達する必要はありません。

安い!と思って飛びつくと……

ネットショップで出物を見つけた!と思っても、海外のサイトや日本でもアマゾンのマーケットプレイスでは注意が必要です。
記録機能は必要?
リードオンリーのドライブというものもあります。読むだけでいいなら機能が少ないぶん安く済みます。焼くこともあるかも…というなら避けましょう。
ATAPI接続だと「CDは焼けるけどDVDはリードオンリー」という「コンボドライブ」もあるのでさらにご注意を。
中古品はバクチ
劣化して買い換えようというのに、中古品を買って劣化しているドライブが来たら悲しいものです。
ただ、同一型番を大量に売っている店だったらリースアップ品かもしれません。企業の現場で光学ドライブを使う人はかなり少ないので、未使用同然品を引き当てられるかも?
商品説明が適当
書き込み機能がついていないのに「書き込み速度:×倍速」と書いてあったり、本当は12.7mm厚なのに9.5mmと書いてあったり……。特に、12.7mm=「スリム」/9.5mm=「ウルトラスリム」と思うのは危険で、12.7mmのウルトラスリムは複数見かけました。
型番はさすがに間違っていないでしょうから、型番で検索してウラを取るのが安全です。
中にはタイトルと商品写真で型番が違ってたりする罠も。

ざっと見たところの相場感

9.5mm厚/SATA接続の光学ドライブ、ざっと見たところの相場感です。

eBayやaliexpressで買ったほうがちょっと安いですが、1000~2000円程度の品だと今の為替ではそう大きくは変わりません。
だったら国内のショップで買ったほうが早く届くし、商品不良時のやり取りもラクでしょう、というわけでアマゾンで。
記録不要:
DellのPC用のリードオンリードライブ DV-18SA が ¥1,380~。 たぶんDell以外のPCでも使えますが、保証はありません。
新品とも中古とも書かれていない場合は、まず新品ということはないかと。
焼きたい&新品がいい(外付けドライブを分解するのは厭わない):
HDDでもそうですが、内蔵ドライブより外付けドライブのほうが安いことがあります。
Qtop ポータブルドライブ 外付けプレイヤー USB3.0対応 CD-RW/DVD-RW タッチ制御 Superdrive搭載 Windows/Mac両対応-ブラック ¥2,188
うまくケースを外して中身を取り出せればお得です。ただし9.5mm厚/SATAだという保証はありません。商品のスペックや写真を見る限りは大丈夫そうですが……。
外付けでいいのでとにかく安く:
内蔵することを諦めれば、外付けのコンボドライブ(CDは焼けるがDVDは読むだけ)が ¥1,200 くらいから見つかります。
いちおう新品扱いですが、今どきコンボドライブが生産されているかは疑問です。ケースは新品だけど、中身のドライブは良くてデッドストック、大半はリースアップ品など中古のような予感が。

安い外付けタイプはいずれも中国からの輸入品のようです。
日本語の説明書が欲しいとか、記録用ソフトが付属していて欲しいという場合は、ケチらずに日本のメーカー品を選ぶのがいいかと。

次回予告

というわけで外付けドライブを買ってバラしてみることにしました。はたして?
⇒ つづき:ノートPCのDVDドライブをお安く換装したい(2)

2015年3月24日

LANの通信が不安定に。原因は「NATアクセラレータ」だった…

無線ルータを買い換えたら、通信が不安定に…

無線ルータを買い換えました。
イーサネットコンバータが壊れたので、これまで使っていた無線ルータをコンバータに回して、無線ルータを新調。

コンバータを買ってくるほうが手っ取り早いかもしれませんが、それまで使っていたルータは11n止まり。
どうせ買うならそろそろ11acを…と探してみたら、ちょうど出物がありました。

WN-AC1167DGR (IO DATA)

型落ちらしいですが、どうせハイエンド機種を買っても対応する子機を持ってないですし。

セットアップは簡単でしたが、どうも通信が不安定。
電波強度は充分なのに、通信ができたりできなかったりする。

最初は無線の問題かと思いましたが、無線LANだけでなく有線LANでも同様。
VDSLモデムとの相性とかあるのかな? そもそもこのモデムもずいぶん長く使ってるし、寿命?

いろいろ疑ってみるものの改善せず悩んでいたのですが、ルータのとある設定を変えてみたところ、すっきり解消。

「NATアクセラレータ」をオフにしたら安定した

このルータには、NATをソフトウェアでなくハードウェアで処理して高速化を図る「NATアクセラレータ」機能が搭載されていました。
これをオフにしてみたら……通信は非常に安定するように!(※工場出荷時はもともとオフ)

詳しい事情は分かりませんが、何とかなってよかった。

我が家は5GHz帯の飛びが悪く、これまで2.4GHz帯の11nを主に使っていたのですが、対応スマホを11acでつないでみたら――なにこれ速い
Webサイトを見ている分には体感できる差は出にくいですが、アプリや電子書籍などのダウンロードでは目に見えて速度が違います。驚いた……。

前のルータよりも5GHz帯の飛びも良く(何が違うんだろう)、いい買い物でした。

LinkWithin


Related Posts with Thumbnails