CentOS Stream8でセキュアにLinuxユーザー作成、LAMP構築【その2】

CentOS Stream8でセキュアにLinuxユーザー作成、LAMP構築【その1】のつづきです。Laravel8、Let’sEncryptのSSL/TLS、Basic認証、Apacheログローテーション、MySQLログローテーション、node.js、git/github、CircleCI、slack、Backlog、そしてローカル開発環境のDocker構築までいきたいです。Laravel8は、Apacheのバーチャルホストの公開ディレクトリのパス設定の変更が発生するため、必ず、Let’sEncryptのSSL/TLS証明証取得設定の前に設定してください。

現状、CentOS Stream release 8、Apache/2.4.37 (centos)、PHP 7.4.16 (cli)、mysql Ver 8.0.21 for Linux on x86_64 (Source distribution)、という構成です。

composerインストール

Laravelインストールのためにcomposerをインストールします。adminconohaユーザーでrootに成って以下のコマンド実行。Laravel8で使うcomposerはLinux全体のグローバルインストールではなく、Apacheバーチャルホスト単位のインストールと考えて、2つ目以降のバーチャルホストで、それぞれLaravel8のルートディレクトリでcnoomposer self-updateを行います。

composerインストール前にwgetをインストール

dnf -y install wget

composerのインストーラーをダウンロード(現在の居場所のディレクトリにインストールされます)

wget https://getcomposer.org/installer -O composer-installer.php

composerのインストール

php composer-installer.php --filename=composer --install-dir=/usr/local/bin

composerの更新

composer self-update

composerバージョン確認

composer -v

Laravel8インストール

現在のドキュメントルートへ移動

cd /var/www/独自ドメイン/DocumentRoot

Laravelをインストール

composer create-project laravel/laravel --prefer-dist プロジェクト名

移動します

cd /var/www/独自ドメイン/DocumentRoot/プロジェクト名

Laravel8バージョン確認

php artisan --version

Laravelの公開ディレクトリは

/var/www/独自ドメイン/DocumentRoot/プロジェクト名/public

となるため、/etc/httpd/conf.d/独自ドメイン_http.conf のDocumentRootとDirectoryを変更します。

/etc/httpd/conf.d/独自ドメイン_http.conf

<VirtualHost *:80>
    ServerName any
  <Location />
    Require all denied
  </Location>
</VirtualHost>

<VirtualHost *:80>
  ServerName 独自ドメイン
  ServerAlias www.独自ドメイン
  DirectoryIndex index.php index.html index.htm
  AddDefaultCharset UTF-8
  DocumentRoot /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
  ErrorLog /var/www/独自ドメイン/logs/独自ドメイン-error_log
  CustomLog /var/www/独自ドメイン/logs/独自ドメイン-access_log common
  <Directory "/var/www/独自ドメイン/DocumentRoot/プロジェクト名/public/">
    Require all granted
  </Directory>
</VirtualHost>

ブラウザで http://独自ドメイン http://www.独自ドメイン で以下のようなLaravel8初期画面を視認できればOK

laravel8
Laravel8

余談として、おそらくですが、2021年内にLravel9が出てきて、LTSになります。

node.jsインストール

インストールできる標準リポジトリのバージョンを確認

dnf info nodejs

モジュールストリームを確認(有効化されているStream番号は、すぐ後ろに[e]と記載されています)

dnf module list nodejs

最も新しいモジュールストリームを有効化

dnf module enable nodejs:14

node.jsをインストール

dnf install nodejs

node.jsバージョン確認

node -v

npmバージョン確認

npm -v

Let’sEncryptでSSL/TLS設定

apacheのhttpd.conf、バーチャルホストまわりでSSLを扱えるように、mod_sslをインストールします。adminconohaユーザーでrootに成ってやります。http→httpsへのリダイレクトは、Apacheのバーチャルホストで設定します。

yum -y install mod_ssl

【参考】yumインストール済のパッケージ一覧表示

yum list installed

certbotをインストールします

yum install certbot

certbotバージョン確認

certbot --version

【参考】certbotコマンドの更新

yum -y --enablerepo=epel update certbot

マルチドメインの初回のSSL/TLS証明書作成のコマンド向け –webroot-path に.well-known/acme-challengeディレクトリを作り、ブラウザでhttp/httpsリクエストの独自ドメイン/.well-known/acme-challenge/の中で静的ファイルを見られるようにしておく

cd /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
mkdir .well-known
cd .well-known
mkdir acme-challenge
cd ..

