sysctl
sysctl 是一个用于在运行时检查和修改内核参数的工具。sysctl 是在 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/sysrq 文件。sysctl --all 命令可用于显示所有当前可用的值。
/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/ 中其他适用的参数文件。
安全
另请参阅 安全#内核加固,以及本文的其余部分。
网络
提升性能
增大接收队列长度。
在从网卡的环形缓冲区获取接收到的帧后,它们将被存储在该队列中。
对于高速网卡,增大此值可能有助于防止丢包。
net.core.netdev_max_backlog = 16384
增加最大连接数
内核将接受的连接上限(默认为 4096)
net.core.somaxconn = 8192
增加分配给网络接口的内存
默认情况下,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
有关更多信息和推荐值,请参阅以下来源:
- http://www.nateware.com/linux-network-tuning-for-2013.html
- https://blog.cloudflare.com/the-story-of-one-latency-spike/
启用 TCP Fast Open
TCP Fast Open 是传输控制协议 (TCP) 的一个扩展,它通过允许在发送方的初始 TCP SYN 期间交换数据来帮助减少网络延迟 [2]。使用值 3 代替默认的 1 允许 TCP Fast Open 用于传入和传出连接。
net.ipv4.tcp_fastopen = 3
调整待处理连接的处理方式
tcp_max_syn_backlog 是处于“等待确认”状态的待处理连接的最大队列长度。
如果发生 SYN 泛洪 DOS 攻击,此队列可能会迅速填满,此时 TCP SYN cookies 将介入,使您的系统能够继续响应合法流量,并允许您获得访问权限以阻止恶意 IP。
如果服务器在高峰时段遭遇过载,您可能需要稍微增加此值。
net.ipv4.tcp_max_syn_backlog = 8192
tcp_max_tw_buckets 是处于 TIME_WAIT 状态的套接字的最大数量。
达到此数量后,系统将开始销毁处于此状态的套接字。
增加此值以防止简单的 DOS 攻击。
net.ipv4.tcp_max_tw_buckets = 2000000
tcp_tw_reuse 设置 TCP 是否应在 TIME-WAIT 状态下为新的传出连接重用现有连接,前提是新时间戳严格大于前一个连接记录的最新时间戳。
默认值为 2,表示仅对环回连接启用。您可以将其设置为 1 以对所有连接启用,这有助于避免耗尽可用网络套接字。
net.ipv4.tcp_tw_reuse = 1
指定在套接字被强制关闭之前等待最终 FIN 数据包的秒数。这严格违反了 TCP 规范,但对于防止拒绝服务攻击是必需的。
net.ipv4.tcp_fin_timeout = 10
tcp_slow_start_after_idle 设置 TCP 是仅针对新连接以默认窗口大小开始,还是也针对空闲时间过长的现有连接以默认窗口大小开始。
此设置会损害持久单连接性能,可以将其关闭。
net.ipv4.tcp_slow_start_after_idle = 0
更改 TCP keepalive 参数
TCP keepalive 是一种 TCP 连接机制,有助于确定另一端是否已停止响应。TCP 将在一段时间的空闲后多次向网络对等方发送包含空数据的 keepalive 探测。如果对等方没有响应,套接字将自动关闭。默认情况下,TCP keepalive 进程在发送第一个 keepalive 探测之前会等待两小时(7200 秒)的套接字活动,然后每 75 秒重新发送一次。只要有 TCP/IP 套接字通信正在进行且处于活动状态,就不需要 keepalive 数据包。
net.ipv4.tcp_keepalive_time = 60 net.ipv4.tcp_keepalive_intvl = 10 net.ipv4.tcp_keepalive_probes = 6
启用 MTU 探测
最大传输单元 (MTU) 越长,性能越好,但可靠性越差。
这是因为丢失的数据包意味着需要重传更多数据,而且互联网上的许多路由器无法交付非常长的数据包。
net.ipv4.tcp_mtu_probing = 1
有关更多信息,请参阅 https://blog.cloudflare.com/path-mtu-discovery-in-practice/。
TCP 时间戳
禁用时间戳生成将减少峰值,并可能在千兆网络上提供性能提升。
net.ipv4.tcp_timestamps = 0
TCP 选择性确认
由布尔值 tcp_sack 控制的 TCP 选择性确认 (TCP SACK) 允许接收端向发送方提供有关丢失段的更多详细信息,从而减少重传量。这在高延迟网络上很有用,但在高速局域网 (LAN) 上禁用此项以提高吞吐量。此外,如果您不发送 SACK,肯定不想发送重复项,因此请禁用 tcp_dsack!转发确认在 SACK 之上工作,如果 SACK 被禁用,它也将被禁用。[5]
net.ipv4.tcp_sack = 1
启用 BBR
BBR 拥塞控制算法可以帮助实现更高的带宽和更低的互联网流量延迟。首先,加载 tcp_bbr 模块。
net.core.default_qdisc = cake net.ipv4.tcp_congestion_control = bbr
增加临时端口范围
Wikipedia:临时端口通常由传输控制协议 (TCP)、用户数据报协议 (UDP) 或流控制传输协议 (SCTP) 用作客户端-服务器通信的客户端端的端口分配。
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 time-wait 刺杀风险,丢弃处于 time-wait 状态的套接字的 RST 数据包。在 Linux 之外不受广泛支持,但符合 RFC 标准。
net.ipv4.tcp_rfc1337 = 1
反向路径过滤
通过启用反向路径过滤,内核将对从机器上所有接口接收到的数据包进行源验证。这可以防止攻击者使用 IP 欺骗方法进行破坏。
内核的默认值为 0(无源验证),但 systemd 附带了 /usr/lib/sysctl.d/50-default.conf,将 net.ipv4.conf.all.rp_filter 设置为 2(宽松模式)[8]。
以下内容将把反向路径过滤机制设置为值 1(严格模式)。
net.ipv4.conf.*.rp_filter = 1 -net.ipv4.conf.all.rp_filter
net.ipv4.conf.default.*、net.ipv4.conf.interface.* 和 net.ipv4.conf.all.* 之间的关系和行为在 ip-sysctl.html 中有说明。
记录 Martian 数据包
Martian 数据包是一个 IP 数据包,它指定了一个为互联网编号分配机构 (IANA) 特殊用途保留的源地址或目标地址。有关详细信息,请参阅 保留 IP 地址。
通常 Martian 和不可路由数据包可能被用于危险目的。记录这些数据包以供进一步检查可能很有用 [9]。
net.ipv4.conf.*.log_martians = 1 -net.ipv4.conf.all.log_martians
禁用 ICMP 重定向
背景信息在 什么是 ICMP 重定向?它们应该被阻止吗?
禁用 ICMP 重定向接受
net.ipv4.conf.*.accept_redirects = 0 -net.ipv4.conf.all.accept_redirects net.ipv6.conf.*.accept_redirects = 0 -net.ipv6.conf.all.accept_redirects
在非路由器上禁用 ICMP 重定向发送
net.ipv4.conf.*.send_redirects = 0 -net.ipv4.conf.all.send_redirects
忽略 ICMP 回显请求
禁用 ICMP 回显(又称 ping)请求
net.ipv4.icmp_echo_ignore_all = 1 net.ipv6.icmp.echo_ignore_all = 1
其他
允许非特权用户创建 IPPROTO_ICMP 套接字
IPPROTO_ICMP (icmp(7)) 套接字类型增加了发送 ICMP_ECHO 消息和接收相应 ICMP_ECHOREPLY 消息的可能性,而无需打开 raw(7) 套接字(这是一项需要 CAP_NET_RAW 能力或带有适当特权所有者的 SUID 位的操作)。这些 ICMP_ECHO 消息由 ping 应用程序发送,因此除了 ICMP Echo 套接字外,IPPROTO_ICMP 套接字也被称为 ping 套接字。
ping_group_range 决定了允许其用户创建 IPPROTO_ICMP 套接字的组的 GID 范围。此外,拥有 CAP_NET_RAW 能力的所有者也被允许创建 IPPROTO_ICMP 套接字。默认情况下,此范围是 1 0,这意味着除了 root 之外,没有人被允许创建 IPPROTO_ICMP 套接字。为了利用此设置,当前使用原始套接字的程序需要移植以改用 IPPROTO_ICMP 套接字。例如,QEMU 使用 IPPROTO_ICMP 进行 SLIRP(即用户模式网络),因此允许运行 QEMU 的用户创建 IPPROTO_ICMP 套接字意味着可以从客户机执行 ping 操作。
仅允许 GID 为 100 的组成员的用户创建 IPPROTO_ICMP 套接字
net.ipv4.ping_group_range = 100 100
允许系统中的所有用户创建 IPPROTO_ICMP 套接字
net.ipv4.ping_group_range = 0 65535
虚拟内存
有几个关键参数可以调整 Linux 内核的虚拟内存子系统以及脏数据写入磁盘的操作。更多信息,请参阅官方 Linux 内核文档。例如
vm.dirty_ratio = 10
- 包含(作为包含空闲页和可回收页的总可用内存的百分比)生成磁盘写入的进程自身开始写出脏数据时的页数。
vm.dirty_background_ratio = 5
- 包含(作为包含空闲页和可回收页的总可用内存的百分比)后台内核刷新线程开始写出脏数据时的页数。
正如参数注释中所述,在设置这些值时需要考虑 RAM 的总量。例如,通过使用已安装的系统 RAM 而不是可用内存来进行简化
- 较高的比例值可能会提高性能,但也会增加数据丢失的风险。
- 将此值设置为
0可能会导致磁盘上的延迟增加和峰值。
有关更多信息,请参阅 https://lonesysadmin.net/2013/12/22/better-linux-disk-caching-performance-vm-dirty_ratio/。
- 共识是,如果 RAM 为 1 GB(即 10% 为 100 MB),将
vm.dirty_ratio设置为 RAM 的 10% 是一个合理的数值。但如果机器有更多的 RAM,例如 16 GB(10% 为 1.6 GB),则该百分比可能不成比例,因为它会变成在旋转磁盘上长达几秒的写回操作。在这种情况下,一个更合理的值可能是3(16 GB 的 3% 约为 491 MB)。 - 类似地,将
vm.dirty_background_ratio设置为5对于小内存值可能完全没问题,但同样,请根据特定系统上的 RAM 量进行考虑和相应调整。
VFS 缓存
减小虚拟文件系统 (VFS) 缓存参数值可能会提高系统响应速度。
vm.vfs_cache_pressure = 50
- 该值控制内核回收用于缓存目录和索引节点对象(VFS 缓存)的内存的倾向。将其从默认值 100 降低会使内核不太倾向于回收 VFS 缓存(不要将其设置为 0,这可能会产生内存不足的情况)。
MDADM
请参阅 RAID#更改同步速度限制。
故障排除
轻微的周期性系统冻结
将脏字节设置为足够小的值(例如 4 MiB)
vm.dirty_background_bytes = 4194304 vm.dirty_bytes = 4194304
dirty_background_bytes 和 dirty_bytes 参数是 dirty_background_ratio 和 dirty_ratio(如在 #虚拟内存 中所见)的对应项。一次只能指定其中一个参数。