お名前ドットコムVPSへ移行への道6-WordPress

※ 当サイトではアフィリエイト広告を利用しています。リンクは広告リンクも含みます。

この記事は約18分で読めます。
広告

お名前.com VPS にこれまでに
owasp/modsecurity-crs:nginxとDjangoのDockerイメージをインストールして、
Djangoを表示できるようにしてある。
今回はWordPressのDockerイメージをインストールする。

メモリのことを何も気にせずやっていたので
メモリ不足になりVPSの再起動を繰り返してやっている状態です。
なのでDjangoのコンテナは削除、owasp/modsecurity-crs:nginx-alpineとWordPress、データベースのコンテナのみにしてます。
次回メモリの対策をしていきます。

あくまでも私は、こうやってみたということで動作やセキュリティの保証はできません。
まとまってないので完全に個人メモになってます。
環境
パソコン Windows11
VPS OS Ubuntu 20.04.3 LTS、 Dockerを使用
こちらの続きです。

広告

WordPressインストール

参考:docker-composeを使ってWordPress環境を構築する #Docker – Qiita

dockerディレクトリの下に
mkdir wordpress
cd wordpress
docker-compose.ymlと.envを作成。
version: '3.9'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWD}

   wordpress:
     depends_on:
       - db
     image: wordpress:latest

     restart: always
     environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: ${DB_USER}
      WORDPRESS_DB_PASSWORD: ${DB_PASSWD}
      WORDPRESS_DB_NAME: ${DB_NAME}
volumes:
    db_data:
networks:
  default:
      name: shared
      external: true

.env

DB_NAME=wp_dbname
DB_USER=wp_user
DB_PASSWD=wp_passwd
DB_ROOT=wp_root

右側は、それぞれ任意の文字列を設定。

docker-compose up -d
インストール前後のメモリ使用量確認。
free
              total        used        free      shared  buff/cache   available
Mem:         987916      516364      125224        5212      346328      310372
Swap:             0           0           0

↓docker-compose up -d後
Mem:         987916      562060      353336        8016       72520      310244
その後なぜか、メモリ使用量が増え重くなった。
Mem:         987912      740764       70660        5424      176488       90448
目次へ

アクセス制限

Nginxのproxy_passを設定する前にWordPressの.htaccessで以下のIP制限をしておいた。
WordPressはapatchではなくNginxで動かしている場合もある。
この記事内ではApache使用ですが
最終的にはNginxを使ってるimage(fpm-alipine)に変更してます。
その場合.htaccessは関係ないので以下参照してください。

sudo docker container exec -it コンテナ名 bash
でコンテナの中に入る。
ls -a
で.のディレクトリやファイルも表示して.htaccessがあるか確認。
.htaccessの中身を確認
cat .htaccess
# BEGIN WordPress

RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress

Vsコードの今、作業しているWordPressのディレクトリに.htaccessを作り中身をコピー。
もとのファイルは念のため、名前を変えて保存しておく。

.htaccessを修正。参考:WordPressのアクセス制限を掛けておくべきファイル・ディレクトリのまとめ 

# BEGIN WordPress

RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
<Files ~ "^(xmlrpc\.php|wp-config\.php)$">
Order deny,allow
Deny from all

</Files>
<Files wp-cron\.php>
Order deny,allow
Deny from all
allow from ***.***.***.***
</Files>
<Files wp-login\.php>
Order deny,allow
Deny from all
allow from ***.***.***.***
</Files>
<Files wlwmanifest\.xml>
Order deny,allow
Deny from all

</Files>
<Files ~ "^(license\.txt|readme\.html|wp-config-sample\.php)$">
Order deny,allow
Deny from all

</Files>
# END WordPress

今回追加した<Files >の中でのファイル名の書き方で動作が違った。
恐らく使っているエディタやWindows、Macなど環境によって違うのかも。
私の場合Windows11、SSH接続のVsコード
NG <Files wp-login\.php>
OK <Files wp-login.php>
ドット’.’の前の’\’はエスケープシーケンスのようで、これをなくしたらうまくいきました。
実際にドメイン/wp-login.phpにアクセスしてForbiddenになるかで確認できます。
記事の中ではエスケースシーケンス付きで記述していますが実際には削除して使ってます。

