Tag: NGINX
使用 NGINX 為 Odoo 提供 SSL 加密服務 中的設定在 2020 年已經有點過時了,因此追加更新修正後的內容在此篇
由於安全性的問題,所有瀏覽器在 2020 年三月移除支援 TLS v1.0、TLS v1.1 協定
在 ssl labs 的測試中,有支援 TLS v1.0、TLS v1.1 協定時只能拿到 B
因此需將此部份
ssl_protocols TLSv1.0 TLSv1.1 TLSv1.2;
修正為
ssl_protocols TLSv1.2;
而在多個網站同時架設在一台主機上時,因此 ssl_session_cache 會出現快取無法重複設定的問題
這時候可以通過修改 nginx.conf 讓全部網站共用此 ssl_session_cache
vim /etc/nginx/nginx.conf
將這段
include /etc/nginx/conf.d/*.conf;
修改為
include /etc/nginx/conf.d/*.conf;
## SSL Cache Setting
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 10m;
以下是以 Magento 2 作為範例寫出來的設定檔(仍需要修改)
/etc/nginx/nginx.conf
# For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/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; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; server_tokens off; 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; ## Magento 2 fastcgi_backend upstream fastcgi_backend { server unix:/run/php-fpm/php-fpm.sock; } ## SSL Cache Setting ssl_session_cache shared:SSL:50m; ssl_session_timeout 10m; }
/etc/nginx/conf.d/m2.cewolf.com.tw.conf
server {
listen 80;
server_name m2.cewolf.com.tw;
#set $MAGE_ROOT /usr/share/nginx/magento_hanyu;
#include /usr/share/nginx/magento_hanyu/nginx.conf.sample;
return 301 https://m2.cewolf.com.tw$request_uri;
#location ^~ /.well-known/acme-challenge/ {
#default_type "text/plain";
#root /etc/letsencrypt/;
#}
}
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name m2.cewolf.com.tw;
set $MAGE_ROOT /usr/share/nginx/magento_hanyu;
include /usr/share/nginx/magento_hanyu/nginx.conf.sample;
ssl_certificate /etc/letsencrypt/live/m2.cewolf.com.tw/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/m2.cewolf.com.tw/privkey.pem;
ssl_protocols TLSv1.2;
ssl_dhparam /etc/dehydrated/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
# Enable OSCP Stapling for Nginx web server
# If you're using the SSL from Letsencrypt,
# use the 'chain.pem' certificate
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4;
ssl_trusted_certificate /etc/letsencrypt/live/m2.cewolf.com.tw/chain.pem;
# Enable HTTP Strict-Transport-Security
# If you have a subdomain of your site,
# be carefull to use the 'includeSubdomains' options
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
}
目前在 GCloud 託管的網站經常會出現不明情況死機
進去使用 TOP 稍微檢查一下,發現記憶體的使用量非常大
使用下面語法檢查 PHP-FPM 每一個行程平均記憶體使用量,發現每個行程約用 170 MB
ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'
使用下面語法檢查共有多少開啟的行程,可以發現有許多開啟中的行程
ps -ylC php-fpm --sort:rss
根據分析我們的網站同時上線人數並沒有很多,所以初步判定是設定上的問題
vim /etc/php-fpm.d/www.conf
pm.max_requests
每個子程序在接受多少請求後自動重啟,可有效防止記憶體溢出,預設值等於0,如果等於0不會自動終止。
網路上部份設置較大52100、102400之類的,建議可以抓在1000左右,基礎服務量提高應先調整線程數為主要重點,雖然重啟會消耗資源跟風險比起來安全更重要。
如果是瞬間流量就是要調整此數值來對應,數字越大瞬間能接受的高峰量越高,調整線程數是每秒一次,超過一秒仍有需求後會另開新線程來輔助。
pm.max_requests = 1000
修改完後重啟服務
systemctl restart php-fpm
修改這個參數後,同時開啟的行程只剩下 9 個,記憶體平均使用量只剩下 100MB
還需要再繼續觀察看看
2020.04.14
同時開啟的行程共有 35 個,每個消耗 123M,但網站線上只有三個人
再次調整設定
pm.max_requests = 1000 pm.max_spare_servers = 35
改成
pm.max_requests = 500 pm.max_spare_servers = 20
看看能否讓線程提早關閉,並減少閒置的線程
經過兩天的測試,同時開啟的行程剩下 15 個,平均每個消耗 88M
於 2020/06/28
經過兩天的測試,同時開啟的行程達到 20 個,平均每個消耗 84M,共消耗 1680 MB
試著再調整看看
pm.max_requests = 400 pm.max_spare_servers = 15
於 2020/07/02
同時開啟的行程達到 15 個,平均每個消耗 51M,共消耗 765MB
剩餘記憶體還有 1042M,在可以接受的範圍內
參考資料:
由於目前 Dehydrated 無法正常使用,官方的 certbot 改的簡單許多,建議使用 certbot 來申請
目前我使用過兩種申請方式
- webroot 驗證:優點是不需要中斷現有的網路服務,但需要修改 NGINX 設定檔
- DNS 驗證:只需要修改 DNS 設定即可通過認證,但後續會需要手動續約,不推薦
安裝 certbot-nginx 主程式
yum install -y python-certbot-nginx
Method 1:webroot 驗證申請
需要先修改網址的 NGINX 設定,最前面改為下方樣式
# http -> https
server {
listen 80;
server_name www.cewolf.com.tw;
location ~ /\.well-known\/acme-challenge {
root /etc/letsencrypt;
allow all;
}
if ($request_uri !~ /\.well-known) {
return 301 https://$server_name$request_uri;
}
}
重新載入 NGINX 設定檔
service nginx reload
申請 SSL 憑證
certbot certonly --webroot -w /etc/letsencrypt/ -d www.cewolf.com.tw
跳出以下的內容就代表成功了
Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator webroot, Installer None Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org Obtaining a new certificate Performing the following challenges: http-01 challenge for m2.cewolf.com.tw Using the webroot path /etc/letsencrypt for all unmatched domains. Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/www.cewolf.com.tw/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/www.cewolf.com.tw/privkey.pem Your cert will expire on 2020-03-20. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
接著修改 NGINX 設定檔的 SSL 設定
vim /etc/nginx/conf.d/www.cewolf.com.tw.ssl.conf
加入這兩行
ssl_certificate /etc/letsencrypt/live/www.cewolf.com.tw/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.cewolf.com.tw/privkey.pem;
重新載入 NGINX 設定即可
systemctl reload nginx
Method 2:DNS 驗證申請
certbot -d m2.cewolf.com.tw --manual --preferred-challenges dns certonly
會跳出 DNS 驗證值
Please deploy a DNS TXT record under the name _acme-challenge.www.cewolf.com.tw with the following value: O3kP443ms6OP84K8NQnZv_vvZ5HAHMKMBdqqSIyxKlo
直接在 DNS Record 設定 txt 之後需確認可成功查詢
nslookup -type=TXT _acme-challenge.www.cewolf.com.tw
接著按下 Enter 就看到,就代表成功了
Before continuing, verify the record is deployed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Press Enter to Continue Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/www.cewolf.com.tw/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/www.cewolf.com.tw/privkey.pem Your cert will expire on 2020-03-20. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
接著修改 NGINX 設定檔的 SSL 設定
vim /etc/nginx/conf.d/www.cewolf.com.tw.ssl.conf
加入這兩行
ssl_certificate /etc/letsencrypt/live/www.cewolf.com.tw/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.cewolf.com.tw/privkey.pem;
重新載入 NGINX 設定
systemctl reload nginx
記得確認 SSL 憑證失效日是否有成功延後喔!
自動展延憑證
我們可以利用 cron 這個小程式來定期自動展期,首先編輯 crontab 設定檔
vim /etc/crontab
加入這兩行(於每周六 AM 3:00 檢查第一組網域是否需要展期,AM 3:30 reload NGINX)
00 3 * * 6 root certbot -d www.cewolf.com.tw --no-redirect 10 3 * * 6 root certbot -d km.cewolf.com.tw --no-redirect 20 3 * * 6 root certbot -d www.gapl.com.tw --no-redirect 30 3 * * 6 root systemctl reload nginx.service
重新啟動 cron service
systemctl restart crond.service
完成!
確認憑證狀態
有時候會收到 letsencrypt 寄來的「憑證即將到期通知 Let’s Encrypt certificate expiration notice for domain “your_domain.com”」。這時候可以輸入下面的指令確認狀態。
sudo certbot certificates
隨著官網的重要性越來越高,將 Magento 雲端化已經是必要的事情了(免除停電、網路斷線等風險)
以下是在 Google Compute Engine(GCE) 中的 CentOS 7.0 進行環境設定
GCE CentOS 7.0 預設模組版本為 PHP 5.4.16、NGINX 1.12.2、OpenSSL 1.0.2k,已經符合我們的最低需求了
資料庫則嘗試採用 Google SQL 取代本機安裝 MariaDB(MySQL) 的方式
安裝
為了方便設定,先設定 root 密碼,在用 su 指令切換至 root 使用者
sudo passwd root su
安裝 NGINX 1.12.2
yum -y install nginx
安裝 PHP 5.4.16 + Zend Optimizer+
yum -y install php php-mysql php-gd php-fpm php-mbstring php-mcrypt php-pear php-process php-tidy php-xml php-xmlrpc php-soap yum -y install php-pecl-zendopcache
安裝 PHP 5.6 + opcache
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm yum -y install php56w php56w-mysql php56w-gd php56w-fpm php56w-mbstring php56w-mcrypt php56w-pear php56w-process php56w-tidy php56w-xml php56w-xmlrpc php56w-soap php56w-devel php56w-opcache
安裝新版 CURL(Magento 必須套件)
rpm -Uvh http://www.city-fan.org/ftp/contrib/yum-repo/rhel7/x86_64/city-fan.org-release-1-13.rhel7.noarch.rpm sed -i '5c enabled=1' /etc/yum.repos.d/city-fan.org.repo yum -y install curl libcurl
設定
修改 SELINUX 模式,http_can_sendmail 設定
sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config && setsebool -P httpd_can_sendmail 1
修改 php.ini 設定
sed -i 's/short_open_tag = Off/short_open_tag = On/' /etc/php.ini && sed -i 's/memory_limit = 128M/memory_limit = 512M/' /etc/php.ini && sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/' /etc/php.ini
修改 php-fpm 設定
sed -i 's@listen = 127.0.0.1:9000@listen = /var/run/php-fpm/php-fpm.sock@' /etc/php-fpm.d/www.conf && sed -i 's@;listen.owner = nobody@listen.owner = nginx@' /etc/php-fpm.d/www.conf && sed -i 's/;listen.group = nobody/listen.group = nginx/' /etc/php-fpm.d/www.conf && sed -i 's/user = apache/user = nginx/' /etc/php-fpm.d/www.conf && sed -i 's/group = apache/group = nginx/' /etc/php-fpm.d/www.conf
優化 /etc/php.d/opcache.ini 設定
sed -i 's/opcache.memory_consumption=128/opcache.memory_consumption=256/' /etc/php.d/opcache.ini && sed -i 's/opcache.max_accelerated_files=4000/opcache.max_accelerated_files=16000/' /etc/php.d/opcache.ini
修改 nginx.conf 設定檔
vim /etc/nginx/nginx.conf
移除此區塊
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 { } }
新增 nginx/conf.d/magento.conf (80 port 專用)
vim /etc/nginx/conf.d/magento.conf
填入以下設定
server { listen 80; server_name 104.199.145.27; root /usr/share/nginx/html; index index.php index.html index.htm; location ~* \.(ico|css|js|gif|jpe?g|png|ogg|ogv|svg|svgz|eot|otf|woff)(\?.+)?$ { expires max; log_not_found off; add_header Access-Control-Allow-Origin "*"; } #location /.well-known/acme-challenge/ { # alias /var/www/dehydrated/; #} location / { try_files $uri $uri/ /index.php?q=$uri&$args; } ## These locations are protected location /downloader/ { allow 192.168.0.0/24; deny all; } ## These locations are protected location ~ /(dev|app|includes|lib|media/downloadable|pkginfo|var)/ { deny all; } location @handler { ## Magento uses a common front handler rewrite / /index.php; } location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler rewrite ^(.*.php)/ $1 last; } location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } #if ($bad_referer) { # return 444; #} }
新增 nginx/conf.d/magento.ssl.conf (443 port 專用)
vim /etc/nginx/conf.d/magento.ssl.conf
填入以下設定
server { listen 443 ssl http2; server_name www.gapl.com.tw www.glamp.com.tw; root /usr/share/nginx/html; index index.php index.html index.htm; ssl_certificate /etc/dehydrated/certs/www.gapl.com.tw/fullchain.pem; ssl_certificate_key /etc/dehydrated/certs/www.gapl.com.tw/privkey.pem; ssl_dhparam /etc/dehydrated/dhparam.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_session_cache shared:SSL:20m; ssl_session_timeout 180m; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4; add_header Strict-Transport-Security "max-age=31536000" always; location ~* \.(ico|css|js|gif|jpe?g|png|ogg|ogv|svg|svgz|eot|otf|woff)(\?.+)?$ { expires max; log_not_found off; add_header Access-Control-Allow-Origin "*"; add_header Strict-Transport-Security "max-age=31536000" always; } location / { deny 203.24.188.5; deny 203.24.188.10; try_files $uri $uri/ /index.php?q=$uri&$args; } ## These locations are protected location /dev/ { allow 192.168.0.0/16; deny all; } location /downloader/ { allow 192.168.0.0/16; deny all; } ## These locations are protected location ~ /(app|includes|lib|media/downloadable|pkginfo|var)/ { deny all; } location @handler { ## Magento uses a common front handler rewrite / /index.php; } location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler rewrite ^(.*.php)/ $1 last; } location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_read_timeout 600s; } if ($bad_referer) { return 444; } }
設定開機啟動 NGINX & PHP-FPM 服務
systemctl enable nginx.service && systemctl enable php-fpm.service
下載 Magento 備份檔並轉移至網站資料夾,並重新啟動讓 SELINUX 設定生效
curl -O https://storage.googleapis.com/www-gapl/magento_2017-12-29.tar.gz rm -rf /usr/share/nginx/html tar -C /usr/share/nginx/ -zxvf magento_2017-12-29.tar.gz chown -R nginx: /usr/share/nginx/html reboot
下一步 SSL 轉移請前往:於 Google Compute Engine CentOS 7.0 設定 Dehydrated 與轉移 SSL 憑證
遇到 403 Forbidden
Nginx Error Log(/var/log/nginx/error.log) 中顯示
2017/12/30 18:16:42 [error] 871#0: *2 open() “/usr/share/nginx/html/LICENSE.txt” failed (13: Permission denied), client: 60.251.46.241, s
erver: 104.199.145.27, request: “GET /LICENSE.txt HTTP/1.1”, host: “104.199.145.27”
延伸閱讀
Google Compute Engine 使用 root 和密碼登入
要加速 Odoo 可以從幾個方向著手:
- 調整 Odoo 的 config 檔
- 調整 PosgreSQL 的 config 檔
- 使用 NGINX 作為 Reverse Proxy(反向代理),甚至進一步開啟 HTTP/2(需一併設定 SSL)
我們在這一篇會著重在設定 NGINX 作為 Reverse Proxy
編輯 NGINX 的 conf 檔
vim /etc/nginx/conf.d/odoo.conf
內容設定為
server { listen 80; server_name 192.168.1.244 odoo.glamping.tw; location / { proxy_pass http://odoo.gapl.com.tw; proxy_buffer_size 128k; proxy_buffers 16 64k; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location ~* /web/static/ { proxy_cache_valid 200 60m; proxy_buffering on; expires 864000; proxy_pass http://odoo.gapl.com.tw; } error_page 500 502 503 504 /50x.html; # location = /50x.html { # root /usr/share/nginx/html; # } }
關於其中的參數可以參考 Understanding Nginx HTTP Proxying, Load Balancing, Buffering, and Caching 這篇
而REVERSE PROXY WITH ODOO 8 | NGINX | UBUNTU 14.04 LTS | LONGPOLLING 這篇
建議加大 proxy_buffer_size 與 proxy_buffers 才能處理 Odoo 的 Web requests
設定完後,重新啟動 NGINX 就可以進行測試囉
/etc/letsencrypt/live/odoo.glamping.tw/fullchain.pem
注意事項:
NGINX 設定檔中的 proxy_pass 參數如果有加入 port 號,NGINX 會啟動失敗,不確定原因
參考資料:
REVERSE PROXY WITH ODOO 8 | NGINX | UBUNTU 14.04 LTS | LONGPOLLING
Install Odoo on a Debian 8 VPS with Nginx as a reverse proxy
Setting Up OpenERP (Odoo) 9 with Nginx on RHEL/CentOS and Debian/Ubuntu
Running Odoo with nginx in https mode
Understanding Nginx HTTP Proxying, Load Balancing, Buffering, and Caching
有鑑於支援 HTTP/2 後,網站連線速度加快不少(可參考 https://www.httpvshttps.com/)
所以著手升級現有的系統加速 Magento 運行的速度
升級 OpenSSL 至 1.0.2+
ALPN 需要 OpenSSL 1.0.2 以上才支援,參照 CentOS 更新 OpenSSL 到最新版 1.0.2j or CentOS 更新 OpenSSL 到最新版 1.1.0 更新到最新版
下載並手動編譯 NGINX
可先用 YUM 將 NGINX 更新至最新版
su yum -y update
再下載對應的 NGINX 來編譯,這樣子比較不會有問題
接下來檢查我們的 NGINX 版本與『編譯參數』
[root@www nginx-1.12.0]# nginx -V nginx version: nginx/1.12.0 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC) built with OpenSSL 1.0.1e-fips 11 Feb 2013 TLS SNI support enabled configure arguments: --prefix=/etc/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 --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --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-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
可以看出 NGINX 版本為 1.12.0,編譯的 OpenSSL 版本為 1.0.1e
最後方的 configure arguments 就是編譯的參數,重新編譯需要在最後加上『–with-openssl=/usr/src/openssl-1.1.0f』
讓 NGINX 將新版 OpenSSL 編譯進去
yum -y install libxslt-devel gd-devel perl-devel perl-ExtUtils-Embed GeoIP GeoIP-devel GeoIP-data cd /root wget http://nginx.org/download/nginx-1.12.0.tar.gz tar zxvf nginx-1.12.0.tar.gz cd nginx-1.12.0 ./configure --prefix=/etc/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 --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --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-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' --with-openssl=/usr/src/openssl-1.1.0f./configure --prefix=/etc/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 --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-openssl=/usr/local/openssl-1.0.2j/ --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_perl_module=dynamic --with-threads --with-stream --with-stream_ssl_module --with-http_slice_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_v2_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic'make make install
編輯 NGINX conf 檔
於 /etc/nginx/conf.d/xxxx.conf 新增 http2 即可
server {
listen 443 ssl http2;
檢查 NGINX 是否編譯成功
[root@www nginx-1.12.0]# nginx -V
nginx version: nginx/1.12.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
built with OpenSSL 1.1.0f 25 May 2017
TLS SNI support enabled
重新啟動後才會正式啟用 ALPN 的功能
service nginx restart
可來此網站測試是否成功
https://tools.keycdn.com/http2-test
參考資料:
How to get already installed NGINX to use OpenSSL 1.0.2 for ALPN?
==================== 更新至新版後,無法正常 renew,請改用 Dehydrated 來處理 ====================
Let’s Encrypt 是各大廠為了提升網路安全性而共同合作推出免費提供憑證的機構(CA), 以下是在 CentOS 7 將 Let’s encrypt 配置到 NGINX 的方法
先安裝 git、 EPEL repo 與 Let’s encrypt 所需套件
su yum install -y git epel-release gcc libffi-devel python-devel openssl-devel
下載 Let’s encrypt:
cd /root git clone https://github.com/letsencrypt/letsencrypt
系統會將 Let’s Encrypt 的最新版本下載到 /root/letsencrypt
先停用 NGINX 後用 letsencrypt-auto 取得 SSL 憑證檔
cd /root/letsencrypt ./letsencrypt-auto certonly -a standalone -d yourdomain.com or cd /root/letsencrypt ./letsencrypt-auto --config /home/test/configs/[your-domain].confcertonlymkdir /root/webroot cd /root/letsencrypt./letsencrypt-auto certonly -a webroot --webroot-path=/usr/share/nginx/html -d odoo.glamping.tw./letsencrypt-auto certonly -a webroot --webroot-path=/root/webroot -d odoo.glamping.tw
Let’s encrypt 會將憑證檔案放到 /etc/letsencrypt/live/.
接下來生成 DH Parameter
mkdir /etc/nginx/cert openssl dhparam 2048 -out /etc/nginx/cert/dhparam.pemopenssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
接著設定 NGINX 的 SSL 設定,加入以下參數
ssl_certificate /etc/letsencrypt/live/odoo.glamping.tw/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/odoo.glamping.tw/privkey.pem; ssl_dhparam /etc/ssl/certs/dhparam.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_session_cache shared:SSL:20m; ssl_session_timeout 180m; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4; add_header Strict-Transport-Security "max-age=31536000 always;
接下來重新啟動 NGINX
service nginx reload
去測試網站跑分,這樣子的設定應該可以直接拿到最高評分 A+ !
最後,由於 Lets Encrypt 憑證有效期限只有 90 天,建議每 60 天自動續約
先建立 renew script:auto-renew.sh
/root/letsencrypt/letsencrypt-auto certonly --webroot --renew-by-default --agree-tos -m cewolf@cewolf.com -w /root/webroot -d gapl.com.tw -d www.gapl.com.tw -d glamp.tw nginx -s reload
接著設定 CRON 於每兩個月的 20號 凌晨 3 點續約
0 3 20 2,4,6,8,10,12 * root /root/auto-renew.sh
Reload crond
systemctl reload crond.service
大功告成!
目前 nginx reload 並不會換上新的憑證
再找到解決方案前先這樣子跑
systemctl stop crond.service /root/letsencrypt/letsencrypt-auto renew /bin/systemctl start nginx.service
測試網站:
Qualys SSL Labs SSL Server Test
DigiCert® SSL Installation Diagnostics Tool
參考資料:
LinuxRHEL / CentOS 7 安裝 Let’s encrypt RHEL / CentOS 7 安裝 Let’s encrypt
Guide to Deploying Diffie-Hellman for TLS
用 nginx 建置一個 A+ 等級的 https 網頁伺服器
How to Validate a Let’s Encrypt Certificate on a Site Already Active on CloudFlare