LinuxのPHPからWindowsのSQLServerに接続

WIndows上のSQLServerに、Linuxサーバー上のPHPプログラムから接続する手順。

Microsoftがドライバーを提供していて、以下のチュートリアルを参考に作業。

https://learn.microsoft.com/ja-jp/sql/connect/php/installation-tutorial-linux-mac?view=sql-server-ver16

今回のLinuxサーバーはCentOS Stream 9なので、Red Hatの部分を参考に進める。

1)ODBCドライバー

1-1)Linux用ODBCドライバー

https://learn.microsoft.com/ja-jp/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server?view=sql-server-ver15&tabs=redhat18-install%2Calpine17-install%2Cdebian8-install%2Credhat7-13-install%2Crhel7-offline

レポを更新して

curl https://packages.microsoft.com/config/rhel/9.0/prod.repo > /etc/yum.repos.d/mssql-release.repo

必要なものをインストールする。

sudo dnf install msodbcsql18
sudo dnf install mssql-tools18
sudo dnf install unixODBC-devel

1-2)WindowsServer側で接続許可

Windows側で、SQLServerのTCP/IP接続設定と、ファイアーウォールでLinuxサーバーからの接続許可をする。

1-3)ODBC設定

/etc/odbc.iniを編集して、DSNを定義。

https://learn.microsoft.com/ja-jp/sql/connect/odbc/linux-mac/connection-string-keywords-and-data-source-names-dsns?source=recommendations&view=sql-server-ver16

1-4)接続確認

sqlcmdで接続確認。暗号化を有効にしているので、証明書エラーになるのでCオプションを指定する。

/opt/mssql-tools18/bin/sqlcmd -D -C -S (DSN名) -U (ユーザー名) -P  (パスワード)

2)PHPからの接続

PHP用のドライバーについては、以下ページ。

https://learn.microsoft.com/ja-jp/sql/connect/php/overview-of-the-php-sql-driver?view=sql-server-ver16

SQLSRV ドライバーと PDO_SQLSRV ドライバーがあるが、今回はSQLSRV ドライバーを使うこととした。

2-1)SQLSRV ドライバーのインストール

以下コマンドでインストール。

sudo pecl install sqlsrv

ConoHaのVPSのCentOS Stream 9では、足りないものがありmakeエラーとなる。