マルチドメインの初回のSSL/TLS証明書作成のコマンド(万が一の更新失敗のrevoke後の為に、サーバーのSSH接続アカウントなどと一緒に保管しておくことを推奨します)

certbot certonly --agree-tos --webroot-path ドキュメントルートのパス -d 独自ドメイン -d www.独自ドメイン --email メールアドレス --no-eff-email

ワイルドカード証明証で初回のSSL/TLS証明書作成のコマンド(万が一の更新失敗のrevoke後の為に、サーバーのSSH接続アカウントなどと一緒に保管しておくことを推奨します)

certbot certonly \
--agree-tos \
--webroot-path ドキュメントルートのパス \
--manual \
--server https://acme-v02.api.letsencrypt.org/directory \
--preferred-challenges dns-01 \
-d *.独自ドメイン \
-d 独自ドメイン \
--email nishi_international_info@yahoo.co.jp --no-eff-email

ワイルドカード証明証で初回のSSL/TLS証明書作成のコマンド実行直後、インタラクティブに、にレジストラにTXTレコード登録指示が表示されるので以下①②の手順でTXTレコードを設定する

①TXTレコードの登録

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.独自ドメイン with the following value:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

以下のような感じでtxtレコードを登録します

_acme-challenge.独自ドメイン txt XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

②コマンド画面でenter

なお、-d で複数のドメインをワイルドカード証明証で登録する場合、txtレコードが複数になるので①②をドメイン毎に繰り返します。その際にtxtレコードのリアルタイム反映確認は、別のシェルを起動して以下のコマンドで行います。

nslookup -type=TXT _acme-challenge.ドメイン 8.8.8.8

SSL/TLS証明書作成が終わったら、/etc/letsencrypt/live/独自ドメイン に以下のように証明証が作成されます

//サーバ証明書(設定ディレクティブ:SSLCertificateFile)
/etc/letsencrypt/live/独自ドメイン/cert.pem

//中間CA証明書(設定ディレクティブ:SSLCertificateChainFile)
/etc/letsencrypt/live/独自ドメイン/chain.pem

//サーバ証明書+中間CA証明書を結合したもの(設定ディレクティブ:SSLCertificateFile)
/etc/letsencrypt/live/独自ドメイン/fullchain.pem

//サーバ証明書の秘密鍵(設定ディレクティブ:SSLCertificateKeyFile)
/etc/letsencrypt/live/独自ドメイン/privkey.pem

Apache設定ディレクトリにシンボリックリンクする

cd /etc/httpd/
ln -s /etc/letsencrypt/live live

証明証の<Certificate Name>を確認(Expiry Dateもわかる)

certbot certificates

【参考】証明書の削除(シンボリックリンクごときれいに削除してくれる)

certbot revoke --cert-name <Certificate Name>

バーチャルホストSSL設定

/etc/httpd/conf.d/独自ドメイン_https.conf を作ります。

vi /etc/httpd/conf.d/独自ドメイン_https.conf

/etc/httpd/conf.d/独自ドメイン_https.conf は以下のように記載します。独自ドメインのwww無しに統一するためのRewriteモジュール各種と上記で作成されたSSL証明書関連をそれぞれ追記します。尚、www無しに統一するためのRewriteモジュールの独自ドメインの記載でドットをエスケープするためのバックスラッシュを忘れないようにご注意ください。

Listen 443 https
Mutex default ssl-cache
SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS
SSLCompression off
SSLCryptoDevice builtin
SSLHonorCipherOrder on
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLSessionCache shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/ocsp(128000)
SSLStrictSNIVHostCheck off
SSLUseStapling on

<VirtualHost *:443>
    ServerName 独自ドメイン
    ServerAlias www.独自ドメイン
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^www\.独自ドメイン$
    RewriteRule ^/(.*)$ https://独自ドメイン/$1 [R=301,L]
    DirectoryIndex index.php index.html index.htm
    AddDefaultCharset UTF-8
    ServerAdmin メールアドレス
    DocumentRoot /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
    ErrorLog /var/www/独自ドメイン/logs/ssl_error_log
    TransferLog /var/www/独自ドメイン/logs/ssl_access_log
    CustomLog /var/www/独自ドメイン/logs/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
    LogLevel warn
    SSLEngine on
    SSLCertificateKeyFile /etc/letsencrypt/live/独自ドメイン/privkey.pem
    SSLCertificateFile /etc/letsencrypt/live/独自ドメイン/cert.pem
    SSLCertificateChainFile /etc/letsencrypt/live/独自ドメイン/chain.pem
    BrowserMatch "MSIE [2-5]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0

  <Directory "/var/www/独自ドメイン/DocumentRoot/プロジェクト名/public/">
    Require all granted
  </Directory>
