在Ubuntu系统中,将/tmp目录单独划分一个独立分区,并在挂载时设置noexec选项,是一项非常实用且推荐的安全加固措施。具体做法是:在磁盘分区阶段为/tmp分配独立空间(建议至少1-2GB),然后在/etc/fstab文件中添加对应的挂载条目,挂载参数中包含noexec、nosuid、nodev等安全选项。这样做的核心目的是防止恶意程序或攻击者在/tmp目录下直接执行二进制文件,从而大幅降低系统被提权或被植入后门的风险。下面我会从原理、操作步骤、注意事项到进阶配置,把这件事讲透。
为什么/tmp分区需要单独划分并设置noexec
/tmp目录是Linux系统中所有用户和程序都可以写入的临时文件存放地。Web服务器、数据库、编译工具、用户脚本都会往这里写文件。正因为它的开放性,/tmp一直是攻击者最喜欢的"落脚点"。如果攻击者通过某个漏洞拿到了一个低权限的shell,他第一件事往往就是往/tmp里上传一个恶意程序并执行。如果/tmp和根分区/挂在一起,攻击者不仅能写文件,还能直接运行,这等于给了他一个执行代码的温床。
把/tmp单独分区的好处有三个:第一,防止/tmp被写满导致根分区空间耗尽,系统不会因为/tmp爆满而崩溃;第二,可以针对/tmp单独设置更严格的挂载参数,而不影响系统其他目录的正常运行;第三,即使/tmp被攻破,攻击者也无法通过/tmp直接执行程序,攻击链被有效切断。
noexec参数的作用非常明确:禁止在该分区上执行任何二进制程序。注意,这不影响脚本解释器的运行(比如你用bash去执行一个.sh脚本是可以的),但直接运行一个编译好的ELF二进制文件会被内核拒绝。这对绝大多数攻击场景来说已经足够有效。
Ubuntu安装时如何划分/tmp独立分区
如果你是在全新安装Ubuntu,可以在安装向导的"分区"步骤中手动划分。选择"Something else"(其他选项),然后在空闲空间上创建一个新分区。具体参数建议如下:
分区大小:1024MB - 4096MB(根据服务器用途调整,桌面用户1GB够用,服务器建议2-4GB) 分区类型:主分区或逻辑分区均可 文件系统:ext4(最常用,稳定可靠) 挂载点:/tmp
如果你已经装好了系统,想后加/tmp分区,也完全可以。用GParted工具或者fdisk/parted命令在磁盘上划出一块空间,格式化成ext4,然后修改fstab即可。关键是要确保新分区的UUID正确获取,后面配置fstab时要用到。
获取新分区的UUID
分区创建并格式化后,用以下命令查看UUID:
sudo blkid /dev/sdXN
其中/dev/sdXN替换成你实际的分区设备名,比如/dev/sda5。输出结果中会有一行类似这样的内容:
/dev/sda5: UUID="a1b2c3d4-e5f6-7890-abcd-ef1234567890" TYPE="ext4"
把这个UUID记下来,后面写fstab要用。
配置/etc/fstab实现noexec挂载
打开fstab文件进行编辑:
sudo nano /etc/fstab
在文件末尾添加一行,格式如下:
UUID=a1b2c3d4-e5f6-7890-abcd-ef1234567890 /tmp ext4 defaults,noexec,nosuid,nodev 0 0
这里逐个解释每个参数的含义:
UUID=...:指定要挂载的分区,用UUID比用设备名更可靠,设备名可能因为硬盘顺序变化而改变。
/tmp:挂载点,告诉系统把这个分区挂到/tmp目录下。
ext4:文件系统类型。
defaults:默认挂载选项,包含rw(读写)、suid、dev、exec、auto、nouser、async等。但后面的noexec、nosuid、nodev会覆盖defaults中对应的选项。
noexec:禁止执行二进制文件,这是本文的核心参数。
nosuid:禁止set-user-identifier和set-group-identifier生效,防止通过/tmp下的程序提权。
nodev:禁止在该分区上创建设备文件,防止攻击者通过/tmp创建恶意设备节点。
最后两个0:第一个0表示不需要dump备份,第二个0表示不需要fsck检查顺序(/tmp不需要开机检查)。
验证挂载是否生效
保存fstab后,不需要重启,直接执行以下命令让配置生效:
sudo mount -a
然后用mount命令查看/tmp的挂载情况:
mount | grep /tmp
正常输出应该类似:
/dev/sda5 on /tmp type ext4 (rw,nosuid,nodev,noexec,relatime)
看到noexec、nosuid、nodev都在里面,说明配置成功。你还可以做一个简单测试:在/tmp下创建一个小的C程序编译后尝试运行,应该会报"Permission denied"错误,这就证明noexec生效了。
桌面用户需要注意的兼容性问题
这里必须提醒一个重要的点:在Ubuntu桌面版中,很多应用程序依赖/tmp来执行临时操作,比如Firefox、LibreOffice、视频播放器、甚至系统更新工具。如果你在桌面环境下对/tmp设置了noexec,可能会导致部分软件报错或功能异常。
解决办法有两个思路。第一,如果你是服务器环境,完全不用担心,服务器上的服务大多不需要在/tmp执行二进制。第二,如果你是桌面用户但仍然想加固,可以考虑使用tmpfs(内存文件系统)来挂载/tmp,而不是独立磁盘分区。tmpfs本身就支持noexec,而且速度更快,重启后自动清空,安全性更高。
# 使用tmpfs挂载/tmp的fstab写法 tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev,size=2G 0 0
size=2G表示限制tmpfs最大使用2GB内存,防止内存被耗尽。桌面用户用这种方式比较稳妥,既安全又不容易出兼容性问题。
进阶:结合其他安全措施形成纵深防御
单独划分/tmp并设置noexec只是安全加固的一环,不能指望它解决所有问题。真正有效的安全策略是多层叠加的。以下是几个建议配合使用的措施:
第一,启用AppArmor或SELinux。Ubuntu默认使用AppArmor,确保核心服务的AppArmor配置文件是启用状态。AppArmor可以限制程序能访问哪些文件和目录,即使攻击者绕过了noexec,也会被AppArmor拦截。
sudo aa-status
第二,定期清理/tmp。虽然noexec阻止了执行,但/tmp里堆积的临时文件仍然可能被利用(比如通过符号链接攻击)。建议设置定时任务定期清理:
# 在/etc/cron.daily/中创建清理脚本 sudo nano /etc/cron.daily/tmp-clean
#!/bin/bash find /tmp -type f -atime +7 -delete find /tmp -type d -empty -delete
sudo chmod +x /etc/cron.daily/tmp-clean
第三,监控/tmp的异常写入。可以用auditd审计系统监控/tmp目录的文件创建和执行行为:
sudo auditctl -w /tmp -p wa -k tmp_monitor
这条规则会记录所有对/tmp的写和属性修改操作,方便事后追溯。
常见问题排查
配置noexec后如果遇到程序报错,首先确认报错信息是否和/tmp有关。可以临时去掉noexec测试:
sudo mount -o remount,exec /tmp
如果去掉noexec后程序正常了,说明确实是noexec导致的。这时需要评估这个程序是否真的需要在/tmp执行,还是可以通过修改程序的临时目录配置(比如设置TMPDIR环境变量指向其他位置)来规避。
另外,如果系统启动时fstab配置有误,可能导致启动失败进入紧急模式。所以修改fstab后一定要先用mount -a测试,确认没有报错再重启。如果真的出问题了,可以在启动时进入恢复模式,手动编辑fstab把有问题的那行注释掉。
总结与建议
将/tmp单独分区并设置noexec是一项低成本、高收益的安全操作。对于Ubuntu服务器来说,这几乎是必做项。操作本身并不复杂,核心就是三步:分区、获取UUID、写fstab。但要注意桌面环境的兼容性,桌面用户优先考虑tmpfs方案。同时,noexec不是银弹,需要配合AppArmor、定期清理、审计监控等措施形成完整的安全体系。安全从来不是单一措施能解决的,而是需要层层设防、持续维护。
最后再强调一遍核心配置,记住这一行就够了:
UUID=你的分区UUID /tmp ext4 defaults,noexec,nosuid,nodev 0 0
把它写进fstab,mount -a生效,你的/tmp就安全了。
