Nginx KTLS

Cách Biên dịch và Cài đặt Nginx kTLS từ mã nguồn trên Ubuntu 22.04

Bài này sẽ hướng dẫn bạn 4 bước chi tiết để cài đặt Nginx và tạo các trang nginx hỗ trợ SSL với kTLS và TLSv1.3 trên máy chủ Ubuntu 22.04.

Giới thiệu

Nginx là một trong những công cụ cân bằng tải, máy chủ web và reverse proxy tiên tiến phổ biến nhất trên thế giới và đang phục vụ các trang web lớn nhất và có lưu lượng truy cập cao.

Một trong những tính năng tuyệt vời của nó là rất nhẹ. Bởi vì Nginx tiêu thụ ít tài nguyên điện toán hơn và có thể xử lý khối lượng kết nối lớn, nó thường được sử dụng làm reverse proxy và cân bằng tải để quản lý lưu lượng đến và phân phối nó đến các máy chủ ứng dụng chậm hơn, bất kỳ thứ gì từ microservices đến các hệ thống khủng như Odoo ERP Online.

Tại sao kTLS?

Bảo mật lớp truyền tải (TLS - Transport Layer Security) là một giao thức mật mã cực kỳ phổ biến. Triển khai TLS trong kernel (kTLS) cải thiện hiệu suất bằng cách giảm đáng kể nhu cầu sao chép các hoạt động giữa không gian người dùng và kernel.

Bằng cách kết hợp kTLS và sendfile(), dữ liệu được mã hóa trực tiếp trong không gian kernel trước khi được chuyển đến ngăn xếp mạng để truyền tải. Điều này giúp loại bỏ nhu cầu sao chép dữ liệu vào không gian người dùng để được mã hóa bởi các thư viện TLS và sau đó quay trở lại không gian kernel để truyền tải. kTLS cũng cho phép giảm tải quá trình xử lý TLS xuống phần cứng, bao gồm chuyển tải quá trình mã hóa đối xứng TLS xuống các thiết bị mạng.

Nginx KTLS
Nginx KTLS

Tại sao sử dụng TLSv1.3?

TLS 1.3 là phiên bản mới nhất của giao thức TLS, được sử dụng bởi HTTPS và các giao thức mạng khác để mã hóa, là phiên bản hiện đại của SSL. TLS 1.3 đã bỏ hỗ trợ cho các tính năng mật mã cũ hơn, kém an toàn hơn và nó đẩy nhanh quá trình bắt tay TLS, cùng với nhiều cải tiến khác.

Tóm tắt

Có hai phương pháp cài đặt NGINX trên Ubuntu 22.04:

  • Sử dụng trình quản lý gói của hệ điều hành. Ví dụ, apt trong Ubuntu 22.04: apt install nginx
  • Biên dịch và cài đặt Nginx từ mã nguồn.

Trong hướng dẫn này, phương pháp chúng ta chọn là biên dịch và cài đặt từ mã nguồn vì chúng ta cần tùy chỉnh cài đặt cho kTLS. Sau khi hoàn thành các bước trong hướng dẫn này, chúng ta kỳ vọng sẽ đạt được những điều sau:

  1. NginX được biên dịch và cài đặt từ mã nguồn và có kích hoạt mô-đun kTLS
  2. Một trang web Nginx mẫu sẽ được triển khai với một tên miền và có Chứng chỉ SSL với TLSv1.3, có hỗ trợ kTLS.
  3. HTTP/2 được kích hoạt để có hiệu suất tốt hơn

Các yêu cầu tiên quyết

Trước khi bắt đầu hướng dẫn này, bạn phải đáp ứng các điều kiện tiên quyết sau:

  1. Bạn nên có một máy chủ Ubuntu 22.04. Tôi khuyên bạn nên sử dụng DigitalOcean nếu bạn chưa có.
  2. Bạn đã thiết lập máy chủ của mình với một người dùng thông thường, không phải root, với các đặc quyền sudo được định cấu hình trên máy chủ của bạn.
  3. Bạn cũng cần có một IP công cộng được gán cho máy chủ.
  4. Bạn đã có một tên miền (ví dụ: your_domain.com) được trỏ đến địa chỉ IP được đề cập ở trên.

