PHPからのメール送信

WebサーバーのPHPプログラムから、ユーザーからの問い合わせ等をメール送信しているが、迷惑メールとなって届かないことが多い。最近、GMailのスパム判定がさらに厳しくなっているかんじがする。

1.従来の方法

PHP標準の以下のメール関数を使って実装。

(mail)https://www.php.net/manual/ja/function.mail.php

(mb-send-mail)https://www.php.net/manual/ja/function.mb-send-mail.php

SMTPサーバーの指定はできず、サーバーのメール転送エージェント(MTA:sendmailあるいはPostfix)から送信される。Webサーバーは、サービスのドメインのMXレコードに指定されているメールサーバー (以下「正式メールサーバー」) ではないので、SPFレコードにWebサーバーのアドレスを追加しても、最近は迷惑メールの判断されることが増えてきた。

2.改善策

サービス提供しているドメインの正式メールサーバー経由でメール送信するように修正した。方法として、1)メールリレーの指定をやってみたが、上手くいかない部分もあったので、2)STMPサーバーからの送信とした。

2.1 メールリレーの指定

PHPプログラムは変更せずに、サーバーのMTAから、正式メールサーバーを経由(メールリレー)して送る方法を試してみた。

CentOSでsendmailから、SMTP認証を利用して正式メールサーバー経由で送る場合の設定は、以下が参考になる。

https://access.redhat.com/ja/solutions/2733021

メールサーバーとしてXServerのメールサーバーを利用している場合、SPF_SOFTFAILとなる問題がある。

https://darekoi.blogspot.com/2018/05/xserver-spf.html

ウィルスチェックサーバーをSPFに追加すれば、改善するかもしれないが、保証はない。↓

(2021/08/14)

ウィルスチェックサーバーをSPFに追加してみたころ、以下となりGmailでは迷惑メールのまま送信できなかったが、他のメールには届いた。

tests=SPF_HELO_NONE,SPF_PASS

2.2 正式メールサーバーからの送信

PHPプログラムから、サーバーのMTAを経由せず、SMTP認証を利用して 正式メールサーバーから送るように変更した。

SMTP認証でのメール送信としては、PHPMailerが広く使われているよう。

https://github.com/PHPMailer/PHPMailer

検索すると、使い方について説明している日本語ページはあるが、古いものも多いので、正式なGitHubのサンプル見る方が良いと思う。英語が苦手でも、サンプルプログラム見れば使い方は簡単にわかる。

https://github.com/PHPMailer/PHPMailer#a-simple-example

ただし、サンプルは多言語に対応していないので、以下の追加は必要。

  $mail->CharSet = "utf-8";
  $mail->Encoding = "base64";

あと、正式版にする時には、以下を変更。

 //$mail->SMTPDebug = SMTP::DEBUG_SERVER; //デバッグ
 //$mail->SMTPDebug = SMTP::DEBUG_CONNECTION; //接続に失敗する場合のデバッグ
  $mail->SMTPDebug = SMTP::DEBUG_OFF;

3.結論

迷惑メールにならないサーバーPHPプログラムからのメール送信には、やはり正式にSMTP認証してメールサーバーから送るのが一番かと。DNSにSPF設定してとか、色々やったけど、さっさとプログラム直せばよかった。

CertbotによるSSL証明書(CentOS7.9)

CentOS 7.9 にLet’s encrypt でSSL証明書を設定した時のメモ。

検索すると、古いやり方が出てくる。最新のやり方は、Certbotの本家サイトに行くのがいい。

https://certbot.eff.org/lets-encrypt/centosrhel7-apache

OSとWebサーバーを選んで、後は指示通りにやるだけ。

一応、CentOS 7.9 で、Apache 2.4 でやった時の手順は以下(2021年2月5日時点)。

1.SSLサーバーの設定

mod_sslは既に入れてあり、SSLは有効化されている。

ただし、SSL証明書を取得したいドメインについては、バーチャルホストとして定義するほうがいい。

デフォルトの/etc/httpd/conf/httpd.confではなく、/etc/httpd/conf.d以下に、バーチャルホストを定義する。ここに定義した、XXXX.com.confに対して、後の手順4で、Certbotが、XXXX.com-le-ssl.confを作成して、XXXX.com.confについても、httpsリダイレクトに修正してくれる。

2.snapdのインストール

https://snapcraft.io/docs/installing-snap-on-centos

