Linux

Ubuntu Linux 設定 Nginx 使用 TLS 1.2 與 1.3 教學與範例

介紹如何設定 Nginx 網頁伺服器,停用不安全的 TLS 1.1 與 TLS 1.0 協定,只使用 TLS 1.2 與 TLS 1.3 協定。

TLS 傳輸層安全性協定(Transport Layer Security)是一種加密的傳輸協定,廣泛用於網頁、電子郵件、即時通訊等各類應用的資料傳輸,而 TLS 有許多版本,在美國國家安全局(National Security Agency,NSA)發布的安全指引中,建議企業停用 TLS 1.0、1.1 與更早期的 SSL 2.0、3.0 協定。

以下是在 Ubuntu Linux 中設定 Nginx 伺服器停用 TLS 1.1 與 1.0,只使用 TLS 1.2 與 1.3 協定的方法。

檢查 Nginx 與 OpenSSL 版本

若要讓 Nginx 支援 TLS 1.3,Nginx 與 OpenSSL 的版本必須滿足以下條件:

  • Nginx 1.13 或更新版本。
  • Nginx 必須搭配 OpenSSL 1.1.1 或更新版本編譯。

若在 Ubuntu Linux 18.10 或 20.04 以後的版本中,官方套件庫的 Nginx 都已經符合這些條件,所以直接使用 apt 安裝的 Nginx 伺服器就可以直接使用 TLS 1.2 與 1.3。

若要查詢 Nginx 與 OpenSSL 的版本,可以使用以下指令:

# 查詢 Nginx 版本與編譯資訊
nginx -V
nginx version: nginx/1.14.0 (Ubuntu)
built with OpenSSL 1.1.1  11 Sep 2018
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-H4cN7P/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=/build/nginx-H4cN7P/nginx-1.14.0/debian/modules/http-auth-pam --add-dynamic-module=/build/nginx-H4cN7P/nginx-1.14.0/debian/modules/http-dav-ext --add-dynamic-module=/build/nginx-H4cN7P/nginx-1.14.0/debian/modules/http-echo --add-dynamic-module=/build/nginx-H4cN7P/nginx-1.14.0/debian/modules/http-upstream-fair --add-dynamic-module=/build/nginx-H4cN7P/nginx-1.14.0/debian/modules/http-subs-filter

若要檢查系統上 OpenSSL 的版本,可以執行:

# 查詢系統上的 OpenSSL 版本
openssl version
OpenSSL 1.1.1  11 Sep 2018

設定 Nginx 只使用 TLS 1.2 與 TLS 1.3

若要讓 Nginx 僅採用 TLS 1.2 協定,可在 Nginx 設定檔的 httpserver 區塊中,加入 ssl_protocols 設定,指定採用 TLS 1.2 協定:

server {
  # ...

  ssl_protocols TLSv1.2;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;

  # ...
}

若要讓 Nginx 可以同時支援 TLS 1.2 與 1.3,可以在 ssl_protocols 的設定上同時指定這兩種協定:

server {
  # ...

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;

  # ...
}

若想要強制 Nginx 只使用 TLS 1.3,則可以這樣設定:

server {
  # ...

  ssl_protocols TLSv1.3;
  ssl_prefer_server_ciphers off;

  # ...
}

修改好 Nginx 設定檔之後,記得要先測試一下設定檔是否有問題:

# 測試 Nginx 設定
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

確認設定檔沒問題之後,就可以重新啟動 Nginx 伺服器:

# 重新啟動 Nginx 伺服器
sudo systemctl restart nginx

測試 Nginx 伺服器 TLS 版本

若要測試 Nginx 伺服器的 TLS 版本,可以使用 curl 指令:

# 使用 TLS 1.2 進行連線
curl -I -v --tlsv1.2 --tls-max 1.2 https://officeguide.cc/

# 使用 TLS 1.3 進行連線
curl -I -v --tlsv1.3 --tls-max 1.3 https://officeguide.cc/

若可以使用 TLS 1.3 正常建立連線的話,輸出會類似這樣:

*   Trying 139.162.102.70...
* TCP_NODELAY set
* Connected to officeguide.cc (139.162.102.70) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Client hello (1):
* TLSv1.3 (OUT), TLS Unknown, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=officeguide.cc
*  start date: Jul 20 17:56:12 2021 GMT
*  expire date: Oct 18 17:56:10 2021 GMT
*  subjectAltName: host "officeguide.cc" matched cert's "officeguide.cc"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* Using Stream ID: 1 (easy handle 0x55b02a88a600)
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
> HEAD / HTTP/2
> Host: officeguide.cc
> User-Agent: curl/7.58.0
> Accept: */*
>
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
< HTTP/2 200
HTTP/2 200
< server: nginx
server: nginx
< date: Mon, 13 Sep 2021 10:08:30 GMT
date: Mon, 13 Sep 2021 10:08:30 GMT
< content-type: text/html; charset=UTF-8
content-type: text/html; charset=UTF-8
< vary: Accept-Encoding
vary: Accept-Encoding
< x-powered-by: PHP/7.3.29
x-powered-by: PHP/7.3.29
< wpo-cache-status: not cached
wpo-cache-status: not cached
< wpo-cache-message: The request method was not GET (HEAD)
wpo-cache-message: The request method was not GET (HEAD)
< link: <https://officeguide.cc/wp-json/>; rel="https://api.w.org/"
link: <https://officeguide.cc/wp-json/>; rel="https://api.w.org/"
< expires: Mon, 20 Sep 2021 10:08:30 GMT
expires: Mon, 20 Sep 2021 10:08:30 GMT
< cache-control: max-age=604800
cache-control: max-age=604800
< x-cache: HIT
x-cache: HIT

<
* Connection #0 to host officeguide.cc left intact

若採用不安全的 TLS 1.0 與 1.1,正常應該要無法建立連線:

# 使用 TLS 1.1 進行連線
curl -I -v --tlsv1.1 --tls-max 1.1 https://officeguide.cc/

# 使用 TLS 1.0 進行連線
curl -I -v --tlsv1.0 --tls-max 1.0 https://officeguide.cc/

無法建立 TLS 1.0 的連線時,輸出會類似這樣:

*   Trying 139.162.102.70...
* TCP_NODELAY set
* Connected to officeguide.cc (139.162.102.70) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS handshake, Client hello (1):
* TLSv1.0 (IN), TLS alert, Server hello (2):
* error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version
* stopped the pause stream!
* Closing connection 0
curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version
Share
Published by
Office Guide
Tags: 資訊安全

Recent Posts

Python 使用 PyAutoGUI 自動操作滑鼠與鍵盤

本篇介紹如何在 Python ...

1 年 ago

Ubuntu Linux 以 WireGuard 架設 VPN 伺服器教學與範例

本篇介紹如何在 Ubuntu ...

1 年 ago

Linux 網路設定 ip 指令用法教學與範例

本篇介紹如何在 Linux 系...

1 年 ago

Linux 以 Cryptsetup、LUKS 加密 USB 隨身碟教學與範例

介紹如何在 Linux 系統中...

1 年 ago