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/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/
中的配置文件中Help:Reading#添加、创建、编辑文件或修改对应的行。
/proc/sys/net/bridge/*
中的参数依赖于 br_netfilter
模块。如果br_netfilter
没有在运行时(或重启后)加载,那么这些参数将安静的不生效。参见内核模块。安全
参阅安全#内核加固,以及本文的其余部分。
网络
性能优化
增加接收队列的大小
进入系统的网络数据帧在从网卡上的环形缓冲区中取出后,会存放在这个队列中。
在使用高速网卡时增加系统的这个设定值可能有助于防止数据包丢失:
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 快速打开:
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 通信在进行并处于活动状态,就不需要保活数据包。
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 时间戳
禁用时间戳生成可以减少低性能尖峰的发生并可能提高千兆网络的性能:
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
模块。
net.core.default_qdisc = cake net.ipv4.tcp_congestion_control = bbr
增加临时端口范围
通常传输控制协议 (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 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
其它
允许非特权用户创建 IPPROTO_ICMP socket
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_bytes
和 dirty_bytes
参数是 dirty_background_ratio
和 dirty_ratio
的对应项(如 #虚拟内存 中所示)。一次只能指定一个参数。