(エラー)
/bin/ld: cannot find -lltdl
collect2: error: ld returned 1 exit status
make: *** [Makefile:238: sqlsrv.la] Error 1
ERROR: `make' failed

libtool-ltdl-develが足りていないよう。

sudo dnf install libtool-ltdl-devel

ところが、見つからないと出る。どうやら、repoの設定が無効になっているようで、/etc/yum.repos.d/centos.repoを修正して、crbを有効にすることで解決。

:
[crb]
:
enabled=1     ※ここを0から1に変更
  
[crb-debuginfo]
:

2-2)PHPの設定

起動時にドライバーを読み込ませる。

https://learn.microsoft.com/ja-jp/sql/connect/php/loading-the-php-sql-driver?view=sql-server-ver16#loading-the-driver-at-php-startup

/etc/php.d に、以下内容で30-sqlsrv.iniを作成。

extension=sqlsrv.so

2-3)接続確認

サンプルプログラムを修正して、ブラウザから確認する。

https://learn.microsoft.com/ja-jp/sql/connect/php/installation-tutorial-linux-mac?view=sql-server-ver16#sqlsrv-example

SQLSRV ドライバーのAPIについては、以下ページ。

(APIリファレンス)

https://learn.microsoft.com/ja-jp/sql/connect/php/sqlsrv-driver-api-reference?view=sql-server-ver16

自己証明書を利用しているので、接続オプションにTrustServerCertificateを追加した。

<?php
$serverName = "myServer,9999";  # 9999:PortNo
$connectionOptions = array(
    "TrustServerCertificate" => "yes", # 自己証明書を信頼
    "database" => "myDatabase",
    "uid" => "myUser",
    "pwd" => "myPassword"
);
:

接続オプションについての詳細は以下ページ。

(接続オプション)

https://learn.microsoft.com/ja-jp/sql/connect/php/connection-options?view=sql-server-ver16

Nginx+NaxsiでWAF

CentOS Strem9サーバーに、Nginx+NaxsiでWAFを構築する。

(Naxsi) https://github.com/nbs-system/naxsi

1.Nginxインストール

Naxsiモジュールをコンパイルするので、Nginxもソースからインストールしたものを使うほうがいいかもしれないが、保守を考えてdnfにてインストール。

dnf install nginx

今回入れたのは、バージョン1.20.1。

2.Naxsiモジュール作成

Naxsiインストールについては、GitHubの以下にある。

https://github.com/nbs-system/naxsi/wiki/naxsi-compile#build-naxsi-as-a-dynamic-extension-for-nginx-from-your-distribution-package-ie-ubuntu

この手順に従って行えばいい。

2.1 コンパイル環境

とりあえず開発用一式を入れる。

dnf groupinstall 'Development Tools'

追加でインストールしたコマンドは以下。

dnf install gd-devel
dnf install libxslt-devel
dnf install perl-ExtUtils-Embed

2.2 Naxsiソース取得

最新のバージョンを確認して、環境変数を設定。現時点では1.3。

以下のようにして、ソースを取得して展開。

export NAXSI_VER=1.3
wget https://github.com/nbs-system/naxsi/archive/$NAXSI_VER.tar.gz -O naxsi_$NAXSI_VER.tar.gz
tar vxf naxsi_$NAXSI_VER.tar.gz

※(2023/1/25) 最新のソースは、GitHubから取得したほうがいい。コメント参照

2.3 Nginxソース取得

以下のようにして、1.20.1のソースを取得して展開。

export NGINX_VER=1.20.1
wget https://nginx.org/download/nginx-$NGINX_VER.tar.gz
tar vxf nginx-$NGINX_VER.tar.gz 

2.4 Naxsi動的ライブラリの作成

dnfでインストールしたNginxと同じ設定でコンパイルする必要があるので、まずNginxの情報を取得する。

nginx -V

このコマンドの出力結果の中のconfigure argumentsを指定してconfigureを行い、モジュールのコンパイルを実行。

cd nginx-$NGINX_VER  

./configure (※ここにconfigure arguments) --add-dynamic-module=../naxsi-$NAXSI_VER/naxsi_src/

make modules

今回の場合のconfigureコマンドは、具体的には以下のようになる。

./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-compat --with-debug --with-file-aio --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-cc-opt='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64-v2 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' --with-ld-opt='-Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,-E' --add-dynamic-module=../naxsi-$NAXSI_VER/naxsi_src/

まあNaxsiのライブラリを作りたいだけなので全部は必要ないかもしれないが、元ドキュメントに”This will ensure module will be compatible with your nginx and will load properly.”とあるように、実運用するシステムであれば、このように同じ条件でNaxsi動的ライブラリを作成するほうが安全で安心かと思う。

3.基本設定

3.1 モジュールの配置

動的ライブラリを適当な場所(/etc/nginx/moduls等)に配置する。

mkdir /etc/nginx/modules
cp objs/ngx_http_naxsi_module.so /etc/nginx/modules/

基本的なルールも、そのまま使うのでコピーする。

cp (naxsiソースディレクトリ)/naxsi_config/naxsi_core.rules /etc/nginx/

3.2 Nginxの設定

/etc/nginx/nginx.confに、モジュールとルールの読み込みと、Naxsiの設定を以下の例を参考に追加していく。

...
load_module /etc/nginx/modules/ngx_http_naxsi_module.so; # naxsiのロード

http {
    include /etc/nginx/naxsi_core.rules; # naxsi基本ルールのロード
    ...
}
...
server {
...

    location / { # naxsi is enabled, and in learning mode

        SecRulesEnabled; # naxsiを有効に
        LearningMode; #学習モードを有効に  ※エラーページにしたい場合はこれを外す
        LibInjectionSql; #SQLインジェクションへのサポートを有効に
        LibInjectionXss; #XSSインジェクションへのサポートを有効に

        DeniedUrl "/RequestDenied"; #naxsiがブロックした場合のリダイレクト先
        CheckRule "$SQL >= 8" BLOCK; #$SQLにスコアが8以上になった場合のアクションがBLOCK
        CheckRule "$RFI >= 8" BLOCK;
        CheckRule "$TRAVERSAL >= 5" BLOCK;
        CheckRule "$UPLOAD >= 5" BLOCK;
        CheckRule "$XSS >= 8" BLOCK;


        proxy_pass http://10.10.10.1; # WAFを設定したいWebサーバーのアドレス  
        ....
    }

    location /admin { # naxsi is disabled ※/admin以下はnaxsiは無効

        SecRulesDisabled; # オプション、デフォルトではnaxsiは無効
        
        allow 1.2.3.4;
        deny all;
        proxy_pass http://127.0.0.1;
        ....
    }

    location /vuln_page.php { # naxsi is enabled, and is *not* in learning mode
                 # ※この/vuln_page.phpはnaxsi有効で、学習モードでない(それ以外のページは上で指定されている学習モードになる)

        SecRulesEnabled;
        proxy_pass http://127.0.0.1;
    }
    
    location /RequestDenied {  # ※上で指定されたnaxsiがブロックした場合のlocation
        internal;
        return 403;
    }
...

}

4.動作確認

4.1 HTTPポート公開

ファイアウォールの設定で、httpのポートを開放する。

firewall-cmd --permanent --add-service=http
firewall-cmd --reload

4.2 Nginx起動

設定したnginx.confに間違いが無いかチェックする。

nginx -t

問題が無ければnginxを起動する。

systemctl start nginx

4.3 Naxsi動作確認

ブラウザからWAFを叩いてテストする。

不正なパラメータ(<scrript>)を付けてURLを叩くと、ブロックが動作しているか確認できる。LearningModeの場合は、エラーログにメッセージが残るだけである。LearningModeでない場合は、エラーページが表示される。

通常ページがブロックされないか念入りに確認する。ブロックされた場合は、ホワイトリストを設定するか、そのページをNaxsiから除外するか、ルールを見直す等の対応をする。

5.公開

問題がなくなれば、正式にhttps化して公開する。

httpsポートの開放は以下。

firewall-cmd --permanent --add-service=https
firewall-cmd --reload

Nginxを有効に。

systemctl enable nginx

CentOS Stream9サーバー設定

ConoHaのVPSで、CentOS Stream9サーバー追加時に最初にやることのメモ

1.サーバー追加時

「オプションを見る」ー「SSH Key」で「キーを選択」で、事前に登録したパブリックキーを選択して、鍵認証にする。

2.サーバーの基本設定

2.1 OS更新

CentOS8以降は、yumでなくてdnfになっている。dnfにシンボリックされているので、今まで通りyumでもいいけど。

dnf update -y 

2.2  hostname設定

/etc/hostnameを変更

2.3 SSHポート変更

1)/etc/ssh/sshd_configでPort指定を追加

Port ???? ※????:適当なポート 

2) ファイアウォールの設定変更

元のSSHポートを閉じて、変更したポートを開ける。

cd /usr/lib/firewalld/services/
cp -p ssh.xml ssh-????.xml
vi ssh-????.xml ※port="22"の22を変更したポート????に
firewall-cmd --permanent --remove-service=ssh
firewall-cmd --permanent --add-service=ssh-????
firewall-cmd --reload

3)sshd再起動

systemctl restart sshd 

2.4 rootログイン時のメール通知

.bash_profileに以下を追加する。

date > /tmp/login
echo $SSH_CLIENT >> /tmp/login
cat /tmp/login | mail -s "root login(`hostname`)" メールアドレス 

SMTPサーバーとして、postfixをインストールする。

dnf -y install postfix
systemctl enable postfix
systemctl start postfix

mailコマンドがない場合は、s-nailをインストールする。

dnf -y install s-nail

3.logwatch設定

1)logwatchをインストール

dnf install logwatch 

2)/etc/logwatch/conf/logwatch.confを編集して、「MailTo = メールアドレス」を追加

4.dnf更新の通知設定

yum-cronに対応するものとして、dnf-automaticをインストールする。

1)dnf-automaticをインストール

dnf install dnf-automatic

2)/etc/dnf/automatic.confの修正

「emit_via = email」「email_to = メールアドレス」に変更し、email_fromも正しいドメイン名に変更。

3)dnf-automaticの有効化

systemctl enable dnf-automatic.timer
systemctl start dnf-automatic.timer 

5.その他設定 

5.1 Cron起動時にmessagesにログが残る対策

/etc/systemd/system.confで、「LogLevel=notice」に変更

5.2 メール関連の設定

DNSにSPFレコードを設定しておく。

5.3 kdumpの無効化

systemctl stop kdump
systemctl disable kdump

5.4 IPアドレス制限

以前のhosts.allowは無くなったので、PAMを有効にして/etc/security/access.confを編集する。

:

# User "root" should be allowed to get access via cron .. tty5 tty6.
+:root:cron crond :0 tty1 tty2 tty3 tty4 tty5 tty6
 ※コメントアウト外す

:

# VPN
+:root:10.10.10.10.1  # rootユーザーを10.10.10.1から許可の例
# All other users should be denied to get access from all sources.
-:ALL:ALL  # これで上記許可以外は接続できなく

※rootでcron実行するために、コメントアウトされていた行を有効にする。

sshdでのPAMの有効化は、/etc/ssh/sshd_configで以下を設定

UsePAM yes

PAM設定ファイルの/etc/pam.d/sshdに以下を設定

account    required pam_access.so

5.5 プライベートネットワーク

ConoHaのVPSの場合、以下の手順でプライベートネットワークの接続設定をする。

5.6 reboot後のメール通知

cronに以下を設定して、リブート後にboot.logの内容をメール通知する。

@reboot (dmesg ; tail -100 /var/log/messages)| mail -s "`hostname` rebooted" メールアドレス

5.7 dnf-makecache.timerの無効化

1時間毎に動いているので、これを無効化する。これが何をしていいるかと、その無効化方法は以下が参考になる。

https://unix.stackexchange.com/questions/579009/why-is-dnf-makecache-timer-needed

対応としては、/etc/dnf/dnf.confに以下を追加。

metadata_timer_sync=0

5.8 rootユーザーへの変更を禁止

rootユーザーへの変更を禁止する場合は、/etc/pam.d/suに以下を設定。

auth            required        pam_wheel.so use_uid root_only

CertbotによるSSL証明書(CentOS Stream9)

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

Certbotの本家ページは以下。

https://certbot.eff.org/

SoftwareでWebサーバーを、SystemでOSを選べばいいのだが、本日時点で、CentOS Stream9は対象にないので、とりあえずCentOS8で。

https://certbot.eff.org/instructions?ws=nginx&os=centosrhel8

1.snapdのインストール

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

1)EPELの登録(既に登録済みだった)

sudo dnf install epel-release
sudo dnf upgrade

2)インストール

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

※この後、一度ログアウトして再ログイン。

2.snapdのバージョン確認と更新

sudo snap install core
sudo snap refresh core

3.Certbotのインストール

sudo snap install --classic certbot

4.Certbotコマンドの設定

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

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

5.証明書の設定

/etc/nginx/nginx.confのserver_nameにドメインが設定されていることが前提。以下コマンドを実行して、server_nameに設定されているドメインを選択する。

sudo certbot --nginx

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

自動更新の確認は以下。

certbot renew --dry-run

スケジューリングは、以下コマンドで確認できる。

sudo systemctl list-timers

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

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

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

https://certbot.eff.org/

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 に設定されている。