sysctl
sysctl 是一个用于在运行时检查和更改内核参数的工具。 sysctl 在 procfs 中实现,procfs 是位于 /proc/
的虚拟进程文件系统。
安装
procps-ng 软件包应该已经安装,因为它是一个base 元软件包的依赖项。
配置
sysctl 预加载/配置文件可以在 /etc/sysctl.d/99-sysctl.conf
创建。对于 systemd,/etc/sysctl.d/
和 /usr/lib/sysctl.d/
是内核 sysctl 参数的 drop-in 目录。命名和源目录决定了处理顺序,这很重要,因为最后处理的参数可能会覆盖较早的参数。例如,/usr/lib/sysctl.d/50-default.conf
中的参数将被 /etc/sysctl.d/50-default.conf
和稍后从两个目录处理的任何配置文件中的相同参数覆盖。
要手动加载所有配置文件,执行
# sysctl --system
这也将输出应用的层级结构。也可以使用以下命令显式加载单个参数文件
# sysctl --load=filename.conf
有关更多信息,请参阅 the new configuration files,更具体地说是 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
模块。如果它在运行时(或重启后)未加载,则这些参数将静默地不被应用。请参阅 内核模块。安全
另请参阅 Security#内核加固,以及本文的其余部分。
网络
提升性能
增加接收队列的大小。
接收到的帧将在从网卡上的环形缓冲区取出后存储在这个队列中。
对于高速网卡,增加这个值可能有助于防止丢包
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
是待处理连接“等待确认”的最大队列长度。
在发生 synflood 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 进程等待两个小时(7200 秒)的套接字活动,然后发送第一个 keepalive 探测包,然后每 75 秒重新发送一次。只要存在正在进行的和活动的 TCP/IP 套接字通信,就不需要 keepalive 数据包。
net.ipv4.tcp_keepalive_time = 60 net.ipv4.tcp_keepalive_intvl = 10 net.ipv4.tcp_keepalive_probes = 6
启用 MTU 探测
最大传输单元 (MTU) 越长,性能越好,但可靠性越差。
这是因为丢失的数据包意味着更多的数据需要重新传输,并且因为 Internet 上的许多路由器无法传递非常长的数据包
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
控制,允许接收方提供有关丢失段的更多详细信息给发送方,从而减少重传量。这在高延迟网络上很有用,但在高速 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.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 中进行了解释。
记录火星包
火星包是一个 IP 数据包,它指定了互联网号码分配机构 (IANA) 保留用于特殊用途的源地址或目标地址。 有关更多详细信息,请参阅 保留 IP 地址。
通常,火星包和不可路由的数据包可能被用于危险目的。记录这些数据包以供进一步检查可能很有用 [9]
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 capability 或具有适当特权所有者的 SUID 位。 这些 ICMP_ECHO 消息由 ping 应用程序发送,因此除了 ICMP Echo 套接字之外,IPPROTO_ICMP 套接字也称为 ping 套接字。
ping_group_range
确定允许其用户创建 IPPROTO_ICMP 套接字的组的 GID 范围。 此外,CAP_NET_RAW capability 的所有者也被允许创建 IPPROTO_ICMP 套接字。 默认情况下,此范围为 1 0
,这意味着除了 root 用户外,任何人都不能创建 IPPROTO_ICMP 套接字。 为了利用此设置,当前使用原始套接字的程序需要移植为使用 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#更改同步速度限制。
故障排除
系统周期性小卡顿
将脏字节设置为足够小的值(例如 4M)
vm.dirty_background_bytes = 4194304 vm.dirty_bytes = 4194304
dirty_background_bytes
和 dirty_bytes
参数是 dirty_background_ratio
和 dirty_ratio
的对应参数(如#虚拟内存中所见)。 一次只能指定其中一个参数。