これも既にやってあったけど、一応、以下をやる。

sudo yum install epel-release

後は、snapdをインストールする。

sudo yum install snapd
sudo systemctl enable --now snapd.socket
ln -s /var/lib/snapd/snap /snap

※この後、一度ログアウトするか、再起動

3.snapdのバージョン確認

sudo snap install core
sudo snap refresh core

4.以前のCertbotのアンインストール

sudo yum remove certbot

5.Certbotのインストール

以下を実行。

sudo snap install --classic certbot

6.Certbotコマンドの設定

コマンドにシンボリックリンクをはる。

sudo ln -s /snap/bin/certbot /usr/bin/certbot

7.証明書の設定

以下コマンドを実行して、サイトを選択して設定。

sudo certbot --apache

8.証明書の自動更新の設定

更新のスケジューリングは自動でされる。スケジューリングは、以下コマンドで確認できる。

sudo systemctl list-timers

※CentOS8の場合は、/etc/crontab に設定されている。

WordPressのXserverへの移行

お名前.comのレンタルサーバーから、Xserverのレンタルサーバーへ移行した。WordPressの移行については、「WordPress簡単移行」で移行した。

https://www.xserver.ne.jp/manual/man_install_transfer_wp.php

便利で楽にできていいのだが、ただ、一つのサイトだけデータ移行のところで失敗して移行できなかった。

【原因】

プラグインの「Google Map WP」がDBでバイナリデータを使っていて、それが通常方法でdumpした場合には復元できないためエラーとなるよう。

【対応方法】

「WordPress簡単移行」を使いたい場合は、一旦、「Google Map WP」プラグインを削除してから移行して、その後、Xser ver側で再度、プラグインを入れるしかないか。

そうじゃなければ、自分で移行する。

https://www.xserver.ne.jp/manual/man_install_transfer_wordpress.php

その場合、DBバックアップ時には「–hex-blob」オプションを指定すること。

https://dev.mysql.com/doc/refman/5.6/ja/mysqldump.html#option_mysqldump_hex-blob

クラウド/VPS/レンタルサーバーの【コントロールパネル】セキュリティ対策(2020年11月)


クラウド、VPSのセキュリティ対策について、サーバー自体のセキュリティ対策をちゃんとしても、コントロールパネルが乗っ取られたら元も子もない。

そこで、知っている範囲での各社の状況 (2029年11月11日時点)についてのメモ。

IP制限2段階認証ログイン通知操作ログ
お名前.com××
ConoHa××
エックスサーバー×××
さくらインターネット×VPS:×
クラウド:〇
×
ニフクラ△※二要素認証×

1. お名前.com

会員情報の「ログインセキュリティ」から、2段階認証とログイン通知の設定が可能。

https://help.onamae.com/answer/20321

2.ConoHa

「アカウント設定」から「2段階認証」「ログイン通知メール」が可能。

https://support.conoha.jp/common/guide/account/?btn_id=c-2stepauthentication-sidebar_guide-account

3.エックスサーバー

二段階認証には対応している。

https://www.xserver.ne.jp/manual/man_order_twostepauth.php

4. さくらインターネット

VPSとクラウドともに操作ログが閲覧できる。

(VPS)

https://help.sakura.ad.jp/hc/ja/articles/206245282-%E6%93%8D%E4%BD%9C%E5%B1%A5%E6%AD%B4%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B

(クラウド)

https://manual.sakura.ad.jp/cloud/controlpanel/eventlog/eventlog.html

クラウドは2段階認証にも対応。

https://manual.sakura.ad.jp/cloud/controlpanel/settings/2-factor-auth.html

5. ニフクラ(旧名称:ニフティクラウド)

ログインのIPアドレス制限が、「アカウント管理」からアカウントを選択して、「IP許可設定追加」で可能。

https://pfs.nifcloud.com/help/acc/detail.htm

また、過去6カ月分のコントロールパネルの操作ログが参照できる。

https://pfs.nifcloud.com/help/log/

ログイン時の通知メールの機能はないが、多要素認証の設定が可能。

バックアップ設定

以下、バックアップの方針に基づいて、CentOSサーバー間で、バックアップ設定した手順。

0.環境

転送元サーバー:CentOS 8.2

  • ホスト名(例):www.xxservice.com
  • グローバルアドレス(例):222.222.222.222
  • プライベートネットワークアドレス(例):10.10.10.1
  • sshdポート(例):7777
  • バックアップを実行するユーザー(例):appuser

