Hướng dẫn tối ưu Linux kernel

Kernel của Linux có rất nhiều những thông số cho phép người dùng tùy chỉnh nhằm tối ưu hiệu năng của hệ thống và ứng dụng. Tùy vào nhu cầu thực tế mà người quản trị có thể tối ưu các tham số này khác nhau.

Để tương tác với các tham số của kernel, ta sử dụng chương trình sysctl (system control) để tương tác với kernel, cho phép thay đổi thông số của kernel trong lúc hệ thống đang chạy mà không bị gián đoạn.

Bạn nào lười đọc chữ thì có thể tham khảo cheat-sheet này^^: GitHub

Tunning Kernel

Để hiển thị toàn bộ các tham số hiện có của kernel, ta dùng lệnh:

huong-dan-toi-uu-linux-kernel-(1)

Có khoảng hơn…900 biến dùng để cấu hình cho kernel

Nhưng trước khi đi sâu vào tùy chỉnh các biến này, ta cần phải nắm sơ lược về /proc filesystem.

proc filesystem

Một số filesystem như /proc được gọi là pseudo filesystem (file system giả) bởi vì filesystem này không tồn tại trên ổ cứng. Filesystem /proc chỉ chứa các file ảo (tồn tại trên bộ nhớ RAM), cho phép người dùng đọc được thông tin hệ thống theo thời gian thực (bộ nhớ RAM, thông tin CPU, các thiết bị được gắn lên, cấu hình phần cứng).

Danh sách các file, thư mục trong /proc

Một số file quan trọng trên /proc là:

  • /proc/cpuinfo
  • /proc/sys
  • /proc/interrupts
  • /proc/meminfo
  • /proc/mounts
  • /proc/partitions
  • /proc/version
  • /proc/<Process-ID>

Ở đây, ta sẽ tập trung vào cấu trúc của thư mục /proc/sys, đây là thư mục chứa hầu như toàn bộ thông tin cấu hình của các thiết bị được kết nối tới máy tính, driver các thiết bị, cấu hình file system… Trong thư mục này gồm có những thư mục con như sau:

  • abi/: application binary interface
  • dev/: chứa thông số cấu hình các thiết bị được kết nối tới máy tính
  • fs/: chứa thông số cấu hình filesystem như (như cấu hình disk quotas hoặc inodes…).
  • kernel/: chứa các cấu hình của kernel.
  • net/: chứa các thông số cấu hình mạng.
  • vm/: chứa các thông số cấu hình vm (virtual memory).
  • user/: chứa các thông số về giới hạn namespace của từng user.

Thay đổi các thông số của kernel

Để thay đổi các thông số của kernel, ta có thể trực tiếp thay đổi thông số của các file trong /proc/sys

Ví dụ: muốn thay đổi thông số net.ipv4.ip_forward, ta sẽ thay đổi giá trị của file /proc/sys/net/ipv4/ip_forward như sau:

Thay đổi trực tiếp giá trị của các file cấu hình

Hoặc ta có thể thay đổi các thông số này qua lệnh sysctl với cờ -w

Thay đổi thông số của kernel thông qua lệnh sysctl

Tuy nhiên, khi dùng lệnh sysctl –w thì thay đổi chỉ có giá trị trong session đó, nếu hệ thống khởi động lại thì giá trị đó sẽ trở về mặc định, không được lưu lại. Để lưu lại giá trị cấu hình kernel, ta cần thay đổi file /etc/sysctl.conf và nạp lại cấu hình bằng lệnh sysctl –p

Một số thông số của kernel cần lưu ý

Có rất nhiều thông số của kernel để tinh chỉnh, nhưng tựu chung lại gồm 1 số nhóm thông số chính sau trong file /etc/sysctl.conf. Lưu ý: có những thông số cần phải có một module nào đó của kernel mới hoạt động được.

Network – Improving Performance

Những thông số dưới đây nhằm tối ưu kết nối mạng trên các hệ điều hành Linux

Tên thông số Ý nghĩa
Congestion Control
net.ipv4.tcp_congestion_control = htcp Dùng thuật toán H-TCP để kiểm soát tắt nghẽn với những kết nối mạng có bandwidth lớn, độ trễ thấp.

Dùng lệnh “modprobe tcp_htcp” trước

net.ipv4.tcp_timestamps = 1 Bật TCP timestamp, timestamp chuẩn giúp các thuật toán congestion control hoạt động tốt hơn.

Tuy nhiên, tính năng khởi tạo timestamp cũng làm tốn 1 phần tài nguyên hệ thống (timestamp tốn thêm 10 byte cho mỗi gói tin).

