Ubuntu静态IP配置实战:Netplan+DNS稳定设置指南
1. 为什么现在还要手动配静态IP别被“自动获取”骗了在Ubuntu桌面版刚装好、连上路由器那一刻你大概率会看到网络图标右下角有个小勾——系统已经通过DHCP自动分配了IP、子网掩码、网关和DNS一切看起来丝滑顺畅。但如果你正准备把这台机器当开发服务器用、要跑Docker容器、要搭内网GitLab、要让同事能稳定SSH连进来或者只是想给树莓派做NAS时确保每次重启地址不变……那这个“自动获取”就成了一颗随时可能引爆的哑弹。我见过太多人踩坑明明昨天还能用ssh pi192.168.1.105连上树莓派今天重启后死活连不上查日志发现IP变成了192.168.1.137也见过团队协作时前端调用后端API的地址写死在.env里是http://192.168.1.50:3000结果后端同学一重启电脑整个联调环境崩掉大家盯着控制台里一堆ECONNREFUSED发呆。这些都不是玄学而是对网络基础配置缺乏掌控力的直接后果。Ubuntu系统入门教程里讲静态IP绝不是教你怎么“复古”而是帮你建立一套可预期、可复现、可交付的网络环境。它解决的核心问题就三个地址不漂移、服务可寻址、解析不抽风。尤其在局域网多设备协同场景下一个稳定的IP是所有后续操作的基石。DNS同理——你以为ping baidu.com能通就万事大吉等你真要用curl https://registry.npmjs.org拉包、用apt update升级系统、甚至只是打开浏览器访问公司内部WikiDNS一旦出问题表现出来的症状全是“连不上”但根源却藏在/etc/resolv.conf里那几行被NetworkManager反复覆盖的配置中。所以这篇教程不讲概念堆砌只讲你打开终端后敲哪几行命令、改哪几个文件、为什么这么改、改错会怎样——全部基于Ubuntu 22.04/24.04 LTS真实环境实测适配桌面版GNOME和Server版双场景新手照着打不会翻车老手也能捡到几个被忽略的细节。2. 网络配置体系全景图别再瞎改/etc/network/interfaces了Ubuntu从18.04开始全面转向Netplan作为默认网络配置后端这是理解整个静态IP设置逻辑的前提。很多人卡在第一步就是因为还在网上搜到的老旧教程里找/etc/network/interfaces改完发现重启网络服务没反应或者systemctl restart networking直接报错。这不是你手误是Ubuntu早已把这套旧机制标记为“deprecated”已弃用。Netplan本身不直接管理网络它是个YAML格式的声明式配置生成器负责把你的意图翻译成底层实际执行的工具通常是systemd-networkd或NetworkManager能读懂的指令。你可以把它想象成一个严谨的项目经理你只用在/etc/netplan/*.yaml里写清楚“我要什么”它自动协调下面的工程师systemd-networkd或NetworkManager去干活。那么问题来了到底该用systemd-networkd还是NetworkManager答案取决于你的Ubuntu版本和使用场景Ubuntu DesktopGNOME默认用NetworkManager它擅长处理Wi-Fi切换、VPN连接、图形界面下的网络状态监控但对静态IP的DNS配置支持比较“佛系”——它会优先读取DHCP服务器下发的DNS手动指定的DNS容易被覆盖。Ubuntu Server默认用systemd-networkd轻量、稳定、启动快对静态IP和DNS的控制粒度更细配置一次基本不用操心。提示不要试图强行把Desktop版的NetworkManager替换成systemd-networkd除非你明确知道自己在做什么。同样Server版也不建议硬装NetworkManager——它会和systemd-networkd抢网卡控制权导致ip a显示地址重复或消失。判断当前系统用的是哪个执行sudo lshw -class network | grep configuration如果看到driverwl或driverr8169后面跟着businfopci...再运行systemctl list-units | grep -E (NetworkManager|systemd-networkd)看哪个服务是active (running)状态即可。Netplan配置文件通常位于/etc/netplan/目录下常见文件名如01-network-manager-all.yamlDesktop或00-installer-config.yamlServer。注意两点一是文件名前缀的数字决定加载顺序越小越先二是必须以.yaml结尾且文件权限必须是600即只有root可读写否则netplan apply会静默失败。我曾经帮一个客户排查问题折腾两小时才发现他用nano编辑后保存成了01-network-manager-all.yml少了个aNetplan根本没读这个文件。3. 手动设置静态IP从识别网卡到永久生效的完整链路3.1 第一步精准识别你的有线网卡名称别想当然地认为网卡就是eth0。Ubuntu 16.04之后全面启用可预测网络接口名Predictable Network Interface Names有线网卡通常叫enp0s3、ens33、eno1这类名字规则是en代表Ethernetp0s3代表PCI总线0设备3s33代表插槽33o1代表板载网卡1号。虽然看着反人类但它彻底解决了USB网卡热插拔导致eth0/eth1乱序的问题。执行这条命令一眼锁定你要配的网卡ip -br a | grep -E UP|LOWER_UP | grep -v lo输出类似enp0s3 UP 192.168.1.105/24 fe80::a00:27ff:fe1c:1a2b/64这里enp0s3就是你的有线网卡名UP表示物理链路已通网线插好了后面的IPv4地址是当前DHCP获取的临时地址。如果看到DOWN先检查网线是否插牢、路由器端口是否亮灯。注意别用ifconfig它已被废弃不显示现代Linux内核的完整信息且在最小化安装的Server版里默认不带。ip命令是唯一可靠选择。3.2 第二步计算静态IP参数——不是随便填个数就行静态IP不是你想设想设就能设。它必须和你的局域网处于同一网段且不能和路由器DHCP池冲突否则要么自己断网要么把别人挤下线。假设你的路由器管理地址是192.168.1.1绝大多数家用路由器默认DHCP地址池通常是192.168.1.100到192.168.1.200那么你的静态IP就必须避开这个范围。计算三要素IP地址选192.168.1.50低于DHCP池起点安全子网掩码家用路由器基本都是255.255.255.0对应CIDR表示法是/24默认网关就是路由器管理地址192.168.1.1验证是否在同一网段把IP和子网掩码做按位与运算。比如192.168.1.50 255.255.255.0 192.168.1.0而192.168.1.1 255.255.255.0 192.168.1.0结果一致说明在同一个广播域内可以通信。实操心得我习惯把关键服务器IP设在.10到.49之间如192.168.1.10是NAS.20是GitLab.30是Jenkins把开发机设在.50到.99之间这样一眼就能从IP看出设备角色也方便防火墙策略分组。3.3 第三步编辑Netplan配置文件——YAML语法是最大陷阱找到你的Netplan文件ls /etc/netplan/用sudo nano打开。以Ubuntu 22.04 Desktop为例文件名通常是01-network-manager-all.yaml。切记YAML对缩进极其敏感必须用空格不能用Tab编辑前先备份sudo cp /etc/netplan/01-network-manager-all.yaml /etc/netplan/01-network-manager-all.yaml.bak原始内容类似# Let NetworkManager manage all devices on this system network: version: 2 renderer: NetworkManager改成重点看ethernets部分# Let NetworkManager manage all devices on this system network: version: 2 renderer: NetworkManager ethernets: enp0s3: dhcp4: false addresses: [192.168.1.50/24] routes: - to: default via: 192.168.1.1 nameservers: addresses: [114.114.114.114, 223.5.5.5, 1.1.1.1]逐行解释dhcp4: false关闭IPv4 DHCP这是开关必须写。addresses: [192.168.1.50/24]/24是子网掩码的CIDR写法等价于255.255.255.0必须带否则Netplan会报错。routes定义默认路由to: default即所有非本机流量都走via: 192.168.1.1也就是网关。没有这行你能ping通网关但ping不通外网。nameservers这才是DNS配置的正确位置不是改/etc/resolv.conf那里是自动生成的。常见错误有人把addresses写成address少个sNetplan直接忽略有人把192.168.1.50/24写成192.168.1.50 255.255.255.0YAML解析失败还有人把renderer: NetworkManager删了结果Netplan找不到执行引擎apply时报No renderer available。3.4 第四步应用配置并验证——三步确认法改完文件千万别直接重启先用Netplan自带的校验工具sudo netplan try它会应用配置并启动一个60秒倒计时期间你如果网络中断60秒后自动回滚。这是最安全的测试方式。倒计时内执行三步验证查IP是否生效ip a show enp0s3 | grep inet 应该看到inet 192.168.1.50/24且没有其他inet行说明DHCP没抢回来。查路由是否正确ip route | grep default输出应为default via 192.168.1.1 dev enp0s3 proto static metric 100其中proto static证明是手动配置的不是DHCP下发的。查DNS是否写入systemd-resolve --status | grep DNS Servers或直接看生成的/etc/resolv.confcat /etc/resolv.conf应该显示# This file is managed by man:systemd-resolved(8). Do not edit. nameserver 114.114.114.114 nameserver 223.5.5.5 nameserver 1.1.1.1全部通过按CtrlD确认保留配置。如果某步失败netplan try会自动回滚你只需重新编辑YAML文件。4. DNS深度配置为什么/etc/resolv.conf会被覆盖怎么破4.1 揭秘/etc/resolv.conf的“幽灵”行为很多新手纳闷我明明在/etc/resolv.conf里写了nameserver 8.8.8.8为什么重启后又变回127.0.0.53这是因为Ubuntu 17.10之后默认启用了systemd-resolved作为本地DNS解析代理。它监听127.0.0.53把所有DNS请求统一转发给上游服务器并缓存结果提升速度。/etc/resolv.conf此时只是一个符号链接指向/run/systemd/resolve/stub-resolv.conf指向本地代理或/run/systemd/resolve/resolv.conf指向真实上游。你直接编辑它下次systemd-resolved重启或网络重连就会被覆盖。提示执行ls -l /etc/resolv.conf就能看到它指向哪里。如果是/run/systemd/resolve/stub-resolv.conf说明你在用本地代理模式如果是/run/systemd/resolve/resolv.conf说明代理直接透传上游DNS。4.2 在Netplan中正确配置DNS的两种模式Netplan的nameservers配置最终会写入systemd-resolved的上游列表。但具体效果取决于rendererNetworkManager渲染器它会把nameservers写入/run/NetworkManager/no-stub-resolv.conf然后systemd-resolved读取这个文件作为上游。所以你必须在Netplan里配不能绕过。systemd-networkd渲染器它会直接写入/run/systemd/network/下的配置由systemd-resolved同步。无论哪种只要Netplan配置正确systemd-resolve --status都能看到你指定的DNS服务器。但要注意一个隐藏坑NetworkManager会优先使用DHCP下发的DNS除非你显式禁用。所以除了Netplan里写nameservers还得在NetworkManager配置里加一行# 创建NM配置文件强制忽略DHCP DNS echo -e [main]\ndhcpnone | sudo tee /etc/NetworkManager/conf.d/99-disable-dhcp-dns.conf sudo systemctl restart NetworkManager4.3 高级技巧为不同网卡配不同DNS或禁用systemd-resolved有些场景需要更精细控制比如有线网卡走国内DNS114.114.114.114Wi-Fi网卡走Google DNS8.8.8.8或者你就是讨厌代理层想让应用直连上游DNS前者在Netplan里可以为每个ethernets块单独配nameserversNetplan会为每张网卡生成独立的resolved配置。后者则需禁用systemd-resolved改用传统/etc/resolv.confsudo systemctl stop systemd-resolved sudo systemctl disable systemd-resolved # 删除符号链接创建真实文件 sudo rm /etc/resolv.conf echo nameserver 114.114.114.114 | sudo tee /etc/resolv.conf echo nameserver 223.5.5.5 | sudo tee -a /etc/resolv.conf但这样做会失去DNS缓存和并行查询优化且某些新应用如Firefox 90可能因/etc/resolv.conf权限问题报错需额外处理。5. 故障排查实战手册从“连不上”到定位根因的速查表5.1 连不上网关IP和路由的双重校验现象ping 192.168.1.1超时但ping 192.168.1.50自己成功。排查步骤确认物理层ethtool enp0s3 | grep Link detected输出Link detected: yes才说明网线通。确认IP绑定ip a show enp0s3 | grep inet 确保只有你配的192.168.1.50/24没有其他inet行。确认路由存在ip route get 192.168.1.1应返回192.168.1.1 via 192.168.1.1 dev enp0s3 src 192.168.1.50 uid 0。如果返回RTNETLINK answers: No route to host说明路由没生效。终极检查sudo tcpdump -i enp0s3 icmp然后另开终端ping 192.168.1.1看tcpdump是否有ICMP echo request发出。如果有请求没回包问题在路由器或网线如果根本没请求发出说明路由或IP配置错误。踩过的坑有一次客户说“配了静态IP就是ping不通网关”我过去一看ip a显示IP是192.168.1.50/24但ip route里default via指向192.168.0.1他手误写错了网关结果所有流量都往错方向发自然石沉大海。5.2 能上内网但上不了外网DNS或网关转发问题现象ping 192.168.1.1成功ping 8.8.8.8成功但ping baidu.com超时。排查步骤DNS解析测试nslookup baidu.com 114.114.114.114如果成功说明DNS服务器工作正常如果失败换nslookup baidu.com 1.1.1.1确认是DNS服务器问题还是配置问题。检查/etc/resolv.conf内容确保它指向的是你期望的DNS且没有被NetworkManager覆盖。检查路由器NAT登录路由器后台确认WAN口已获取公网IP且NAT转发功能开启。家用路由器一般默认开启但企业级设备可能关闭。抓包定位sudo tcpdump -i enp0s3 port 53然后nslookup baidu.com看是否有DNS查询包发出以及是否有响应包回来。没有发出包说明应用没走你配的DNS有发出无响应说明DNS服务器不可达或被防火墙拦截。5.3 配置生效后又变回DHCPNetplan文件权限和加载顺序现象netplan apply后一切正常但重启系统IP又变回192.168.1.105DHCP地址。根本原因只有两个文件权限错误ls -l /etc/netplan/确保你的YAML文件权限是-rw------- 1 root root。如果不是执行sudo chmod 600 /etc/netplan/*.yaml。文件名前缀冲突ls /etc/netplan/如果存在多个YAML文件如00-installer-config.yaml和01-network-manager-all.yamlNetplan会按数字顺序加载后加载的会覆盖前面的。删除或重命名冲突文件只留一个。实操心得我给自己定的铁律是——所有Netplan文件名前缀用三位数如001-static-ip.yaml这样未来加新配置002-wifi.yaml也不会乱序。另外每次修改后必执行sudo netplan generate它会把YAML编译成/run/systemd/network/下的.network文件你可以直接看编译结果是否符合预期。5.4 常见问题速查表问题现象可能原因快速验证命令解决方案netplan apply报错Invalid YAMLYAML缩进错误、用了Tab、冒号后少空格sudo netplan --debug generate用在线YAML校验器如yamllint.com粘贴内容检查ping网关通curl外网超时DNS未生效或/etc/resolv.conf被覆盖cat /etc/resolv.confsystemd-resolve --status检查Netplannameservers配置确认renderer匹配静态IP配了但ip a里看不到网卡名写错或dhcp4: false没写ip -br a确认网卡名sudo netplan get查看当前生效配置修正YAML中的网卡名和dhcp4开关重启后IP变回DHCPNetplan文件权限不对或存在冲突文件ls -l /etc/netplan/ls /etc/netplan/sudo chmod 600 删除多余YAML文件systemd-resolved占用53端口影响本地DNS服务与dnsmasq、bind9等冲突sudo ss -tuln | grep :53sudo systemctl stop systemd-resolvedsudo systemctl disable systemd-resolved6. 进阶场景与生产环境加固建议6.1 多网卡环境一张上网一张内网通信企业服务器常有双网卡enp0s3接外网配静态IPenp0s8接内网交换机配另一网段静态IP如10.0.0.10/24。Netplan支持为每张网卡独立配置network: version: 2 renderer: systemd-networkd ethernets: enp0s3: dhcp4: false addresses: [203.0.113.50/24] routes: - to: default via: 203.0.113.1 nameservers: addresses: [114.114.114.114] enp0s8: dhcp4: false addresses: [10.0.0.10/24] # 内网无需默认路由避免流量误走内网关键点enp0s8不配routes这样所有非10.0.0.0/24的流量仍走enp0s3的默认路由保证外网访问不受影响。6.2 安全加固限制SSH只监听内网IP配好静态IP后顺手加固SSH服务。编辑/etc/ssh/sshd_config# 只监听内网IP不监听外网IP ListenAddress 10.0.0.10 # 或监听所有IP但用防火墙限制 # ListenAddress 0.0.0.0然后sudo systemctl restart sshd。这样即使外网IP暴露SSH端口也不会在外网暴露大幅降低攻击面。6.3 自动化部署Ansible一键配置静态IP如果你要批量配置几十台Ubuntu服务器手动改YAML太慢。用Ansible写个playbook--- - name: Configure static IP on Ubuntu hosts: ubuntu_servers become: true vars: static_ip: 192.168.1.50/24 gateway: 192.168.1.1 dns_servers: - 114.114.114.114 - 223.5.5.5 tasks: - name: Copy Netplan config template: src: netplan-static.yaml.j2 dest: /etc/netplan/01-static-ip.yaml mode: 0600 - name: Apply Netplan command: netplan apply - name: Verify IP command: ip -br a \| grep enp0s3 \| awk {print $3} \| cut -d/ -f1 register: ip_check changed_when: false - name: Assert IP is correct assert: that: ip_check.stdout static_ip \| regex_replace(/.*, )模板文件netplan-static.yaml.j2用Jinja2变量填充实现配置即代码Infrastructure as Code。6.4 最后一个提醒别忘了更新/etc/hosts静态IP配好后顺手把本机hostname映射加到/etc/hosts避免某些服务如Docker Compose因hostname解析失败报错echo 192.168.1.50 $(hostname) | sudo tee -a /etc/hosts这样ping $(hostname)就能通很多脚本依赖这个。我个人在实际操作中的体会是静态IP配置本身不难难的是建立一套完整的验证闭环。每次改完我必做三件事ip a看地址、ip route看路由、nslookup看DNS三者缺一不可。很多看似玄学的问题其实就卡在其中一个环节没到位。这个习惯让我在客户现场平均3分钟内定位90%的网络问题。另外永远备份原配置netplan try是你的安全气囊别怕多试几次——毕竟网络配置的终极目标不是“设上去”而是“稳得住”。