転送先サーバー1:CentOS 7.8

  • ホスト名(例):bak1.xxservice.com
  • プライベートネットワークアドレス(例):10.10.10.200
  • sshdポート(例):8888

転送先サーバー2:CentOS 7.8

  • ホスト名(例):bak2.xxservice.com
  • 転送元サーバーとは別拠点で、プライベトネットワーク未接続
  • sshdポート(例):9999

1.転送先サーバーの設定

バックアップ用ユーザー(例):backupuser

バックアップディレクトリ(例):/home/backupuser/xxservice/

1-1)sshd_configの修正

/etc/ssh/sshd_configの設定が以下となるようにする。

  • ホストベース認証を有効
  • ホストベース認証の既知ホストは、ユーザーディレクトリ下を許可
  • ユーザーディレクトリ下の.shostsを有効にする。
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
HostbasedAuthentication yes
# Change to yes if you don't trust ~/.ssh/known_hosts for HostbasedAuthentication 
IgnoreUserKnownHosts no 
# Don't read the user's ~/.rhosts and ~/.shosts files 
IgnoreRhosts no

後、プライベートネットワークでは逆引きできない。余計なログを出さないようにUseDNSがyesの場合は、noに変更する。

UseDNS no

設定変更後に、設定の読み込み。

$ systemctl reload sshd

1-2)rootユーザーへのスイッチ禁止

/etc/pam.d/suで、以下を設定し、rootユーザへのスイッチを禁止する。

auth required pam_wheel.so use_uid root_only

1-3)バックアップ用ユーザー作成

$ adduser backupuser

1-4)バックアップ用ディレクトリ作成

$ su - backupuser
[backupuser ~]$ mkdir xxservice

1-5)既知ホストの追加

バックアップユーザーで、転送元サーバーにssh接続を試みて、公開鍵を取得して既知ホストに登録する。

※転送先サーバー1の場合
[backupuser ~]$ ssh -p 7777 10.10.10.1

※転送先サーバー2の場合
[backupuser ~]$ ssh -p 7777 www.xxservice.com

既知ホストに追加するかと聞いてくるので、yesで登録すると、~/.ssh/known_hostsに登録される。

ポート番号が入った形で登録されるので、viコマンドで修正する。

※転送先サーバー2の場合、以下のように修正する

[www.xxservice.com]:7777,[222.222.222.222]:7777 (公開鍵) 
↓
www.xxservice.com,222.222.222.222 (公開鍵)

1-6).shostsの設定

viコマンドで、.shostsファイルを作成し、中身は以下とする。転送元サーバーのIPアドレスを設定する。

※転送先サーバー1の場合

10.10.10.1 appuser 

※転送先サーバー2の場合

222.222.222.222 appuser 

パーミッションを変更して、.shostsファイルを見えないようにする。

[backupuser ~]$ chmod 600 .shosts

2.転送元サーバーの設定

2-1)ssh_configの修正

従来はssh_configを直接修正していたが、CentOS 8.2 では、以下ディレクトリにファイル追加するのが作法みたい。

/etc/ssh/ssh_config.d/99-hostbase.confを、以下内容で作成する。

HostbasedAuthentication yes
EnableSSHKeysign yes

2-2)既知ホストの追加と接続確認

以下コマンドで接続し、既知ホストに追加するかと聞いてくるので、yesで登録する。

※転送先サーバー1への接続
[appuser ~]$ ssh -p 8888 -l backupuser 10.10.10.200

※転送先サーバー2
[appuser ~]$ ssh -p 9999 -l backupuser bak2.xxservice.com

問題なければ、無事にログインできる。

2-3)バックアップ処理の登録

以下のコマンドを作成して、実行権を付けて、cron実行する。

2-3-1)バックアップコマンド

do_backupという名前で以下ファイルを作成する。timeコマンドで実行時間を計測しながら、低優先度でバックアップを実行する。

引数は、バックアップサーバーのアドレス、ポート、バックアップファイルの接尾辞で、このコマンドは、バッチから引数を渡されて実行される。

【do_backup】

#!/bin/sh
#
alias dotime='time ionice -c 2 -n 7 nice -n 19'