pwd
/var/www/html
で今いるところを確認。
exit
sudo docker cp .htaccess <コンテナID>:/var/www/html
でコピー。

wp-adminのアクセス制限については
Vsコードで.htaccess0を作って中身は
Order deny,allow
Deny from all
allow from ***.***.***.***
コンテナの中にコピー
sudo docker cp .htaccess0 <コンテナID>:/var/www/html/wp-admin/.htaccess

REST API アクセス制限については
コンテナの中に入って
WordPressインストールディレクトリに「wp-json」というディレクトリを作成
exit
でコンテナから出る。
Vsコードで.htaccess1を作って中身は
Order deny,allow
Deny from all
allow from ***.***.***.***
後で分かったがallow fromで自分のIPを許可しないと新規投稿で
「jsonレスポンスがありません。」というエラーの原因になっているかもしれません。
この件はあいまい。wafをオフしただけでも新規投稿できたかもしれないので記憶があやふやです。

コンテナの中にコピー
sudo docker cp .htaccess1 <コンテナID>:/var/www/html/wp-json/.htaccess
目次へ
wp-cronにアクセス制限してやったとき
WordPressで投稿した直後に以下のエラーが出る。
もしIP制限にするには自分のIPアドレスではなく
sudo docker inspect ネットワーク名で調べたGatewayのIPで
Allow from にしないとダメなのかと思ったが、なぜclientがGatewayのIPになっているのか分からないのでGatewayのIPをallow fromにするのはやめた。
[error] 128#128: *364 access forbidden by rule, client: GatewayのIP, server: kikuichigevps.com, request: "POST /wp-cron.php?doing_wp_cron=**** HTTP/1.1", host: "kikuichigevps.com"
(要調査)→https://kikuichige.com/24955/#toc2

接続

前回作ったmodsecurity/jikken1.confの以下をWordPressのコンテナに変えます。

80と443の設定を以下に変更
    location / {
        #allow ***.***.***.***;  # ***.***.***.***からのアクセスのみ許可
        #deny all;  
        proxy_pass   http://wordpress-wordpress-1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $remote_addr;# クライアントのIPを渡す
    }
最初アクセスしたときwp-admin/install.php が HTTPS で、
dashicons.min.css等が HTTPになっていて
cssが当たっていない状態でした。以下追加したらうまく表示しました。
proxy_set_header X-Forwarded-Proto https;
多分httpとhttpsで混ざった状態でアクセスするとダメで、
こうすればhttpがhttpsになるんだと思います。

またproxy_set_header X-Forwarded-For $remote_addr;は
http://wordpress-wordpress-1にクライアントのIPを渡すためです。
これがないとwaf-nginxのIPがWordPressに渡ってアクセス制限できませんでした。
X-Forwarded-Forについてはこちらに書かれてます。
 https://beyondjapan.com/blog/2024/02/nginx-access-log/
コメントアウトしている2行を使うとIPアドレス制限できます。
準備中は自分のIPアドレスだけ許可するようにしてます。
confを反映させる
sudo docker restart コンテナ名
目次へ

セキュリティ対策

すでに上で実施している部分もあります。

シン・クラウド for FreeのWordPressセキュリティ設定の項目を参考に対策

プラグインを入れすぎると何かあったとき調べるのが大変になるのではないかと思っているので、
セキュリティ対策にプラグインは使わないことにしました。
シン・クラウド for FreeのWordPressセキュリティ設定の項目を参考に対策していきます。