net.ipv4.tcp_window_scaling = 1 Bật chế độ windows scaling (mặc định là 1)
net.ipv4.tcp_sack = 1 Bật chế độ TCP SACK (Selective ACK). Cho phép client chỉ cần gởi lại những gói tin bị mất trên đường truyền, không cần gởi lại toàn bộ.
Tuy nhiên, trong một số trường hợp TCP SACK có thể gây tiêu tốn nhiều tài nguyên CPU, RAM, giảm tốc độ truyền tải.
Điều chỉnh buffer của các socket
net.ipv4.tcp_rmem = 8192 87380 16777216 Tăng buffer nhận (min – default – max) của socket TCP. Tối ưu tốc độ chuyển file có dung lượng lớn qua các kết nối WAN.
net.ipv4.udp_rmem_min = 16384 Kích thước buffer tối thiểu của các socket UDP nhận (tính theo bytes).
net.core.rmem_default = 262144 Kích thước buffer mặc định của toàn bộ các socket nhận (nếu ta có cấu hình tcp_rmem hoặc udp_rmem thì hệ thống sẽ ưu tiên 2 giá trị này hơn).
net.core.rmem_max = 16777216 Kích thước buffer tối đa của toàn bộ các socket nhận
net.ipv4.tcp_wmem = 8192 65536 16777216 Tăng buffer gởi (min – default – max) của socket TCP. Tối ưu tốc độ chuyển file có dung lượng lớn qua các kết nối WAN.
net.ipv4.udp_wmem_min = 16384 Kích thước buffer tối thiểu của các socket UDP gởi (tính theo bytes).
net.core.wmem_default = 262144 Kích thước buffer mặc định của toàn bộ các socket gởi (nếu ta có cấu hình tcp_wmem hoặc udp_wmem thì hệ thống sẽ ưu tiên 2 giá trị này hơn).
net.core.wmem_max = 16777216 Kích thước buffer tối đa của toàn bộ các socket gởi.
Tăng số lượng kết nối (hàng đợi)
net.core.somaxconn = 16384 Giới hạn số kết nối tối đa nằm trong hàng đợi của các socket.

Chỉ tăng tham số này lên khi lượng kết nối mới tới server tăng thường xuyên.

Tăng số lượng gói tin xử lý
net.core.netdev_max_backlog = 16384 Số lượng gói tin tối đa nằm trong hàng đợi của card mạng.
net.core.dev_weight = 64 Số lượng gói tin tối đa mà mỗi CPU có thể xử lý được trong 1 interrupt.
Connection Tracking
net.nf_conntrack_max = 100000

Hoặc

net.netfilter.nf_conntrack_max = 100000
(Thay đổi 1 trong 2 biến này, biến kia sẽ thay đổi theo)

Biến này quyết định số lượng kết nối đồng thời tới máy chủ. Mỗi một kết nối sẽ được ghi lại trong 1 bảng gọi là connection tracking table, mặc định thì bảng này có thể ghi lại được 65536 kết nối.

Đối với những máy chủ có số lượt truy cập cao thì bản danh sách này sẽ bị đầy và các gói tin mới đến sẽ bị drop.

Để khắc phục lỗi này, ta cần phải tăng kích thước của bảng này lên.

net.netfilter.nf_conntrack_tcp_timeout_established = 600 Giảm thời gian time out của 1 connection trong tracking table (mặc định là 432000s = 5 ngày)

Network – Improving Security

Thay đổi các thông số dưới đây nhằm tăng cường tính bảo mật về kết nối cho máy chủ, giảm thiểu và ngăn chặn một số loại tấn công cơ bản, tiết kiệm được tài nguyên hệ thống. Tham khảo: link

Tên thông số Ý nghĩa
Chặn SYN Attack bằng kỹ thuật SYNcookies
net.ipv4.tcp_syncookies = 1
(mặc định đã được bật sẵn)
Bật tính năng SYN Cookies để phòng chống SYN Flood Attack.

Tính năng này sẽ được kích hoạt khi số gói tin SYN vượt quá giá trị max_syn_backlog.

Không nên bật tính năng này nếu server thật sự nhận được nhiều gói tin SYN từ người dùng.

net.ipv4.tcp_max_syn_backlog = 4096 Tăng hàng đợi các gói tin ACK từ người dùng (mặc định là 128).
net.ipv4.tcp_syn_retries = 2 Số lần gởi lại gói tin SYN cho 1 connection.
net.ipv4.tcp_synack_retries = 2 Số lần gởi lại gói tin SYN-ACK cho 1 connection.
Tắt tính năng packet forwarding
net.ipv4.ip_forward = 0 Forward packet giữa các interface, chỉ nên bật tính năng này khi server nhận vai trò router
net.ipv4.conf.all.forwarding = 0 Tắt tính năng forwarding trên toàn bộ các interface hiện có.
net.ipv4.conf.default.forwarding = 0 Mặc định là tắt tính năng forwarding trên các interface được gắn thêm sau này.
net.ipv6.conf.all.forwarding = 0 Tương tự như với 2 cấu hình cho IPv4 ở trên
net.ipv6.conf.default.forwarding = 0
Tắt tính năng IP Source Routing
net.ipv4.conf.all.accept_source_route = 0 Tính năng source routing có thể bị người dùng lợi dụng cho mục đích xấu, nên tắt tính năng này để ép gói tin tuân theo bảng định tuyến chuẩn trên các thiết bị.