</VirtualHost>

httpからhttpsへのリダイレクトを追記するため以下のファイルを編集

vi /etc/httpd/conf.d/独自ドメイン_http.conf

Redirect permanent / https://独自ドメイン/を追記

<VirtualHost *:80>
    ServerName any
  <Location />
    Require all denied
  </Location>
</VirtualHost>

<VirtualHost *:80>
  ServerName 独自ドメイン
  ServerAlias www.独自ドメイン
  Redirect permanent / https://独自ドメイン/
  DirectoryIndex index.php index.html index.htm
  AddDefaultCharset UTF-8
  DocumentRoot /var/www/独自ドメイン/DocumentRoot
  ErrorLog /var/www/独自ドメイン/logs/独自ドメイン-error_log
  CustomLog /var/www/独自ドメイン/logs/独自ドメイン-access_log common
  <Directory "/var/www/独自ドメイン/DocumentRoot/">
    Require all granted
  </Directory>
</VirtualHost>

ブラウザで http://独自ドメイン http://www.独自ドメイン がすべてSSLにリダイレクトされることを確認してください。

1台のVPS内に複数バーチャルホストを設定する場合、独自ドメイン_http.conf や 独自ドメイン_https.conf で<VirtualHost *:80>や<VirtualHost *:443>を追記して、公開ディレクトリのパスなどを作り、/etc/letsencrypt/renewal にある独自ドメイン.confファイルの最後尾で以下を参考に追記してください。

[[webroot_map]]

独自ドメイン = /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
www.独自ドメイン = /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public

apacheを再起動

systemctl restart httpd
systemctl status httpd

また、シェルへのアクセス権を持っている場合、Let’sEncryptのTLS証明証構築には、EPELをインストール/upgradeして、snapdをインストールして、メインスナップ通信ソケットを管理するsystemdユニットを有効にするなどの場合もLinuxディストリビューションの種類によってはあるかもしれません。certbotインストールからSSL証明症発行までは、本家ドキュメント、Certbotにてご確認ください。

CloudFlare 無料プラン

無料プランでアカウントを作り、CloudFlareにログインした状態で独自ドメインの登録を行い、「概要」→「DNS設定」でお名前ドットコムに設定するネームサーバーを入手してください。お名前ドットコムの各種DNSレコードのスクショを撮っておき、お名前ドットコムに設定していたDNSレコードをCloudFlareに同じ様に設定します。そして、ネームサーバーでCloudFlareを指定します。

CloudFlareを導入するとエンドユーザーデバイス(パソコン/タブレット/スマホ)からConohaVPSのWEBサーバーというhttp/httpsリクエストの経路が2つに別れます。

  1. エンドユーザーデバイス(パソコン/タブレット/スマホ)とCloudFlareの間
  2. CloudFlareとConohaVPSのWEBサーバーの間

正しいセキュリティを考えると、1と2、それぞれの通信をSSL/TLS暗号化する必要があり、CloudFlareはLet’sEncryptではなく、上記 1 の部分について自前で無料SSLを持っています。

Let’sEncryptのcertbot設定が出来上がった状態のコノハVPSを想定した初期設定です。

DNSレコードをCloudFlareに設定後、Let’sEncryptは上記 2 の部分でSSLを引き続き提供している状態となります。CloudFlareの「SSL/TLS」→「概要」→「お客様のSSL/TLS暗号化モード」で「フル(strict:厳密)」を選択し、CloudFlareとコノハVPSの間の通信の暗号化を無料でLet’sEncryptで出来ました。ただの「フル」は無効なオレオレ証明書でも可能なSSL設定ということになります。Let’sEncryptで有効な証明証を使っているので、念の為に「フル(strict:厳密)」を選びました。

CloudFlareの 1 の無料SSLは、ルートドメイン(sample.com)とワイルドカードによるファーストレベルサブドメイン(www.sample.com や blog.sample.com)までの対応です。セカンドレベルサブドメイン以降でマルチレベルサブドメインなどは別途CloudFlare専用SSLを購入する必要があります。

certbotのSSL証明証更新は、cloudflareのAPIを使うと自動更新も簡単になります