国外IPアクセス制限 ←結果的に国内外区別せず制限することになった。
 ダッシュボード アクセス制限
  →wp-login.php、wp-adminを.htaccessでIP制限した。
   参考:https://kingsite.jp/blog/0174#11
   参考:WordPressのアクセス制限を掛けておくべきファイル・ディレクトリのまとめ  
 XML-RPC API アクセス制限
  →XML-RPC API を.htaccessでアクセス制限した。
   参考:WordPressのアクセス制限を掛けておくべきファイル・ディレクトリのまとめ  
  →(代替方法)function.phpを直接編集。詳細XML-RPCを無効にしてみる
 REST API アクセス制限
  →REST API「wp-json」を.htaccessでアクセス制限した。
   参考:WordPressのアクセス制限を掛けておくべきファイル・ディレクトリのまとめ  
  →(限定的代替方法)ユーザー名を表示させないようにする対策のみ。
   詳細:ユーザー名を見えなくした
 wlwmanifest.xml アクセス制限
  →wlwmanifest.xml を.htaccessでアクセス制限した。
   参考:WordPressのアクセス制限を掛けておくべきファイル・ディレクトリのまとめ  
その他、WordPressのアクセス制限を掛けておくべきファイル・ディレクトリのまとめに書かれていることをやりました。  
ログイン試行回数制限
 ログイン試行回数制限
  →調べるとプラグインを使う方法しか見つからなかったのでやらない。
   IP制限のみで様子を見て必要ならプラグイン導入を考える。

コメント・トラックバック制限
 単一ユーザーからの大量投稿
 国外IPアドレスからの投稿
  →コメントできないようにした。

【WorldPress入門】スパムコメント対策
WorldPressダッシュボードを見るとコメントに1となっていた。見てみると外人からコメントがきた。明らかに宣伝のコメントだ。さらにメールで「 モデレートしてください: "Hello world!"」ときた。ということ

その他

個人メモ
WordPressのテーマファイルエディタを使うとき「ファイルの更新」をクリックすると
「致命的なエラーをチェックするためにサイトと通信できないため、PHP の変更は取り消されました。SFTP を使うなど、他の手段で PHP ファイルの変更をアップロードする必要があります。」
対策:WAFのnginxのconfでGatewayのIPを一時的にallowにする。
以下↓に詳しく書きました。

シン・クラウド for FreeのWordPressのログを見たり運営していて気付いた対策。

ユーザー名を見えなくした

こちらを参照してください。