Tắt tính năng source routing trên toàn bộ các card mạng hiện tại.

net.ipv4.conf.default.accept_source_route = 0 Mặc định tắt tính năng source routing cho các card mạng được gắn thêm sau này.
net.ipv6.conf.all.accept_source_route = 0 Tắt source routing cho IPv6.
net.ipv6.conf.default.accept_source_route = 0 Tắt source routing cho IPv6.
Block các gói tin ICMP redirect để chặn kiểu tấn công Man-in-the-Middle
net.ipv4.conf.all.accept_redirects = 0 Các gói tin ICMP redirect thường được các router gởi đi để thông báo cho server biết rằng có một đường đi khác tốt hơn tới đường đi hiện tại mà server đang chọn.

Kẻ xấu có thể lợi dụng tính năng này để thay đổi bản định tuyến của server, ta nên chặn các gói tin này để đảm bảo an tòa cho hệ thống.

Không chấp nhận các gói tin ICMP redirect trên các card mạng.

net.ipv4.conf.default.accept_redirects = 0 Mặc định không chấp nhận các gói tin ICMP redirect trên các card mạng gắn thêm sau này.
net.ipv4.conf.all.send_redirects = 0 Không gởi các gói tin ICMP redirect trên toàn bộ card mạng (có thể bật tính năng này nếu server nhận vai trò là router)
net.ipv4.conf.default.send_redirects = 0 Mặc định không cho phép các card mạng gắn thêm sau này được gởi gói tin ICMP redirect.
Phòng chống IP spoofing
net.ipv4.conf.all.rp_filter = 1 IP spoofing là kỹ thuật giả mạo source IP của gói tin, thường được dùng trong những cuộc tấn công từ chối dịch vụ.

Bật tính năng xác thực địa chỉ IP source của gói tin (Source Address Verification) trên toàn bộ các card mạng.

Tính năng này sử dụng cơ chế reverse path filtering, nếu gói tin nhận được có thể được định tuyến ngược lại qua interface vừa nhận, hệ thống sẽ chấp nhận gói tin này, nếu không thì gói tin này sẽ bị drop.

net.ipv4.conf.default.rp_filter = 1 Mặc định là bật tính năng xác thực địa chỉ IP source của gói tin trên các card mạng được gắn thêm sau này.
Ghi lại log của các gói tin spoof IP, source routing, redirect
net.ipv4.conf.all.log_martians = 1 Ghi lại log các gói tin lạ trên toàn bộ card mạng.
net.ipv4.conf.default.log_martians = 1 Mặc định ghi lại log các gói tin lạ trên các card mạng được gắn thêm sau này.
Giảm thời gian chờ mặc định của trạng thái tcp_fin_timeout
net.ipv4.tcp_fin_timeout = 5 Giảm thời gian chờ ở trạng thái FIN-WAIT-2. Mặc định là 60s.
Giảm thời gian chờ của cơ chế keep alive
net.ipv4.tcp_keepalive_time = 300 TCP keep alive là cơ chế xác định các TCP connection còn hoạt động hay không.

Giá trị này mặc định là 7200s (2 giờ), nếu connection không có bất cứ hoạt động nào thì socket sẽ chờ trong thời gian tcp_keepalive_time trước khi gởi đi lần lượt gởi đi 5 gói tin giữ kết nối, mỗi gói tin cách nhau 15s.

Tổng cộng lại, ứng dụng sẽ biết được một kết nối TCP có còn hoạt động hay không sau 375s (300s + 15s + 15s + 15s + 15s + 15s)

net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
Cấu hình ICMP
net.ipv4.icmp_echo_ignore_all = 1 Không nhận các gói tin ICMP ping. Tùy vào nhu cầu cụ thể mà ta nên bật/tắt tùy chọn này.
net.ipv4.icmp_echo_ignore_broadcasts = 1 Không trả lời các gói tin ICMP broadcast/multicast để phòng tránh Smurf Attack
net.ipv4.icmp_ignore_bogus_error_responses = 1 Không ghi log các gói tin ICMP bị lỗi/sai cú pháp
Một số cấu hình khác
net.ipv4.conf.all.proxy_arp = 0 Tắt tính năng Proxy ARP
net.ipv4.ip_local_port_range = 16384 65535 Xác định dãy port local để server dùng khi cần khởi tạo thật nhiều nhiều kết nối ra ngoài.
net.ipv4.tcp_rfc1337 = 1 Sửa lỗi “Time-Wait Assassination” của TCP theo RFC1337

