跳至內容
出自 Arch Linux 中文维基

sysctl是一種用於在運行時檢查和更改內核參數的工具。sysctl在procfs中實現,procfs 是位於/proc/的虛擬進程文件系統。

安裝

procps-ng 包應該已經安裝了,因為它是 base 元包的依賴項。

配置

sysctl預加載/配置文件可以在 /etc/sysctl.d/99-sysctl.conf 中創建。對於 systemd/etc/sysctl.d//usr/lib/sysctl.d/ 是內核 sysctl 參數的配置目錄。命名和源目錄決定了處理的順序,這很重要,因為處理的最後一個參數可能會覆蓋前面的參數。例如,/usr/lib/sysctl.d/50-default.conf 中的參數將被 /etc/sysctl.d/50-default.conf 中的相同參數以及之後從這兩個目錄處理的任何配置文件覆蓋。

要手動加載所有配置文件,可以執行:

# sysctl --system 

這也將輸出應用的層次結構。單個參數文件也可以顯式加載:

# sysctl --load=filename.conf

有關詳細信息,請參閱新的配置文件新的配置文件,更具體地說是 sysctl.d(5)

可用參數列在 /proc/sys/ 下。 例如,kernel.sysrq 參數指的是文件系統上的文件 /proc/sys/kernel/sysrqsysctl --all 命令可用於顯示所有當前可用的值。

注意:如果您安裝了內核文檔 (linux-docs),您可以在 /usr/lib/modules/$(uname -r)/build/Documentation/admin-guide/sysctl/ 中找到有關 sysctl 設置的詳細信息。在線版本由本文的#參閱部分引用。強烈建議在更改 sysctl 設置之前閱讀這些內容。

也可以通過文件操作或使用 sysctl(8) 實用程序更改設置。例如,臨時啟用萬能SysRq鍵

# sysctl kernel.sysrq=1

或者:

# echo "1" > /proc/sys/kernel/sysrq 

有關 kernel.sysrq 的詳細信息,請參閱 Linux 內核文檔

要在重新啟動之間保留更改,在/etc/sysctl.d/99-sysctl.conf 以及/etc/sysctl.d/ 中的配置文件中Help:Reading#添加、創建、編輯文件或修改對應的行。