シン・クラウド for FreeのアクセスログをPythonで解析する方法
シン・クラウド for Freeでアクセスログが見れるようになったのでPython(JupiterNotebook)を使って解析してみました。アクセスログについてはこちらで説明されています。実施してみて危なそうなログが見つかったので対策(X

ニックネームを変える

フィードに含まれるユーザー名を隠す。
→ニックネームを変える。詳細:feed

PHPのバージョンをかくす

参考:[技術ブログVol.4] Webサーバセキュリティの基本の「き」 – DENET 技術ブログ

アクセスログに以下があったので調べた
"GET /?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000 HTTP/1.1"
アクセスしてブラウザの開発者ツールのネットワークタブで
ヘッダを見るとX-Powered-By:PHP/*.*.*
とPHPのバージョンが表示される。

対策
vim php.iniに以下追加
expose_php = Off

保存したら
sudo docker cp ./php.ini コンテナ名:/usr/local/etc/php/php.ini
コンテナ名はsudo docker ps -aで調べられます。
sudo docker restart コンテナ名で再起動
目次へ

アップロードMAXサイズを変更

ダッシュボードのメディア→新しいメディアファイルを追加
で最大アップロードサイズ: 2 MB。と表示されます。
テーマをアップロードするときなど必要なときだけ大きくしようと思います。
やり方は、こちら↓。最後WordPressのコンテナをrestartすると設定が反映されます。

テーマをアップロードするときmodsecurityをOFFにしないと引っかかります。
私は自分のIPだけ許可するルールを追加して使ってます。

サイト内検索スパムの対策(執筆中)

ログにこんなのがあった。(いろいろ私が変えて貼り付けてります。)

"GET /?s=Prepare+For+Adobe+略+www.どっかのサイト.com+%E2%AE%84+%E2%9C%8AValid+AD0-E559+Exam+Sample HTTP/2.0"

移行

2024/4/15~レンタルサーバーからVPSに変更し、当ブログを運営してます。
実行する順番はよく考えてからやってください。バックアップが取れなくなったりします。
以下は例です。手順はだいぶ抜粋されてます。(いろいろハマったので記録してない。)

お名前.comレンタルサーバーからVPSへ移行する場合
データベース、アップロード、その他をダウンロード
プラグインとテーマはバックアップを使わず直接インストールしてます。
またファイルサイズを確認してアップロードできるサイズを広げるために
あとで以下の調整が必要です。
php.iniwordpressのnginx、wafのnginxのconf
全体の流れは、こちら↓を参照してください。
ドメインを移行した後はバックアップが取れなくなるので注意してください。
また別のドメインで作ったWordPressに復元するとドメインを変えるのが大変なので
ドメイン移行、SSL対応後、初期状態のWordPressに復元したほうがいいです。

シン・クラウド for FreeとUpdraftPlusでサーバー移行の練習をした!
データベースだけをバックアップして移行先ではテーマやプラグインは手動でインストールした後にデータベースだけ復元すればスムーズに移行できるのではないかと考えたので実験した。具体的にはシン・クラウド for Freeのサーバー内の2つのWord
ドメイン移行は
ネームサーバーを変更する。参考:https://www.onamae-server.com/guide/rs/p/24
VPS(KVM)のところの設定するをクリック→有料サービスは設定しない→設定する
ドメインのDNS設定→ドメインを選ぶ→DNSレコード設定を利用する
Aレコードを空欄とwwwの2つ作成する。参照:https://www.onamae.com/column/domain/33/
MXやTXT(default._domainkey~)などのメール関係は、
このまま使えるか分からないので使ってません。
改めてメールアドレスを新規で作ってます。↓
SSL対応では
/etc/letsencrypt/archive/kikuichige.com/privkey.pem;のパーミッションが
600でうまくいかないので644に変更。(変更していいものなのかは不明)

wafのnginx(本シリーズの最終形態)のconfで80と443のドメインを変更→sudo docker restart waf-nginxで変更反映

移行先でバックアップファイルをアップロードに3つドラッグアンドドロップ
復元→全部チェック→次へ→復元
1回失敗したけどWordPressとデータベースのコンテナとボリュームを削除してcomposeupしたら再開できた。

移行して表示はできました。しかし、次項に続く。

公開に失敗しました。 返答が正しい JSON レスポンスではありません。

新規投稿すると「公開に失敗しました。 返答が正しい JSON レスポンスではありません。」
ログを見るとModSecurityに引っかかっている。
→offにして新規投稿したらできましたが下に対策があります。

2024/03/19 07:52:10 [error] 127#127: *102 [client ***.***.***.***] ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:BLOCKING_INBOUND_ANOMALY_SCORE' (Value: `10' ) [file "/etc/modsecurity.d/owasp-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "176"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 10)"] [data ""] [severity "0"] [ver "OWASP_CRS/4.0.0"] [maturity "0"] [accuracy "0"] [tag "modsecurity"] [tag "anomaly-evaluation"] [hostname "***.***.***.***"] [uri "/wp-json/wp/v2/posts/24801/autosaves"] [unique_id "171080233091.334238"] [ref ""], client: ***, server: django7.kikuichigevps.com, request: "POST /wp-json/wp/v2/posts/24801/autosaves?_locale=user HTTP/2.0", host: "django7.kikuichigevps.com", referrer: "https://django7.kikuichigevps.com/wp-admin/post-new.php"

対策として2つ
WordPressのwp-jsonの.htaccessで自分のIPを許可した。(関係ないかも)
Modesecurityで自分のIPを許可した。↓(ymlのenviromentでon/off切り替えるのが大変なので)

所感

wafも効いてるし結構対策できたと思う。
しかしメモリ不足の問題を解決しないといけないので次回やります。(次回で解決した。)
取り合えずVsコードでサクサクやってfreeでメモリ見て0.7G超えるとメモリ不足になって
VPSの再起動が必要になった。
不便だがシリアルコンソールをなるべく使うようにしてる。
目次へ

イチゲをOFUSEで応援する(御質問でもOKです)Vプリカでのお支払いがおすすめです。
MENTAやってます(ichige)

コメント

タイトルとURLをコピーしました