CentOS 7 のインストールと SSH 接続 (さくらのVPS)

:warning: 注意 (2020-02-13 記載)
================================

当記事は CentOS 7 がカスタムOSだった頃の古い記事 (最終更新日は[記号や暗号化方式の互換性](#-記号や暗号化方式の互換性)を除いて2015-07-24) であり、2019-04-16以降 CentOS 7 は標準OSとして提供が開始し [^centos7] 、2019-09-03以降はデフォルトのOSとなり [^初期提供時の標準OS]  、2019-10-01に CentOS 8 のカスタムOSとしての提供が開始しています。 [^centos8]

[^centos7]: [さくらのVPS (バージョン v1/v2) で「標準OS」「カスタムOS」の種類を拡充 | さくらインターネット](https://www.sakura.ad.jp/information/announcements/2019/04/16/1968199990/)
[^初期提供時の標準OS]: [さくらのVPS 標準インストールOSを「CentOS 7」に変更しました – さくらのVPSニュース](https://vps-news.sakura.ad.jp/2019/09/03/vps-os-d-centos7/)
[^centos8]: [さくらのVPS カスタムOS「CentOS 8」の提供を開始 – さくらのVPSニュース](https://vps-news.sakura.ad.jp/2019/10/01/vps_cos_centos8/)

[CentOS 7 に Apache と MariaDB 10.0 をインストールし SFTP 接続]: http://qiita.com/100/items/5a07ab0abcabd1296ef8 "CentOS の公式 yum リポジトリで Apache 2.4 の RPM パッケージが提供されているので、それをインストールします。さくらの VPS の場合はすでにインストールされていますが、有効化と起動は必要です。"

----------------------------------------------------------------------



 導入
=====
さくらの VPS の標準OSである CentOS 6 では、初心者でもトラブルが起きにくいような設定になっています。カスタムOSである CentOS 7 は、標準OSと設定値などが異なります。OS再インストールによって CentOS 7 にアップグレードした際に非常に手間取りましたので、備忘として残しておきます。

サーバーには CentOS 標準の SSH サーバーである OpenSSH、クライアントには Windows 7 上で [Tera Term] を使用しています。

[Tera Term]: https://ja.wikipedia.org/wiki/Tera_Term "Tera Term(テラターム)は、元々は寺西 高によって開発・公開され、現在ではTeraTerm Projectによって修正BSDライセンスでサポートされているリモートログオンクライアントである。SSH・telnet・シリアルの各通信プロトコルに対応し、Microsoft Windowsで使用できる。"

 記号や暗号化方式の互換性
=========================
* ユーザー名、パスワード、パスフレーズに用いる文字列
	* 文字化けなどを避けるため、ASCII印字可能文字 (半角英数記号) のみを利用する
	* キー配列の違いによる誤入力などを防ぐため、記号を用いる場合は `!` `#` `$` `%` `,` `-` `.` `/` `<` `>` `?` のみを利用する [^キー配列] [^ゲストOS] [^VNC] [^TTL] [^MariaDB]
* ユーザー名、パスワード、パスフレーズの長さ
	* Linux のユーザー名は8文字以内で [^Linuxユーザー名] [^psコマンド]
	* Linux のパスワードは128文字以内で [^Linuxパスワード]
	* 暗号鍵のパスフレーズは128文字以内で [^暗号鍵パスフレーズ]
	* MariaDB のユーザー名は16文字以内で [^MySQL] [^MariaDB]
* SSH接続時の公開鍵認証
	* 秘密鍵は (bcrypt KDF 形式ではなく) OpenSSH 形式で保存 [^秘密鍵]
	* 公開鍵は (RFC 4716 形式ではなく) OpenSSH 形式で保存 [^公開鍵]
	* 暗号化方式は RSA-2048 [^暗号化方式] [^Ed25519]

[^キー配列]: [JISキーボードなのにUS配列の環境で文字を打つ — Qiita](https://qiita.com/hachisukansw/items/efd4b3c2df7e6a8b3779#jis%E9%85%8D%E5%88%97%E3%81%A8us%E9%85%8D%E5%88%97%E3%81%A7%E9%81%95%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%A8%E3%81%93%E3%82%8D)
[^ゲストOS]: VirtualBox のキーボードキャプチャーを通して自動入力した際、`"` `'` `^` `` ` `` `~` は正常に入力できなかった。
[^VNC]: さくらの VPS コントロールパネルのVNCコンソールで自動入力した際、`"` `'` `` ` `` `~` は正常に入力できなかった。
[^TTL]: Tera Term マクロの `connect` コマンドにおいて `"` で囲まれたパスフレーズを指定する場合、パスフレーズ中の `"` `\` に `\` を前置してエスケープする必要がある。自動でエスケープするのは困難なため、`"` `\` を含むパスフレーズの暗号化は難しい。
[^MariaDB]: `mysql_secure_installation` コマンドでパスワードを設定する場合、`\` は `\\` と入力する必要がある。SQLの文字列リテラル内に記述する場合、`'` `\` はエスケープしてそれぞれ `\'` `\\`としなければならない。また、phpMyAdmin の設定ファイルなどで PHP スクリプトに直接ユーザー名・パスワードを埋め込む場合、`'` と `\` は `\` を前置してエスケープする必要がある。
[^Linuxユーザー名]: [Linuxで8文字を超えるユーザ名を使うと、topやpsコマンドでの表記がuidとなる - Y-Ken Studio](http://y-ken.hatenablog.com/entry/linux-over-8characters-username)
[^psコマンド]: [技術メモ - 01-004_psで長いuser名を表示](https://w.atwiki.jp/a24wiki/pages/18.html)
[^Linuxパスワード]: 256文字のパスワードを設定したところ、GUIでの認証に失敗した。
[^暗号鍵パスフレーズ]: Tera Term マクロにおける文字列変数の最大文字数は511文字。`connect` コマンドを使用する際、ユーザー名や暗号鍵ファイルのパスも同じ変数にまとめる必要があるので、パスワードが長すぎると自動化できなくなる。また、`getpassword` コマンドは長い文字列の保存に失敗する。
[^MySQL]: ユーザー名は最大16文字。
[^MariaDB]: ユーザー名は最大80文字で、補助文字 (4バイト文字) は使用できない。
[^秘密鍵]: PuTTY、FileZilla は、bcrypt KDF 形式の秘密鍵を解析できない。
[^公開鍵]: OpenSSH では、RFC 4716 形式の公開鍵を解析できない。
[^暗号化方式]: PuTTY、FileZilla は、Ed25519 に対応していない。
[^Ed25519]: CnetOS 7.1 の SSH サーバー、および Tera Term は Ed25519 に対応しているので、私は管理者ユーザーの認証のみ Ed25519 を使用しています。

# CentOS7のインストール

インストーラーでフォーマットするため、データベースのデータや秘密鍵など、必要なデータのバックアップを忘れずに行ってください。

* [OS再インストール・カスタムOSインストール – さくらのサポート情報](https://help.sakura.ad.jp/360000338401482/ "「さくらの専用サーバ」は、標準OSとして『 CentOS 』をインストールして提供しています。他のOSを利用したい」「パーティションを切り直したい」といった場合や、「OSが起動しなくなった」時に利用いただく機能です。")
* [カスタムOSインストールガイド – CentOS7 / ScientificLinux7 / Fedora 28 – さくらのサポート情報](https://help.sakura.ad.jp/206055602/#ac02 "さくらのVPSでは、カスタムOSインストール機能を利用することで、お客様のご希望のOSを選択し、利用することができます。ここでは、CentOS7のインストール方法について説明します。")

以上のページによく目を通し、インストールを完了させます。

以下の手順には、_以上のページの手順とは違う部分_ があります。

1. VPS コントロールパネルのサーバページを開きます。
1. ページ右上の「OSインストール」プルダウンメニューから「カスタムOSインストール」を選択すると、カスタムOSインストールダイアログが開きます。
1. インストールOSのプルダウンメニューから「CentOS 7 x86_64」を選択し、「設定内容を確認する」ボタンを押します。
1. インストールOSが「CentOS 7 x86_64」になっていることを確認し、「インストールを実行する」ボタンを押します。
1. 表示されたメッセージ内の「VNCコンソールを起動」ボタンを押します。
1. CentOS 7 のインストーラーが起動するので、「Install CentOS 7」を選択してEnterキーを押します。
1. _「LANGUAGE SUPPORT」を選択し、「日本語 (日本)」を追加します。_
1. 「INSTALLATION DESTINATION」を選択し、ディスクの選択とフォーマットを行います。
1. 「Begin Installation」ボタンを押して、CONFIGURATION画面に移動します。
1. 「ROOT PASSWORD」を選択し、root ユーザーのパスワードを設定します。
1. _「USER CREATION」を選択し、【SSH接続でシェルにログインするユーザー】を追加します。_ [^記号]
	* 「Username」を入力すると、「Full name」も同時に埋まります。
	* `sudo` `sudoedit` コマンドを有効にするため、 **「Make this user administrator」にチェックを入れます。** [^管理者]
	* パスワードを入力します。
1. インストールが完了するまで待ちます。

[^記号]: いざログインしようとしたときに認証失敗しないよう、[記号や暗号化方式の互換性](#-記号や暗号化方式の互換性) に目を通しておいてください。
[^管理者]: administrator (管理者) というのは、wheel グループに所属するユーザーのことを指しています。

# パスワード認証でログイン

まず、VPS コントロールパネルのサーバページを開き、ページ左上の「起動」ボタンを押します。

 IPアドレス・ホスト鍵の確認
---------------------------
1. VPS コントロールパネルのサーバページを開きます。
1. 接続元の回線で IPv6 を利用できるなら「IPv6」の項、利用できなければ「IPv4」の項の「アドレス」をメモしておきます。
1. 「コンソール」プルダウンメニューから「VNCコンソール (HTML5版)」を選択します。
1. `login:` という表示が出るので、インストール中に作成した管理者ユーザー名を入力し、Enterキーを押します。
1. `Password:` という表示が出るので、同ユーザーのパスワードを入力してログインします。

```sh
# ホスト公開鍵の指紋とアスキーアートの確認
ssh-keygen -lvf /etc/ssh/ssh_host_ecdsa_key.pub
ssh-keygen -lvf /etc/ssh/ssh_host_ed25519_key.pub
ssh-keygen -lvf /etc/ssh/ssh_host_rsa_key.pub

# ログアウト
exit
```

以上のコマンドを実行し、3種類のホスト公開鍵の指紋と、必要であればアスキーアート表現もメモしておきます。どのホスト公開鍵が使われるかは、クライアント側の設定に依ります。なお、オプションを `-lf` とすれば、アスキーアートは表示されません。

 シェルにログイン
-----------------
ユーザーに公開鍵を設定していないため、まずはパスワードでシェルにログインします。

1. Tera Term を起動し、ホスト欄にサーバーのIPアドレスを入力し、「OK」ボタンを押します。
1. セキュリティ警告ダイアログが出るので、表示されているサーバ側のホスト鍵指紋と、記録しておいた指紋が一致するかチェックします。問題が無ければ「続行」ボタンを押します。
1. 「ユーザ名」に管理者ユーザー名、「パスフレーズ」欄に同ユーザーのパスワードを入力し、「OK」ボタンを押します。

 公開鍵認証でログイン
=====================
 SSH公開鍵を設定
----------------
パスワード認証でログインしたまま、次の手順に従い、管理者ユーザーが公開鍵認証でログインできるようにします。

1. Tera Term メニューバーから、設定 ▸ SSH鍵生成 を開きます。
1. 「生成」ボタンを押すと鍵が生成されます。
1. パスフレーズを入力します。[^記号]
1. 「秘密鍵の保存」ボタンを押し、任意の場所に保存します。[^OpenSSH]
1. 「公開鍵の保存」ボタンを押し、任意の場所に保存します。[^OpenSSH]
1. 保存した公開鍵を Tera Term ウィンドウ内にドラッグ&ドロップし、「SCP」でファイルを転送します。

```sh
# SSHの設定ディレクトリを作成
mkdir --mode=500 ~/.ssh

# 公開鍵を設定ディレクトリに配置
mv ~/id_rsa.pub ~/.ssh/authorized_keys

# 公開鍵のアクセス権を変更
chmod 400 ~/.ssh/authorized_keys

# ログアウト
exit
```

[^OpenSSH]: OpenSSH 形式で保存されます。

 シェルにログイン
-----------------
1. Tera Term を起動し、「OK」ボタンを押します。
1. 「ユーザ名」に管理者ユーザー名、「パスフレーズ」欄に秘密鍵のパスフレーズを入力します。
1. 「RSA/DSA/ECDSA/ED25519鍵を使う」を選択し、「秘密鍵」ボタンから秘密鍵ファイルを選択して「OK」ボタンを押します。

 テキストエディタの設定
=======================
Vim 以外のテキストエディタはインストールされていないため、Vim 以外のテキストエディタを使う場合は、あらかじめインストールしておきます。

```sh
# Emacs を使う場合
sudo yum install emacs

# nano を使う場合
sudo yum install nano
```

最初に `yum` コマンドを使用したとき、以下のように GPG 公開鍵を取り込んでも良いか訊ねられるため、Fingerprint が https://www.centos.org/keys/#centos-7-signing-key と大文字小文字無視で一致するか確認します。

```
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Importing GPG key 0xF4A80EB5:
 Userid     : "CentOS-7 Key (CentOS 7 Official Signing Key) <security@centos.org>"
 Fingerprint: 6341 ab27 53d7 8a78 a7c2 7bb1 24c6 a8a7 f4a8 0eb5
 Package    : centos-release-7-1.1503.el7.centos.2.8.x86_64 (@CentOS-7)
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Is this ok [y/N]:
```

 Emacsのカスタマイズ
--------------------
私は以下のように設定しています。[^el1] [^el2] [^el3]

```el:.emacs.el
;; バックアップファイルを作成しない
(setq make-backup-files nil)
;; オートセーブファイルを作成しない
(setq auto-save-default nil)
;; 対応する括弧をハイライトする
(show-paren-mode t)
;; カーソル位置の桁数をモードライン行に表示する
(column-number-mode t)
;; メニューバーを消す
(menu-bar-mode 0)
;; タブ幅を 4 に
(setq default-tab-width 4)
(setq tab-stop-list '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60
                      64 68 72 76 80 84 88 92 96 100 104 108 112 116 120))
```

[^el1]: [Emacs の設定ファイル (.emacs.el) の小技](http://www.yumi-chan.com/emacs/emacs_el_small.html)
[^el2]: [Emacs講座 -第8回- タブ幅 / マスタカの ChangeLog メモ](https://masutaka.net/chalow/2009-07-10-4.html)
[^el3]: [Emacs 24 とツールバー - とりあえず暇だったし何となく始めたブログ](https://khiker.hatenablog.jp/entry/20100422/emacs_toolbar)

 sudoeditなどで利用するテキストエディタ
---------------------------------------
既定のテキストエディタは Vim なので、それ以外のテキストエディタを利用する場合は環境変数の設定が必要です。以下の `emacs` は利用するエディタに合わせて読み替えてください。

```sh:~/.bash_profile
# sudoeditコマンドで利用するテキストエディタを設定
export EDITOR=gedit
```

`source ~/.bash_profile` を実行し、設定を反映します。なお、EDITOR 環境変数の代わりに VISUAL 環境変数を利用することもできますが、[Composer] など EDITOR しか参照しないコマンドもあるので注意が必要です。

[Composer]: https://getcomposer.org/doc/03-cli.md#usage "EDITOR 環境変数で定義されているテキストエディタを使用して、ローカルの composer.json ファイルを開きます。"

 suの設定
=========
管理者ユーザー以外は使えないようにします。

```sh:/etc/pam.d/su
#%PAM-1.0
auth		sufficient	pam_rootok.so
# Uncomment the following line to implicitly trust users in the "wheel" group.
#auth		sufficient	pam_wheel.so trust use_uid
# Uncomment the following line to require a user to be in the "wheel" group.
auth		required	pam_wheel.so use_uid
## ↑この行のコメントアウトを外す ##
auth		substack	system-auth
auth		include		postlogin
account		sufficient	pam_succeed_if.so uid = 0 use_uid quiet
account		include		system-auth
password	include		system-auth
session		include		system-auth
session		include		postlogin
session		optional	pam_xauth.so
```

 OpenSSHの設定
==============

```sh:/etc/ssh/sshd_config
                        ##############
                        ## 以上省略 ##
                        ##############

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin yes
PermitRootLogin no
## ↑この行を追加 ##
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

                        ##############
                        ##   中略   ##
                        ##############

# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
PasswordAuthentication no
## ↑この行の値を、「yes」から「no」に変更 ##

# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
ChallengeResponseAuthentication no

                        ##############
                        ##   中略   ##
                        ##############

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
## ↑この行の値を、「yes」から「no」に変更し、コメントアウト ##
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes


                        ##############
                        ## 以下省略 ##
                        ##############
```

```sh
# 設定ファイルの文法チェック
sudo sshd -t 

# 設定ファイルの再読み込み
sudo systemctl reload sshd
```

文法に問題が無い場合、`sshd -t` は何も表示しません。

 socketユニットの利用
---------------------
CentOS 7 以降で採用されている [systemd] は、サービスなどをユニットファイルで管理します。socket 型のユニットは、[xinetd] 経由のサービスと同じような働きをします。

既定で有効な OpenSSH のユニットは `sshd.serivce` で、これを `sshd.socket` に切り替えます。ユニット名を指定する際、それが service 型の場合などには、以下のように `.service` の部分を省略できます。

```sh
# sshd.socket の有効化 (OS起動時に自動的に起動)
sudo systemctl enable sshd.socket

# sshd.socket の起動
sudo systemctl start sshd.socket

# sshd.service の停止
sudo systemctl stop sshd

# sshd.service の無効化
sudo systemctl disable sshd
```

念のため、新しく Tera Term を立ち上げ、接続できるか確認しておきます。

[systemd]: https://ja.wikipedia.org/wiki/Systemd "systemdはシステム管理デーモン、ライブラリおよびユーティリティ一式であり、管理および設定における中心的プラットフォームとしてLinuxコンピュータオペレーティングシステム用に設計されている。UNIX System VやBSDから継承されたLinuxのinitシステムを置き換えることを第一の目標としている。"
[xinetd]: https://ja.wikipedia.org/wiki/Xinetd "xinetdは、Unix系オペレーティングシステムで動作するオープンソースのスーパーサーバ型デーモンで、インターネットベースの接続性を管理する。inetdをよりセキュアに拡張したバージョンである。"

 ポート番号の変更 [^ポート番号]
-------------------------------
```sh
# firewalld のサービス定義ファイルを修正用のディレクトリにコピー
sudo cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/

# sshd.socket の設定を上書きするファイルを配置するディレクトリの作成
sudo mkdir /etc/systemd/system/sshd.socket.d
```

OpenSSH の設定ファイルを修正します。

```sh:/etc/ssh/sshd_config
                        ##############
                        ## 以上省略 ##
                        ##############

# If you want to change the port on a SELinux system, you have to tell
# SELinux about this change.
# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
#
Port ⦅ポート番号⦆
## ↑この行のコメントアウトを外し、ポート番号を変更 ##
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

# The default requires explicit activation of protocol 1
#Protocol 2

                        ##############
                        ## 以下省略 ##
                        ##############
```

firewalld のサービス定義ファイルを修正します。

```xml:/etc/firewalld/services/ssh.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>SSH</short>
  <description>Secure Shell (SSH) is a protocol for logging into and executing \
commands on remote machines. It provides secure encrypted communications. If yo\
u plan on accessing your machine remotely via SSH over a firewalled interface, \
enable this option. You need the openssh-server package installed for this opti\
on to be useful.</description>
  <port protocol="tcp" port="⦅ポート番号⦆"/>
                     <!-- ↑port属性値のポート番号を変更 -->
</service>
```

sshd.socket の設定を上書きするファイルを作成します。[^sshd.socket]

```ini:/etc/systemd/system/sshd.socket.d/port.conf
[Socket]
ListenStream=⦅ポート番号⦆
```

サービスのポート番号の情報を変更します。

```sh:/etc/services
                        ##############
                        ## 以上省略 ##
                        ##############

ftp-data        20/tcp
ftp-data        20/udp
# 21 is registered to ftp, but also used by fsp
ftp             21/tcp
ftp             21/udp          fsp fspd
ssh             ⦅ポート番号⦆/tcp                # The Secure Shell (SSH) Protocol
               ## ↑sshのポート番号を変更 ##
ssh             22/udp                          # The Secure Shell (SSH) Protocol
telnet          23/tcp
telnet          23/udp

                        ##############
                        ## 以下省略 ##
                        ##############
```

標準OSと違い、SELinuxはデフォルトで有効になっています。

```sh
# SELinux の設定を変更
sudo semanage port --add --type ssh_port_t --proto tcp ⦅ポート番号⦆

# firewalld の設定を再読み込み
sudo firewall-cmd --reload

# sshd.socket を再有効化することで設定を再読み込みさせる
sudo systemctl reenable sshd.socket
```

念のため、新しく Tera Term を立ち上げ、接続できるか確認しておきます。

[^ポート番号]: [CentOS 7 で sshd のポート番号を変更する - Web Application Security Memo](https://www.pupha.net/archives/2919/)
[^sshd.socket]: [ソケットアクティベーションで SSH ポート番号を変更する (sshd.socket) | Secure Shell - ArchWiki](https://wiki.archlinuxjp.org/index.php/Secure_Shell#.E3.82.BD.E3.82.B1.E3.83.83.E3.83.88.E3.82.A2.E3.82.AF.E3.83.86.E3.82.A3.E3.83.99.E3.83.BC.E3.82.B7.E3.83.A7.E3.83.B3.E3.81.A7_SSH_.E3.83.9D.E3.83.BC.E3.83.88.E7.95.AA.E5.8F.B7.E3.82.92.E5.A4.89.E6.9B.B4.E3.81.99.E3.82.8B_.28sshd.socket.29)

# locateコマンドのインストール

標準OSと違い、`locate` コマンドはインストールされていません。[^locate]

```sh
# インストール
sudo yum install mlocate

# ファイル一覧データベースの生成
sudo updatedb
```

[^locate]: [locateコマンドのインストール | CentOSサーバ構築術 文具堂](https://centos.bungu-do.jp/archives/64 "minimalでOSをインストールすると、システム内のファイルを素早く検索してくれるlocateコマンドはインストールされていない。locateはmlocateパッケージに入っているのでyumでインストールする。")