--- tags: 主機管理, PHP, Apache --- :::info [快速linux指令教學(mac, windows, ubuntu...等等適用)|工程師必備技能](https://youtu.be/-fzO7iWCSWY?si=nf-GIgxT4zW8x7z7) [伺服器架設篇目錄 - RockyLinux 9](https://linux.vbird.org/linux_server/rocky9/) [Linux 基礎學習訓練教材 - RockyLinux 9.x](https://linux.vbird.org/linux_basic_train/rockylinux9/) ::: # RockyLinux 9 安裝Apache、PHP8筆記 ## 基本設定 * 安裝環境(OS發行版本) ![](https://hackmd.io/_uploads/Bkxfq7ajj.png) * 預設安裝OpenSSL v3 ![](https://hackmd.io/_uploads/BkX1y46oj.png) * 設定主機名稱(假設為Rocky) ```bash hostnamectl set-hostname Rocky hostname Rocky ``` * 設定IP > [nmcli指令設定網卡](https://dywang.csie.cyut.edu.tw/dywang/rhel7/node22.html) > [nmcli指令說明書](https://networkmanager.dev/docs/api/latest/nmcli.html) > [Linux 使用 nmcli 指令新增刪除修改網卡 IP](https://ssorc.tw/8749/linux-use-nmcli-commandline-add-delete-ethernet-ip/) * 先確認網卡名稱:`ip link show` * 假設有兩張網卡,分別為`ens192`、`ens224` * 假設一張網卡`ens192`對外網(對外連網),一張網卡`ens224`對內網(用來接NFS Storage) * 設定外網(ens192),設定IP為`140.130.*.*`及預設閘道`140.130.*.254` ```bash! nmcli con add type ethernet ifname ens192 con-name ens192 ipv4.addresses 140.130.*.*/24 ipv4.gateway 140.130.*.254 ipv4.dns "140.130.1.20,140.130.1.2" ipv4.method manual ``` * 確認外網(ens192)設定 ```bash nmcli con show ens192 ``` * 設定內網(ens224),設定IP為`10.0.0.*`,這張網卡**僅用於內部連接 NFS**,因此不需要設定閘道,避免影響主要網卡的路由。 ```bash! nmcli con add type ethernet ifname ens224 con-name ens224 ipv4.addresses 10.0.0.*/24 ipv4.method manual ``` * 確認內網(ens224)設定 ```bash nmcli con show ens224 ``` * 設定路由確保外網優先 ```bash nmcli con modify ens192 ipv4.routes "0.0.0.0/0 140.130.*.*" nmcli con modify ens224 ipv4.routes "10.0.0.0/24 10.0.0.*" ``` * 重跑網路: `systemctl restart NetworkManager` * 確認網路狀態 ```bash ip a ip r ``` * 停用ipv6 ```bash sysctl net.ipv6.conf.all.disable_ipv6=1 sysctl net.ipv6.conf.default.disable_ipv6=1 ``` * 在家目錄新增 `.vimrc` ``` set nu set tabstop=4 ``` ## 套件更新/基本套件 * 更新現有套件到最新 ```bash yum upgrade --refresh ``` * 安裝及啟用第三方repo ```bash yum config-manager --set-enabled crb yum install https://rpms.remirepo.net/enterprise/remi-release-9.rpm yum config-manager --set-enabled remi ``` * 安裝wget ```bash yum install wget ``` * 如果在主機會使用到`nslookup`指令,就要安裝`bind-utils` ```bash yum install bind-utils ``` ## SSH設定/校時/防毒 * SSH服務設定調整 ```bash # TWGCB01-012-0044 # DEFAULT:預設全系統加密原則。允許使用 TLSv1.2與 1.3 協定,以及 IKEv2 與SSH2 協定,要求 RSA 密鑰與 Diffie-Hellman 金鑰至少為 2,048 位元 # FUTURE:採取保守之安全原則,可承受近期相關攻擊,不允許使用 SHA-1 演算法,要求 RSA 密鑰與Diffie-Hellman 金鑰至少為3,072 位元 # 查看原設定值為 DEFAULT cat /etc/crypto-policies/config # 執行下列指令改為 FUTURE update-crypto-policies --set FUTURE update-crypto-policies ``` - 記錄 sshagent 程序使用情形: `vim /etc/audit/rules.d/audit.rules` ``` ## TWGCB01-012-0163 -a always,exit -F path=/usr/bin/sshagent -F perm=x -F auid>=1000 -F auid!=4294967295 -k privilegedssh ``` - [Fail2ban](https://net.nthu.edu.tw/netsys/security:fail2ban) * [How To Protect SSH with Fail2Ban on Rocky Linux 9](https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-rocky-linux-9) * 校時設定 > 在 CentOS 8 預設已經沒有 ntpdate 來做系統校時,改用 chrony 來完成系統校時的工作。chrony 是一個 NTP Client/Server 並存的套件 。 * 將原來的chrony.conf設定檔備一份下來 ```bash cp /etc/chrony.conf /etc/chrony.conf_bak ``` * 修改 /etc/chrony.conf,只留下列資訊 (`vi /etc/chrony.conf`) ``` server 140.130.1.254 iburst ``` * 重起chronyd服務 ```bash systemctl restart chronyd ``` * 立即校時指令 ```bash chronyc -a makestep ``` * 查看詳細的校時資訊 ```bash chronyc tracking chronyc sources -v ``` * 安裝防毒軟體clamav > [參考文件](https://blog.maxkit.com.tw/2021/05/install-clamav-in-centos-7.html) * 安裝 ```bash # 安裝 yum install -y clamav clamd clamav-update sudo setsebool -P antivirus_can_scan_system on # 配置文件刪除 Example 字符串 sed -i -e "s/^Example/#Example/" /etc/clamd.d/scan.conf sed -i -e "s/^Example/#Example/" /etc/freshclam.conf ``` * 建立的log檔 ```bash mkdir -p /var/log/clamav chown -R clamupdate:clamupdate /var/log/clamav/ mkdir -p /var/log/clamd/ touch /var/log/clamd/clamd.scan chown -R clamscan:clamscan /var/log/clamd ``` * 更新配置文件 `/etc/freshclam.conf` ``` # 增加下面一條台灣的mirror site DatabaseMirror db.tw.clamav.net ``` * 調整配置設定 `/etc/clamd.d/scan.conf` ``` # 啟用紀錄 LogFile /var/log/clamd/clamd.scan # 啟用LocalSocket LocalSocket /var/run/clamd.scan/clamd.sock # 啟用記錄訊息時間 LogTime yes # 啟用ExtendedDetecionInfo ExtendedDetectionInfo yes # 啟用PidFile PidFile /var/run/clamd.scan/clamd.pid ``` * 更新病毒碼 ```bash # 更新病毒碼 freshclam # 查詢病毒碼版本 clamscan --version ``` * 啟用服務 ```bash systemctl start clamd@scan systemctl enable clamd@scan systemctl status clamd@scan ## on-access scanning systemctl start clamonacc systemctl enable clamonacc ``` * 設定自動更新病毒碼,建立一個批次檔 `/etc/cron.daily/freshclam.sh` (如下) 讓crontab跑 ```bash #!/bin/bash freshclam --quiet -l /var/log/clamav/freshclam.log ``` * 設定批次檔權限 ```bash chmod 755 /etc/cron.daily/freshclam.sh ``` * 手動掃描 ```bash # 掃檔案 clamscan filename # 掃目錄 clamscan -r directoryname ``` ## 安裝HTTP * 安裝 Apache ```bash yum install httpd httpd-tools mod_ssl -y httpd -v systemctl start httpd systemctl enable httpd ``` ![](https://hackmd.io/_uploads/Sy1qkV6oo.png) ## 安裝PHP * [PHP Release Cycle Update](https://php.watch/news/2024/09/php-release-cycle-updates) * 安裝 oracle instant client ![image](https://hackmd.io/_uploads/H1tUj_kyJe.png) > #9 – 11.2.0.3 or 11.2.0.4 only. For Oracle Autonomous Transaction Processing and Oracle Autonomous Data Warehouse, there is additional limitation and 11.2.0.4 is the minimum supported client version. > #12 – 12.1.0.2 only. For 11.2 interoperability, 11.2.0.4 is required. > Client-server version interoperability is detailed in [Doc ID 207303.1](https://support.oracle.com/epmos/faces/DocumentDisplay?id=207303.1). Oracle Call Interface 23 can connect to Oracle Database 19c or later, while Oracle Call Interface 19.3 can connect to Oracle Database 11.2 or later. Some tools may have other restrictions. > [PHP 8.2.26 起有安裝限制,必 >= 23.1](https://www.rpmfind.net/linux/RPM/remi/enterprise/8/x86_64/php82-php-oci8-8.2.26-1.el8.remi.x86_64.html) * 安裝指令 ```bash wget https://download.oracle.com/otn_software/linux/instantclient/2390000/oracle-instantclient-basic-23.9.0.25.07-1.el9.x86_64.rpm wget https://download.oracle.com/otn_software/linux/instantclient/2390000/oracle-instantclient-devel-23.9.0.25.07-1.el9.x86_64.rpm yum install oracle-instantclient-basic-23.9.0.25.07-1.el9.x86_64.rpm --nogpgcheck -y yum install oracle-instantclient-devel-23.9.0.25.07-1.el9.x86_64.rpm --nogpgcheck -y yum list installed | grep oracle ``` * 設定oracle環境參數 > vi /etc/profile.d/client.sh ```bash export PHP_DTRACE=yes export ORACLE_HOME=/usr/lib/oracle/23.9/client64 export PATH=$PATH:$ORACLE_HOME/bin export LD_LIBRARY_PATH=$ORACLE_HOME/lib export TNS_ADMIN=$ORACLE_HOME/network/admin ``` * 確認設定生效 ```bash > sh /etc/profile.d/client.sh > source /etc/profile.d/client.sh > echo $ORACLE_HOME ``` * 安裝PHP * 查看可以安裝的PHP版本 ```bash yum module list php ``` ![](https://hackmd.io/_uploads/r1rDuQToo.png) * 設定預設要安裝的PHP版本 ```bash yum module enable php:remi-8.3 -y ``` ![](https://hackmd.io/_uploads/HkVR97aoi.png) * 安裝指令 > php-zip在php7.4時被移到pecl裡,改安裝php-pecl-zip,是PhpSpreadsheet必要的延伸安裝 > php-oci8在php8.4時被移到pecl裡,改安裝php-pecl-oci8 > [PHP 8.4: OCI8 and PDO-OCI extensions from PHP Core to PECL](https://php.watch/versions/8.4/oci8-pdo_oci-unbundled) > 在 RHEL 7 或以前的版本, 預設會使用 mod_php 配合 Apache 執行, 從 RHEL 8 開始會預設使用 PHP-FPM 執行 PHP, 所以需要啟動 PHP-FPM > ```bash yum install php php-fpm # <= php8.3 yum install php-soap php-oci8 php-bcmath php-devel php-gd php-ldap php-mysqlnd yum install php-pecl-zip # >= php8.4 yum install php-soap php-bcmath php-devel php-gd php-ldap php-mysqlnd yum install php-pecl-zip php-pecl-oci8 systemctl start php-fpm systemctl enable php-fpm systemctl restart httpd ``` * 安裝composer套件管理指令工具 ```bash wget https://getcomposer.org/installer -O composer-installer.php php composer-installer.php --filename=composer --install-dir=/usr/local/bin composer --version ``` ![image](https://hackmd.io/_uploads/HyfQKdUgR.png) ## 安全性設定調整 > [SELinux 初探](https://linux.vbird.org/linux_server/rocky9/0140selinux.php) > [The Apache HTTP Server and SELinux](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/chap-managing_confined_services-the_apache_http_server) > [Sharing NFS and CIFS volumes](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-managing_confined_services-the_apache_http_server-configuration_examples#sect-Managing_Confined_Services-Configuration_examples-Sharing_NFS_and_CIFS_file_systems) > ![image](https://hackmd.io/_uploads/rJzxLuLmle.png) * 防火牆設定 ```bash # SELinux設定 setsebool -P httpd_can_network_connect on # 如果有掛載storage setsebool -P httpd_use_nfs on # 加上http和https開放設定 firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https # 重新載入 firewall-cmd --reload # 查看規則 firewall-cmd --list-all ``` * 遇到自定義上傳檔案的資料夾,要額外下指令設定 > [Configuring SELinux Policies for Apache Web Servers](https://www.serverlab.ca/tutorials/linux/web-servers-linux/configuring-selinux-policies-for-apache-web-servers/) ```bash chcon -R -t httpd_sys_rw_content_t <資料夾路徑> # Laravel專案內需要額外針對storage資料夾進行設定 cd <laravel_project_path> chcon -R -t httpd_sys_rw_content_t storage ``` * 在 `/var/www/html/` 內新增 `info.php`,驗證PHP安裝結果。 ![](https://hackmd.io/_uploads/BkdtTV6ss.png) * 驗證完後,記得把info.php刪掉。 * 設定調校 * 在 `/etc/php.ini` 做設定調整 ``` expose_php = Off error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE & ~E_WARNING date.timezone = Asia/Taipei session.cookie_httponly = 1 session.cookie_samesite = "Lax" # 下面這行原本有註解,要去註解啟用它 error_log = php_errors.log ``` * 在 `/etc/httpd/conf/httpd.conf`、`/etc/httpd/conf.d/vhost.conf` 等設定檔,做開放資料夾權限設定調整 ```conf Options -Indexes +FollowSymLinks ``` * 新增 `/etc/httpd/conf.d/security.conf` 檔案 ```conf # set up response header <IfModule mod_headers.c> # 隱藏 Apache、PHP 版本 Header unset Server RequestHeader unset Server Header always unset X-Powered-By Header unset X-Powered-By Header unset X-CF-Powered-By Header unset X-Mod-Pagespeed Header unset X-Pingback # 增加隱私權 # Referrer 代表的是你從 A 網站跳到 B 網站的時候,這個欄位會被記錄為 A # 簡單來說,他是記錄你上一個瀏覽的地方的東西 Header set Referrer-Policy: "no-referrer" # 防禦 Clickjacking 攻擊 # 防止釣魚網站透過iframe來嵌入自己的網站 # 政府組態 TWGCB-04-005-0036 Header always append X-Frame-Options SAMEORIGIN Header always append Frame-Options SAMEORIGIN # IE8+ and variants, XSS Protection Header always append X-XSS-Protection "1;mode=block" # Protection from drive-by dynamic/executable IE files # 避免瀏覽器誤判文件形態 # X-Content-Type-Options 是拿來防止 Content-Type 被竄改 # 比較要注意的是,這個屬性只會套用在 script style Header always append X-Content-Type-Options "nosniff" # cookie設定 Header always edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure;SameSite=Lax Header set Cache-Control "no-cache=\"Set-Cookie\"" # 隱藏Etag資訊 Header unset ETag FileETag None </IfModule> # Apache Range Exploit RequestHeader unset Range RequestHeader unset Request-Range # 隱藏Apache版本 # 政府組態 TWGCB-04-005-0048 ServerTokens Prod # 政府組態 TWGCB-04-005-0049 ServerSignature Off #關閉HTTP TRACE 避免Cross Site Scripting風險 # 政府組態 TWGCB-04-005-0030 TraceEnable Off ``` * httpd的設定調校後,可以執行 `apachectl configtest` 指令看看有沒有設定錯誤的地方。 * 相關設定完後,請執行 `systemctl restart httpd` 重跑服務。 * 部署 https * 確認環境 ![](https://hackmd.io/_uploads/HJC-bDuTo.png) * 利用 [SSL Configuration Generator](https://ssl-config.mozilla.org/) 產生 ssl.conf 設定內容 * [產生的設定內容](https://ssl-config.mozilla.org/#server=apache&version=2.4.57&config=intermediate&openssl=3.0.7&guideline=5.7) * 將產生的內容,經過整理貼到 `/etc/httpd/conf.d/ssl.conf` 去。 * 設定https後,重跑服務遇到 `SSLCertificateKeyFile: file '/etc/httpd/2022_SSL/xxx.cer' does not exist or is empty` 的解決方式 ([參照](https://serverfault.com/questions/416612/apache-sslcertificatekeyfile-file-does-not-exist-or-is-empty)): ```bash restorecon -Rv /etc/httpd/2022_SSL/ ``` * ==Laravel專案移機部署要特別留意 `.env` 檔中的 `APP_URL`==,如果 `.env` 檔跟 `httpd.conf` 設定檔兩邊的domain name沒有一致,容易發生404系列的錯誤。 * 修改 httpd 的設定,要重跑 httpd 服務 (`systemctl restart httpd`)。 * 修改 php.ini 的設定,則要重跑 php 服務 (`systemctl restart php-fpm`)。 * 其他紀錄 ```bash composer config -g -- secure-http false composer config -g -- disable-tls true ``` ## PHP升級方式 * 若是從PHP8.2(含)以下版本,升級至PHP8.3(含)以上者,先確認Oracle instant client是否有升級至23.1以上版本。 * 升級指令如下: ```bash dnf module reset php -y dnf module enable php:remi-8.3 -y yum update php -y systemctl restart php-fpm php -v ```