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) 工具来更改设置。例如,要临时启用 Magic SysRq key
# sysctl kernel.sysrq=1
或者
# echo "1" > /proc/sys/kernel/sysrq
有关 kernel.sysrq 的详细信息,请参阅 Linux 内核文档。
要使更改在重启后仍然有效,请在 /etc/sysctl.d/99-sysctl.conf 或 /etc/sysctl.d/ 中的其他适用的参数文件中 添加 或修改相应的行。
- 可以应用的某些参数可能依赖于内核模块,而这些模块可能尚未加载。例如,
/proc/sys/net/bridge/*中的参数依赖于br_netfilter模块。如果在运行时(或重启后)未加载该模块,这些参数将*静默地*不被应用。请参阅 内核模块。 - 还可以使用*内核命令行*参数应用 sysctl 参数,方法是在参数名称前加上
sysctl.(例如sysctl.vm.swappiness=40)。这对于永久更改而不修改系统范围的配置很有用。
安全
另请参阅 Security#Kernel hardening 以及本文其余部分。
网络
提升性能
增加接收队列大小。
接收到的帧将在从网卡上的环形缓冲区取出后存储在此队列中。
增加高速网卡的此值可能有助于防止丢包。
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 flood 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 规范,但对于防止拒绝服务攻击是必需的。在 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 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 选择性确认 (TCP SACK),由布尔值 tcp_sack 控制,允许接收方向发送方提供有关丢失段的更多详细信息,从而减少重传量。这在高延迟网络上很有用,但在高速局域网上禁用此项以提高吞吐量。如果您不发送 SACK,您肯定不想发送重复项!前向确认 (Forward Acknowledgement) 工作在 SACK 之上,如果 SACK 被禁用,它也将被禁用。[6]
net.ipv4.tcp_sack = 1
启用 BBR
BBR 拥塞控制算法 可以帮助实现更高的带宽和更低的互联网流量延迟。首先,加载 tcp_bbr 模块。
net.core.default_qdisc = cake net.ipv4.tcp_congestion_control = bbr
增加临时端口范围
在 TCP、UDP 或 SCTP 的客户端-服务器通信中,Wikipedia:Ephemeral port 通常由传输控制协议 (TCP)、用户数据报协议 (UDP) 或流控制传输协议 (SCTP) 用作客户端端的端口分配。
net.ipv4.ip_local_port_range = 30000 65535
TCP/IP 栈加固
以下指定了一组参数,用于收紧内核的 IPv4 协议网络安全选项,以及存在等效参数的 IPv6 参数。
对于某些用例,例如将系统用作路由器,其他参数可能也很有用或必需。
TCP SYN cookie 保护
有助于防止 SYN flood 攻击。仅在 net.ipv4.tcp_max_syn_backlog 达到时才生效。更多详细信息,例如,请参阅 [7]。从 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(松散模式)[9]。
以下将反向路径过滤机制设置为值 1(严格模式)。
net.ipv4.conf.default.rp_filter = 1 net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.*、net.ipv4.conf.interface.* 和 net.ipv4.conf.all.* 的关系和行为在 ip-sysctl.html 中有解释。
记录非法报文
一个 martian packet 是一个 IP 数据包,它指定了一个由 Internet 分配号码局 (IANA) 保留的特殊用途的源地址或目标地址。有关更多详细信息,请参阅 保留 IP 地址。
通常,martian 和不可路由的数据包可能用于危险目的。记录这些数据包以供进一步检查可能很有用 [10]。
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
其他
允许非特权用户创建 IPPROTO_ICMP 套接字
IPPROTO_ICMP (icmp(7)) 套接字类型增加了发送 ICMP_ECHO 消息并接收相应 ICMP_ECHOREPLY 消息的可能性,而无需打开 raw(7) 套接字,这是一项需要 CAP_NET_RAW 能力 或 SUID 位以及正确特权所有者的操作。这些 ICMP_ECHO 消息由 ping 应用程序发送,因此 IPPROTO_ICMP 套接字除了作为 ICMP Echo 套接字外,也称为 ping 套接字。
ping_group_range 决定了允许用户创建 IPPROTO_ICMP 套接字的组的 GID 范围。此外,具有 CAP_NET_RAW 能力的所有者也允许创建 IPPROTO_ICMP 套接字。默认情况下,此范围为 1 0,这意味着除 root 用户外,没有人可以创建 IPPROTO_ICMP 套接字。要利用此设置,当前使用 raw 套接字的程序需要移植到使用 IPPROTO_ICMP 套接字。例如,QEMU 对 SLIRP(即用户模式网络)使用 IPPROTO_ICMP,因此允许运行 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
- 该值控制内核回收用于目录和 inode 对象缓存(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(如 #虚拟内存 中所示)的对应项。一次只能指定其中一个参数。