Ubuntu服务器的安全运维不是装完系统就完事了,真正决定服务器能不能扛住攻击、稳不稳的核心就在内核参数。日常巡检中你必须盯死五个关键内核参数:net.ipv4.tcp_syncookies、net.ipv4.conf.all.rp_filter、kernel.randomize_va_space、net.ipv4.icmp_echo_ignore_broadcasts、vm.swappiness。这五个参数分别控制着SYN Flood防御、源地址验证、ASLR地址随机化、ICMP广播抑制和内存交换策略,任何一个配置不当都可能成为安全缺口或者性能瓶颈。下面逐一拆解每个参数的含义、推荐值、怎么查、怎么改、改完怎么验证。
一、net.ipv4.tcp_syncookies——SYN Flood攻击的第一道防线
SYN Flood是最经典的DDoS攻击方式,攻击者疯狂发送SYN包但不完成三次握手,把服务器的半连接队列打满,正常用户就连不上了。tcp_syncookies这个参数开启后,内核不再为每个半连接分配资源,而是用一种加密cookie机制来验证连接合法性。简单说,开启它等于给服务器穿了一件防弹衣。
查看当前值的方法:
sysctl net.ipv4.tcp_syncookies
推荐值为1(开启)。如果返回0,说明你的服务器在裸奔。修改方法分临时和永久两种:
# 临时生效 sysctl -w net.ipv4.tcp_syncookies=1 # 永久生效,写入配置文件 echo "net.ipv4.tcp_syncookies = 1" >> /etc/sysctl.conf sysctl -p
这里有个细节很多人忽略:tcp_syncookies在高并发场景下可能导致某些老旧客户端连接失败,如果你的业务有这种情况,需要在应用层做兼容处理,而不是关掉这个参数。巡检时建议同时关注net.ipv4.tcp_max_syn_backlog(半连接队列上限),推荐设为4096或更高,配合syncookies效果更好。
二、net.ipv4.conf.all.rp_filter——防止IP地址伪造的关键开关
rp_filter是反向路径过滤,核心作用是验证数据包的源IP地址是否真的能从收到这个包的网络接口路由回来。如果不能,说明源IP大概率是伪造的,内核直接丢弃。这个参数对于防止IP欺骗攻击、防止服务器被当作跳板机至关重要。
rp_filter有三个可选值:0表示关闭验证,1表示严格模式(必须从最佳路由接口回来),2表示松散模式(只要能从任何接口路由回来就行)。生产环境强烈建议设为1:
sysctl net.ipv4.conf.all.rp_filter
如果返回值不是1,执行以下命令修复:
# 临时修改 sysctl -w net.ipv4.conf.all.rp_filter=1 sysctl -w net.ipv4.conf.default.rp_filter=1 # 永久修改 echo "net.ipv4.conf.all.rp_filter = 1" >> /etc/sysctl.conf echo "net.ipv4.conf.default.rp_filter = 1" >> /etc/sysctl.conf sysctl -p
注意,如果你的服务器是多网卡环境或者做了复杂的路由策略(比如负载均衡、NAT网关),rp_filter设为1可能导致部分合法流量被误杀。这种情况下可以针对单个接口单独设置,比如:
sysctl -w net.ipv4.conf.eth0.rp_filter=2
巡检时要把all、default、每个具体网卡接口都检查一遍,很多运维只改了all就以为万事大吉,实际上default没改一样有漏洞。
三、kernel.randomize_va_space——ASLR地址随机化的安全等级
ASLR(地址空间布局随机化)是现代操作系统对抗缓冲区溢出攻击的核心机制。它让程序每次运行时栈、堆、共享库的内存地址都随机变化,攻击者没法预测目标地址,利用难度大幅提升。kernel.randomize_va_space控制的就是ASLR的随机化程度。
这个参数有三个值:0表示关闭ASLR,1表示随机化栈、共享库、VDSO等(部分随机),2表示在1的基础上额外随机化堆内存(完整随机)。Ubuntu默认通常是2,但很多自定义内核或者老版本可能是0或1。
sysctl kernel.randomize_va_space
如果返回值小于2,立即修改:
echo "kernel.randomize_va_space = 2" >> /etc/sysctl.conf sysctl -p
这里有个容易踩的坑:某些老旧的32位程序或者特殊调试场景下,ASLR设为2可能导致程序崩溃。如果你的业务有这类程序,可以先设为1做折中,但绝对不能设为0。巡检时建议配合检查/proc/sys/kernel/kptr_restrict(内核指针隐藏),推荐设为2,防止通过信息泄露绕过ASLR。
四、net.ipv4.icmp_echo_ignore_broadcasts——堵住ICMP广播放大攻击的口子
ICMP广播放大攻击(Smurf攻击)的原理是攻击者伪造目标IP发送ICMP请求到广播地址,网络中所有主机都会回复,流量被放大几十倍甚至上百倍砸向目标。icmp_echo_ignore_broadcasts设为1后,内核会忽略发往广播地址的ICMP Echo请求,从源头掐断这种攻击。
sysctl net.ipv4.icmp_echo_ignore_broadcasts
推荐值为1。修改命令:
echo "net.ipv4.icmp_echo_ignore_broadcasts = 1" >> /etc/sysctl.conf sysctl -p
另外建议巡检时一并检查net.ipv4.icmp_ignore_bogus_error_responses(忽略非法ICMP错误响应),同样设为1。这两个参数组合起来能有效降低ICMP类攻击的风险。需要注意的是,关闭ICMP广播响应不会影响正常的ping单播测试,日常监控脚本该怎么跑还怎么跑,不用担心。
五、vm.swappiness——内存交换策略直接影响安全和性能
swappiness控制的是内核把内存数据换出到swap分区的倾向程度,取值范围0到100。值越高越积极使用swap,值越低越倾向于保留在内存中。这个参数看似和安全关系不大,实际上影响非常深远。
为什么说它和安全有关?两个原因:第一,如果swappiness设得太高(比如默认60),服务器在内存紧张时会大量使用swap,而swap通常在磁盘上,读写速度比内存慢几个数量级,这会导致关键安全进程(比如入侵检测、日志分析、加密运算)响应迟缓甚至超时,给攻击者可乘之机。第二,swap分区如果没有加密,敏感数据可能以明文形式写到磁盘上,存在数据泄露风险。
sysctl vm.swappiness
对于大多数Ubuntu服务器,推荐值为10。如果是数据库服务器或者内存密集型应用,可以设为1甚至0(0表示尽量不用swap,只在绝对必要时才换出):
echo "vm.swappiness = 10" >> /etc/sysctl.conf sysctl -p
巡检时还要确认swap分区是否加密。如果用了LUKS加密swap,可以放心设低值;如果没加密,建议把swappiness设高一些(比如60)减少swap使用频率,同时尽快规划加密方案。另外配合检查vm.dirty_ratio和vm.dirty_background_ratio,控制脏页回写策略,避免内存压力过大时系统卡死。
巡检实操:写一个自动化检查脚本
上面五个参数如果每次都手动查太麻烦,建议写个脚本放进crontab每天跑一次,输出结果到日志或者发告警。下面是一个实用的Shell脚本示例:
#!/bin/bash
LOG="/var/log/kernel_param_check.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
check_param() {
local param=$1
local expected=$2
local current=$(sysctl -n "$param" 2>/dev/null)
if [ "$current" != "$expected" ]; then
echo "[$DATE] WARNING: $param is $current, expected $expected" >> "$LOG"
else
echo "[$DATE] OK: $param = $current" >> "$LOG"
fi
}
check_param "net.ipv4.tcp_syncookies" "1"
check_param "net.ipv4.conf.all.rp_filter" "1"
check_param "kernel.randomize_va_space" "2"
check_param "net.ipv4.icmp_echo_ignore_broadcasts" "1"
check_param "vm.swappiness" "10"
把这个脚本保存为/usr/local/bin/check_kernel_params.sh,加执行权限,然后加入crontab每天凌晨2点执行:
0 2 * * * /usr/local/bin/check_kernel_params.sh
额外提醒:参数修改后的验证和回滚
任何内核参数修改都不是改完就不管了。首先要验证修改是否生效,用sysctl命令逐个确认。其次要观察业务是否受影响,至少监控24小时看有没有连接异常、性能下降、程序崩溃。如果出问题,临时回滚的方法是:
sysctl -w 参数名=原值
永久回滚就是把/etc/sysctl.conf里对应的行删掉或者注释掉,然后sysctl -p重新加载。建议在修改前先备份配置文件:
cp /etc/sysctl.conf /etc/sysctl.conf.bak.$(date +%Y%m%d)
总结:安全运维是持续的过程
这五个内核参数只是Ubuntu安全巡检的基础项,不是全部。真正的安全运维还需要关注内核版本更新、模块加载策略(/etc/modprobe.d/)、文件系统挂载选项(noexec、nosuid、nodev)、用户权限审计、日志监控等多个层面。但如果你连这五个参数都没配置好,其他做得再花哨也是空中楼阁。把这五项纳入日常巡检SOP,写进运维手册,定期检查、定期审计,你的Ubuntu服务器安全基线就能立住。安全不是一次性工程,是每天都要做的事。