Filesystem Tuning

Tối ưu các thông số về filesystem, thường được dùng cho các hệ thống web server, database, log server…

Tên thông số Ý nghĩa
fs.file-max = 300000 Tăng số lượng file handler, cần thiết cho những hệ thống sử dụng nhiều file như web server, database, log…

Memory Tuning

Các thông số dưới đây dùng để tối ưu bộ nhớ (virtual memory) của hệ thống

Tên thông số Ý nghĩa
vm.swappiness = 10 Cho kernel biết khi nào thì nên dùng swap memory. Giá trị càng cao thì hệ thống sẽ thường xuyên dùng bộ nhớ swap.

VD: Giá trị 10 có nghĩa là nếu dung lượng ram trống còn dưới 10%, hệ thống sẽ chuyển sang dùng swap memory.

vm.dirty_background_ratio = 5 Thông số này là số phần trăm bộ nhớ RAM dùng để chứa dirty page (những trang nhớ được cache lại trước khi ghi xuống đĩa cứng vật lý).

Khi số dirty page vượt quá giá trị này, các tiến trình chạy ngầm như pdflush/flush/kdmflush sẽ bắt đầu ghi các giá trị cache này xuống đĩa cứng.

Giá trị ở đây là 5 có nghĩa là 5% tổng số RAM của hệ thống, nếu hệ thống có 8GB RAM thì sẽ có 5% * 8GB tức là 400MB RAM chứa dirty page trước khi các tiến trình chạy ngầm ghi bớt dữ liệu xuống ổ đĩa.

vm.dirty_ratio = 10 Phần trăm bộ nhớ RAM tối đa để chứa các dirty page trước khi ghi toàn bộ các dữ liệu này xuống đĩa cứng.

Khi lượng dữ liệu đạt mức này, toàn bộ các thao tác I/O mới sẽ tạm thời bị block cho tới khi toàn bộ các dirty page được các process lưu lại an toàn dưới ổ cứng.

vm.overcommit_memory = 0 Ta có thể đặt 3 giá trị cho tham số này:

  • Với cờ là 0, mỗi khi ứng dụng yêu cầu thêm bộ nhớ, kernel sẽ ước tính lượng bộ nhớ trống còn lại trước khi cấp phát.
  • Với cờ là 1, kernel sẽ luôn cấp phát thêm bộ nhớ khi ứng dụng yêu cầu.
  • Với cờ là 2, kernel sẽ không bao giờ overcommit bộ nhớ.

Trong nhiều trường hợp, tính năng này sẽ rất hữu dụng vì sẽ có nhiều ứng dụng yêu cầu cấp lượng bộ nhớ nhiều hơn cần thiết.

vm.overcommit_ratio = 50 Nếu cờ của vm.overcommit_memory là 2 thì tổng bộ nhớ mà kernel được cấp phát cho các ứng dụng là: Swap Space + vm.overcommit_ratio * RAM Memory

Kernel Hardening

Mục này chứa các thông số cấu hình kernel nhằm ngăn chặn khai thác các lỗi về buffer, stack, heap…và tối ưu một số thông số trong kernel.

Tên thông số Ý nghĩa
kernel.exec-shield = 1 Bật tính năng Exec Shield để phòng chống mã độc khai thác lỗi về buffer, stack, heap…

Trong phiên bản CentOS7/RHEL7, tính năng này đã được bật tự động, không thể cấu hình lại.

kernel.randomize_va_space = 2 Bật tính năng Address space randomization để ngăn ngừa nhiều loại tấn công của mã độc.
kernel.pid_max = 4194303 Tăng giới hạn process cho toàn hệ thống.

IPv6

Tắt tính năng tự động cấu hình IPv6 trên các card mạng.

Tên thông số Ý nghĩa
net.ipv6.conf.all.autoconf=0 Không tự động cấu hình IPv6 trên các card mạng.
net.ipv6.conf.all.accept_ra=0
net.ipv6.conf.default.autoconf=0
net.ipv6.conf.default.accept_ra=0

Tham khảo

https://en.wikipedia.org/wiki/Sysctl

https://www.tecmint.com/change-modify-linux-kernel-runtime-parameters/

https://klaver.it/linux/sysctl.conf

https://wiki.archlinux.org/index.php/Sysctl

https://www.kernel.org/doc/Documentation/sysctl/

Leave a Reply

Your email address will not be published. Required fields are marked *