之前我的一個CentOS 7 Apache的站點被攻擊,導致流量過載損失了一筆錢,由於也是邊學習邊部署的,有不少安全隱患,爲了避免常見安全隱患再次發生,後來找出大概的原因後決定重新部署一個基於CentOS 8 Nginx的服務器。這也是充分利用Google和自己探索的一些從零部署的技巧和方法。
注意:請按照由上至下的順序操作,不保證每個人的Linux服務器都沒有差錯,如果保證服務器系統的純淨,大體上是沒有問題的,如果出現問題可以自己根據問題日誌谷歌一下尋找原因。我自己也是這麼一步一步過來的。我的其中一個網站購買的是 Vultr 的(以前也用過Bluehost、Linode公司的),用了很多年了,作爲國外服務器的品牌來說是很不錯的一個選擇。性價比不錯,對於非土豪的我來說是絕佳選擇。
購買完CentOS 8.0版本的服務器之後,就可以正式開始從零部署咯,因爲我的主系統是使用WordPress,因此我的配置也是需要支持PHP的,當然Node也是需要的(同理你可以配置支持其它後端語言),我把一些用到的配置和命令都整理成文章,也方便自己未來查閱鞏固。同時對於一個從來沒有部署過或者使用過其它配置的Linux服務器的你,相信也能夠提供不少幫助。目前自己的那個網站運營三個月以上暫沒有受到相同的攻擊和流量注入,對於一個新人來說我還是比較滿意的,不求人,靠自己穩定運營下去:)
服務器需要支持的基礎功能關係如下:
整體步驟分爲下面的八個:
(一)購買VPS,設置Server Hostname
(二)Point a Domain Name to a Server域名指向
(三)CentOS8系統-進程監控和bandwidth帶寬監控
(四)安裝解壓軟件
(五)CentOS 8.0 LEMP (with Nginx, MySQL , and PHP-FPM)安裝
(六)增加Nginx維護頁面,臨時維護使用
(七)完成 LEMP基礎配置後,升級性能和安全性,其它配置
(八)Node環境配置(請完成此文檔上面所有步驟後再繼續)
開始之前,我們先熟悉一些整個過程常用的一些命令:
#VI相關操作: #在用vi創建文件後,點擊 i 即可進入編輯文本模式的insert狀態,再點擊ESC即可退出編輯,然後輸入 :wq 即可保存文本並退出 #後面不要有空格,在「命令行模式(command mode)」下,按一下 : 冒號鍵進入「Last line mode」) #先按 / 鍵,再輸入您想尋找的字符,如果第一次找的關鍵字不是您想要的,可以一直按 n 會往後尋找到您要的關鍵字爲止。 #先按 ? 鍵,再輸入您想尋找的字符,如果第一次找的關鍵字不是您想要的,可以一直按 n 會往前尋找到您要的關鍵字爲止。 #查找後再 i 修改即可 #向下查找關鍵字,按 n 可繼續查找 vi /path/filename.ext #修改/新增文件 : w filename #輸入 「w filename」將文章以指定的文件名filename保存 : wq #輸入「wq」,存盤並退出vi : q! #輸入q!, 不存盤強制退出vi /word #這個是查找文件中“word”這個單詞,是從文件上面到下面查找 ?word #這個是查找文件中“word”這個單詞,是從文件下上面到面查找 dd #刪除遊標所在的一整行(非編輯模式) #退出當前正在執行的命令 ctrl z #(字母是L)查看某文件夾內文件或者文件夾的權限 ll /var/lib/nginx/ #(字母是L)查看當前目錄的文件夾和文件 ls -d * #根據文件名查找文件路徑 find / -xdev -name filename.suffix #查看某屬性 cat /etc/vsftpd/vsftpd.conf | grep write_enable #查看centOS版本 (目前版本:CentOS Linux release 7.1.1503 (Core) ) cat /etc/redhat-release #遠程連接終端 ssh [email protected] ssh -vv [email protected] (可查看連接日誌錯誤) 密碼:****** #如果無法登陸遠程終端,嘗試 ssh-keygen -R 12.34.56.789 #然後再登陸 #新建文件夾 mkdir /??? #文件夾改名 mv ??? ??? #列出目錄下所有文件 ls #查找安裝的程序的路徑(比如查看Node) which node #重裝系統登錄失敗要清楚公鑰使用命令: sudo rm /Users/mac/.ssh/known_hosts #或者 sudo rm ~/.ssh/known_hosts #若登陸成功後出現” warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory”,則添加一個文件即可: #如果訪問被拒絕,可能是IP原因,日本東京無法登陸,輕換VPN。 sudo vi /etc/environment #添加以下代碼: LANG=en_US.utf-8 LC_ALL=en_US.utf-8 #出現『Connection closed by 12.34.56.789』錯誤,嘗試修正權限錯誤: sudo chmod 700 /etc/ssh_host_dsa_key #查看網絡進程(比如httpd, mysqld, sshd等) netstat -plntu #查看所有端口的進程 ss -tpln #訪問URL獲取請求信息 curl -I https://yoursite.com #檢查httpd進程狀態 systemctl list-unit-files # 輸出激活的單元列表 systemctl list-units # 列出Nginx日誌文件 ls -laZ /var/log/nginx/ #打開錯誤或訪問日誌 cat /var/log/nginx/access.log cat /var/log/nginx/error.log #查看最新100條錯誤日誌 sudo tail -100 /var/log/nginx/error.log #錯誤日誌會佔用很多性能,要定期清理(配置 logrotate 來維護日誌文件。 #刪除日誌 find /var/log/nginx/error.log -type f -delete find /var/log/nginx/error.log-* -type f -delete #查看日誌及其大小 ls -la /var/log/nginx/ #下載解壓 wget https://wordpress.org/latest.tar.gz tar -xzvf latest.tar.gz #刪除文件 rm xxxxxx.zip #刪除文件夾和文件 (強制刪除) rm -rf xxxxx #改名 mv file1.txt file2.txt #查找5天內修改過的文件 find /usr/share/nginx/html/wordpress/ -type f -mtime -5 #5days #查找包含某字符串的文件 grep -r "jqueryeasyui" /usr/share/nginx/html/wordpress/ #將新解壓的位於/usr/share/nginx/html/wordpress/目錄中的wordpress 文件夾的文件移動 cp -r /usr/share/nginx/html/wordpress/wordpress/* /usr/share/nginx/html/wordpress/
熟悉一下此次從零開始部署服務器過程中我常用的這些命令,好了,接下去我們正式開始。
(一)購買VPS,設置Server Hostname
設置爲你的域名比如 yoursite.com
1、每次登錄到linux上,就會看到gaofeng@ubuntu:~$ 這樣的提示符,@後面的就是hostname
gaofeng@ubuntu:~$ hostname ubuntu
2、hostname有什麼用呢?
- 可以知道自己是不是登錄錯機器了。
- 在本機的/etc/hosts文件中添加經常訪問的機器的ip地址和主機名的映射關係,下次訪問時,可以ssh gaofeng@ubuntu來登錄,不用記住IP地址了(前提是人家的ip沒有變)。
(二)Point a Domain Name to a Server域名指向
1、域名註冊商綁定IP,並設置DNS指向到VPS註冊商,
比如
點擊自助解析DNS(這裏我修改爲Vultr 的DNS信息)
2.註冊商配置NDS
(三)CentOS8系統-進程監控和bandwidth帶寬監控
添加 EPEL 存儲庫
sudo yum install epel-release
安裝進程監控軟件
sudo yum install htop
運行
htop
安裝帶寬監控軟件iftop
iftop 是一個簡單、易用、實時的類似 top 的基於命令行的網絡帶寬監控工具,用於快速瞭解界面上的網絡活動。 它平均每 2、10 和 40 秒顯示一次網絡使用帶寬更新。
sudo yum install iftop -y
運行 interface top 命令以查看終端上的網絡帶寬活動。
iftop
運行後如圖:
(四)安裝解壓軟件
Tar 不再默認安裝在 RHEL 8 / CentOS 8 上,需要安裝
yum install -y tar
P7Zip用於zip文件包的解壓
dnf install p7zip p7zip-plugins
解壓命令如:
tar -zxvf /path/***.tar.gz 7za x /path/***.zip
備份整站壓縮命令如:
cd /usr/share/nginx/html/wordpress/ 7za a /usr/share/nginx/html/wordpress/xxx.7z /usr/share/nginx/html/wordpress rm -rf /usr/share/nginx/html/wordpress/xxx.7z #下載後刪除
(五)CentOS 8.0 LEMP (with Nginx, MySQL , and PHP-FPM)安裝
注意:請嚴格按1~11的步驟進行
1.安裝Nginx
2.安裝MariaDB
3.安裝PHP7.4
4.配置PHP到Nginx服務器
5.新建WordPress數據庫需要的表,測試是否能連接
6.安裝WordPress
7.Nginx 基礎配置和基本安全配置
8. WordPress命令配置(不通過網址進入UI界面,參考)
9. 安裝SFTP
10.配置HTTPS
11.修改Nginx配置,將http跳轉到https
12.Nginx配置https支持PHP和常用功能,重裝配置WordPress
我們先查看一下CentOS版本
cat /etc/os-release
1.安裝Nginx
當前版本:1.14.1
yum install nginx -y
運行:
systemctl start nginx
開機時啓動
systemctl enable nginx
狀態查看
systemctl status nginx
查看版本(目前使用1.14.1)
nginx -v
RHEL 8 / CentOS 8 默認沒有配置 firewalld 來服務 Web 流量,運行以下命令
允許 HTTP 和 https 的 Web 服務器流量的命令,具有永久規則,這些規則將在一段時間後持續存在
重啓。
firewall-cmd --permanent --zone=public --add-service=http firewall-cmd --permanent --zone=public --add-service=https
重新加載防火牆守護程序以進行更改
firewall-cmd --reload
重啓
systemctl restart nginx
運行綁定好的域名,可以看到:
2.安裝MariaDB
使用 dnf 安裝 MariaDB 包
sudo dnf install mariadb-server
啓動
sudo systemctl start mariadb
檢查狀態
sudo systemctl status mariadb
設置開機啓動
sudo systemctl enable mariadb
保護 MariaDB 服務器,MariaDB 包含一個安全腳本,用於更改一些不太安全的默認選項,例如遠程 root 登錄和示例用戶。 使用此命令運行安全腳本:
sudo mysql_secure_installation
鍵入 Y 然後按 ENTER 輸入 root 數據庫用戶的密碼,然後按照提示操作。更新密碼後,我們將通過按 y 然後按 ENTER 接受所有安全建議。 這將刪除匿名用戶,禁止遠程 root 登錄,刪除測試數據庫,並重新加載權限表。現在我們已經保護了安裝,我們將通過連接到數據庫來驗證它是否正常工作。
根據提示設置密碼。
測試登錄
mysqladmin -u root -p version
重啓MariaDB
systemctl restart mariadb.service
3.安裝PHP7.4
Nginx本身不能處理PHP,它只是個web服務器,當接收到請求後,如果是php請求,則發給php解釋器處理,並把結果返回給客戶端。nginx一般是把請求發fastcgi管理進程處理,fascgi管理進程選擇cgi子進程處理結果並返回被Nginx。
PHP-FPM是一個PHP FastCGI進程管理器,此版本安裝默認就附帶。
使用dnf安裝
dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
要確認 EPEL 存儲庫是否存在,請運行以下 rpm 命令
rpm -qa | grep epel
接下來,運行以下命令以添加 Remi 存儲庫
dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
再次,要驗證 Remi 存儲庫是否存在,請運行該命令
rpm -qa | grep remi
成功添加 EPEL 和 Remi 存儲庫後,執行以下命令以獲取可用 PHP 模塊流的列表
dnf module list php
從上面的輸出來看,remi-7.4 是合適版本的PHP 流,因此我們將啓用模塊流,如下所示
dnf module enable php:remi-7.4
啓用 PHP remi-7.4 模塊後,您可以使用以下命令繼續安裝 PHP。 這還將安裝許多其他軟件包,例如 Apache 和 Nginx 模塊
dnf install php php-cli php-common
檢查版本(目前安裝7.4.26)
php -v
安裝完核心模塊後,繼續安裝缺失的模塊(特別是mysqli數據庫模塊),解決WordPress無法運行的問題,數據庫無法鏈接的問題
yum install -y php-mysqlnd php-gd
安裝服務和模塊後,啓動 PHP-FPM
systemctl start php-fpm
配置開機啓動
systemctl enable php-fpm
檢查狀態
systemctl status php-fpm
默認的 PHP-FPM 配置文件設置爲以 apache 用戶身份運行,找到並更改以下內容
條目如下所示(將apache改成nginx):
先備份一個原配置:
cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.bak
修改配置:
vi /etc/php-fpm.d/www.conf
配置如下:
user = nginx group = nginx listen.owner = nginx listen.group = nginx
重新加載 PHP-FPM 以進行更改
systemctl restart nginx php-fpm
4.配置PHP到Nginx服務器
首先,使用cat命令找出PHP-FPM FastCGI服務器配置的位置
cat /etc/nginx/conf.d/php-fpm.conf
確保 Unix 套接字已啓動並正在運行,運行:
ls -l /run/php-fpm/www.sock
我的 CentOS 8 和 Nginx 的 php-fpm 配置,運行命令行獲取到代碼
cat /etc/nginx/default.d/php.conf
代碼如下:
# pass the PHP scripts to FastCGI server # # See conf.d/php-fpm.conf for socket configuration # index index.php index.html index.htm; location ~ \.php$ { try_files $uri =404; fastcgi_intercept_errors on; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass php-fpm; }
再次運行 systemctl 命令:
sudo systemctl restart nginx.service
新建測試文件:
sudo vi /usr/share/nginx/html/hello.php
內容如下
<?php phpinfo(); ?>
運行網址,我們可以看到瀏覽器如下界面:
注意看數據庫連接的模塊:
php -m
5.新建WordPress數據庫需要的表,測試是否能連接
進入 MySQL 腳本(shell,注意要寫分號),輸入剛纔創建的密碼
mysql -u root -p
具體的命令如下(注意把名稱和密碼換成你自己的):
數據庫名:wpdbname 用戶名: membername 密碼:password!!here 創建數據庫wpdbname CREATE DATABASE wpdbname; 查看數據庫列表 SHOW DATABASES; 查看版本狀態 STATUS; 針對MySQL 5.7 or MySQL 8的命令,mysql_native_password是插件名,不要去修改它 #目前使用此命令 CREATE USER 'membername'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password!!here'; 針對MySQL 5.1, MySQL 5.5, MySQL 5.6的命令(參考): CREATE USER 'membername'@'localhost' IDENTIFIED BY 'password!!here'; 授予此用戶 membername 訪問您的 wpdbname 數據庫的權限 #目前使用此命令 GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON wpdbname.* TO 'membername'@'localhost'; 或者 GRANT ALL ON wpdbname.* TO membername@localhost; (可選)授予此用戶 membername FILE 全局權限:(如果啓用,由於 LOAD DATA INFILE 功能,報告將被更快地存檔) GRANT FILE ON *.* TO 'membername'@'localhost'; 繼續刷新權限 FLUSH PRIVILEGES; 退出mysql命令 QUIT;
重啓mysql
sudo systemctl restart mysqld
測試數據庫連接:
vi /usr/share/nginx/html/data.php
代碼爲(使用mysqli鏈接):
<?php // echo "Welcome to Connecting of DB Tutorial!"; // echo " "; // 1. PDO - Php Data Objects // 2. MySQLi extension // Set Connection Variable $server = "localhost"; $username = "membername"; $password = "password!!here"; $database = "dbname"; // Create A Connection $con = mysqli_connect($server, $username, $password, $database); // Check For Connection if(!$con){ die ("Connection Terminated! by Die() function". mysqLi_connect_error()); } else { echo "Connection Succefully Happened! "; }
代碼爲(使用PDO模塊鏈接數據庫):
<?php $servername = "localhost"; $username = "membername"; $password = "password!!here"; $database = "dbname"; try { $conn = new PDO("mysql:host=$servername;dbname=$database", $username, $password); // set the PDO error mode to exception $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); echo "Connected successfully"; } catch(PDOException $e) { echo "Connection failed: " . $e->getMessage(); }
測試成功以後刪除它
rm -rf /usr/share/nginx/html/data.php
備份SQL,輸入root密碼
mysqldump -u root -p mydatabasename > /usr/share/nginx/html/wordpress/data-dump-2022-XXX.sql
6.安裝WordPress
注意:5.8以上版本推薦PHP7.4
如果已經存在/usr/share/nginx/html/wordpress/文件夾,要安裝根目錄的WordPress cd /usr/share/nginx/html/wordpress 下載並解壓: wget https://wordpress.org/wordpress-5.8.2.tar.gz 解壓: tar -zxvf wordpress-5.8.2.tar.gz 刪除文件(刪除文件夾是rm -rf xxx) rm -rf wordpress-5.8.2.tar.gz 將/usr/share/nginx/html/wordpress/wordpress/裏的所有文件和文件夾 複製到/usr/share/nginx/html/wordpress/裏 cp -r /usr/share/nginx/html/wordpress/wordpress/* /usr/share/nginx/html/wordpress/ 刪除原文件夾 rm -rf /usr/share/nginx/html/wordpress/wordpress/
切換到 Nginx 根目錄
cd /usr/share/nginx/html
下載並解壓:
wget https://wordpress.org/wordpress-5.8.2.tar.gz
解壓:
tar -zxvf wordpress-5.8.2.tar.gz
刪除文件(刪除文件夾是rm -rf xxx)
rm -rf wordpress-5.8.2.tar.gz
解壓後設置權限(每次安裝新的WordPress或者上傳新的文件夾時都要執行)
find /usr/share/nginx/html/wordpress -type d -exec chmod 755 {} \; #所有【目錄】更新八進制權限 find /usr/share/nginx/html/wordpress -type f -exec chmod 644 {} \; #所有【文件】更新八進制權限
確保您的文檔根目錄和所有內容都歸myftp1和 www-data 所有
①支持FTP上傳文件
②wordpress能選擇語言/寫入文件/創建config.php/在線刪除、安裝主題插件
sudo chown -R myftp1:www-data /usr/share/nginx/html/wordpress
設置完權限後FTP工具顯示如:
打開臨時安全通道,可以讓其寫入,否則就算設置了寫入權限和分組也無法執行
sudo setenforce 0
然後就可以看到選擇語言界面
【注意:必須是選擇語言的界面,纔算成功】
安裝主題,插件,緩存插件配置後再運行:
關閉臨時安全通道,無法在線安裝主題插件,無法寫入
sudo setenforce 1
7.Nginx 基礎配置和基本安全配置
接下來對於我們的 WordPress LEMP CentOS 8 安裝,我們將繼續進行 Nginx 和 wpconfig.php 設置,包括一些安全檢查。 此配置不適用於 SSL,文檔後面會講述配置SSL。如果您發現自己面臨各種與 SSL 相關的錯誤,Really Simple SSL 插件可能是一個非常有用的工具。
從您的主 nginx.conf 中排除 XML-RPC 支持,因爲它是常見的 DOS 攻擊位置。
先備份一個原配置:
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
先添加一個錯誤日誌到核心配置中
vi /etc/nginx/nginx.conf
默認配置的代碼(增加了一行錯誤日誌配置,註釋了server{}默認配置,其它未改動,做初始參考):
# For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ # user nginx; user myftp1; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error.log warn; #這是增加的代碼 sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; # 這裏是註釋掉的 server {...} 部分的代碼 # server { # listen 80 default_server; # listen [::]:80 default_server; # server_name _; # root /usr/share/nginx/html; # # Load configuration files for the default server block. # include /etc/nginx/default.d/*.conf; # location / { # } # error_page 404 /404.html; # location = /40x.html { # } # error_page 500 502 503 504 /50x.html; # location = /50x.html { # } # } # Settings for a TLS enabled server. # # server { # listen 443 ssl http2 default_server; # listen [::]:443 ssl http2 default_server; # server_name _; # root /usr/share/nginx/html; # # ssl_certificate "/etc/pki/nginx/server.crt"; # ssl_certificate_key "/etc/pki/nginx/private/server.key"; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 10m; # ssl_ciphers PROFILE=SYSTEM; # ssl_prefer_server_ciphers on; # # # Load configuration files for the default server block. # include /etc/nginx/default.d/*.conf; # # location / { # } # # error_page 404 /404.html; # location = /40x.html { # } # # error_page 500 502 503 504 /50x.html; # location = /50x.html { # } # } }
重要提示:請註釋掉 /etc/nginx/nginx.conf 文件中的server{}80端口部分代碼,使用獨立的配置文件去管理,避免混淆。
新建文件/etc/nginx/conf.d/default.conf(它將默認替代原配置文件-如果存在, 核心服務配置文件/etc/nginx/nginx.conf內的server {...}內容就無效化,包括原來默認存在的80端口代碼)
server_name( 請不要寫多個) 進行調整,這樣就可以把wordpress目錄鏡像到根目錄
vi /etc/nginx/conf.d/default.conf代碼如下:
server { listen 80; server_name "~^www\.(.*)$" ; return 301 $scheme://$1$request_uri ; } server { listen 80; server_name yoursite.com; # note that these lines are originally from the "location /" block root /usr/share/nginx/html/wordpress; index index.php index.html index.htm; # MIME sniffing prevention add_header X-Content-Type-Options "nosniff"; # Enable cross-site scripting filter in supported browsers. add_header X-Xss-Protection "1; mode=block"; # Fix WordPress upload error client_max_body_size 100M; # robots support location = /robots.txt { allow all; log_not_found off; access_log off; } # Github source location ~* \/poemkit($|/$) { return 301 https://yoursite.com:3000/index; } # PHP support location ~ \.php$ { try_files $uri =404; fastcgi_intercept_errors on; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass php-fpm; } # -------------------------------------- location / { try_files $uri $uri/ =404; #503 if (-f /usr/share/nginx/html/maintenance.html) { return 503; } } #debug status # location / { # try_files $uri $uri/ /maintenance.html; # } #502 error_page 502 =503 /50x.html; #other page status(Original configuration modification) error_page 404 /404.html; error_page 500 502 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } error_page 503 /maintenance.html; location = /maintenance.html { root /usr/share/nginx/html/wordpress; } # -------------------------------------- }
location ~ \.php$ { ... } 是上面通過 cat /etc/nginx/default.d/php.conf 命令獲取的代碼
如果/usr/share/nginx/html/wordpress目錄中存在404.html頁面,網站會渲染自定義404
下面的代碼都是可選的,根據情況添加(目前都未添加)
圖片防盜鏈:
#Prevent image hotlinking / stealing from your site with nginx location ~* \.(gif|png|jpe?g)$ { valid_referers none blocked yoursite.com *.yoursite.com; if ($invalid_referer) { rewrite (.*) /path/to/image/hotlinking-denied.jpg redirect; } }測試防盜鏈的重寫效果,修改valid_referers屬性,然後直接使用瀏覽器輸出圖片地址,即可被重寫跳轉。
#Prevent image hotlinking / stealing from your site with nginx location ~* \.(gif|png|jpe?g)$ { valid_referers yoursite.com *.yoursite.com; if ($invalid_referer) { rewrite (.*) /path/to/image/hotlinking-denied.jpg redirect; } }禁止訪問某些文件:
# Prevent access to hidden files location ~* /\.(?!well-known\/) { deny all; } # Prevent access to certain file extensions location ~\.(ini|log|conf)$ { deny all; }緩存靜態文件【注意:此緩存是儲存在客戶端(瀏覽器)上的配置,不是直接從服務端讀取】
#all content in static and media folders will be cached by browsers during 30 days location ~* \.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|otf|ogg|ogm|opus|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip|glb|obj|usdz|gltf)$ { expires 30d; add_header Pragma public; add_header Cache-Control "public"; }靜態文件的重寫,rewrite寫在 location XXX{} 外面也會生效。當我訪問https://xxxxx/abc/navs的時候,實際訪問的是 https:/xxxxx/abc/navs.html
# For HTML Files location /abc { rewrite ^/abc/(.*)$ /abc/$1.html break; }某些網址的指定跳轉,比如 /abc 跳轉到/abc/index
# Github source location ~* \/abc$ { return 301 /abc/index; }
測試配置文件是否正常
nginx -t
確保 Nginx 和 PHP-FPM 接受更改
systemctl restart nginx php-fpm
檢測www是否直接301跳轉到沒有non-www的域名
curl -I http://www.xxxxxx.com
正確運行WordPress!!
由於SELinux模式保留權限問題,WordPress不能訪問遠程的api,需要設置防火牆,才能允許遠程安裝插件和主題
【強烈建議不要禁用 SELinux,而是將模式更改爲 permissive。 僅在應用程序正常運行需要時禁用 SELinux】
查看錯誤日誌
sudo cat /var/log/audit/audit.log | grep nginx | grep denied下面的代碼測試是否可以遠程連接:
curl http://api.wordpress.org -I
查看SELinux Mode狀態
sestatus
將 SELinux 模式更改爲Permissive啓用後,SELinux 可以處於強制或許可模式。 您可以使用以下命令暫時將模式從有針對性更改爲寬鬆模式:
下面的代碼是臨時關閉SELinux安全策略【建議使用,不要永久改變,它可能保護流量的非法攻擊,也可以保護網站被黑的風險】
sudo setenforce 0使用後重新開啓
sudo setenforce 0注意:下面的代碼開啓後也會運行遠程連接(但它不會控制文件讀寫)。在布爾值關閉的情況下,PHP 代碼無法與遠程網站通信(就像 curl_ 函數被禁用一樣)。
sudo setsebool -P httpd_can_network_connect 1
永久更改:
但是,此更改僅對當前運行時會話有效,並且不會在重新啓動之間持續存在。要將 SELinux 模式永久設置爲 permissive,請按照以下步驟操作:
打開 /etc/selinux/config 文件並將 SELINUX mod 設置爲 permissive:
vi /etc/selinux/config把 SELINUX=enforcing 改爲 SELINUX=permissive
保存文件並運行 setenforce 0 命令來更改當前會話的 SELinux 模式,關機重啓:
sudo shutdown -r now
8. WordPress命令配置(參考,不使用)
進入wordpress目錄
cd /usr/share/nginx/html/wordpress
將 wp-config-sample.php 文件複製到 wp-config.php。
sudo cp wp-config-sample.php wp-config.php
將 wp-config.php 的所有權更改爲 Nginx
chown nginx.nginx wp-config.php
生成安全密鑰
curl -s https://api.wordpress.org/secret-key/1.1/salt/
如下獲取匹配的輸出並替換您的 wp-config.php 中的相應行文件,打開您的 wp-config.php 並修改以匹配我們配置時使用的憑據MariaDB 服務。
vi wp-config.php
將wp-config.php的內容替換爲下面的部分:
define('DB_NAME', 'dbname'); define('DB_USER', 'membername'); define('DB_PASSWORD', 'password!!here');
重新啓動 PHP-FPM 和 Nginx 服務以獲取最近的更改
systemctl restart php-fpm nginx
9. 安裝SFTP
運行yum命令安裝
yum install -y vsftpd systemctl enable vsftpd systemctl start vsftpd
狀態檢查
systemctl status vsftpd
生成用於加密連接的 SSL 證書,輸入一個CN即可,其它留空生成
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/vsftpd/vsftpd.pem -out /etc/vsftpd/vsftpd.pem
修改配置文件:
vi /etc/vsftpd/vsftpd.conf
確保以下設置,它們應該是默認值
anonymous_enable=NO local_enable=YES write_enable=YES
以下條目將需要手動添加
rsa_cert_file=/etc/vsftpd/vsftpd.pem rsa_private_key_file=/etc/vsftpd/vsftpd.pem ssl_enable=YES
重啓sftp
systemctl restart vsftpd
防火牆需要打開端口
firewall-cmd --permanent –add-port=20-21/tcp firewall-cmd –reload
設置 SFTP 用戶和權限
創建新的 FTP 用戶,其中 /usr/share/nginx/ 是用戶的主文件夾 useradd -d /usr/share/nginx/ myftp1 設置密碼 passwd myftp1 創建 www-data 組 groupadd www-data 將 myftp1 用戶添加到 www-data 組 usermod -aG www-data myftp1
打開 核心nginx.conf 並更新 Nginx 用戶
vi /etc/nginx/nginx.conf
user myftp1;
測試 Nginx 配置,您可以在設置權限之前避免重新加載
nginx -t
打開 www.conf 並更新 PHP-FPM 用戶
vi /etc/php-fpm.d/www.conf
代碼如下(注意最後一行):
user = myftp1 group = www-data listen.owner = myftp1 listen.group = www-data listen.acl_users = apache,nginx,myftp1
測試文件
php-fpm -t
使用新用戶和組設置所有權
chown -R myftp1:www-data /usr/share/nginx/html
更新 /var/lib/nginx 的所有權
chown -R myftp1:www-data /var/lib/nginx
確保日誌權限到位
chown -R myftp1:www-data /var/log/nginx
確認權限和配置通過測試後,繼續重啓 Nginx 和 PHP-FPM
systemctl restart nginx systemctl restart php-fpm
注意;連接的時候端口使用22,默認遠程路徑是/html
10. 配置HTTPS
Step 1:使用 dnf 命令安裝 mod_ssl 模塊:
dnf install mod_ssl
Step 2:首先在服務器上生成一個csr文件
如果您選擇使用商業上受信任的證書,則可以通過運行以下命令來生成 CSR。 相應地替換密鑰和 CSR 的名稱。
這裏命名爲:ca.key
openssl req -new -newkey rsa:4096 -nodes -keyout ca.key -out ca.csr
一次輸入自己的證書信息,如下:
生成後,將 CSR 內容提交給簽名證書頒發機構。上面的命令會生成私鑰和 CSR。 確保私鑰安全,因爲稍後安裝證書時需要。接下去我們查看內容
Step 3:查看csr文件的內容(此內容也用於網站申請發放證書和簽名,驗證等)
cat ca.csr內容如下:
-----BEGIN CERTIFICATE REQUEST----- ….... -----END CERTIFICATE REQUEST-----
將ca.csr的內容填入到證書商家的表單生成:
Step 4:FTP上傳頒發的3個證書文件到根目錄
上傳到nginx目錄/usr/share/nginx/html/中【如果更新證書,必須修改原來的3個證書文件】
新建一個證書目錄(因爲權限問題,FTP無法直接上傳到此):
mkdir /usr/share/nginx/ssl
FTP上傳後拷貝3個證書文件到所需要的目錄
sudo cp /usr/share/nginx/html/yoursite.com.crt /usr/share/nginx/ssl/ sudo cp /usr/share/nginx/html/yoursite.com.ca-bundle /usr/share/nginx/ssl/ sudo cp /usr/share/nginx/html/yoursite.com.p7b /usr/share/nginx/ssl/
拷貝後刪除:
rm -rf /usr/share/nginx/html/yoursite.com.crt rm -rf /usr/share/nginx/html/yoursite.com.ca-bundle rm -rf /usr/share/nginx/html/yoursite.com.p7b
查看私鑰ca.key的內容
cat ca.key
內容如下:
-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----
將ca.key的內容,重新創建成一個文件,供nginx配置文件使用
vi /usr/share/nginx/ssl/ca.key
Step 5:創建bundle.crt最終證書文件
nginx中沒有證書鏈的選項,只需連接域的證書文件和 CA 的鏈文件,用編輯吧yoursite.com.crt和yoursite.com.ca-bundle文件的內容拼接在一起即可,注意順序要正確。
vi /usr/share/nginx/ssl/bundle.crt
內容爲拼接後的內容
Step 6:修改nginx配置文件,新增443端口的代碼(將www跳轉到non-www):
vi /etc/nginx/conf.d/default.conf
內容如下:
server { listen 443 ssl http2; server_name "~^www\.(.*)$" ; return 301 $scheme://$1$request_uri; ssl on; ssl_certificate /usr/share/nginx/ssl/bundle.crt; ssl_certificate_key /usr/share/nginx/ssl/ca.key; ssl_session_cache shared:SSL:20m; ssl_session_timeout 60m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256; ssl_buffer_size 8k; ssl_session_tickets off; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 10s; } server { listen 443 ssl http2; server_name yoursite.com; ssl on; ssl_certificate /usr/share/nginx/ssl/bundle.crt; ssl_certificate_key /usr/share/nginx/ssl/ca.key; ssl_session_cache shared:SSL:20m; ssl_session_timeout 60m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256; ssl_buffer_size 8k; ssl_session_tickets off; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 10s; }
檢查
nginx -t
重啓
systemctl restart nginx
最後測試一下證書的級別
http://stool.chinaz.com/https?url=yoursite.com
11. 修改Nginx配置,將http跳轉到https
修改配置文件
vi /etc/nginx/conf.d/default.conf
在偵聽80端口(非www跳轉)的地方增加一行即可:
return 301 https://$host$request_uri;
重啓
systemctl restart nginx
12.Nginx配置https支持PHP和常用功能,重裝配置WordPress
修改Nginx配置,讓https支持php等常用配置,代碼如下,修改443端口(非www部分)
vi /etc/nginx/conf.d/default.conf
代碼如下:
server { listen 443 ssl http2; server_name yoursite.com; ssl on; ssl_certificate /usr/share/nginx/ssl/bundle.crt; ssl_certificate_key /usr/share/nginx/ssl/ca.key; ssl_session_cache shared:SSL:20m; ssl_session_timeout 60m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256; ssl_buffer_size 8k; ssl_session_tickets off; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 10s; # note that these lines are originally from the "location /" block root /usr/share/nginx/html/wordpress; index index.php index.html index.htm; # MIME sniffing prevention add_header X-Content-Type-Options "nosniff"; # Enable cross-site scripting filter in supported browsers. add_header X-Xss-Protection "1; mode=block"; # Fix WordPress upload error client_max_body_size 100M; # robots support location = /robots.txt { allow all; log_not_found off; access_log off; } # Github source location ~* \/poemkit($|/$) { return 301 https://yoursite.com:3000/index; } # PHP support location ~ \.php$ { try_files $uri =404; fastcgi_intercept_errors on; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass php-fpm; } # -------------------------------------- location / { try_files $uri $uri/ =404; #503 if (-f /usr/share/nginx/html/maintenance.html) { return 503; } } #debug status # location / { # try_files $uri $uri/ /maintenance.html; # } #502 error_page 502 =503 /50x.html; #other page status(Original configuration modification) error_page 404 /404.html; error_page 500 502 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } error_page 503 /maintenance.html; location = /maintenance.html { root /usr/share/nginx/html/wordpress; } # -------------------------------------- }
重啓
systemctl restart nginx
刪除WordPress舊的文件夾(看接下去的步驟增加一個維護頁面臨時使用)
rm -rf /usr/share/nginx/html/wordpress
重新安裝和配置WordPress(參看安裝步驟),根據需要修改名稱
(如果上傳到根目錄則不需要改名,因設置了 Nginx的root目錄/usr/share/nginx/html/wordpress/)
cd /usr/share/nginx/html/wordpress/{NEW_FOLDER_NAME}這時候安裝後需要改名
mv /usr/share/nginx/html/wordpress /usr/share/nginx/html/wordpress/{NEW_FOLDER_NAME}
修改Nginx配置443端口(非www部分)
vi /etc/nginx/conf.d/default.conf
WP 配置(1)
由於nginx不支持.htaccess文件重寫,當使用了Permalink功能重寫網址的功能後,需要配置nginx來適配你的重寫功能。如果您在 /blog 等子目錄(即/usr/share/nginx/html/wordpress/blog) URL 下運行您的博客,如:
# -------------------------------------- For WordPress Settings begin # WordPress Permalink location /blog { index index.php index.html index.htm; try_files $uri $uri/ /blog/index.php?$args; #503 if (-f /usr/share/nginx/html/maintenance.html) { return 503; } } # -------------------------------------- For WordPress Settings end如果是默認的網站根目錄,就寫成注意:如果有重複的location / { ... }代碼段,請刪除它
# -------------------------------------- For WordPress Settings begin # WordPress Permalink location / { index index.php index.html index.htm; try_files $uri $uri/ /index.php?$args; #503 if (-f /usr/share/nginx/html/maintenance.html) { return 503; } } # -------------------------------------- For WordPress Settings endWP 配置(2)
WordPress EDD插件需要的配置保護:
# -------------------------------------- For WordPress Plugin-EDD Settings begin # To protect your EDD files while using EDD location ~* \/wp-content\/uploads\/edd\/(.*?)\.(gz|zip|tar|rar)$ { rewrite (.*) / permanent; } # -------------------------------------- For WordPress Plugin-EDD Settings endWP 配置(3)
WordPress安全保護:
# -------------------------------------- For WordPress Security begin # DDos prevent location = /xmlrpc.php { deny all; access_log off; log_not_found off; return 444; } location = /blog/xmlrpc.php { deny all; access_log off; log_not_found off; return 444; } # -------------------------------------- For WordPress Security endWP 配置(4)(可選 ,不需要使用)
WordPress網站地圖重寫(如果已經增加了WordPress Permalink配置,就不用增加):last標記告訴 NGINX 跳過當前服務器或位置塊中的任何後續 Rewrite-module 指令,並開始搜索與重寫的 URL 匹配的新位置。
# -------------------------------------- For WordPress Sitemap begin rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.xml$ "/index.php?xml_sitemap=params=$2" last; rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.xml\.gz$ "/index.php?xml_sitemap=params=$2;zip=true" last; rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.html$ "/index.php?xml_sitemap=params=$2;html=true" last; rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.html.gz$ "/index.php?xml_sitemap=params=$2;html=true;zip=true" last; # -------------------------------------- For WordPress Sitemap begin
重啓
systemctl restart nginx
即可看到目錄/usr/share/nginx/html/wordpress/blog 內的wordpress系統的效果:
(六)增加Nginx維護頁面,臨時維護使用
新建一個目錄
mkdir /usr/share/nginx/html/wordpress
在Nginx根目錄上傳一個文文件用來識別維護狀態(作爲保留備用)
vi /usr/share/nginx/html/maintenance.html
不需要維護模式時記得改名:
mv /usr/share/nginx/html/maintenance.html /usr/share/nginx/html/maintenance-no.html
maintenance.html 和 404.html 的HTML代碼請自己搞定)
在/usr/share/nginx/html/wordpress/目錄新建2個文件:maintenance.html和404.html
vi /usr/share/nginx/html/wordpress/maintenance.html vi /usr/share/nginx/html/wordpress/404.html
設置權限(每次安裝新的WordPress或者上傳新的文件夾時都要執行)
find /usr/share/nginx/html/wordpress -type d -exec chmod 755 {} \; #所有【目錄】更新八進制權限 find /usr/share/nginx/html/wordpress -type f -exec chmod 644 {} \; #所有【文件】更新八進制權限
確保您的文檔根目錄和所有內容都歸myftp1和 www-data 所有,
①支持FTP上傳文件
②wordpress能選擇語言/寫入文件/創建config.php/在線刪除、安裝主題插件
sudo chown -R myftp1:www-data /usr/share/nginx/html/wordpress
如果只是調試狀態【當網站有正式內容時才使用】,並不是真正的全站維護返回503,按下面的步驟進行:
(1)先改名
mv /usr/share/nginx/html/maintenance.html /usr/share/nginx/html/maintenance-no.html(2)再在Nginx配置中增加維護頁面判斷代碼(在443端口非www的部分):
vi /etc/nginx/conf.d/default.conf修改方法:註釋代碼: location / { try_files $uri $uri/ =404; #503 if (-f /usr/share/nginx/html/maintenance.html) { return 503; } } 執行代碼(只強制跳轉根目錄的,子目錄不會強制跳轉): #debug status location / { try_files $uri $uri/ /maintenance.html; }
檢查
nginx -t
重啓
systemctl restart nginx
(七)完成 LEMP基礎配置後,升級性能和安全性,其它配置
下面這些配置是保證WordPress能夠更好的運行
1. Mariadb和Nginx服務斷開後自動重啓
2. PHP配置修改
3. 啓用GZIP壓縮
4. 創建交換空間swap space
5. 進一步優化Mariadb
6. 靜態文件緩存和PHP緩存
7. 配置Redis緩存mysql數據
8. 學會檢查內存佔用的程序
這一部分篇幅有有點分量,當您完成第(一)到(六)步驟後,服務器就可以使用了,此部分性能和安全提升的內容,我會在下一篇相關文章中進行歸納整理。
(八)Node環境配置(請完成此文檔上面所有步驟後再繼續)
Step1: Node環境
安裝Node16+ (目前安裝後版本爲 16.13.1)
curl -fsSL https://rpm.nodesource.com/setup_16.x | sudo bash - sudo yum install -y nodejs node -v
全局安裝pm2
sudo npm install pm2@latest -g
全局安裝babel
sudo npm install -g babel-cli
全局安裝最新babel
sudo npm install -g @babel/core @babel/cli @babel/preset-env
全局安裝ts-node
sudo npm install -g ts-node
Step2: 防火牆設置
設置Node應用需要的防火牆(這裏需要3000端口):
firewall-cmd --permanent --zone=public --add-port=3000/tcp firewall-cmd --reload
如果是同一個域名掛載反向代理,可能會被阻止訪問,這時需要考慮遠程連接的問題:
SELinux 提供了一個安全層,用於在 Linux 內核中實現強制訪問控制 (MAC)。 每個操作系統對象(進程、文件描述符、文件等)都標有一個 SELinux 上下文,該上下文定義了對象可以執行的權限和操作。setsebool命令是用來修改SElinux策略內各項規則的布爾值。
Nginx 被標記爲 httpd_t 上下文,因此,除非明確允許,否則有許多配置被 SELinux 阻止。 爲了演示這一點,請運行以下命令以確認 Nginx 服務標記爲 httpd_t:
ps -eZ該命令提供進程狀態信息,搜索Nginx特定進程信息可以看到標籤。 您將看到 httpd_t,類似於以下內容:
... system_u:system_r:httpd_t:s0 10208 ? 00:00:00 nginx system_u:system_r:httpd_t:s0 10209 ? 00:00:00 nginx ...查看安全策略列表(按q退出)
getsebool -a | less修改SELinux 中httpd對外訪問的狀態,httpd_can_network_connect默認是off的。請改爲on,這樣才能訪問。
注意:下面的代碼開啓後也會運行遠程連接(但它不會控制文件讀寫)。在布爾值關閉的情況下,PHP 代碼無法與遠程網站通信(就像 curl_ 函數被禁用一樣)。sudo setsebool -P httpd_can_network_connect 1
Step3: 部署node應用測試端口
測試一下是不是成功用pm2掛載上了,使用IP能正常訪問 https://yoursite.com:3000
部署express的https端口,需要再原來的服務器文件中增加以下代碼:
// Supprt https const cert = fs.readFileSync('/usr/share/nginx/ssl/bundle.crt'); const key = fs.readFileSync('/usr/share/nginx/ssl/ca.key'); import https from 'https'; const server = https.createServer({key: key, cert: cert }, app); ... app.get('/', (req, res) => { res.send('this is an secure server') }); ... server.listen(port, () => console.log(`Frontend service listening on port: ${port}, access https://localhost:${port} in the web browser`));
下面的代碼可以查看使用端口的程序
sudo netstat -pan | grep ":3000"
Step4: 反向代理配置(不同域名的時候才使用)
vi /etc/nginx/conf.d/default.conf
代碼如下:
server { listen 443 ssl; server_name backend1.example.com; ... location / { proxy_set_header Host $http_host; proxy_pass http://{YOUR_IP}:3000; } }
檢查
nginx -t
重啓
systemctl restart nginx
結語
好咯,這漫長的一篇文章終於OK了,下一次我們會繼續完成第七部分性能和安全的內容,如果文章對你有幫助,也可以繼續關注我。希望看完它,你可以從零開始部署配置你自己的Linux服務器:)其他語言同理可以擴展到Nginx中,可以自由發揮。
如果覺得內容較多閱讀不方便,可以直接瀏覽我的沒位道博客原文:)
從零部署Linux服務器完全指南2022版(CentOS 8+Nginx+PHP)
希望對大家有幫助:)