certbot+certbot-dns-cloudflare でワイルドカード証明書を取得&自動更新する

CloudFlareはAWS,GCP,Azureなどでロードバランサの前段に組み合わせて使うことも可能で、低価格帯のCDN/WAFとしてのポジショニングを意識的に狙っていると感じられます。

certbotによるSSL更新、cronによるSSL更新の自動化

Let’s EncryptのcertbotによるSSL更新、cronによるSSL更新の自動化(CloudFlareのAPIを使うか迷っていたので、こちらも念のために調べました)

基本的に、certbot-autoコマンドや古いletsencryptコマンドではなくcertbotコマンドで

certbot renew --dry-run

で試して問題なければ cronで

certbot renew --post-hook "systemctl restart httpd"

を90日以内のリズムで定期実行となります。

ただし、ワイルドカード証明証の場合、自動化の難易度が高くなります。簡単な方法は、「ワイルドカード証明証で初回のSSL/TLS証明書作成のコマンド」と同じ手順でcertbotをcertbot-autoに置き変えて同じ作業を90日に1回行うことになります。

また、ワイルドカード証明証について

certbot certificates

にて、<Certificate Name>を確認して

certbot renew --cert-name <Certificate Name>

でインタラクティブに進める方があります。

ワイルドカードの場合、cloudflareのプラグインを使うと自動化出来るらしいです。

Basic認証

certbotによるSSL更新がこける場合の原因になる可能性があるため、certbotのSSL初期設定とcertbot renew –dry-runの後にBasic認証をかけること。

モジュール確認

httpd -M | grep auth
auth_basic_module (shared) があればOK。

/etc/httpd/conf.modules.d/00-base.conf でモジュールのロード確認

LoadModule auth_basic_module modules/mod_auth_basic.so

上記のように記載されていればOK

独自ドメイン_https.confを編集

vi /etc/httpd/conf.d/独自ドメイン_https.conf

Directoryの中でRequire all grantedを削除してAuthUserFileなどを指定

Listen 443 https
Mutex default ssl-cache
SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS
SSLCompression off
SSLCryptoDevice builtin
SSLHonorCipherOrder on
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLSessionCache shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/ocsp(128000)
SSLStrictSNIVHostCheck off
SSLUseStapling on

<VirtualHost *:443>
    ServerName 独自ドメイン
    ServerAlias www.独自ドメイン
    DirectoryIndex index.php index.html index.htm
    AddDefaultCharset UTF-8
    ServerAdmin メールアドレス
    DocumentRoot /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
    ErrorLog /var/www/独自ドメイン/logs/ssl_error_log
    TransferLog /var/www/独自ドメイン/logs/ssl_access_log
    CustomLog /var/www/独自ドメイン/logs/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
    LogLevel warn
    SSLEngine on
    SSLCertificateKeyFile /etc/letsencrypt/live/独自ドメイン/privkey.pem
    SSLCertificateFile /etc/letsencrypt/live/独自ドメイン/cert.pem
    SSLCertificateChainFile /etc/letsencrypt/live/独自ドメイン/chain.pem
    BrowserMatch "MSIE [2-5]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0

  <Directory "/var/www/独自ドメイン/DocumentRoot/プロジェクト名/public/">
      AuthUserFile /var/www/独自ドメイン/.htpasswd
      AuthGroupFile /dev/null
      AuthName "Basic Auth"
      AuthType Basic
      Require valid-user
  </Directory>
</VirtualHost>

Basic認証のユーザー名とパスワードを準備して以下のコマンドを実行。実行するとインタラクティブにパスワード設定を求められ、入力して『Adding password for user ユーザー名』と表示されたらOK。

htpasswd -c /var/www/独自ドメイン/.htpasswd ユーザー名

Apache文法チェック

apachectl configtest

httpd再起動(念のため)

systemctl restart httpd

ブラウザで独自ドメインを打って、Basic認証出来ることを確認してください。

次回は、cloudflareのAPIを使うLet’sEncryptのSSL更新。Apacheログローテーション、MySQLログローテーション、git/github、CircleCI、slack、Backlog、そしてローカル開発環境のDocker構築などを行っていきたいです。

コメントをいただくことがしばしばあるため、コメント機能を有効化しました。わからないこと、間違っていること、疑問に思うこと、何でも質問受け付けます。間違っていることは適宜修正させていただきます。お気軽にコメントください。また、正しい回答を出来る方は、正しい回答でぶった斬ってコメントいただけますと幸いです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください