いますぐ実践! Linuxシステム管理

いますぐ実践! Linux システム管理 / Vol.252 / 読者数:2506名

こんばんは、うすだです。

Ubuntuが入っているメインのノートPCを、あれこれといじくっていたら、 ログイン後、背景に壁紙は表示されるものの、 他には何も動作しない状態に陥ってしまいました。

ランチャーもアプリケーションメニューもインジケータもワークスペースもダッシュも、 あれもこれもなにもかも、存在しません。

かろうじて、右クリックして端末を起動できましたので、そこを起点に、 Emacs やらブラウザやらを起動することはできました。

ただ、インジケータがないので、ネットワークの切り替えができません。
ですが、そのうち、コマンドラインで使えることがわかりました。

  $ nmcli con up id ネットワーク接続名

nmcli con list で設定一覧が表示されたり、 nmcli con status で状態の確認ができたりもします。
昔々、cnetworkmanager なるものを使ったり、 dbus-send を駆使した操作を試みたりしましたが、 いまはコマンドがちゃんとあるのですね。
(nmcli は 0.8.1 に追加されているので、下記の頃はなかったはず…。)

Vol.174 - NetworkManager をもう少し活用してみる
http://www.usupi.org/sysad/174.html
Vol.176 - NetworkManager とやりとりする
http://www.usupi.org/sysad/176.html

ちなみに、ccsm(compizconfig-settings-manager) を起動して、 本来有効であるはずのプラグインを有効にしていったら、もとに戻りました。

もし Unity がとち狂ったときは、ccsm を起動するとよさそうです。
(実のところは、わたしのいじり方が悪かったいただけなのですが…。)

たまには違う環境というのも新鮮だよねえー、と自分に言い訳をしつつ、 今回もはりきってまいります。

今回のお題 - openssl でSSL/TLSと戯れてみる (レベル:中級)

世の中に存在する Linux なサーバのうち、 99.9% くらいには入っている思われるパッケージは、 意外とたくさんありそうな気がします。

そんな中、地味だけど必須なパッケージとして真っ先に挙げられるのが、 「openssl」ではないでしょうか。

OpenSSL: The Open Source toolkit for SSL/TLS
http://www.openssl.org/

https なサイトにアクセスしたり、証明書を作ったり確認したりする際、 お世話になる大切なひとです。

ですが、お世話になっているのは主にライブラリで、同名のコマンドの方は、 あまり使ったことがないか、 決められた手順で実行しているだけではないかと思っております。

そこで今回は、openssl コマンドにスポットライトを当て、 有意義な使い方を探ってみたいと思います。

まずは定番の証明書関連から

まずは王道の、SSL/TLS で使われる証明書や鍵の作成をしてみましょう。

…と、その前に、証明書や鍵について、ざっくり説明します。

SSL/TLS では、接続したら、公開鍵暗号を使って、 データの暗号化に使う鍵の受け渡しを行います。
そのため、サーバは自分の公開鍵をクライアントに渡す必要があります。
でも、偽サーバがなりすまして、偽の鍵を送ってしまうかもしれません。

そこで、公開鍵の改竄を防ぐため、認証局(Certification Authority, CA) というところで署名してもらいます。これが、サーバ証明書(Certificate, CRT)です。

で、まず鍵を作るには、 openssl の「genrsa」もしくは「gendsa」というコマンドを使います。

  $ openssl genrsa -des3 -out server.key 2048
  Generating RSA private key, 2048 bit long modulus
  ....................................+++
  ...中略...
  e is 65537 (0x10001)
  Enter pass phrase for server.key: (パスフレーズを入力)
  Verifying - Enter pass phrase for server.key: (再度同じのを入力)

鍵をそのまま置いておくのは危険なため、 さらに共通鍵暗号で暗号化する必要があります。 そのためのオプションが「-des」や「-des3」「-idea」です。 上記では「des3」(トリプルDES)を指定しています。

また、「-out」オプションで、生成するファイル名を指定しています。
でもって、最後の「2048」は、鍵の長さ(bit)です。

以上で、server.key という秘密鍵ができました。

ちなみに、gendsa の場合は、 DSAパラメータというファイルを作っておく必要があります。 詳細の説明は割愛しますが、以下のような感じです。

  $ openssl dsaparam -out dsaparam.out 2048
  Generating DSA parameters, 2048 bit long prime
  This could take some time
  ...後略...
  $ openssl gendsa -des -out server.key dsaparam.out
  Generating DSA key, 2048 bits
  Enter PEM pass phrase: (パスフレーズを入力)
  Verifying - Enter PEM pass phrase: (再度同じのを入力)

 

次に、公開鍵を CA で署名してもらって、CRTを作ります。
署名をお願いするときに必要なファイルが、 証明書発行要求(Certificate Signing Request, CSR)です。

CSRを作成するには、「req」コマンドを使います。

  $ openssl req -new -key server.key -out server.csr
  Enter pass phrase for server.key: (先ほど入力したパスフレーズ)
  ...中略...
  Country Name (2 letter code) [AU]:JP
  State or Province Name (full name) [Some-State]:Aichi-ken
  Locality Name (eg, city) []:Nagoya-shi
  ...後略...

「-new」オプションで生成、「-out」で出力ファイル名の指定です。

 

できあがった server.csr を、 VeriSignGeoTrustなどといった署名をしてくれるところに送り、 それなりの費用を支払えば、もれなくCRTができあがります。

…が、ちょっと試すのに、万単位のお金を出すわけにはいきませんので、 ここでは自分自身で署名してしまいましょう。

CRTを作成するには、「x509」コマンドを使います。

  $ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
  Signature ok
  subject=/C=JP/ST=Aichi-ken/L=Nagoya-shi/O=Hoge Company/OU=Dev/CN=usupi.org/emailAddress=usu@usupi.org
  Getting Private key
  Enter pass phrase for server.key: (先ほど入力したパスフレーズ)

「-req」オプションで、CRTの生成をお願いします。
「-days」オプションで、有効期限を日数で指定します。
そして、「-in」オプションでCSR、「-signkey」オプションで署名に使う鍵、 「-out」オプションで出力ファイル名を指定しています。

 

これで秘密鍵や CRT ができましたので、あとは、 それぞれのサービスでよきように使えばよいです。

たとえば、Apache の場合は、「mod_ssl」モジュールをロードするようにして、 「SSLCertificateFile」および「SSLCertificateKeyFile」というディレクティブで、 CRTと秘密鍵のファイルを指定します。
(CSR は、署名の依頼に必要なだけで、実際の運用では必要ありません。)

 

CSR と CRT の中身を確認することもできます。
CSR が問題ないか確認するには、「-verify」オプションを使います。

  $ openssl req -in server.csr -verify -noout
  verify OK

そのままだと CSR の中身も出力されますので、 「-noout」オプションを指定して阻止しています。
「-text」オプションを指定すると、CSR の中身をわかりやすく出力してくれます。

  $ openssl req -in server.csr -text -noout
  Certificate Request:
    Data:
      Version: 0 (0x0)
      Subject: C=JP, ST=Aichi-ken, L=Nagoya-shi, O=Hoge Company, ...
  ...後略...

CRT の場合も、「-text」オプションで中身を確認できます。

  $ openssl x509 -in server.crt -text -noout
  Certificate:
    Data:
      Version: 1 (0x0)
  ...中略...
    Signature Algorithm: sha1WithRSAEncryption
      Issuer: C=JP, ST=Aichi-ken, L=Nagoya-shi, O=Hoge Company, ...
  ...中略...
      Validity
        Not Before: Nov 30 17:42:18 2013 GMT
        Not After : Nov 30 17:42:18 2014 GMT
      Subject: C=JP, ST=Aichi-ken, L=Nagoya-shi, O=Hoge Company, ...
  ...後略...

Issuerが発行者すなわち CA、Subjectが対象すなわち我々自身です。
ここでは自分自身で署名したため、どちらも同じになっていますが、 お金を払って署名してもらっていたら、前者がその会社になっています。 また、Validityを見ると、有効期限がわかります。

https などにつなげられます

…ふぅ。すでに証明書関連で力を使い果たしそうですが、次にいきます。

openssl コマンドで、SSL/TLS を使ったポートにつなげられます。
つなぐには、「s_client」コマンドを使います。
以下では、https://www.google.com/ へつなぎにいっています。

  $ openssl s_client -connect www.google.com:443 -quiet
  depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
  verify error:num=20:unable to get local issuer certificate
  verify return:0

上記では、verify error と出力されています。ちょっと不安になりますが、 これは、証明局(CA)のルート証明書をopensslが持っていないため、 確認できないと言っているだけです。今は気にしないでおきましょう。

さて、上記を実行したらつながったままの状態になっていますので、 以下のように、HTTP で最小限の要求を出してみましょう。
(先頭から空行までの4行を入力します。)

  HEAD / HTTP/1.1
  Host: www.google.com
  Connection: close

  HTTP/1.1 302 Found
  ...後略...

なにかしら返事をくださいました。

さて、ルート証明書ですが、もし手元にあれば、 「-CAfile」オプションでそれを指定することで、ちゃんと確認してくださいます。
(以下は、Ubuntu 13.04 の場合です。)

  $ openssl s_client -CAfile /etc/ssl/certs/GeoTrust_Global_CA.pem \
  -connect www.google.com:443 -quiet
  depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
  verify return:1
  depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
  verify return:1
  depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2
  verify return:1
  depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = www.google.com
  verify return:1
  ...後略...

 

もちろん、https だけではありません。
またまた Google様を利用させていただいていますが、 SMTP や IMAP なども問題なくつながります。 (各ポート番号は、Google様のサイトのどこかに書いてありましたが、失念しました…。)

  $ openssl s_client -connect smtp.gmail.com:465 -quiet
  ...中略...
  verify return:0
  220 mx.google.com ESMTP なにか - gsmtp
  QUIT  ←これを入力して終了
  221 2.0.0 closing connection なにか - gsmtp
  read:errno=0

  $ openssl s_client -connect imap.gmail.com:993 -quiet
  ...中略...
  verify return:0
  * OK Gimap ready for requests from IPアドレス なにか
  1 logout  ←これを入力して終了
  * BYE Logout Requested なにか
  1 OK Quoth the raven, nevermore... なにか
  read:errno=0

ちなみに、「-quiet」オプションを省略すると、接続時の詳細な情報が、 たくさん出力されます。害はないので、興味があればお試しください。

さらにちなみに、「s_server」コマンドで、サーバとして動作させることもできます。

  $ openssl s_server -accept 14433 -cert server.crt -key server.key
  Enter pass phrase for server.key: (パスフレーズを入力)
  Using default temp DH parameters
  Using default temp ECDH parameters
  ACCEPT

「-accept」オプションで、待ち受けるポート番号を指定しています。
他から openssl コマンドでつなぎ、入力しあうと、 相手の入力が自分の方へ出力されます。

  $ openssl s_client -connect localhost:14433 -quiet

暗号化もできます

OpenSSLは、SSL/TLSだけでなく、いろいろなアルゴリズムで暗号化や復号化、 ハッシュ値の計算などを行うことができます。

「list-cipher-commands」や「list-message-digest-command」コマンドで、 共通鍵暗号による暗号化や、ハッシュ値の計算に使用できるコマンド名がわかります。

  $ openssl list-cipher-commands
  aes-128-cbc
  aes-128-ecb
  ...中略...

  $ openssl list-message-digest-commands
  md4
  md5
  rmd160
  sha
  sha1

それではまず暗号化・復号化から。
共通鍵暗号で暗号化を行う場合は、「enc」コマンドを使います。

  $ openssl enc -aes-128-cbc -in foo.txt -out foo.enc
  enter aes-128-cbc encryption password: (パスワードを入力)
  Verifying - enter aes-128-cbc encryption password: (再度入力)
  $ file foo.enc
  foo.enc: data

上記では、「aes-128-cbc」を使って暗号化しています。
出力ファイル foo.enc を file コマンドで確認してみると、 少なくともテキストファイルでないことはわかります。

復号化は、encコマンドで「-d」オプションを指定します。

  $ openssl enc -d -aes-128-cbc -in foo.enc -out foo.dec.txt
  enter aes-128-cbc decryption password: (先ほどのパスワードを入力)
  $ cmp foot.txt foo.dec.txt && echo OK
  OK

復号化した foo.dec.txt と foo.txt が同じであることが、 cmp コマンドで確認できました。

 

公開鍵暗号の場合は、まず鍵を作る必要があります。
秘密鍵は、前述の genrsa コマンドで作成しましたので、 そこから公開鍵を作って暗号化・復号化をしてみたいと思います。

RSAの公開鍵を生成するには、「rsa」コマンドで「-pubout」オプションを指定します。

  $ openssl rsa -pubout -in server.key -out server.pub
  Enter pass phrase for server.key: (パスフレーズを入力)

次に、公開鍵で暗号化を行います。
「rsautl」コマンドで「-encrypt」オプションを指定すると、RSAで暗号化を行います。 以下では、this is a test というメッセージを暗号化しています。

  $ echo this is a test | \
  openssl rsautl -encrypt -pubin -inkey server.pub -out test.enc

「-inkey」オプションで鍵を指定します。ただし、 デフォルトでは秘密鍵で暗号化しようとするため、 「-pubin」オプションを指定して、公開鍵で暗号化するよう伝えます。

復号化には、「-decrypt」オプションを指定します。

  $ openssl rsautl -decrypt -inkey server.key -in test.pub.enc 
  Enter pass phrase for server.key:
  this is a test

もとのメッセージ(this is a test)が得られました。
ただし、入力データには制限があり、長いデータを暗号化しようとすると叱られます。

  $ openssl rsautl -encrypt -pubin -inkey server.pub -in long.txt
  RSA operation error
  ...中略...:data too large for key size:rsa_pk1.c:151:

 

ハッシュ値の計算は、「md5」や「sha1」などのコマンドで行えます。

  $ openssl md5 foo.txt
  MD5(foo.txt)= 562585047553f5cd155a0124a5a17672
  $ openssl sha1 foo.txt
  SHA1(foo.txt)= 1612f15cda9b77ba59732f23620f92010ae8c5f3

もちろん、「md5sum」や「sha1sum」コマンドの結果と一致します。

  $ md5sum foo.txt
  562585047553f5cd155a0124a5a17672  foo.txt
  $ sha1sum foo.txt
  1612f15cda9b77ba59732f23620f92010ae8c5f3  foo.txt

openssl があれば、md5 や md5sum コマンドがないオールドな OS でも、 ハッシュ値を求めることができます。(数年前、実際に体験しました。)

おわりに

以上、openssl コマンドの使い方を、ざっくりご紹介しました。

上記は一部で、openssl の機能はまだまだいっぱいあります。
詳しくは、オンラインマニュアル(man openssl や man コマンド名 など)をご覧ください。

宿題の答え

前回の宿題は、

  inotifywaitによる監視が途切れないようにしてみましょう。

でした。

早速ですが、わたしなりの答えを以下に示します。

#!/bin/bash
LEASEFILE=/var/lib/dhcp/dhcpd.leases
TIMEOUT=5
inotifywait -e modify,attrib,create -qm $LEASEFILE \
    | while [ 1 ]; do
    total_events=""
    while read -t $TIMEOUT file event; do
        total_events="$total_events $event"
    done
    [ -n "$total_events" ] \
        && while read l1 l2 l3 l4 l5 l6 l7 l8 l9; do
            case "$l1" in
                lease)
                    IPADDR=$l2;;
                hardware)
                    MAC=$(echo $l3 | tr -d \;);;
                client-hostname)
                    NAME=$(echo $l2 | tr -d \"\;);;
                starts)
                    l4=$(echo $l4 | tr -d \;)
                    T1=$(date --date="$l3 $l4 UTC" "+%F %T");;
                ends)
                    l4=$(echo $l4 | tr -d \;)
                    T2=$(date --date="$l3 $l4 UTC" "+%F %T");;
                binding)
                    STAT=$(echo $l3 | tr -d \;);;
                \})
                    if [ -n "$NAME" ]; then
                        echo "$IPADDR $MAC $T1 $T2 $STAT ($NAME)"
                    else
                        echo "$IPADDR $MAC $T1 $T2 $STAT"
                    fi
                    IPADDR=
                    MAC=
                    NAME=
                    T1=
                    T2=
                    STAT=;;
            esac
        done < $LEASEFILE | Mail -s '[dhcp] updated' root
    done

どんどん間延びしていますが、 内側のwhile〜done と Mailコマンド実行のところまでは、前回と同じです。 (ので、説明は割愛します。)

肝は、4行目の inotifywait コマンドで「-m」オプションを指定しているところと、 それを while がパイプで受け、さらに while で read を延々と繰り返すところです。

inotifywaitの -m オプションは、イベントを受けても終了せず、 永遠に処理し続ける、というものです。これでずっとイベントを受け続けます。

それを while で受けて、内側の while で read し続けます。
ただ、read コマンドには「-t」オプションを指定して、 制限時間付きで実行しています。ここでは、5秒経つと read コマンドが諦めて、 whileのループから抜けます。

つまり、inotifywaitコマンドがイベントを受けて出力してから、 5秒以上何も出力しなければ、 dhcpd.leases を読んでまとめた内容を root 宛にメールする、 という処理を延々繰り返します。

ちなみに、このネタは、以前にご紹介しております。

Vol.157 - inotify でディレクトリを監視してみる
http://www.usupi.org/sysad/157.html

 

それよりも、inotifywait で待つイベントを減らし、 更新の際に1つしかイベントが来ないようにすれば、 こんな周りくどいことをしなくてもよいのではないか、と思いました。

ですが、その野望は、もろくも崩れ去りました。
多少苦労しましたので、以下に経緯を示させてください。

dhcpdさんは、dhcpd.leases を基本的にはopenしっぱなしにしています。

  $ sudo ls -l /proc/$(cat /run/dhcp-server/dhcpd.pid)/fd
  Total 0
  lrwx------ 1 root root 64 Nov 24 19:11 0 -> /dev/null
  lrwx------ 1 root root 64 Nov 24 19:11 1 -> /dev/pts/3
  lrwx------ 1 root root 64 Nov 24 19:11 2 -> /dev/pts/3
  ...中略...
  l-wx------ 1 root root 64 Nov 24 19:11 8 -> /var/lib/dhcp/dhcpd.leases

そのためか、中身を更新しても、 書き換えたことを示す modify イベントだけが飛んできます。

  $ inotifywait -m /var/lib/dhcp/dhcpd.leases
  Setting up watches.  
  Watches established.
  /var/lib/dhcp/ MODIFY dhcpd.leases
  /var/lib/dhcp/ MODIFY dhcpd.leases

…うーん、それでも複数飛んできますね。
それだけではなく、たまに dhcpd.leases~ というバックアップをとり、 まるっと更新することがあります。

  $ inotifywait -m /var/lib/dhcp/dhcpd.leases
  Setting up watches.  
  Watches established.
  /var/lib/dhcp/dhcpd.leases MODIFY 
  /var/lib/dhcp/dhcpd.leases CLOSE_WRITE,CLOSE 
  /var/lib/dhcp/dhcpd.leases ATTRIB 

というわけで、ひょっとすると他のケースもあるかもしれず、どれか1つに絞る、 ということが難しそうでしたので、この方法は断念しました。

今回の宿題

今回の宿題は、

  秘密鍵や CRT、CSR を改竄するとエラーになることを確かめましょう。

です。

もしエラーにならず滞りなく動作したら、根底が覆されてしまいますが、 まあ、大方の予想通り、エラーになります。

でも、実際に確認したことはないんじゃないでしょうか。やりましょう。

あとがき

前回、バックアップの話をここでしましたが、そもそも、 バックアップの重要さは、二次記憶装置の信頼性によるのではないかと思います。

というわけで、以下では、 ハードディスクの寿命について調査した結果がどどーんと載っています。

「ハードディスクは何年くらい使えるのか?」を調査したら、 ほぼ4年間はいけそうという結果に : ライフハッカー[日本語版]
http://www.lifehacker.jp/2013/11/131115harddriveduration.html

タイトルですべてを語られているようですが…。

ハードディスクの8割以上は4年間問題なく使える、という調査結果が出ています、 という内容です。しかし、この結果から、4年間は大丈夫と判断してよいのかどうかは、 個人の感覚によるような気がします。

また、調査対象のディスクと、自分のディスクとでは、 使用頻度など条件がいろいろ異なると思いますので、調査結果を鵜呑みにするのも、 あまりよくなさそうにも思います。

個人的には、結局いつ壊れるかわからないので、バックアップは必須だ、 という結論に達しました。

…上記を読んだ意味が皆無な結論ですが、ここで大事なのは、 上記をどう解釈するかということよりも、自分で判断して、 次の行動につなげていくことではないか、と思います。

ついつい、自分よりも賢い人、行動力のある人に決断を委ねがちです。
しかし、自分で考えて、自分で決めることを、恐れずに、やっていきたいものですね。

…以上、ブーメランの如く自分へ返ってくる言葉を、最後に書きました。

 

さて、今日から、12月。師走。私が言うまでもなく、忙しい月ですね。

日々、てきとーに過ごしている私ですが、本業やらなにやらで、 人並みに忙しくなってまいりました。

そこでといいますか、例年通りといいますか、我ながら甘いと思うのですが、 今年最後の1回をお休みにさせていただきたいと思います。

というわけで、次の発行は、年明けの 1月5日 になります。

しかし、今年は、おおっぴらにはしませんでしたが、 個人的にいろいろなことがありました。もういいっす、と神さまに言いたいです。

そんな中、お給料が下がらなかったことが、波乱の1年の中での奇跡的な幸運だった、 と言えるのではないかと思っています。
来年も、お給料が下がらないように、がんばろうと思います。

…来年までに、もう少し前向きな目標を立てます。

それでは、少し早いですが、よいお年をお迎えください。
そして、なんといっても、健康が第一です。くれぐれもご自愛ください。

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、1月5日(日) の未明にお会いしましょう! よいお年を!!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。

「栗日記」- 栗の季節は過ぎ去りましたが、栗日記は年中無休です。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)
http://twitter.com/kuriking/ (栗つぶやき)
http://facebook.com/kuriking3 (栗顔本)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本