# param
if [ $# -ne 3 ]; then
  echo "param error!!"
  exit 1
fi
BACKUP_SERVER=$1
BACKUP_SERVER_PORT=$2
BACKUP_SUFFIX=$3

# file setting
BIN_DIR=(コマンドの配置ディレクトリ)
BACKUP_DIR=(バックアップファイルを置くディレクトリ)
BACKUP_LOG="$BACKUP_DIR/bak_$BACKUP_SUFFIX.log"

BACK_FILE_DB="$BACKUP_DIR/dbbak_$BACKUP_SUFFIX"

APP_DIR=(アプリケーションデータのディレクトリ)
BACK_APP_DIR="$BACKUP_DIR/appdata/"

TRNS_DB_DIR="/home/backupuser/xxservice/"
TRNS_APP_DIR="/home/backupuser/xxservice/appdata/"

#--------------------------------------------------
# Start
echo "---- START : `date`"  > $BACKUP_LOG

####################
# DB
echo "---- DB S : `date`"  >> $BACKUP_LOG
(dotime $BIN_DIR/do_db_backup $BACK_FILE_DB &>> $BACKUP_LOG) &>> $BACKUP_LOG

echo "---- DB GZIP S : `date`"  >> $BACKUP_LOG
(dotime gzip -f $BACK_FILE_DB &>> $BACKUP_LOG) &>> $BACKUP_LOG

####################
# APP
echo "---- APP S : `date`"  >> $BACKUP_LOG
(dotime rsync -auv --rsync-path="ionice -c 2 -n 7 nice -n 19 rsync" \
  $APP_DIR $BACK_APP_DIR &>> $BACKUP_LOG) &>> $BACKUP_LOG

####################
# Transfer

# transfer DB backup
echo "---- TRN DB S : `date`"  >> $BACKUP_LOG
(dotime scp -P $BACKUP_SERVER_PORT $BACK_FILE_DB.gz ubackup@$BACKUP_SERVER:$TRNS_DB_DIR \
  &>> $BACKUP_LOG) &>> $BACKUP_LOG

# transfer APP backup
echo "---- TRN APP S : `date`"  >> $BACKUP_LOG
(dotime rsync -auvz -e "ssh -p $BACKUP_SERVER_PORT" $BACK_APP_DIR \
  ubackup@$BACKUP_SERVER:$TRNS_APP_DIR  &>> $BACKUP_LOG) &>> $BACKUP_LOG

# End
echo "---- END : `date`"  >> $BACKUP_LOG

最初のrsyncで、–rsync-path=”ionice -c 2 -n 7 nice -n 19 rsync”オプションを付けているのは、受信側も同じアプリサーバーのため優先度を下げている。転送時には付けていないのは、転送先サーバーはバックアップ専用のため、優先度を気にしなくていいため。

2-3-2)DBバックアップコマンド

do_db_backupという名前で以下ファイルを作成する。3-1)バックアップコマンドから呼ばれるコマンドで、DBに応じたコマンドを作成する。

【do_db_backup】

※MariaDBの例

#!/bin/sh
#
#  $1: backup file name
#

mysqldump --user=(DBユーザー) --password=(DBパスワード) --single-transaction (データベース名) > $1

※PostgreSQLの例

#!/bin/sh
#
#  $1: backup file name
#

pg_dump -Fc -b (データベース名)> $1

2-3-3)実行コマンド

バッチで実行するための、以下の2つのファイルを作成する。

【BACKUP_HOURLY】

#!/bin/sh
#

BACKUP_SERVER=10.10.10.200
BACKUP_SERVER_PORT=8888
BACKUP_SUFFIX=h`date +%H`

(コマンドの配置ディレクトリ)/do_backup \
  $BACKUP_SERVER $BACKUP_SERVER_PORT $BACKUP_SUFFIX

【BACKUP_DAILY】

#!/bin/sh
#

BACKUP_SERVER=bak2.xxservice.com
BACKUP_SERVER_PORT=9999
BACKUP_SUFFIX=d`date +%d`

(コマンドの配置ディレクトリ)/do_backup \
  $BACKUP_SERVER $BACKUP_SERVER_PORT $BACKUP_SUFFIX

2-4)cron設定

“crontab -e”で、実行コマンドをスケジューリングする。

毎時42分と、毎日3時13分にバックアップする設定の例。

# m h dom mon dow command
42 * * * * (コマンドの配置ディレクトリ)/BACKUP_HOURLY
13 3 * * * (コマンドの配置ディレクトリ)/BACKUP_DAILY