1. 为什么“加个网关”这件事值得单独写一篇在 Linux 系统里给主机补一条网关路由看起来是运维工作里最不起眼的一个动作——一条ip route add命令的事。但我这些年帮人排查网络问题的经历里因为网关路由配错、配漏、配了不生效而卡住半天的案例占比高得离谱。尤其是在 Ubuntu 这类默认启用 Netplan 管理网络配置的发行版上很多人第一反应是敲route add default gw敲完发现当前终端能通一重启全没了或者改完配置文件ping网关通、ping外网不通回头一看是路由表里多了一条优先级更高的旧记录在捣乱。这篇内容就围绕“在 Ubuntu 上添加网关路由”这一件事展开把临时生效和永久生效两条路径都讲透把 Netplan、ip route、route这几套工具的关系理清楚再补上策略路由、多网卡场景、路由优先级这些实际工作中绕不开的细节。适合刚接触 Linux 网络配置的新手照着做也适合有一定基础但被 Netplan 的 YAML 缩进和renderer字段坑过的朋友对照排查。核心关键词就三个Ubuntu、网关路由、默认网关全文围绕它们展开不跑偏。先说清楚一个前提概念避免后面混淆。网关Gateway本质上是本网段内一台能帮你把流量转发到其他网段的设备通常是路由器的内网口地址。默认网关Default Gateway则是路由表里0.0.0.0/0这条目标为“任意地址”的路由所指向的下一跳所有没有更精确匹配的流量都走它。而“添加网关路由”这个动作在实操中可能指两件不同的事一是给主机设置默认网关二是给某个特定目标网段单独指定一个网关也就是静态路由。这两件事命令长得像但配置位置和生效逻辑不一样后面会分开讲。2. 动手之前先把路由表看懂2.1 三条命令看清当前网络状态在改任何配置之前先摸清现状这是我一直坚持的习惯。Ubuntu 上查看路由表最推荐的是ip route输出干净、信息全ip route show典型输出长这样default via 192.168.1.1 dev ens33 proto static metric 100 192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.50 metric 100逐字段拆一下。default via 192.168.1.1就是默认网关dev ens33说明走的是哪块网卡proto static表示这条路由是静态配置来的如果是 DHCP 下发的会显示proto dhcpmetric 100是度量值数值越小优先级越高。第二行是本网段的直连路由scope link表示目标就在本地链路上不需要经过网关。配套再看两个命令。ip addr show确认网卡名和 IP 地址网卡名这一步很关键Ubuntu 从 16.04 之后普遍采用ens33、enp0s3这类可预测命名不再是eth0配置里写错网卡名是新手最常见的翻车点之一。cat /etc/resolv.conf或者resolvectl status看 DNS因为网关配好了但 DNS 没配表现同样是“上不了网”容易误判。2.2 临时路由和永久路由的本质区别很多人搞不清为什么命令行加的路由重启就没了。原因在于 Linux 的路由表是内核里的一张内存表ip route add直接操作的是这张运行时表掉电或重启内核重新初始化表就清空了。而开机时谁来把路由表填回去在 Ubuntu 上这个角色由Netplan扮演——它读取/etc/netplan/下的 YAML 文件翻译成后端systemd-networkd或NetworkManager能理解的配置再由后端在网卡启动时把地址、路由、DNS 一并下发。所以逻辑链条是YAML 配置文件 → Netplan 解析 → 后端渲染 → 内核路由表。你只改内核表命令行链条上游没动重启自然丢失你只改 YAML 不执行netplan apply配置没被渲染当前也不生效。理解这条链后面所有操作就都有了依据。提示Ubuntu 17.10 之后 Netplan 成为默认网络配置工具老教程里改/etc/network/interfaces的方法在新版本上基本失效看到这类教程要留个心眼先确认系统版本。3. 临时添加网关路由快速验证的正确姿势3.1 设置默认网关的命令与参数拆解临时改默认网关用ip route系列最稳妥sudo ip route add default via 192.168.1.1 dev ens33如果路由表里已经存在一条默认路由上面这条会报RTNETLINK answers: File exists。这时候要么先删旧的再添新的要么用replace一步到位sudo ip route replace default via 192.168.1.1 dev ens33replace的语义是“有则替换、无则新增”比“先 del 再 add”少一次中间状态脚本里用它能避免删掉旧路由后、新路由还没加上那一瞬间的断网窗口。这个细节在网络自动化脚本里很重要我见过因为这两条命令之间隔了几百毫秒导致健康检查探针误判服务下线的案例。给特定网段加静态路由则是另一个形态sudo ip route add 10.20.0.0/16 via 192.168.1.254 dev ens33意思是“要去 10.20.0.0/16 这个网段的包交给 192.168.1.254 转发”。注意这里的via地址必须和本机某块网卡在同一网段、且可达否则内核会直接拒绝并报Nexthop has invalid gateway。这个报错我踩过不止一次本质是内核在加路由前会做一次下一跳可达性校验网关地址本身都 ping 不通路由自然加不上。3.2 用 route 命令的兼容写法及注意事项老系统或老脚本里常见route命令sudo route add default gw 192.168.1.1它在 Ubuntu 上通常还能用但route属于net-tools包新版本 Ubuntu 默认不再预装需要sudo apt install net-tools才有。而且route的输出格式老旧、不支持策略路由等新特性我的建议是新环境一律用ip routeroute只在维护老脚本时作为兼容手段。两者操作的是同一张内核路由表混用不会冲突但排查时容易看花眼统一工具能省不少事。临时路由的价值在于“验证”。比如你怀疑是网关地址配错了先用ip route replace切到正确网关ping一下外网通了就说明判断成立再去改永久配置。这种“先验证后固化”的顺序比直接改配置文件然后netplan apply试错要安全得多——后者一旦 YAML 写错可能直接把网卡配置搞挂远程连接当场断掉。注意如果你是通过 SSH 远程操作服务器改默认网关前务必确认新网关可达、且不会把你自己的管理连接路由到黑洞里。稳妥做法是开一个带定时回滚的后台任务或者干脆用带外管理口操作。4. Netplan 永久配置YAML 里的门道4.1 找到并读懂现有的 Netplan 配置文件先看目录里有什么ls -l /etc/netplan/常见文件名是00-installer-config.yaml、01-netcfg.yaml或50-cloud-init.yaml。文件名前面的数字决定加载顺序数字小的先加载后面的会覆盖前面的同名配置。云主机上经常是50-cloud-init.yaml这个文件由 cloud-init 生成直接改它有时会被下次启动覆盖更稳的做法是新建一个序号更大的文件比如99-custom.yaml来叠加配置。打开文件看结构典型内容network: version: 2 renderer: networkd ethernets: ens33: dhcp4: false addresses: - 192.168.1.50/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: [223.5.5.5, 119.29.29.29]几个关键字段必须理解到位。renderer决定后端是networkd还是NetworkManager服务器版一般是networkd桌面版可能是NetworkManager写错会导致配置不生效且不报明显错误。routes下的to: default就是默认网关的写法等价于0.0.0.0/0老版本 Netplan 用的是gateway4字段新版本已标记废弃混用会出警告甚至报错。4.2 添加默认网关和静态路由的完整写法给已有网卡补默认网关在对应网卡的routes列表里加一项network: version: 2 renderer: networkd ethernets: ens33: dhcp4: false addresses: [192.168.1.50/24] routes: - to: default via: 192.168.1.1 metric: 100加静态路由就是再加一个列表项routes: - to: default via: 192.168.1.1 metric: 100 - to: 10.20.0.0/16 via: 192.168.1.254 metric: 200metric字段建议显式写上。不写时不同后端给的默认值不一样多网卡环境下容易出现“默认路由抢主”的问题——两块网卡都配了默认网关谁先起来谁生效重启顺序一变网络行为就变非常难排查。显式指定 metric让主线路数值小、备线路数值大行为就确定了。YAML 的缩进是硬性要求只能用空格不能用 Tab同级字段对齐必须严格。我见过太多因为复制粘贴带进了 Tab 或者多了一个空格netplan apply报Invalid YAML的情况。写完先用netplan try验证sudo netplan try它会先应用配置并启动一个 120 秒倒计时期间网络若异常你可以按回车回滚超时无操作则自动确认。这个机制对远程操作极其友好相当于给你留了一条退路。确认没问题后再sudo netplan apply正式生效。4.3 多网卡多网关的配置策略一台机器两块网卡、各连一个网络、各有网关这是很常见的双线路场景。配置时给两块网卡分别写 routes用 metric 区分主备ethernets: ens33: dhcp4: false addresses: [192.168.1.50/24] routes: - to: default via: 192.168.1.1 metric: 100 ens34: dhcp4: false addresses: [192.168.2.50/24] routes: - to: default via: 192.168.2.1 metric: 200这样默认流量走 ens33ens33 断了配合链路监测才切到 ens34。但要注意metric 只影响默认路由的选择源地址选择是另一套逻辑——从 ens34 出去的包源 IP 可能还是 ens33 的地址导致对端回包走错路径。这种非对称路由问题在双线路环境里很典型解决办法是上策略路由用ip rule按源地址或目的地址分流这部分内容放在第 6 节展开。5. 配置生效与验证的完整闭环5.1 从 apply 到路由表落地的检查清单netplan apply执行完不代表万事大吉按顺序做这几步检查ip route show确认默认路由和静态路由都在via地址和metric符合预期ip addr show ens33确认 IP 地址没丢改配置时误删addresses字段是常见事故ping -c 3 192.168.1.1确认网关可达ping -c 3 223.5.5.5确认外网 IP 层通ping -c 3 www.example.com确认 DNS 解析正常。这五步是一个从链路层到应用层的递进验证链哪一步断了问题范围立刻缩小。网关通但外网 IP 不通问题在网关设备或上游外网 IP 通但域名不通问题在 DNS。分层的排查思路比盲目重启服务高效得多。5.2 重启后配置丢失的排查路径如果netplan apply后正常、重启后失效按这个顺序查排查点检查命令常见原因配置文件是否被覆盖ls -l /etc/netplan/cloud-init 重新生成了配置YAML 是否语法正确sudo netplan generate缩进、Tab、字段名拼写renderer 是否匹配systemctl status systemd-networkd后端服务未运行是否有更高优先级配置检查文件名序号后加载文件覆盖了前面的网卡名是否变化ip link show硬件变动导致命名改变sudo netplan generate只做语法解析和配置生成、不实际应用是排查 YAML 问题的利器报错信息比apply更直接。另外云主机上要特别留意 cloud-init它可能在每次启动时根据元数据重写网络配置这时候需要修改 cloud-init 的配置源或者在 Netplan 文件里做好叠加而不是跟它对着干。6. 进阶策略路由解决“网关加了但不走”的怪问题6.1 什么时候需要策略路由默认路由只有一条时一切简单。但当你遇到“明明加了去某网段的路由流量却还是从另一块网卡出去”的情况多半是源地址选择在作祟。Linux 默认的路由决策只看目的地址选好出口网卡后源 IP 由该网卡的主地址决定。如果出口网卡的主地址不是对端期望的地址回包就可能被丢弃。策略路由的思路是不只看目的地址还看源地址、入接口、防火墙标记等条件为不同流量指定不同的路由表。这在多线路、多租户、容器网络场景里是刚需。6.2 用 ip rule 和自定义路由表分流假设需求是来自 192.168.2.0/24 的流量走 ens34 的网关 192.168.2.1其余走默认。步骤是先在自定义路由表里写好路由再用规则把流量导过去# 在表 100 里加默认路由 sudo ip route add default via 192.168.2.1 dev ens34 table 100 # 让来自 192.168.2.0/24 的流量查表 100 sudo ip rule add from 192.168.2.0/24 table 100 priority 1000 # 查看规则 ip rule showpriority数值越小越先匹配内置规则里local表优先级是 0main表是 32766自定义规则插在中间即可。这套配置要永久生效Netplan 里对应写法是在网卡下加routing-policyrouting-policy: - from: 192.168.2.0/24 table: 100 routes: - to: default via: 192.168.2.1 table: 100注意routes里的table字段和routing-policy要成对出现只写一个不生效。这块配置的坑在于自定义路由表里的路由不会自动出现在ip route show的默认输出里得用ip route show table 100单独看排查时容易误以为没配上。7. 实操中踩过的坑与速查表7.1 高频报错与对应解法报错信息触发场景解决方向RTNETLINK answers: File exists重复添加同目标路由改用replace或先delNexthop has invalid gateway网关地址不可达检查网关与本机是否同网段、链路是否 upInvalid YAML缩进或 Tab 问题用netplan generate定位行号Permission denied忘记 sudo加sudo执行配置生效但重启丢失只改了运行时表改 Netplan YAML 并 apply网关通但域名不通DNS 未配置检查nameservers字段7.2 几条不写在文档里的经验第一改网络配置前先备份。sudo cp /etc/netplan/xxx.yaml /etc/netplan/xxx.yaml.bak一行命令的事出问题时能救命。远程操作时我还会额外开一个at定时任务十分钟后自动恢复备份并重启网络给自己留足回滚窗口。第二netplan try比apply更适合远程。它的自动回滚机制相当于给配置加了个保险尤其是改默认网关这种可能断连的操作养成先用try的习惯。第三metric 一定要显式写。默认值的不确定性是多网卡环境最大的隐形炸弹写死数值让行为可预测比事后排查省心一百倍。第四验证要分层。网关、外网 IP、域名三步走别一上来就ping域名DNS 问题会掩盖路由问题让你在错误的方向上浪费时间。第五容器和虚拟机里的路由要分清命名空间。在宿主机上ip route看到的路由和容器内看到的是两套表排查容器网络问题时记得nsenter进对应命名空间再看否则会对着宿主机正常的路由表一头雾水。这套流程我在不同版本的 Ubuntu 上反复用过从 18.04 到 24.04 主体逻辑没变变的只是 Netplan 字段的废弃与新增比如gateway4退场、routes成为标准写法。遇到老教程和老脚本先对照版本确认字段是否还受支持比直接照抄稳妥。网络配置这件事慢一点、验一层、留条后路比快一步然后断线重连要划算得多。