提示:一些參數是否生效可能取決於內核模塊,而這些內核模塊又可能不會被加載。 例如 /proc/sys/net/bridge/* 中的參數依賴於 br_netfilter 模塊。如果br_netfilter沒有在運行時(或重啟後)加載,那麼這些參數將安靜的不生效。參見內核模塊

安全

參閱安全#內核加固,以及本文的其餘部分。

網絡

性能優化

增加接收隊列的大小

進入系統的網絡數據幀在從網卡上的環形緩衝區中取出後,會存放在這個隊列中。

在使用高速網卡時增加系統的這個設定值可能有助於防止數據包丟失:

net.core.netdev_max_backlog = 16384
注意:在 SIP 路由器等實時應用中,此選項需要高速 CPU,否則隊列中的數據將過時。

增加最大連接數

可以更改設置內核接受的連接數上限(默認 4096):

net.core.somaxconn = 8192
警告:增加此值可能只會提高高負載伺服器的性能,並可能導致處理速度變慢(例如單線程阻塞伺服器)或工作線程/進程數量不足。[1].

增加專用於網絡接口的內存

這篇文章的某些內容需要擴充。

原因:需要解釋清楚每個選項的單位是什麼(字節、千字節或是內存頁?) (在 Talk:Sysctl 中討論)

本文或本章節的事實準確性存在爭議。

原因: 本節似乎受到 Cloudflare 博客文章的啟發,但 Red Hat's tuned profile 建議使用更小的值,並聲稱「這似乎只在 40Gb 速度下才有必要」。 因此,這些設置似乎對消費級硬體不實用。(在 Talk:Sysctl 中討論)


默認情況下,Linux 網絡堆棧未配置為通過 WAN 連結進行高速大文件傳輸(即處理更多網絡數據包),設置正確的值可以節省內存資源:

net.core.rmem_default = 1048576
net.core.rmem_max = 16777216
net.core.wmem_default = 1048576
net.core.wmem_max = 16777216
net.core.optmem_max = 65536
net.ipv4.tcp_rmem = 4096 1048576 2097152
net.ipv4.tcp_wmem = 4096 65536 16777216

也可以增加默認的 4096 UDP 限制:

net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192

有關詳細信息和推薦值,請參閱以下來源:

啟用 TCP Fast Open

這篇文章的某些內容需要擴充。

原因:提及默認情況下使所有偵聽器支持快速打開而無需手動顯式設置 TCP_FASTOPEN sockect 選項,即值 1027 (0x1+0x2+0x400)。 (在 Talk:Sysctl#TCP Fast Open 中討論)

TCP Fast Open 是傳輸控制協議 (TCP) 的擴展,它通過在發送方的初始 TCP SYN [2] 時使用值 3 而不是默認值 1 允許傳入和傳出連接的 TCP 快速打開:

net.ipv4.tcp_fastopen = 3

調整掛起的連接處理

tcp_max_syn_backlog 是掛起連接等待確認的最大隊列長度。

在碰到 synflood DOS 攻擊的情況下,這個隊列會很快填滿,此時 TCP SYN cookies 將開始允許您的系統繼續響應合法流量,並允許您獲得阻止惡意 IP 的權限。

如果伺服器在尖峰時間系統網絡過載,您可能需要稍微增加此值:

net.ipv4.tcp_max_syn_backlog = 8192

tcp_max_tw_buckets 表示系統內允許處於 TIME_WAIT 狀態的最大sockect連接數。

達到此數字後,系統將開始銷毀處於此狀態的 socket 連接。

增加該值可以防止簡單的 DOS 攻擊:

net.ipv4.tcp_max_tw_buckets = 2000000

tcp_tw_reuse 設置當新時間戳嚴格大於上一個連接記錄的最新時間戳時,TCP 是否應該為新的傳出連接重用 TIME-WAIT 狀態下的現有連接。

默認值為 2,表示僅對迴環連接啟用。您可以將其設置為 1 以對所有連接啟用,這有助於避免用完可用的網絡 sockets:

net.ipv4.tcp_tw_reuse = 1

指定在強制關閉 socket 之前需要等待的最終 FIN 數據包時間(秒數)。這完全違反了 TCP 規範,但防止拒絕服務攻擊需要這個。在 Linux 2.2 中,默認值為 180 [3]

net.ipv4.tcp_fin_timeout = 10

tcp_slow_start_after_idle 設置 TCP 是否應僅對新連接或空閒時間過長的現有連接開啟'以默認窗口大小啟動連接'。

此設置會破壞持久的單連接性能,可以將其關閉:

net.ipv4.tcp_slow_start_after_idle = 0

更改 TCP 保活參數

TCP 保活是一種 TCP 連接機制,有助於確定另一端是否已停止響應。TCP會在一段時間的空閒時間後,多次向網絡對端發送包含空數據的保活探測。如果對端沒有響應,socket 將自動關閉。默認情況下,TCP 保活進程在發送第一個保活探測之前等待 socket 活動兩個小時(7200 秒),然後每75秒重新發送一次。只要有 TCP/IP socket 通信在進行並處於活動狀態,就不需要保活數據包。

注意:使用以下設置,您的應用程式將在120秒後才檢測失效 TCP 連接 (60s + 10s + 10s + 10s + 10s + 10s + 10s)。
net.ipv4.tcp_keepalive_time = 60
net.ipv4.tcp_keepalive_intvl = 10
net.ipv4.tcp_keepalive_probes = 6

啟用 MTU 探測

最大傳輸單元 (MTU) 越長,性能越好,但可靠性越差。

這是因為MTU設置大了一旦發生數據包丟失就意味著需要重新傳輸的數據更多,而且網際網路上的許多路由器並不能傳送非常長的數據包:

net.ipv4.tcp_mtu_probing = 1

更多信息,可以參閱這篇文章

TCP 時間戳

警告:TCP 時間戳可以防止 TCP 實現中的(以Gbps速度傳輸的)序號迴繞(sequence numbers wrap-around)問題和時間的重複計算問題,參考 RFC 1323。不建議關閉 TCP 時間戳,因為它可能會導致安全風險[4]

禁用時間戳生成可以減少低性能尖峰的發生並可能提高千兆網絡的性能:

net.ipv4.tcp_timestamps = 0

也可以參考這篇文章了解關於 TCP 時間戳的信息。

TCP 選擇性確認

TCP 選擇性確認 (TCP SACK),由布爾值 tcp_sack 控制,允許接收方向發送方提供有關丟失段的更多詳細信息,從而減少重傳量。這在延遲較高的網絡上非常有用,但在高速區域網上禁用此功能可以提高吞吐量。如果您不發送 SACK,也請禁用 tcp_dsack,因為您肯定不希望發送重複數據!前向確認在 SACK 之上工作,如果 SACK 被禁用,它也將被禁用。[5]

net.ipv4.tcp_sack = 1

啟用 BBR

BBR 擁塞控制算法可以幫助實現更高的帶寬和更低的網際網路流量延遲。

啟用 BBR 需要先加載 tcp_bbr 模塊。

注意:BBR GitHub says, "這不是 Google 的官方產品。"
net.core.default_qdisc = cake
net.ipv4.tcp_congestion_control = bbr

增加臨時埠範圍

本文或本章節的事實準確性存在爭議。

原因: 此更改可以提高性能?原理是什麼?(在 Talk:Sysctl#net.ipv4.ip_local_port_range 中討論)


通常傳輸控制協議 (TCP)、用戶數據報協議 (UDP) 或流控制傳輸協議 (SCTP) 會使用Wikipedia:Ephemeral port 作為客戶端與伺服器端之間的埠分配協商。

net.ipv4.ip_local_port_range = 30000 65535

TCP/IP 協議棧加固

下面指定了一個參數集,用於加強 IPv4 協議內核的網絡安全選項,並且也存在等效項的相關 IPv6 參數。

對於某些用例,例如將系統用作路由器,其他參數也可能有用或需要。

TCP SYN cookie 保護

此項設置有助於抵禦 SYN 洪水攻擊。只有訪問請求達到 net.ipv4.tcp_max_syn_backlog 時才會啟動。更多詳細信息,例如 [6]。 從 linux 5.10 開始,它是默認設置的。

net.ipv4.tcp_syncookies = 1

TCP rfc1337

本文或本章節的事實準確性存在爭議。

原因: 這好像不是 TCP 標準的一部分? 描述可能不準確。[7](在 Talk:Sysctl#net.ipv4.tcp_rfc1337 中討論)


可以防止 tcp time-wait assassination 缺陷,丟棄處於 time-wait 狀態的 socket 的 RST 數據包。 除 Linux 之外並不廣泛支持,但符合 RFC:

net.ipv4.tcp_rfc1337 = 1

反向路徑過濾

通過啟用反向路徑過濾,內核將對從機器上所有網絡接口接收到的數據包進行來源驗證。這可以防止使用 IP 欺騙方法的攻擊者破壞系統。

內核的 net.ipv4 .conf.all.rp_filter 默認值為 0(關閉來源驗證),但 systemd 提供默認 /usr/lib/sysctl.d/50-default.conf 將其設置到 2(寬鬆模式)[8]

以下配置將反向路徑過濾機制設置為值 1 (嚴格模式):

net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1

ip-sysctl.html 這裡解釋了 net.ipv4.conf.default.*net.ipv4.conf.interface.*net.ipv4.conf.all.* 之間的關係和行為。

記錄 martian 數據包

martian 數據包是指那些包內的源地址或目標地址被設置成 IP 保留地址的特殊數據包。IP 保留地址由 IANA 為了特殊用途而保留。這些包要麼在廣域網上要麼根本無法傳輸數據,要麼包內的源地址與實際的發包源地址不符(例如特地偽造虛假源地址的數據包)。

net.ipv4.conf.default.log_martians = 1
net.ipv4.conf.all.log_martians = 1
注意:這可能會導致大量信息填滿您的日誌,建議僅在測試時啟用它。

禁用 ICMP 重定向

相關背景知識可以參考什麼是 ICMP 重定向? 他們應該被阻止嗎?

下面的配置用來禁用 ICMP 重定向的接收功能:

net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

下面的配置用來在非路由器上禁用 ICMP 重定向的發送功能:

net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

忽略 ICMP 回應請求

要禁用 ICMP 回應(又叫 ping)請求:

net.ipv4.icmp_echo_ignore_all = 1
net.ipv6.icmp.echo_ignore_all = 1
注意:請注意,這可能會導致依賴 ICMP 回顯(ping)響應的網絡記錄工具和或應用程式出現問題。

其它

允許非特權用戶創建 IPPROTO_ICMP socket

本文或本節內容已經過時。

原因: /usr/lib/sysctl.d/50-default.conf 會將 net.ipv4.ping_group_range 設置為 0 2147483647. (在Talk:Sysctl討論)

IPPROTO_ICMP (icmp(7)) socket 類型增加了在不打開 raw(7) socket 的情況下發送 ICMP_ECHO 消息和接收相應 ICMP_ECHOREPLY 消息的功能,該操作需要設置 CAP_NET_RAW 功能權限或具有指定特權用戶的 SUID 位。這些 ICMP_ECHO 消息由 ping 應用程式發送,因此除了 ICMP Echo socket 之外,IPPROTO_ICMP socket 也稱為 ping socket。

ping_group_range 確定允許其用戶創建 IPPROTO_ICMP socket 的組的 GID 範圍。此外,還允許有 CAP_NET_RAW 功能權限的用戶創建 IPPROTO_ICMP socket。默認情況下這個範圍是 1 0,意味著除了 root 之外沒有人被允許創建 IPPROTO_ICMP socket。要利用這項設置,當前使用原始 socket 的程序需要移植到使用 IPPROTO_ICMP socket。例如,QEMU 將 IPPROTO_ICMP 用於 SLIRP,即用戶模式網絡,因此允許運行 QEMU 的用戶創建 IPPROTO_ICMP socket,這樣就可以在客戶機內進行 ping 操作了。

下面的配置只允許 GID 為 100 的組成員的用戶創建 IPPROTO_ICMP 套接字:

net.ipv4.ping_group_range = 100 100

下面的配置允許系統中的所有用戶創建 IPPROTO_ICMP 套接字:

net.ipv4.ping_group_range = 0 65535

虛擬內存

有幾個關鍵參數可以調整 Linux 內核的虛擬內存子系統的操作以及將髒數據(dirty data)寫出到磁碟。有關詳細信息,請參閱官方 Linux 內核文檔。 例如:

  • vm.dirty_ratio = 10
包括占可用內存總量(可用頁面和可回收頁面)的百分比,和正在發生磁碟寫入的進程本身將開始寫出髒數據的頁數。
  • vm.dirty_background_ratio = 5
包括可用頁面和可回收頁面的總可用內存的百分比以及後台內核刷新線程將要開始寫出髒數據的頁數。

如參數注釋中所述,在設置這些值時需要考慮 RAM 總量。例如,可以通過用已安裝的系統內存而不是可用內存來簡化計算:

警告:
  • 較高的比率值可能會提高性能,但也會增加數據丟失的風險。
  • 將此值設置為 0 可能會導致更高的磁碟延遲和低性能尖峰。

更多信息請參考 [9]

  • 共識是,如果 RAM 為 1 GB,則將 vm.dirty_ratio 設置為 RAM 的 10% 是一個合理的值(10% 也就是 100 MB)。 但是如果機器有更多的 RAM,比如 16 GB(10% 就是 1.6 GB),這個百分比可能因為機械磁碟上旋轉回寫的幾秒鐘時間差異而不是線性的。 在這種情況下更合理的值可能是 3(16 GB 的 3% 大約是 491 MB)。
  • 同樣,將 vm.dirty_background_ratio 設置為 5 可能只適用於小內存值,所以要考慮並根據特定系統上的內存容量進行相應調整。

VFS 緩存

降低虛擬文件系統 (VFS) 緩存參數值可能會提高系統響應能力:

  • vm.vfs_cache_pressure = 50
這個值控制內核回收用於緩存目錄和 inode 對象(即 VFS 緩存)內存的積極性。 將它從默認值 100 降低會使內核不太願意回收 VFS 緩存(不要將其設置為 0,這可能會產生內存不足的情況)。

MDADM

參考 RAID#修改同步速度限制

故障排除

小周期系統凍結

如果遇到這個問題,可以將髒字節(dirty bytes)設置為足夠小的值(例如 4M):

vm.dirty_background_bytes = 4194304
vm.dirty_bytes = 4194304
注意:dirty_background_bytesdirty_bytes 參數是 dirty_background_ratiodirty_ratio 的對應項(如 #虛擬內存 中所示)。一次只能指定一個參數。

參考資料