Bước 1 - Chuẩn bị máy chủ Nginx

Nạp module kTLS vào Kernel

Vì chúng ta đang triển khai Nginx có hỗ trợ kTLS, chúng ta cần nạp mô-đun kTLS vào Kernel bằng cách chạy lệnh sau:

sudo modprobe tls

Xin lưu ý rằng nếu bạn đang sử dụng một máy ảo container linux chẳng hạn như LXD / LCX có kernel được chia sẻ bởi máy chính mà chứa máy ảo thì thay vì chạy lệnh trên trên máy ảo, bạn sẽ cần thực hiện trên máy chính.

Cài đặt các gói phụ thuộc cho Nginx

Như thường lệ, chúng ta cần cập nhật hệ thống trước.

sudo apt update; sudo apt dist-upgrade

Bây giờ, hãy cài đặt phần mềm và gói được Nginx yêu cầu:

sudo apt install unzip build-essential \
libpcre3 libpcre2-dev libpcre3-dev zlib1g \
zlib1g-dev libssl-dev libgd-dev libxml2 \
libxml2-dev uuid-dev libmaxminddb-dev \
libgeoip-dev libxslt1-dev

Chuẩn bị tài khoản user và group cho Nginx

Chúng ta cần một nhóm có tên nginx mà các tiến trình của nginx worker sẽ sử dụng.

sudo addgroup nginx

Chúng tôi cũng cần có một người dùng không có đặc quyền tên là nginx thuộc nhóm nginx đã đề cập ở trên, mà các tiến trình của Nginx worker sẽ sử dụng.

Tài khoản người dùng sẽ có /var/www làm thư mục chính (thư mục home) của nó.

sudo adduser nginx --system \
--home=/var/www --disabled-login \
--disabled-password --ingroup nginx

Tạo các thư mục làm việc của Nginx

Đầu tiên, tạo thư mục tạm thời client body:

sudo mkdir -p /var/lib/nginx/body

Thứ hai, tạo thư mục tạm thời cho proxy HTTP

sudo mkdir /var/lib/nginx/proxy

Và bây giờ, tạo thư mục tạm thời HTTP FastCGI

sudo mkdir /var/lib/nginx/fastcgi

Sau đó, tạo thư mục tạm thời uWSGI HTTP

sudo mkdir /var/lib/nginx/uwsgi

Tiếp theo nữa, tạo thư mục tạm thời HTTP SCGI (Simple Common Gateway Interface)

sudo mkdir /var/lib/nginx/scgi

Và sau đó, tạo thư mục để chứa các mô-đun Nginx sau này

sudo mkdir -p /usr/lib/nginx/modules

Sau đó, tạo thư mục /etc/nginx/sites-available để lưu trữ các tệp cấu hình trang Nginx (Nginx Site):

sudo mkdir /etc/nginx/sites-available

Sau đó tạo thư mục /etc/nginx/sites-enabled để lưu trữ các liên kết tượng trưng đến các tệp bên trong sites-available mà chúng tôi muốn Nginx tải.

sudo mkdir /etc/nginx/sites-enabled

Cuối cùng, tạo thư mục chứa các chứng chỉ SSL:

sudo mkdir -p /etc/nginx/ssl

Bước 2 - Biên dịch và Cài đặt Nginx

Hãy bắt đầu với việc tải xuống mã nguồn Nginx rồi sau đó biên dịch và cài đặt nó.

Tải xuống mã nguồn Nginx

Hỗ trợ kTLS đã được thêm vào Nginx Phiên bản 1.21.4 (phiên bản mainline). Tại thời điểm viết bài này (tháng 10 năm 2022), phiên bản ổn định (stable) mới nhất là 1.22.1. Chúng ta sẽ tải xuống phiên bản này bằng cách sử dụng wget:

wget https://nginx.org/download/nginx-1.22.1.tar.gz

Sau khi hoàn tất quá trình tải xuống, bạn có thể chạy lệnh sau để giải nén kho lưu trữ mã nguồn tải xuống vào thư mục hiện hành:

tar xvfz nginx-1.22.1.tar.gz

Tải xuống mô-đun Nginx bổ sung

