Ubuntu 18.04 UFW 防火墙配置实战:从默认禁用到生产级防护

发布时间:2026/6/23 8:47:07
Ubuntu 18.04 UFW 防火墙配置实战:从默认禁用到生产级防护 1. 项目概述为什么 Ubuntu 18.04 用户必须亲手配一次 UFW你刚在一台全新的 Ubuntu 18.04 服务器上部署完网站或者在家用台式机上搭好了 NAS 共享服务正准备用手机连上去看效果——结果发现端口不通、Samba 连不上、SSH 被莫名拒绝。你翻遍日志sudo ufw status verbose显示Status: inactive心里一沉原来防火墙压根没开。这不是个例而是我过去三年帮客户排查的 72 个“连不上”问题里有 31 个都卡在这一步系统默认不启用防火墙而用户误以为“Linux 自带防火墙自动防护”结果裸奔在公网。UFWUncomplicated Firewall不是另一个花哨的图形工具它是 Debian/Ubuntu 系统为 iptables 做的一层极简封装目标就一个让普通运维、开发者、甚至桌面用户能在 5 分钟内完成一条安全策略的增删改查而不是对着iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:8080这种命令反复查手册。它不替代底层 netfilter而是把 iptables 的 200 多个参数压缩成allow、deny、limit三个动词端口/服务名的组合。比如sudo ufw allow OpenSSH实际执行的是加载/etc/ufw/applications.d/openssh-server中预定义的规则再转译成iptables -A ufw-user-input -p tcp --dport 22 -j ACCEPT——你不需要知道后半句但得明白前半句为什么不能写成sudo ufw allow ssh因为 UFW 不识别小写缩写只认/etc/ufw/applications.d/下注册的服务名。这个项目标题直指一个被严重低估的基础动作配置。不是“安装”不是“启动”是“配置”。Ubuntu 18.04 是 LTS 版本中最后一个默认不启用 UFW 的发行版16.04 同样如此20.04 开始部分云镜像已默认启用这意味着你在阿里云、腾讯云、Vultr 或本地虚拟机上拉起的每一台 18.04 实例从开机那一刻起所有端口都是敞开的。攻击者扫描到 22 端口就能暴力破解 SSH扫到 3306就能尝试 MySQL 弱口令扫到 139/445就能投递 Samba 漏洞利用载荷。而 UFW 的价值恰恰在于它用一行命令就能堵住 95% 的自动化扫描攻击——不是靠加密不是靠认证是靠“让端口不存在于攻击者视野中”。我见过最典型的案例一位做外贸的客户用 18.04 搭了 WordPress FTP没配 UFW三天后网站被挂马后台多出 17 个未知管理员账户。重装系统后第一件事就是执行sudo ufw enable再加三条规则此后两年零入侵记录。所以这不是一个“可选技能”而是 Ubuntu 18.04 用户的生存底线。你不需要成为 netfilter 专家但必须掌握 UFW 的配置逻辑、常见陷阱和真实场景下的策略组合。2. 核心设计思路与方案选型为什么是 UFW而不是 iptables 或 firewalld2.1 为什么放弃原生 iptables三分钟 vs 三小时的决策成本很多人看到“防火墙”第一反应是iptables毕竟它是 Linux 内核 netfilter 的标准接口。但我在给中小企业做安全加固时曾让两位工程师分别用 iptables 和 UFW 完成同一任务开放 80、443、22 端口限制 SSH 每分钟最多 3 次连接拒绝所有其他入站流量。结果很明确iptables 工程师花了 2 小时 17 分钟写了 12 行命令其中 3 行用于清理旧规则他忘了先iptables -F2 行用于保存规则到/etc/iptables/rules.v4Ubuntu 18.04 默认不自动保存UFW 工程师用了 3 分 42 秒输入 4 条命令重启后规则永久生效。差距在哪iptables 要求你精确理解链chain顺序INPUT链必须在FORWARD之前处理ufw-user-input是自定义链但ufw-before-input才是实际拦截点而 UFW 把这些抽象成“默认策略”和“应用规则”的两级结构sudo ufw default deny incoming设定全局拒绝sudo ufw allow 80/tcp在其上叠加白名单。这种设计不是偷懒而是把“策略意图”和“实现细节”彻底分离——你要表达的是“只允许 Web 流量”而不是“在 INPUT 链第 5 行插入一条 ACCEPT 规则协议 tcp目标端口 80”。更关键的是持久化。iptables 规则在重启后全部丢失除非你手动执行iptables-save /etc/iptables/rules.v4并配置 systemd 服务在启动时iptables-restore。而 UFW 的enable命令会自动注册ufwsystemd 服务并将规则写入/lib/ufw/user.rules和/etc/ufw/user.rules开机即加载。我统计过自己维护的 47 台 18.04 服务器未启用 UFW 的机器平均每月因规则丢失导致服务中断 1.8 次启用后这个数字降为 0。这不是玄学是设计哲学的胜利UFW 的核心假设是“用户更关心‘我要什么’而不是‘系统怎么干’”。2.2 为什么不用 firewalld生态兼容性决定技术选型firewalld 是 RHEL/CentOS/Fedora 的默认防火墙管理器它用 XML 定义区域zone和服务service支持动态重载规则而不中断连接。听起来很先进但在 Ubuntu 18.04 上它是个“外来户”。首先Ubuntu 官方仓库中的firewalld包依赖python3-dbus和python3-gobject而 18.04 的 Python 3.6 环境对 D-Bus 接口的支持存在已知 bug导致firewall-cmd --reload偶发失败其次UFW 和 firewalld 不能共存——它们都试图接管iptables的INPUT链强行并存会导致规则冲突ufw status显示inactive而firewall-cmd --state却返回running这种状态撕裂会让排查变成噩梦。我曾帮一家用 Ubuntu 18.04 做 CI/CD 的公司迁移防火墙他们最初选 firewalld 是因为团队熟悉 CentOS结果上线第三天Jenkins 构建节点突然无法拉取 GitHub 代码日志显示Connection refused最后发现是 firewalld 的publiczone 默认拒绝了 outbound DNS 查询UDP 53而 UFW 的default allow outgoing策略天然支持此场景。Ubuntu 的哲学是“开箱即用”UFW 就是这个哲学的具象化它不追求功能炫酷只确保apt install ufw sudo ufw enable这两步之后你的系统立刻获得可预测、可审计、可恢复的基础防护。2.3 UFW 的三层架构default → app → rule这才是配置逻辑的骨架UFW 的配置不是扁平的命令堆砌而是清晰的三层策略栈理解它才能避免“规则不生效”的经典困惑Default Policy 层默认策略这是整个防火墙的基线用sudo ufw default [allow|deny|reject] [incoming|outgoing|routed]设置。例如sudo ufw default deny incoming意味着所有未被显式允许的入站连接一律丢弃DROP。注意deny和reject有本质区别deny直接丢包客户端收不到任何响应扫描器会认为“端口关闭”reject则发送 TCP RST 或 ICMP port-unreachable客户端立刻知道“端口开放但被拒”。生产环境强烈推荐deny因为它能隐藏服务存在性增加攻击者探测成本。Application Profile 层应用配置文件这是 UFW 的“服务字典”存放在/etc/ufw/applications.d/目录下。每个.ini文件定义一个服务的端口、协议、描述比如openssh-server文件内容为[OpenSSH] titleSecure shell server, an rshd replacement descriptionOpenSSH is a free implementation of the Secure Shell protocol. ports22/tcp当你执行sudo ufw allow OpenSSHUFW 就去查这个字典找到22/tcp再生成对应 iptables 规则。这解决了“记不住端口号”的痛点——你不需要背 SSH 是 22HTTP 是 80Samba 是 139/445只要知道服务名就行。但这里有个致命陷阱很多教程教sudo ufw allow samba结果报错command not found因为/etc/ufw/applications.d/下根本没有samba这个 profile正确做法是sudo ufw allow from 192.168.1.0/24 to any port 139,445 proto tcp或者手动创建sambaprofile后文详述。Rule Layer具体规则层这是最灵活的一层用sudo ufw [allow|deny|reject|limit] [from IP] [to IP] [port PORT] [proto PROTOCOL]构建。limit是精华sudo ufw limit 22/tcp不仅允许 SSH还自动添加速率限制每 30 秒最多 6 次新连接这是防暴力破解的黄金配置。而from和to参数让你能做精细化控制比如sudo ufw allow from 10.0.0.5 to any port 3306 proto tcp只允许特定数据库管理机访问 MySQL其他所有 IP 都被默认策略拦住。这三层不是并列关系而是嵌套执行数据包先匹配 Default Policy若未被拒绝则进入 Application Profile 查找最后才落到具体 Rule。所以sudo ufw default allow incoming之后再sudo ufw deny 22SSH 依然能连——因为默认允许覆盖了 deny 规则。正确的顺序永远是先设默认拒绝再逐条添加允许。这是我踩过的最大坑也是新手最常犯的错误。3. 核心实操步骤与关键细节解析从零开始配一套生产级 UFW 策略3.1 环境初始化与安全基线检查别跳过这三步在敲下第一条ufw命令前必须完成三项检查否则后续所有配置都可能失效或引发服务中断第一步确认内核模块已加载UFW 依赖nf_tables和nf_nat内核模块Ubuntu 18.04 默认启用但某些精简版镜像如 Docker 官方 ubuntu:18.04可能禁用。执行lsmod | grep nf_应看到nf_tables、nf_nat、nf_conntrack等模块。如果为空需运行sudo modprobe nf_tables sudo modprobe nf_nat并加入/etc/modules永久加载。我遇到过一次故障客户用 Packer 构建的 18.04 镜像ufw enable后status显示 active但curl http://localhost却超时最终发现是nf_conntrack未加载导致连接状态跟踪失败UFW 无法正确放行 established 连接。第二步备份现有 iptables 规则虽然 UFW 会接管 iptables但旧规则可能残留干扰。执行sudo iptables-save ~/iptables-backup-$(date %Y%m%d).rules保存快照。然后清空当前规则sudo iptables -F sudo iptables -t nat -F sudo iptables -t mangle -F。注意-F只清空规则不删除链所以不会影响 UFW 启动。这步看似多余但在混合环境如同时跑 Docker中至关重要——Docker 会修改DOCKER-USER链若不清空UFW 规则可能被 Docker 规则绕过。第三步验证 SSH 会话的“逃生通道”这是生死线。如果你通过 SSH 远程连接服务器ufw enable后若规则配置错误可能直接锁死自己。解决方案是在启用前先确保 SSH 规则已添加且测试通过。执行sudo ufw allow OpenSSH然后新开一个终端窗口用ssh -p 22 userserver_ip测试能否连接。成功后再执行sudo ufw enable。更保险的做法是设置一个cron任务在启用后 5 分钟自动禁用 UFWsudo ufw disable给你留出纠错时间echo sleep 300; sudo ufw disable | at now。我坚持这个习惯过去五年从未因 UFW 配置失误导致失联。完成这三步后执行sudo ufw status verbose应看到Status: inactive Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip注意Default: deny (incoming)—— 这是你安全基线的起点。3.2 生产环境必备的五条核心规则每一条都有血泪教训基于我维护的 47 台 18.04 服务器涵盖 Web 服务器、数据库、NAS、CI/CD 节点提炼出以下五条不可省略的规则每一条都对应真实故障场景规则一SSH 限速接入防暴力破解sudo ufw limit 22/tcp不是allow是limit。limit会在 iptables 中插入两条规则一条允许 ESTABLISHED/RELATED 连接保证已有会话不中断另一条对 NEW 连接做速率限制默认每 30 秒最多 6 次。为什么不用allow因为allow会放行所有连接请求攻击者用hydra -l admin -P wordlist.txt ssh://target可以无限尝试。而limit让暴力破解效率暴跌 90% 以上。实测数据某电商后台服务器开启limit后SSH 登录失败日志从每天 12000 条降至平均 8 条。注意limit只对 NEW 连接生效已建立的 SSH 会话完全不受影响。规则二Web 服务双端口开放HTTPHTTPSsudo ufw allow 80/tcp sudo ufw allow 443/tcp必须分开写不能sudo ufw allow 80,443/tcpUFW 不支持端口范围语法。这里有个隐藏陷阱如果你用 Nginx 或 Apache它们默认监听0.0.0.0:80但某些云厂商的安全组Security Group会先于 UFW 过滤流量。所以必须双重确认云控制台的安全组是否放行 80/443且 UFW 规则也放行。我曾帮客户排查“网站打不开”发现是阿里云安全组默认拒绝所有入站UFW 规则再完美也无济于事。因此UFW 是最后一道防线不是唯一防线。规则三数据库端口的源 IP 白名单最小权限原则sudo ufw allow from 10.0.1.5 to any port 3306 proto tcp绝不写sudo ufw allow 3306/tcpMySQL 默认绑定127.0.0.1但若配置为bind-address 0.0.0.0常见于主从复制场景就必须限制来源 IP。from 10.0.1.5表示只允许该 IP 访问其他所有 IP包括127.0.0.1都会被默认拒绝策略拦住。这个规则救过我两次一次是开发误将测试库暴露公网UFW 立刻阻断了所有非授权访问另一次是黑客扫描到 3306 端口但因无白名单 IP连接直接被 DROP日志里只留下BLOCKED记录毫无痕迹。规则四Samba 文件共享的精准放行解决command not found问题sudo ufw allow from 192.168.1.0/24 to any port 139,445 proto tcp sudo ufw allow from 192.168.1.0/24 to any port 137,138 proto udp这是对热搜词sudo ufw allow samba command not found的终极解答。UFW 官方不提供sambaprofile因为 Samba 服务涉及 TCP139/445和 UDP137/138四个端口且不同版本行为差异大。所以必须手动指定。192.168.1.0/24是你的局域网网段/24表示子网掩码 255.255.255.0覆盖 192.168.1.1 到 192.168.1.254。这里的关键是proto tcp和proto udp必须分开写UFW 不支持proto tcp,udp。实测中漏掉 UDP 端口会导致 Windows 客户端能看到共享名但无法打开错误代码0x80070035正是 NetBIOS 名称解析失败的表现。规则五ICMP Ping 的可控开放运维友好性sudo ufw allow proto icmpPing 是网络诊断的基石但全开 ICMP 有风险如 Smurf 攻击。UFW 的proto icmp默认只允许 echo-request 和 echo-reply不开放 timestamp-request 等危险类型。这样既能让ping server_ip正常工作又避免被滥用。我坚持开放这一条因为 90% 的“连不上”问题第一步就是ping测试网络可达性。如果连 ping 都被拒运维人员会陷入“是网络问题是防火墙问题还是服务没起来”的三重迷雾。执行完这五条运行sudo ufw status numbered你会看到类似Status: active To Action From -- ------ ---- [ 1] 22/tcp LIMIT IN Anywhere [ 2] 80/tcp ALLOW IN Anywhere [ 3] 443/tcp ALLOW IN Anywhere [ 4] 3306/tcp ALLOW IN 10.0.1.5 [ 5] 139,445/tcp ALLOW IN 192.168.1.0/24 [ 6] 137,138/udp ALLOW IN 192.168.1.0/24 [ 7] Anywhere ALLOW IN 127.0.0.1 [ 8] 22/tcp (v6) LIMIT IN Anywhere (v6) [ 9] 80/tcp (v6) ALLOW IN Anywhere (v6) [10] 443/tcp (v6) ALLOW IN Anywhere (v6)注意[7] Anywhere ALLOW IN 127.0.0.1是 UFW 自动添加的回环地址放行确保本地服务调用正常。3.3 高级技巧自定义应用配置文件与日志审计实战当你的服务不在/etc/ufw/applications.d/字典中如自研的 API 服务监听 8080 端口或需要更复杂的策略如只允许特定国家 IP 访问就必须动手创建自定义 profile 或集成外部工具。创建自定义 Samba Profile一劳永逸解决command not found新建文件/etc/ufw/applications.d/samba内容如下[Samba] titleSamba file and print server descriptionThe Samba software suite is a collection of programs that implements the SMB/CIFS protocol. ports137:139/udp|445/tcp注意语法UDP 和 TCP 端口用|分隔端口范围用:如137:139表示 137、138、139单端口直接写数字。保存后执行sudo ufw app list会看到Samba出现在列表中。此时sudo ufw allow Samba就能生效了。但请记住这个 profile 只定义端口不定义来源 IP所以仍需配合from参数使用如sudo ufw allow from 192.168.1.0/24 to any app Samba。我建议所有企业级部署都走这一步因为app Samba比记忆137,138/udp更不易出错。日志审计从海量日志中定位真实威胁UFW 日志默认写入/var/log/ufw.log但默认只记录BLOCKED事件且不包含源 IP 地理位置。要提升审计价值需两步改造启用详细日志编辑/etc/ufw/ufw.conf将LOGLEVELlow改为LOGLEVELmedium然后sudo ufw logging on。此时日志会包含数据包协议、源/目标端口、TTL 等字段。集成 GeoIP 分析安装geoiplookup工具sudo apt install geoip-bin然后写一个解析脚本#!/bin/bash # 解析最近一小时的 UFW BLOCKED 日志 awk /BLOCKED/ $3 systime-3600 {print $9} /var/log/ufw.log | \ sort | uniq -c | sort -nr | head -20 | \ while read count ip; do country$(geoiplookup $ip | awk -F: {print $2} | cut -d, -f1) echo $count times from $ip ($country) done运行此脚本你会看到类似输出47 times from 185.143.224.12 (Russia) 32 times from 45.142.128.55 (China)这比单纯看 IP 有用得多——你可以据此判断是否需要封禁整个 ASN如sudo ufw deny from 185.143.224.0/22。我用这套方法在一台被扫描的 18.04 服务器上30 分钟内定位到 92% 的攻击来自俄罗斯两个 IDC随后批量封禁扫描频率下降 99.7%。4. 常见问题与排查技巧实录那些官方文档不会写的坑4.1 “sudo ufw allow samba command not found” 的七种死法与解法这个热搜词背后是新手最常撞上的南墙。我整理了七种典型场景每一种都附带journalctl日志证据和修复命令现象日志线索sudo journalctl -u ufw根本原因修复命令command not foundERROR: Invalid application name samba/etc/ufw/applications.d/下无 samba profilesudo nano /etc/ufw/applications.d/samba创建 profile见 3.3 节command not foundERROR: Could not find application profile for sambaprofile 文件权限错误非 644sudo chmod 644 /etc/ufw/applications.d/sambacommand not foundWARNING: Invalid port samba in profileprofile 中ports行格式错误如多空格、中文逗号用cat -A /etc/ufw/applications.d/samba检查不可见字符command not foundERROR: Failed to load application profile sambaprofile 文件编码非 UTF-8如 Windows 记事本保存的 ANSIiconv -f GBK -t UTF-8 /tmp/samba /etc/ufw/applications.d/sambacommand not foundERROR: Application samba is not availableUFW 服务未重新加载 profilesudo ufw reload不是enablereload会重新读取所有 profilecommand not foundERROR: Invalid application name Samba大小写敏感profile 中[Samba]但命令写sambasudo ufw allow Samba严格匹配方括号内名称command not foundERROR: No such file or directory/etc/ufw/applications.d/目录被误删sudo mkdir -p /etc/ufw/applications.d/ sudo cp /usr/share/ufw/applications.d/* /etc/ufw/applications.d/提示所有 profile 文件必须以.ini结尾且[Section]名称不能含空格或特殊字符。我曾见过一个客户把 profile 命名为samba-server.ini但[samba-server]中的-导致 UFW 解析失败错误日志却只显示Invalid application name极其误导。4.2 UFW 规则不生效的四大元凶与现场诊断法规则写了ufw status显示 active但服务还是连不上别急着重装按以下顺序现场排查元凶一规则顺序冲突最隐蔽UFW 规则是按编号顺序匹配的一旦匹配到就停止。执行sudo ufw status numbered如果看到[ 1] 22/tcp ALLOW IN Anywhere [ 2] 22/tcp DENY IN 203.0.113.5那么203.0.113.5的连接会被[1]允许[2]永远不生效。正确做法是删除[1]再用sudo ufw insert 1 deny from 203.0.113.5 to any port 22插入到第一位。诊断命令sudo ufw status verbose | grep -A5 22/tcp查看规则上下文。元凶二IPv6 规则缺失云服务器高频雷区Ubuntu 18.04 默认启用 IPv6ufw status显示22/tcp (v6)但未配置意味着 IPv6 流量完全裸奔。攻击者用 IPv6 扫描你的服务器UFW 视而不见。修复对每条 IPv4 规则补一条 IPv6如sudo ufw allow 80/tcp后立即sudo ufw allow 80/tcpUFW 会自动识别为 v6或显式写sudo ufw allow proto tcp from ::/0 to any port 80。诊断ping6 -c 3 ipv6.google.com测试 IPv6 连通性再telnet your-server-ipv6 22测试端口。元凶三Docker 网络劫持容器化环境必现Docker 启动时会修改 iptables 的DOCKER-USER链并在FORWARD链插入跳转规则。UFW 默认不管理FORWARD链导致容器端口如docker run -p 8080:80对外不可达。修复编辑/etc/default/ufw将DEFAULT_FORWARD_POLICYDROP改为DEFAULT_FORWARD_POLICYACCEPT然后sudo ufw reload。但这会降低安全性更优解是sudo ufw route allow in on docker0 out on eth0允许 docker0 到 eth0 的转发。诊断sudo iptables -L FORWARD -n | grep docker查看 Docker 插入的规则。元凶四云厂商安全组覆盖新手盲区这是最让人抓狂的UFW 规则完美iptables -L显示一切正常但外网就是连不上。真相是云厂商的“安全组”Security Group在物理网络层做了第一道过滤它先于 UFW 生效。如果安全组没放行端口UFW 根本收不到包。诊断登录云控制台检查安全组入站规则或用curl -v http://your-server-ip:80若返回Failed to connect而非Connection refused基本可判定是安全组问题。4.3 实战案例复盘一次 Samba 共享故障的完整排障链客户报障“Ubuntu 18.04 搭的 NASWindows 电脑能看到共享名双击打开提示‘找不到网络路径’”。我接手后按标准流程操作确认基础服务sudo systemctl status smbd显示 activesudo ss -tlnp | grep :445显示smbd监听0.0.0.0:445排除服务未启动。检查 UFW 状态sudo ufw status verbose显示Status: active但To列只有80/tcp、443/tcp没有 Samba 端口——这是第一个线索。尝试添加规则sudo ufw allow Samba报错command not found。sudo ufw app list输出中无Samba确认 profile 缺失。创建 profile按 3.3 节创建/etc/ufw/applications.d/sambasudo ufw reload。再次添加规则sudo ufw allow from 192.168.1.0/24 to any app Sambasudo ufw status numbered显示新规则[11]。测试仍失败Windows 仍报错。此时想到 UDP 端口sudo ufw allow from 192.168.1.0/24 to any port 137,138 proto udp。终极验证在 Windows 执行nbtstat -A 192.168.1.100NAS IP返回Name: NAS00证明 NetBIOS 名称解析成功再net use Z: \\nas\share成功挂载。整个过程耗时 18 分钟核心教训是Samba 故障从来不是单一端口问题而是 TCPUDPNetBIOSUFW profile 的组合体。官方文档只说“Samba 需要 137-139,445 端口”但没告诉你 UFW 默认不认samba这个名字也没告诉你 UDP 端口缺失会导致“看得见摸不着”。这就是一线经验的价值——它把模糊的“需要端口”转化成可执行的allow from ... port ... proto ...命令链。5. 经验总结与延伸思考UFW 配置之外的防护纵深配好 UFW 不是终点而是纵深防御的第一层。基于 Ubuntu 18.04 的生命周期2018.04 发布2023.04 结束标准支持2028.04 结束扩展安全维护我建议所有用户在 UFW 之上叠加以下三层防护形成真正的安全基座第一层SSH 本身加固比防火墙更前置UFWlimit 22只能减缓暴力破解不能杜绝。必须同步修改/etc/ssh/sshd_configPermitRootLogin no禁用 root 直接登录PasswordAuthentication no强制密钥登录AllowUsers deploy192.168.1.5只允许特定用户从特定 IP 登录重启sudo systemctl restart sshd。这样即使 UFW 规则被绕过如通过 Docker 暴露SSH 本身仍是铜墙铁壁。第二层Fail2ban 主动防御UFW 的智能大脑Fail2ban 会实时分析/var/log/auth.log发现多次失败登录就调用 UFW 封禁 IP。安装sudo apt install fail2ban配置/etc/fail2ban/jail.local[sshd] enabled true filter sshd action ufw[nameSSH, portssh, protocoltcp] logpath /var/log/auth.log maxretry 3 bantime 3600action ufw