Bài viết này thân thiện với người mới vì dữ liệu được trình bày từ đơn giản đến phức tạp. Khi bắt đầu sự nghiệp của mình với tư cách là một kỹ sư DevOps, tôi đã thiếu những vật liệu như vậy. Tôi sẽ cố gắng nói về cách hoạt động của Nginx và một số mẹo và thủ thuật từ kinh nghiệm thực tế.
NGINX được xây dựng trên kiến trúc hướng sự kiện, không chặn. Nó có một quy trình chính, một số worker_processes và hai quy trình quản lý bộ nhớ cache. Để xem điều này, bạn chỉ cần chạy lệnh ps với các công tắc:
ps -ef --forest | grep nginx
Quá trình chính chạy dưới quyền root và thực hiện các hoạt động yêu cầu độ cao, chẳng hạn như:
đọc cấu hình;
mở cổng;
tạo ra các quy trình mới.
Công nhân làm tất cả các công việc:
Thông thường, số lượng nhân công tương đương với số lõi CPU. Điều đó cho phép bạn sử dụng tài nguyên hệ thống một cách hiệu quả nhất có thể.
Worker_processes lắng nghe trên hai loại ổ cắm:
Worker_processes đợi một sự kiện sử dụng hai loại API: epoll hoặc kqueue . Khi nhận được một sự kiện máy khách mới trên socket lắng nghe, worker_process sẽ tạo một kết nối socket mới.
Sau khi nhận được một sự kiện trên ổ cắm kết nối, worker_process thực hiện yêu cầu này. Sau khi xử lý sự kiện, nó không bị chặn mà chuyển sang chế độ chờ và do đó giảm thiểu số lần chuyển đổi ngữ cảnh của hệ điều hành.
Với kiến trúc trên, việc cập nhật cấu hình NGINX đơn giản như việc gửi tín hiệu SIGHUP tới quy trình chính. Với NGINX được định cấu hình đầy đủ, mỗi quy trình công nhân có khả năng xử lý hàng trăm nghìn kết nối cùng một lúc.
Sau đó, worker_processes sẽ ngừng chấp nhận các kết nối mới và các kết nối hiện tại, sau khi xử lý sự kiện, sẽ bị đóng (mà không cần đợi tiếp tục hoạt động). Ngay sau khi tất cả các kết nối được đóng lại, worker_process sẽ kết thúc. Điều đó cho phép bạn cập nhật cấu hình máy chủ mà không làm mất kết nối, tài nguyên nhàn rỗi hoặc làm gián đoạn dịch vụ máy khách.
1. Kiểm tra tính đúng đắn của cấu hình đã viết trước khi áp dụng
Sau khi thay đổi hoặc tạo cấu hình, bạn cần kiểm tra cú pháp và tính đúng đắn của việc ghi tệp cấu hình. Nginx cho phép bạn kiểm tra tính đúng đắn của việc viết cấu hình bằng lệnh sau:
nginx -t
2. Tải lại Nginx mà không cần khởi động lại dịch vụ
Bạn nên áp dụng cài đặt mà không cần khởi động lại dịch vụ. Điều này không chấm dứt các kết nối hiện tại và loại bỏ khoảng thời gian chờ đợi khi tải dịch vụ, tức là không có thời gian chết:
nginx -s reload
hoặc
/etc/init.d/nginx reload
hoặc
service nginx reload
3. Vô hiệu hóa Nginx server_tokens
Theo mặc định, chỉ thị server_tokens trong Nginx hiển thị số phiên bản của Nginx. Nó hiển thị trực tiếp trên tất cả các trang lỗi được tạo tự động và trong tất cả các phản hồi HTTP trong tiêu đề máy chủ.
Điều này có thể dẫn đến tiết lộ thông tin - người dùng trái phép có thể tìm hiểu về phiên bản Nginx của bạn. Sẽ hữu ích nếu bạn tắt lệnh server_tokens
trong tệp cấu hình Nginx bằng cách thiết lập:
server_tokens off;
4. Tắt các giao thức SSL / TLS kế thừa
ssl_protocols TLSv1.2 TLSv1.3;
5. Vô hiệu hóa bất kỳ phương thức HTTP không mong muốn nào
Tắt bất kỳ phương thức HTTP nào sẽ không được sử dụng và không cần triển khai trên máy chủ web.
Nếu bạn thêm điều kiện sau vào khối vị trí của tệp cấu hình máy chủ ảo Nginx, máy chủ sẽ chỉ cho phép các phương thức GET, HEAD
và POST
và sẽ lọc ra các phương thức như DELETE
và TRACE
:
location / { limit_except GET HEAD POST { deny all; } }
Một cách tiếp cận khác là thêm điều kiện sau vào phần máy chủ (hoặc khối máy chủ). Nó có thể được coi là chung chung hơn, nhưng bạn phải cẩn thận với các câu lệnh if trong ngữ cảnh vị trí:
if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; }
6. Thiết lập và cấu hình các bản ghi lỗi và truy cập Nginx
Nhật ký lỗi và truy cập Nginx được bật theo mặc định và nằm trong logs/error.log
và logs/access.log,
tương ứng.
Bạn có thể sử dụng chỉ thị error_log trong tệp cấu hình Nginx nếu bạn muốn thay đổi vị trí. Bạn cũng có thể sử dụng chỉ thị này để chỉ định các bản ghi sẽ được ghi theo mức độ nghiêm trọng của chúng.
Ví dụ: mức độ nghiêm trọng nghiêm trọng sẽ khiến Nginx ghi lại các vấn đề quan trọng và tất cả các vấn đề có mức độ nghiêm trọng cao hơn những vấn đề nghiêm trọng. Để đặt mức độ nghiêm trọng thành nghiêm trọng, hãy đặt chỉ thị error_log như sau:
error_log logs/error.log crit;
Bạn có thể tìm thấy danh sách đầy đủ các mức độ nghiêm trọng của error_log trong tài liệu chính thức của Nginx.
Bạn cũng có thể thay đổi chỉ thị access_log trong tệp cấu hình Nginx để chỉ định vị trí không chuẩn cho nhật ký truy cập.
Cuối cùng, bạn có thể sử dụng chỉ thị log_format để tùy chỉnh định dạng của thư đã ghi, như được mô tả trong tài liệu Nginx.
7. Kết nối nhân viên Nginx
Một cài đặt quan trọng mà chúng tôi định cấu hình là số lượng quy trình công nhân và số lượng kết nối công nhân trong tệp cấu hình Nginx /etc/nginx/nginx.conf
.
Chúng tôi sẽ dần dần điều chỉnh quy trình làm việc và kết nối của nhân viên thành giá trị cao hơn hoặc thấp hơn để xử lý các cuộc tấn công DDoS:
events { worker_connections 20000; }
Cài đặt này cho phép mỗi quy trình công nhân xử lý tối đa 20.000 kết nối.
8. Yêu cầu giới hạn tỷ lệ
Trong số nhiều chiến thuật có giá trị để ngăn chặn các cuộc tấn công DDoS, một trong những cách đơn giản và hiệu quả nhất là hạn chế tỷ lệ lưu lượng truy cập.
Ví dụ: bạn có thể chỉ định tốc độ NGINX chấp nhận các yêu cầu đến với tốc độ trung bình cho dịch vụ của bạn từ một địa chỉ IP máy khách cụ thể trong một khoảng thời gian cụ thể.
Chúng tôi đặt chỉ thị limit_req_zone trong tệp cấu hình Nginx để giới hạn số lượng yêu cầu:
limit_req_zone $binary_remote_addr zone=req_per_ip:1m rate=30r/m; server { location /login { limit_req zone=req_per_ip; } }
Ví dụ này tạo một vùng lưu trữ được đặt tên là vùng có thể chứa tới 16.000 (1 triệu) địa chỉ IP duy nhất và 30r / m có nghĩa là chỉ cho phép 30 yêu cầu mỗi phút.
Sau đó, chúng tôi sử dụng chỉ thị limit_req để giới hạn tốc độ kết nối đến một vị trí hoặc tệp cụ thể, trong trường hợp này, hãy đăng nhập.
9. Giới hạn số lượng kết nối
Bạn có thể giới hạn số lượng kết nối có thể mở từ một địa chỉ IP máy khách và ở đây chúng tôi đang thiết lập các chỉ thị limit_conn_zone và limit_conn
để hạn chế số lượng kết nối trên mỗi địa chỉ IP:
limit_conn_zone $binary_remote_addr zone=conn_per_ip:1m; server { location / { limit_conn conn_per_ip 10; } }
Ví dụ này tạo một vùng lưu trữ có tên conn_per_ip
để lưu trữ các yêu cầu cho khóa được chỉ định, trong trường hợp này là địa chỉ IP của khách hàng, $ binary_remote_addr. Sau đó, chỉ thị limit_conn
đặt mười kết nối từ địa chỉ IP của mỗi máy khách.
10. Tùy chọn thời gian chờ
Kết nối chậm có thể thể hiện nỗ lực giữ kết nối mở trong một thời gian dài. Do đó, máy chủ không thể chấp nhận các kết nối mới:
server { client_body_timeout 5s; client_header_timeout 5s; }
Trong ví dụ này, chỉ thị client_body_timeout
chỉ định thời gian Nginx chờ giữa các mục nhập thân máy khách và client_header_timeout
chỉ định thời gian Nginx chờ giữa các mục nhập tiêu đề máy khách. Cả hai đều được đặt thành 5 giây.
11. Giới hạn kích thước của các yêu cầu
Tương tự, các giá trị bộ đệm lớn hoặc kích thước yêu cầu HTTP lớn làm cho các cuộc tấn công DDoS dễ dàng hơn. Vì vậy, chúng tôi giới hạn các giá trị đệm sau trong tệp cấu hình Nginx để giảm thiểu các cuộc tấn công DDoS:
client_body_buffer_size 200K; client_header_buffer_size 2k; client_max_body_size 200k; large_client_header_buffers 3 1k;
Ở đâu,
client_body_buffer_size 1k
- (mặc định 8k hoặc 16k) Chỉ thị chỉ định kích thước của bộ đệm thân yêu cầu máy khách;
client_header_buffer_size 1k
- chỉ thị đặt kích thước bộ đệm tiêu đề cho tiêu đề yêu cầu từ máy khách. Kích thước bộ đệm 1Kb là đủ cho phần lớn các yêu cầu.
Tăng giá trị này nếu bạn có một tiêu đề tùy chỉnh hoặc một cookie khổng lồ được gửi bởi một khách hàng (như một ứng dụng khách wap);
client_max_body_size 1k
- chỉ thị đặt kích thước tối đa cho phép của nội dung yêu cầu ứng dụng khách, được chỉ định bởi dòng Nội dung-Độ dài trong tiêu đề yêu cầu.
Nếu kích thước lớn hơn kích thước được chỉ định, máy khách sẽ nhận được lỗi "Đối tượng Yêu cầu Quá lớn" (413). Tăng giá trị này khi bạn tải tệp lên bằng phương pháp POST;
large_client_header_buffers 2 1k
- chỉ thị chỉ định số lượng và kích thước bộ đệm tối đa để đọc các tiêu đề lớn từ một yêu cầu của khách hàng.
Theo mặc định, kích thước của một vùng đệm bằng với kích thước trang tùy thuộc vào nền tảng, nó là 4K hoặc 8K.
Nếu kết nối chuyển sang trạng thái duy trì ở cuối yêu cầu làm việc, thì các bộ đệm này sẽ được giải phóng.
Ví dụ: 2x1k sẽ chấp nhận URI dữ liệu 2 KB. Nó cũng sẽ giúp chống lại các bot xấu và các cuộc tấn công DoS.
12. Danh sách đen IP
Nếu bạn có thể xác định các địa chỉ IP máy khách được sử dụng cho cuộc tấn công, bạn có thể đưa chúng vào danh sách đen với lệnh từ chối để NGINX và NGINX Plus không chấp nhận các kết nối hoặc yêu cầu của chúng:
location / { deny 111.111.111.4; deny 111.111.111.0/24; }
Trong ví dụ này, từ chối đầu tiên chặn một địa chỉ IP cụ thể và từ chối thứ hai chặn toàn bộ dải địa chỉ IP.
13. Danh sách trắng IP
Nếu trang web hoặc ứng dụng của bạn chỉ được phép truy cập từ một hoặc nhiều tập hợp hoặc dải địa chỉ IP máy khách cụ thể, bạn có thể sử dụng đồng thời các lệnh cho phép và từ chối để chỉ cho phép các địa chỉ đó truy cập vào trang web hoặc ứng dụng:
location / { allow 111.111.111.4; deny all; }
Bạn có thể hạn chế quyền truy cập chỉ vào các địa chỉ trên một mạng cục bộ cụ thể. Ở đây, lệnh từ chối tất cả chặn tất cả các địa chỉ IP máy khách không nằm trong phạm vi được chỉ định bởi chỉ thị allow.
14. Chặn quyền truy cập vào một tệp hoặc vị trí
Bạn có thể sử dụng Nginx để chặn hoàn toàn quyền truy cập vào một tệp hoặc vị trí. Ví dụ: nếu bạn nhận thấy rằng tệp register.php là mục tiêu của một cuộc tấn công, bạn hoàn toàn có thể chặn quyền truy cập vào tệp này:
location /register { deny all; return 444; }
Điều đó sẽ loại bỏ tất cả các yêu cầu cố gắng truy cập tệp này. Mã 444 đóng kết nối mà không có phản hồi.
15. Kích hoạt tính năng bảo vệ dựa trên sysctl
Bật tính năng bảo vệ dựa trên sysctl. Chúng tôi có thể điều chỉnh hạt nhân và các biến hệ thống trên máy chủ của mình. Chỉnh sửa tệp /etc/sysctl.conf
và đặt hai dòng này thành 1 như sau:
net.ipv4.conf.all.rp_filter = 1 net.ipv4.tcp_syncookies = 1
Cài đặt đầu tiên cho phép bảo vệ chống giả mạo địa chỉ IP và cài đặt thứ hai cho phép bảo vệ cookie TCP SYN.
16. Nginx như một bộ cân bằng tải
Khi Nginx được sử dụng làm bộ cân bằng tải, các cài đặt có thể được định cấu hình để giới hạn số lượng kết nối trên mỗi máy chủ:
upstream domain { server 111.111.111.4:80 max_conns=100; server 111.111.111.5:80 max_conns=100; queue 20 timeout=10s; }
Ở đây, chỉ thị max_conns chỉ định số lượng kết nối mà Nginx có thể mở tới máy chủ. Chỉ thị hàng đợi giới hạn số lượng yêu cầu được xếp hàng đợi khi tất cả các máy chủ trong nhóm đó đã đạt đến giới hạn kết nối.
Cuối cùng, chỉ thị thời gian chờ chỉ định thời gian một yêu cầu có thể được giữ trong hàng đợi.
17. Từ chối một số tác nhân người dùng
Bạn có thể dễ dàng chặn các tác nhân người dùng, tức là trình thu thập thông tin, bot và người gửi thư rác có thể đang lạm dụng máy chủ của bạn:
## Block download agents ## if ($http_user_agent ~* LWP::Simple|BBBike|wget) { return 403; }
## Block some robots ## if ($http_user_agent ~* msnbot|scrapbot|PxBroker) { return 403; }
18. Chặn thư rác giới thiệu
Thư rác giới thiệu là nguy hiểm. Điều đó có thể ảnh hưởng đến xếp hạng SEO của bạn thông qua các nhật ký web (nếu được xuất bản) vì trường liên kết giới thiệu liên kết đến trang web spam của họ. Với những dòng này, bạn có thể chặn quyền truy cập vào những người gửi spam liên kết giới thiệu:
if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) ) { return 403; }
19. Ngừng liên kết nóng hình ảnh
Liên kết nóng hình ảnh hoặc HTML có nghĩa là ai đó liên kết trang web của bạn với một trong những hình ảnh của bạn nhưng hiển thị nó trên trang web của họ.
Bạn sẽ phải trả tiền cho băng thông và làm cho nội dung giống như một phần của trang web. Điều này thường được thực hiện trên các diễn đàn và blog. Tôi thực sự khuyên bạn nên chặn và ngừng liên kết nóng hình ảnh ở cùng cấp độ máy chủ của bạn:
location /images/ { valid_referers none blocked www.domain.com domain.com; if ($invalid_referer) { return 403; } }
20. Giới hạn số lượng kết nối trên mỗi địa chỉ IP ở cấp tường lửa
Máy chủ web phải giám sát các kết nối và giới hạn số lượng kết nối mỗi giây. Điều này phục vụ 101. Cả pf và iptables đều có thể chặn người dùng cuối trước khi truy cập máy chủ Nginx của bạn.
Linux Iptables: Điều chỉnh kết nối Nginx mỗi giây.
Trong ví dụ sau, các kết nối đến sẽ bị ngắt nếu IP thực hiện hơn 15 lần thử kết nối trên cổng 80 trong vòng 60 giây:
/sbin/iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --set && \ /sbin/iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --update --seconds 60 --hitcount 15 -j DROP && \ service iptables save
21. Tắt tính năng dò tìm kiểu nội dung trong một số trình duyệt
Nếu một phản hồi chỉ định loại nội dung không chính xác, thì các trình duyệt có thể xử lý phản hồi theo những cách không mong muốn.
Nếu loại nội dung được xác định là định dạng dựa trên văn bản có thể kết xuất lại, thì trình duyệt thường sẽ cố gắng diễn giải phản hồi ở định dạng đó, bất kể nội dung thực tế của phản hồi là gì.
Ngoài ra, một số loại nội dung được chỉ định khác đôi khi có thể được hiểu là HTML do các lỗi trong các trình duyệt cụ thể. Điều này có thể dẫn đến nội dung “an toàn”, chẳng hạn như hình ảnh được hiển thị dưới dạng HTML, kích hoạt các cuộc tấn công tập lệnh trên nhiều trang web trong một số điều kiện nhất định. Thêm phần sau vào cấu hình của bạn:
add_header X-Content-Type-Options nosniff;
22. Bật bộ lọc tập lệnh trên nhiều trang web (XSS)
Thêm dòng sau vào tệp cấu hình của bạn để bật tiêu đề X-XSS-Protection trên máy chủ web Nginx của bạn. Khi bạn hoàn tất, hãy lưu các thay đổi của bạn và tải lại Nginx:
add_header X-XSS-Protection "1; mode=block";
23. Định cấu hình hỗ trợ HTTP / 2
HTTP / 2 là sự kế thừa của giao thức mạng HTTP 1.x. HTTP / 2 được sử dụng rộng rãi để giảm độ trễ, giảm thiểu chi phí giao thức, thêm hỗ trợ ưu tiên yêu cầu và tăng tốc độ tải ứng dụng web.
Do đó, điều quan trọng là phải luôn cập nhật các chiến lược và kỹ thuật tối ưu hóa hiệu suất. Trọng tâm chính của HTTP / 2 là giảm thời gian tải tổng thể của một trang web, giúp tối ưu hóa hiệu suất.
Nó cũng tập trung vào việc sử dụng tài nguyên mạng và máy chủ, cũng như tăng cường bảo mật, vì mã hóa SSL / TLS là bắt buộc khi sử dụng HTTP / 2.
Điều kiện tiên quyết là đảm bảo phiên bản Nginx 1.9.5 trở lên khi nó được tạo, nếu không, bạn sẽ phải thêm nó theo cách thủ công và máy chủ phải bật SSL / TLS. Khối máy chủ HTTPS của bạn bây giờ sẽ trông giống như sau:
server { listen 443 ssl http2; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; }
24. Thêm Nội dung-Bảo mật-Chính sách (CSP)
CSP là một lớp bảo mật bổ sung giúp phát hiện và giảm thiểu một số loại tấn công nhất định, bao gồm cả các cuộc tấn công tạo kịch bản qua trang web (XSS) và các cuộc tấn công đưa vào dữ liệu. Các cuộc tấn công này được sử dụng để đánh cắp dữ liệu, hỏng trang web và phát tán phần mềm độc hại:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
25. Giám sát Nginx
Trạng thái của máy chủ của bạn phải được theo dõi liên tục. Bạn có thể xem những gì máy chủ trả về bằng cách gửi yêu cầu định kỳ đến nó, ví dụ: thông qua các dịch vụ trả phí của bên thứ ba. Hoặc bạn có thể tinh chỉnh mọi thứ và có nhiều cách để làm điều đó — thông tin thêm về nó trong blog Nginx .
Thay vào đó là kết luận
Điều cần thiết là phải linh hoạt và phát triển cấu hình cho từng trường hợp riêng biệt.