Bước này là tùy chọn nếu bạn không có nhu cầu sử dụng GeoIP2. Nhưng thật tốt nếu có nó nếu bạn đang triển khai Nginx làm proxy để Cài đặt Odoo.

wget https://github.com/leev/ngx_http_geoip2_module/archive/refs/tags/3.4.zip
unzip 3.4.zip
mv ngx_http_geoip2_module-3.4 /usr/lib/nginx/modules/

Cấu hình biên dịch Nginx

Trước tiên, bạn cần đổi thư mục hiện hành sang thư mục mã nguồn Nginx bằng lệnh dưới đây:

cd nginx-1.22.1

Sau đó, bạn có thể chạy lệnh sau để xem các tùy chọn cấu hình trước khi biên dịch Nginx:

./configure --help

Hoặc, đọc đầy đủ các thông số cấu hình nginx để biết chi tiết.

Bây giờ, chúng ta có thể bắt đầu định cấu hình biên dịch Nginx bằng cách sử dụng các tùy chọn biên dịch phổ biến mà tôi đã lựa chọn bằng cách chạy lệnh bên dưới. Xin lưu ý rằng tùy chọn --with-openssl-opt=enable-ktls là bắt buộc phải có để hỗ trợ kTLS. Nếu bạn cũng muốn hỗ trợ mã hóa yếu cho phiên bản TLS cũ hơn (ví dụ: TLSv1.2, tùy chọn sẽ là --with-openssl-opt='enable-ktls enable-weak-ssl-ciphers'. Đây là các tùy chọn cấu hình tôi thường sử dụng để dựng Nginx làm proxy cho việc Cài đặt Odoo trên Ubuntu 22.04.

./configure \
--prefix=/usr/local/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log \
--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 \
--lock-path=/var/lock/nginx.lock \
--pid-path=/run/nginx.pid \
--user=nginx \
--group=nginx \
--with-pcre-jit \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_auth_request_module \
--with-http_addition_module \
--with-http_dav_module \
--with-http_geoip_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_image_filter_module \
--with-http_v2_module \
--with-http_sub_module \
--with-http_xslt_module \
--with-stream \
--with-stream_ssl_module \
--with-file-aio \
--with-mail \
--with-mail_ssl_module \
--with-http_slice_module \
--with-debug \
--with-compat \
--with-threads \
--with-stream_ssl_preread_module \
--with-http_mp4_module \
--with-openssl-opt='enable-ktls enable-weak-ssl-ciphers' \
--add-module=/usr/lib/nginx/modules/ngx_http_geoip2_module-3.4 \
--with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' \
--with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

Kết quả có thể như sau:

Configuration summary
  + using threads
  + using system PCRE library
  + using system OpenSSL library
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/etc/nginx"
  nginx configuration file: "/etc/nginx/nginx.conf"
  nginx pid file: "/run/nginx.pid"
  nginx error log file: "/var/log/nginx/error.log"
  nginx http access log file: "/var/log/nginx/access.log"
  nginx http client request body temporary files: "/var/lib/nginx/body"
  nginx http proxy temporary files: "/var/lib/nginx/proxy"
  nginx http fastcgi temporary files: "/var/lib/nginx/fastcgi"
  nginx http uwsgi temporary files: "/var/lib/nginx/uwsgi"
  nginx http scgi temporary files: "/var/lib/nginx/scgi"

Biên dịch và cài đặt Nginx

Sau khi bạn hoàn thành cấu hình tùy chỉnh, bây giờ có thể biên dịch mã nguồn NGINX bằng cách sử dụng lệnh bên dưới:

make

Cài đặt Nginx:

sudo make install

Xác minh xem bạn đã cài đặt Nginx thành công hay chưa bằng cách chạy lệnh bên dưới:

nginx -V

Bạn sẽ thấy kết quả như sau:

Xác minh xem Nginx có được cài đặt đúng cách hay không
Xác minh xem Nginx có được cài đặt đúng cách hay không

Tạo tệp cấu hình Nginx

Tôi đang sử dụng trình soạn thảo văn bản nano để chỉnh sửa tệp cấu hình /etc/nginx/nginx.conf:

sudo nano /etc/nginx/nginx.conf

Sau đó thay thế nội dung hiện có bằng nội dung sau:

user nginx;
worker_processes auto;
pid /run/nginx.pid;

events {
        worker_connections 1024;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

Sau đó, bạn có thể lưu tệp cấu hình Nginx bằng cách nhấn Ctrl + X và nhập y khi được hỏi rồi nhấn đi vào.

QUAN TRỌNG: Bạn phải có chỉ thị sendfile on; trong khối http để hỗ trợ kTLS.

Khởi động Nginx

Bây giờ, bạn gần như đã hoàn tất và có thể khởi động Nginx bằng cách sử dụng lệnh sau:

sudo nginx

Và sau đó, bạn có thể chạy lệnh bên dưới để kiểm tra xem Nginx worker có đang chạy ở chế độ nền hay không:

sudo ps aux | grep nginx

Bạn sẽ thấy kết quả như dưới đây:

Xác minh xem Nginx có đang chạy không
Xác minh xem Nginx có đang chạy không

Dừng Nginx

Để dừng Nginx, hãy chạy lệnh dưới đây:

sudo nginx -s stop

Bước 3- Chạy Nginx dưới dạng Dịch vụ / Daemon

Chạy dịch vụ NGINX (hay còn gọi là daemon) sẽ không chỉ cho phép chúng ta quản lý việc khởi động, dừng và tải lại NGINX theo cách chuẩn hơn mà còn giúp việc khởi động NGINX khi khởi động máy chủ đơn giản hơn nhiều.

Tạo tệp đơn vị Nginx

Chúng tôi sẽ sử dụng trình soạn thảo văn bản nano để tạo tệp:

sudo nano /lib/systemd/system/nginx.service

Bây giờ, bạn có thể sao chép và dán những thứ sau vào giao diện người dùng nano:

# Stop dance for nginx
# =======================
#
# ExecStop sends SIGSTOP (graceful stop) to the nginx process.
# If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control
# and sends SIGTERM (fast shutdown) to the main process.
# After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends
# SIGKILL to all the remaining processes in the process group (KillMode=mixed).
#
# nginx signals reference doc:
# http://nginx.org/en/docs/control.html
#
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

Sau đó lưu tệp và thoát.

Bây giờ, chỉ cần chạy lệnh sau để thông báo systemd rằng tệp đơn vị mới tồn tại:

sudo systemctl daemon-reload

Tự khởi chạy Nginx khi khởi động máy chủ

sudo systemctl enable nginx

Làm việc với Dịch vụ Nginx

Khởi động Nginx

sudo systemctl start nginx

Dừng Nginx

sudo systemctl stop nginx

Kiểm tra trạng thái dịch vụ Nginx

sudo systemctl status nginx

Bước 4 - Tạo website Nginx có hỗ trợ kTLS

Trong phần này, tôi sẽ hướng dẫn bạn tạo một trang web mẫu hỗ trợ:

  1. Chứng chỉ SSL. Bạn có thể sử dụng Let's Encrypt miễn phí hoặc mua từ các Tổ chức phát hành chứng chỉ công cộng.
  2. kTLS: xem Tại sao sử dụng kTLS
  3. HTTP/2: HTTP/2 (tên ban đầu là HTTP/2.0) là một bản sửa đổi lớn của giao thức mạng HTTP được World Wide Web sử dụng. Nó được bắt nguồn từ giao thức SPDY thử nghiệm trước đó, ban đầu được phát triển bởi Google

Tạo trang web Nginx

Hãy chắc chắn rằng:

  1. Bạn đã có tên miền được trỏ đến địa chỉ IP máy chủ Nginx của mình;
  2. Bạn đã có Chứng chỉ SSL cho tên miền và được lưu trữ trong /etc/nginx/ssl;

Tạo một trang HTML mẫu:

sudo mkdir /var/www/html

Sử dụng nano để tạo trang

sudo nano /var/www/html/index.html

Sao chép và dán nội dung sau:

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Sau đó, lưu tệp và thay đổi chủ sở hữu của thư mục /var/www/html và nội dung của nó thành nginx:

sudo chown -hR nginx: /var/www/html

Bây giờ, hãy tạo tệp cấu hình trang bằng nano như bên dưới:

sudo nano /etc/nginx/sites-available/your_domain.com.conf

Sau đó, sao chép và dán nội dung sau vào giao diện người dùng nano:

server {
        listen 443 ssl http2;
        server_name your_domain.com;

        error_log /var/log/nginx/your_domain_com_error.log debug;
        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        ssl_certificate ssl/your_ssl_certificate.crt;
        ssl_certificate_key ssl/your_ssl_certificate.key;
        ssl_conf_command Options KTLS;
        ssl_protocols TLSv1.3;

        location / {
                try_files $uri $uri/ =404;
        }
}

Xin lưu ý rằng:

  1. Chúng ta đã bật gỡ lỗi bằng cách thiết lập debug trong chỉ mục error_log để chúng ta có thể có thông tin gỡ lỗi sau này trong tệp nhật ký lỗi /var/log/nginx/your_domain_com_error.log. Sau khi mọi thứ đã ổn, bạn nên tắt gỡ lỗi bằng cách xóa gỡ lỗi, đặc biệt là trong môi trường thật. Ghi nhật ký gỡ lỗi làm giảm kinh khủng hiệu suất do khối lượng lớn các hoạt động ghi; Ngoài ra, nhật ký gỡ lỗi có thể rất lớn và nhanh chóng làm cạn kiệt dung lượng có sẵn trên phân vùng lưu trữ trên máy chủ của bạn.
  2. Bạn sẽ phải thay đổi giá trị của các chỉ thị ssl_certificatessl_certificate_key để khớp với đường dẫn lưu trữ chứng chỉ SSL của bạn.
  3. Chỉ mục ssl_conf_command Options KTLS; là để kích hoạt hỗ trợ kTLS cho trang web này.

Bây giờ, hãy tạo một shortcut / symbolic link cho tệp mới tạo your_domain.com.conf để Nginx có thể nạp nó:

sudo ln -s /etc/nginx/sites-available/your_domain.com.conf /etc/nginx/sites-enabled/your_domain.com.conf

Sau đó, kiểm tra xem có lỗi nào trong cấu hình Nginx không bằng cách chạy lệnh:

sudo nginx -t

Nếu không có lỗi, bạn sẽ kết quả tương tự như sau:

Kiểm tra cấu hình Nginx
Kiểm tra cấu hình Nginx

Bây giờ, hãy khởi động lại Nginx để trang web mới có hiệu lực:

sudo systemctl restart nginx

Sau đó, mở trình duyệt web của bạn và nhập https://your_domain.com để thấy kết quả là một trang giống như bên dưới:

Nginx Holding Trang

Xin lưu ý rằng URL phải là https. Trong ví dụ trên, tôi sử dụng miền cục bộ với chứng chỉ SSL tự ký. Trong môi trường sản xuất, nó phải là tên miền của bạn và có SSL hợp lệ.

Xác minh xem kTLS có được Bật không

Để xác minh rằng NGINX đang sử dụng kTLS, hãy kiểm tra BIO_get_ktls_send()SSL_sendfile() trong nhật ký lỗi.

Chạy lệnh dưới đây để kiểm tra xem BIO_get_ktls_send có ở trong nhật ký không:

sudo grep BIO /var/log/nginx/tuan_local_error.log

Sau đó, bạn sẽ thấy kết quả tương tự như dưới đây:

2022/10/26 03:40:31 [debug] 10662#10662: *3 BIO_get_ktls_send(): 1
2022/10/26 03:50:35 [debug] 10667#10667: *7 BIO_get_ktls_send(): 1

Theo cách tương tự, hãy chạy lệnh dưới đây để kiểm tra xem SSL_sendfile có ở trong nhật ký không:

sudo grep SSL_sendfile /var/log/nginx/tuan_local_error.log

Sau đó, kết quả sẽ là:

2022/10/26 03:55:35 [debug] 274550#274550: *2 SSL_sendfile: 1048576
2021/11/10 03:56:49 [debug] 274550#274550: *3 SSL_sendfile: 1048576

Kết luận

Bây giờ, bạn vừa hoàn tất quá trình cài đặt Nginx trên Ubuntu 22.04 với một trang web mẫu hỗ trợ HTTP/2 và kTLS. Để tạo nhiều trang hơn, chỉ cần lặp lại bước 4.

Để lại một câu trả lời