Debian系统默认的内核参数在很多场景下偏保守,尤其是直接暴露在公网的服务器,如果不做调整,SYN洪水、连接表耗尽、IP伪装的垃圾流量会迅速拖垮服务。真正有效的加固不是安装某个“安全脚本”一键完成,而是理解网络栈、内存、文件句柄和内核错误处理之间的联动,按业务负载逐项收紧。
先从网络层开始。Debian默认允许内核响应ICMP重定向、接受源路由包,这两项在公网环境里几乎没有任何正当用途,只会给中间人攻击和路径探测留下空间。直接通过sysctl关闭:
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.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 net.ipv6.conf.all.accept_redirects = 0 net.ipv6.conf.default.accept_redirects = 0 net.ipv6.conf.all.accept_source_route = 0 net.ipv6.conf.default.accept_source_route = 0
这些参数要同时写all和default,因为all只影响当前已启用的接口,default决定之后新出现的接口行为。很多管理员只写all,重启网卡或添加虚拟网卡后规则就失效了。
反向路径过滤是另一个容易被忽略的点。开启rp_filter可以让内核丢弃那些源地址明显伪造、从错误接口进入的数据包。对于单网卡服务器,设为1即可;多网卡且存在非对称路由时,需要设为2宽松模式,否则会误伤正常流量。
net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1
TCP SYN队列和连接追踪表是抗DDoS的第一道防线。默认的tcp_max_syn_backlog通常只有1024,syn_retries为6,意味着攻击者可以用很少的带宽占满半连接队列。建议将syn_retries降到2或3,缩短重试时间,同时增大backlog。但backlog不是越大越好,内存有限时过大的队列反而会拖慢正常握手。
net.ipv4.tcp_syn_retries = 2 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_max_syn_backlog = 8192 net.ipv4.tcp_abort_on_overflow = 1
tcp_abort_on_overflow设为1后,当全连接队列满时内核直接发送RST而不是静默丢弃,这能让客户端快速失败重试,避免长时间挂起。对于API服务和高并发Web,这个参数能显著改善过载时的行为。
连接追踪表nf_conntrack是NAT和防火墙的基础,默认最大连接数往往只有65536。一旦表满,新连接会被直接丢弃,表现为服务间歇性不可用。查看当前值和峰值:
sysctl net.netfilter.nf_conntrack_max sysctl net.netfilter.nf_conntrack_count
根据内存调整,通常1GB内存可以支撑约65536条追踪记录,但具体要看每条记录占用的内存。生产环境建议至少设为262144,同时缩短超时时间,让僵尸连接尽快释放。
net.netfilter.nf_conntrack_max = 262144 net.netfilter.nf_conntrack_tcp_timeout_established = 600 net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30 net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60 net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 30
如果服务器不承担NAT转发任务,只是作为终端节点,可以考虑直接卸载nf_conntrack模块,彻底消除追踪表耗尽的风险。但前提是防火墙规则没有使用状态匹配,否则卸载后iptables/nftables的state模块会失效。
TIME_WAIT状态堆积是短连接场景下的经典问题。高并发API或反向代理服务器上,大量socket停留在TIME_WAIT会占满本地端口,导致无法建立新连接。启用tcp_tw_reuse可以让内核复用处于TIME_WAIT的端口用于新的出站连接,注意这只对客户端方向有效,服务端监听端口不受影响。
net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_fin_timeout = 15 net.ipv4.ip_local_port_range = 1024 65535
不要使用tcp_tw_recycle,它在较新的内核中已被移除,而且过去启用它会破坏NAT环境下的连接。扩大本地端口范围是更直接有效的办法,配合tw_reuse可以支撑很高的短连接速率。
TCP keepalive参数需要根据业务调整。默认的keepalive时间长达7200秒,对于长连接服务来说,死连接占用资源的时间太长了。建议缩短到600秒左右,并减少探测间隔,让异常断开的连接能更快被清理。
net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_keepalive_intvl = 30 net.ipv4.tcp_keepalive_probes = 5
文件句柄限制是另一个高频故障点。Debian默认的单进程打开文件数限制为1024,对于Nginx、数据库或Java应用来说远远不够。内核层面的fs.file-max决定系统全局上限,通常不需要调整,但用户级限制必须显式提高。在/etc/security/limits.conf中设置:
* soft nofile 65535 * hard nofile 65535 * soft nproc 65535 * hard nproc 65535
同时确认systemd的服务单元文件里没有单独的LimitNOFILE覆盖这个设置。很多服务通过systemd启动时,默认限制仍然是4096,需要在服务文件中明确指定。
内存层面的参数同样关键。vm.swappiness默认60,对于数据库服务器来说偏高,系统会过早使用swap,导致性能骤降。建议设为10或1,让内核尽量使用物理内存。但如果服务器内存紧张且跑的是突发性负载,保持默认值反而更安全。
vm.swappiness = 10 vm.vfs_cache_pressure = 50
vfs_cache_pressure控制内核回收目录项和inode缓存的倾向,默认100。降低到50可以让缓存保留更久,提升文件系统性能,代价是内存占用略高。对于文件服务器或静态资源服务器,这个调整收益明显。
内核错误处理方面,panic_on_oops和panic参数决定系统遇到致命错误时的行为。公网服务器如果内核崩溃后挂起,监控系统可能无法及时发现,建议设置自动重启。
kernel.panic = 10 kernel.panic_on_oops = 1 kernel.sysrq = 0
kernel.sysrq设为0禁用SysRq组合键,防止物理接触服务器的人通过键盘触发底层操作。对于云服务器,这个风险较低,但关闭它没有副作用。
IPv6是很多管理员容易遗漏的攻击面。如果业务完全不需要IPv6,最彻底的做法是在内核启动参数中禁用,或者通过sysctl关闭所有IPv6接口的自动配置和路由通告。
net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1
但要注意,部分应用程序在编译时依赖IPv6的socket接口,直接禁用可能导致启动失败。更稳妥的方式是先确认业务兼容性,再决定是否关闭。
ICMP参数也值得收紧。完全禁止ICMP会让排障变得困难,但可以限制重定向和广播响应。对于公网服务器,建议关闭ICMP重定向的接受和发送,同时忽略广播ICMP请求。
net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 net.ipv4.icmp_echo_ignore_broadcasts = 1 net.ipv4.icmp_ignore_bogus_error_responses = 1
icmp_ignore_bogus_error_responses开启后,内核会丢弃那些声称来自非法地址的ICMP错误消息,这类消息常被用于探测和欺骗。
所有sysctl参数都应该写入/etc/sysctl.d/目录下的配置文件,而不是直接修改/etc/sysctl.conf。推荐创建一个专门的安全配置文件,例如/etc/sysctl.d/99-hardening.conf,便于版本管理和审计。修改后执行sysctl --system加载生效,不需要重启服务器。
加固不是一次性的工作。内核参数需要配合实际的流量特征、硬件配置和业务模型持续调整。建议在变更前记录基线数据,包括连接数、内存使用、文件句柄占用和网络吞吐,变更后观察至少一周,确认没有引入新的瓶颈。安全性和性能之间永远存在权衡,盲目套用他人的参数值而不理解其含义,往往比保持默认设置更危险。
