1. 项目概述与核心需求最近在折腾一台Ubuntu 20.04的服务器它有两张物理网卡我需要实现一个有点“拧巴”但又很实用的网络配置让两张网卡同时工作一张走NAT模式用于安全地访问外网另一张走桥接模式获得一个与物理网络同网段的独立IP方便局域网内其他设备直接访问。最关键的是无论通过哪张网卡我都要能从外部远程SSH连接上这台机器。这个需求听起来简单但实际操作时如果对Linux网络管理、路由表和防火墙规则没有清晰的理解很容易把自己绕进去导致要么上不了网要么远程连不上或者两张网卡“打架”。这种配置的典型场景比如你有一台开发测试服务器eth0通过NAT连接公司内网或家庭路由器后的网络可以安全地访问互联网下载包而eth1桥接出来获得一个固定的局域网IP如192.168.1.100方便同局域网内的其他开发机、测试设备用低延迟、高带宽直接访问它上面的服务如数据库、Web API。这比单纯用端口转发要灵活和直接得多。下面我就把这次配置的完整思路、详细步骤以及我踩过的几个坑从头到尾捋一遍。2. 网络拓扑设计与核心思路拆解2.1 物理与逻辑拓扑首先我们要在脑子里构建出清晰的网络拓扑图。假设我们的Ubuntu 20.04服务器有两张网卡ens33 (或 eth0) 我们计划将它配置为NAT模式。在虚拟机环境下如VMware/VirtualBox这意味着它连接到一个虚拟的NAT网络由虚拟网络设备如VMnet8分配一个私有IP通常是192.168.xxx.xxx并通过宿主机进行地址转换访问外网。对于物理服务器这可以理解为连接到一个已经做了NAT转换的路由器LAN口。ens38 (或 eth1) 我们计划将它配置为桥接模式。在虚拟机环境下这意味着它直接“桥接”到宿主机的物理网卡上从宿主机的物理网络比如你的家庭路由器DHCP获取一个同网段的IP。对于物理服务器就是直接插到交换机上从上层DHCP获取IP。我们的目标是系统同时使用这两张网卡但默认路由去往互联网的流量走NAT网卡ens33而去往局域网特定网段的流量比如桥接网卡所在的网段走桥接网卡ens38。并且两个IP地址都要能响应SSH连接。2.2 配置策略与潜在冲突这里最核心的挑战是避免路由冲突和策略混乱。如果两张网卡都从DHCP获取了默认网关系统就会产生两个默认路由导致网络行为不可预测时通时断。因此我们的策略必须明确单一默认网关原则 只有一张网卡这里是NAT网卡ens33配置网关作为系统访问非本地网络主要是互联网的出口。静态路由补充 为桥接网卡ens38所在的局域网网段添加一条明确的静态路由指定从ens38网卡发出。这样访问局域网内其他设备时流量就不会“绕路”走NAT再折返而是直接通过桥接网卡高效通信。防火墙放行 Ubuntu 20.04默认使用ufw或iptables管理防火墙。必须确保防火墙规则允许从两个网络接口的IP地址接入SSH端口默认为22。SSH服务监听 确保SSH服务配置为监听所有接口0.0.0.0而不是只监听某个特定IP。注意 在开始之前请务必确认你的两张网卡在系统中已被正确识别。使用ip link show或ls /sys/class/net命令查看网卡名称可能是ens33, ens34, eth0, eth1等。下文将以ens33(NAT)和ens38(桥接)为例。3. 详细配置步骤与实操要点我们将通过修改Ubuntu 20.04的Netplan配置文件来完成主要配置。Netplan是Ubuntu 17.10之后引入的网络配置工具使用YAML格式比传统的/etc/network/interfaces更现代。3.1 备份与定位Netplan配置文件首先进入Netplan配置目录并找到主配置文件。cd /etc/netplan ls -la你可能会看到类似01-netcfg.yaml、50-cloud-init.yaml或00-installer-config.yaml的文件。请根据你的实际文件名进行后续操作。强烈建议先备份sudo cp /etc/netplan/01-netcfg.yaml /etc/netplan/01-netcfg.yaml.backup3.2 编辑Netplan配置文件使用你喜欢的编辑器如vim或nano打开配置文件。sudo vim /etc/netplan/01-netcfg.yaml以下是完整的配置示例请根据你的网络环境修改IP地址、网关、DNS等参数network: version: 2 renderer: networkd # 或者 networkd 20.04 server版通常用networkd ethernets: # 配置NAT网卡 - ens33 ens33: dhcp4: no # 禁用DHCP我们使用静态IP以便控制网关 addresses: - 192.168.122.100/24 # 静态IP地址需与你的NAT网络网段匹配如VMware的VMnet8通常是192.168.122.0/24 routes: - to: 0.0.0.0/0 via: 192.168.122.1 # NAT网络的网关地址通常是虚拟网卡的IP如VMnet8的192.168.122.1 metric: 100 # 为默认路由设置一个度量值优先级值越小优先级越高 nameservers: addresses: [8.8.8.8, 114.114.114.114] # DNS服务器 optional: true # 设置为true即使此网卡未连接系统也能正常启动 # 配置桥接网卡 - ens38 ens38: dhcp4: no # 同样使用静态IP addresses: - 192.168.1.100/24 # 静态IP地址需与你的物理局域网网段匹配如常见的192.168.1.0/24 # 注意这里不配置默认网关via只配置IP和掩码 routes: - to: 192.168.1.0/24 # 添加一条到本地局域网的路由 via: 192.168.1.1 # 指定该局域网的网关通常是你的物理路由器IP metric: 200 # 设置一个比默认路由更大的metric确保去往互联网的流量优先走ens33 nameservers: addresses: [8.8.8.8, 114.114.114.114] optional: true关键参数解析addresses: 指定网卡的静态IP地址和CIDR掩码。routes: 这是实现双网卡共存的关键。对于ens33(NAT)我们添加了一条到0.0.0.0/0即所有目标的路由指向NAT网关并设置metric: 100。这成为了系统的默认路由。对于ens38(桥接)我们添加了一条到其所在局域网网段192.168.1.0/24的特定路由指向物理局域网的网关并设置metric: 200。这样访问192.168.1.x的流量会匹配这条更具体的路由/24掩码比/0更具体即使它的metric更高。metric: 路由的度量值用于决定优先级。当有多条路由可以到达同一目标时系统优先选择metric值小的。这里我们让默认路由的metric更小确保其优先级。optional: true: 这个设置非常实用。它告诉系统即使这张网卡在启动时没有插线或没有连接也不要等待它超时而阻塞整个系统启动过程。对于服务器特别是有一张网卡可能不常使用时建议加上。3.3 应用网络配置保存并退出编辑器后使用以下命令测试配置语法并应用sudo netplan try这条命令会应用配置并给你一个回滚的倒计时通常是120秒。在此期间如果你的SSH连接没有断开说明配置基本正确你可以按回车确认。如果连接断开配置会在倒计时结束后自动回滚。如果netplan try顺利或者你想直接应用可以使用sudo netplan apply应用后立即检查新的配置是否生效ip addr show # 查看IP地址是否配置正确 ip route show # 查看路由表这是最重要的检查项你应该在路由表中看到类似下面的输出default via 192.168.122.1 dev ens33 proto static metric 100 192.168.1.0/24 via 192.168.1.1 dev ens38 proto static metric 200 192.168.1.0/24 dev ens38 proto kernel scope link src 192.168.1.100 192.168.122.0/24 dev ens33 proto kernel scope link src 192.168.122.100这表示默认路由走ens33去往192.168.1.0/24网段的流量会通过ens38网关192.168.1.1发出第一行特定路由同时系统也知道192.168.1.100这个IP本身在ens38上第三行直连路由。3.4 配置SSH服务监听默认情况下Ubuntu的SSH服务(sshd)是监听在所有网络接口(0.0.0.0)上的。但为了确保无误我们可以检查一下sudo ss -tlnp | grep :22输出中应该看到0.0.0.0:22或*:22。如果不是需要编辑SSH配置文件sudo vim /etc/ssh/sshd_config找到#ListenAddress 0.0.0.0这一行可能被注释确保它没有被改成具体的IP地址。保持注释或设置为ListenAddress 0.0.0.0即可。修改后重启SSH服务sudo systemctl restart sshd3.5 配置防火墙UFWUbuntu 20.04默认可能启用了UFW防火墙。我们需要允许SSH端口通过。sudo ufw allow ssh # 或者明确指定端口 # sudo ufw allow 22/tcp如果你需要更精细的控制可以指定允许来自特定网段的SSH连接但为了测试双网卡连通性我们先简单允许所有。启用UFW如果尚未启用sudo ufw enable查看规则sudo ufw status verbose4. 功能验证与连通性测试配置完成后必须进行全面的测试确保每张网卡都按预期工作。4.1 基础连通性测试测试NAT网卡(ens33)的外网访问ping -I ens33 8.8.8.8使用-I参数指定从ens33网卡发出ping包。应该能收到回复。测试桥接网卡(ens38)的局域网访问ping -I ens38 192.168.1.1 # 假设192.168.1.1是你的物理路由器同样指定从ens38发出。应该能ping通同网段的其他设备。4.2 路由路径测试使用traceroute或tracepath命令查看去往不同目标的实际路径。# 测试去往外网的路径应该第一跳是NAT网关(192.168.122.1) tracepath -i ens33 8.8.8.8 # 测试去往同局域网另一台主机的路径应该直接到达不经过NAT网关 tracepath -i ens38 192.168.1.50 # 假设这是同局域网的另一台电脑4.3 远程SSH连接测试这是最终目标需要从两个不同的网络位置进行测试。从NAT网络内部或宿主机连接 在你的宿主机或与NAT网卡同网段的机器上使用SSH客户端连接NAT IP。ssh username192.168.122.100应该能成功连接。从桥接网络所在的物理局域网连接 在连接到你物理局域网如192.168.1.0/24的另一台电脑上使用SSH客户端连接桥接IP。ssh username192.168.1.100同样应该能成功连接。实操心得 在进行远程测试时务必先确保能在服务器本地通过ssh localhost连接成功以排除SSH服务本身的问题。另外如果使用虚拟机请确保虚拟网络编辑器的设置正确NAT网络和桥接网络已正确配置并启用。5. 高级排错与深度优化即使按照步骤操作也可能遇到各种问题。下面是我在实际操作中遇到的一些典型问题及解决方法。5.1 常见问题排查表问题现象可能原因排查命令与解决方案应用netplan apply后网络断开1. 配置文件语法错误。2. 网关地址错误或不可达。3. IP地址冲突。1. 使用sudo netplan --debug apply查看详细错误。2. 在服务器本地控制台检查ip addr和ip route并用ping测试网关连通性。3. 回滚备份配置sudo cp /etc/netplan/01-netcfg.yaml.backup /etc/netplan/01-netcfg.yaml sudo netplan apply。可以ping通外网但无法apt update域名解析失败DNS服务器配置错误或未生效。1. 检查/etc/netplan/*.yaml中的nameservers。2. 检查/etc/resolv.conf看是否被其他服务如systemd-resolved覆盖。可以临时修改/etc/resolv.conf或配置systemd-resolved。3. 直接ping IP地址如ping 8.8.8.8测试网络再ping域名如ping google.com测试DNS。只能从一个IP地址SSH连接另一个连不上1. 防火墙(UFW)规则可能只允许了某个子网或接口。2. SSH服务可能绑定到了特定IP。3. 路由问题导致返回流量路径错误。1. 检查UFW规则sudo ufw status numbered。确保有22/tcp ALLOW Anywhere规则。2. 检查SSH配置sudo grep ^ListenAddress /etc/ssh/sshd_config。3. 在服务器上从“连不上的那个IP”所在网络ping服务器该IP看是否可达。检查服务器到该客户端的回程路由。桥接网卡无法获取到IP或无法ping通网关1. 物理连接问题网线、虚拟机桥接设置。2. 桥接的物理网络有MAC地址过滤或DHCP限制。3. IP地址冲突。1. 虚拟机检查确保桥接模式已启用并正确桥接到了活动的物理网卡。2. 物理服务器检查ethtool ens38查看链路状态Link detected: yes。3. 尝试为桥接网卡配置一个非常用IP或查看路由器DHCP分配列表。访问互联网速度慢或部分网站打不开可能出现了路由环路或策略路由问题流量没有按预期路径走。1. 使用ip route get 8.8.8.8查看去往某个外网地址的实际路由出口确认是否从ens33出去。2. 检查是否有其他网络管理服务如NetworkManager干扰Server版建议只用networkd。3. 使用mtr命令进行持续路由追踪观察路径是否异常。5.2 防火墙策略精细化配置上面的sudo ufw allow ssh是允许所有来源。在生产环境中你可能需要更安全。# 假设我们只想允许来自NAT网络(192.168.122.0/24)和桥接局域网(192.168.1.0/24)的SSH连接 sudo ufw delete allow ssh # 先删除之前的宽松规则 sudo ufw allow from 192.168.122.0/24 to any port 22 proto tcp sudo ufw allow from 192.168.1.0/24 to any port 22 proto tcp这样配置后只有指定两个网段的IP才能连接SSH安全性更高。5.3 使用systemd-networkd的额外配置如遇复杂路由对于更复杂的路由策略如基于源地址的路由Netplan的YAML配置可能不够用。这时可以编写systemd-networkd的底层drop-in文件。例如为ens38添加一个路由表并设置规则让来自ens38IP的流量使用该路由表创建路由表文件。编辑/etc/iproute2/rt_tables添加一行例如200 bridge-net为ens38创建networkd配置片段sudo vim /etc/systemd/network/10-ens38.route内容如下[Route] Gateway192.168.1.1 Destination192.168.1.0/24 Tablebridge-net创建路由规则配置片段sudo vim /etc/systemd/network/10-ens38.routing-policy内容如下[RoutingPolicyRule] From192.168.1.100/32 Tablebridge-net Priority100重启systemd-networkd服务sudo systemctl restart systemd-networkd这种方法提供了极强的灵活性但对于简单的双网卡NAT/桥接共存之前的Netplan配置通常已足够。5.4 开机自启与服务依赖确保网络配置在开机时能正确应用。Netplan服务通常由systemd-networkd实现其开机自启是默认的。你可以检查相关服务状态sudo systemctl status systemd-networkd sudo systemctl status netplan-apply如果服务器上运行着一些依赖网络的服务如Docker, Nginx你可能需要在Netplan配置中为网卡设置optional: true并考虑在服务配置中添加Afternetwork-online.target和Wantsnetwork-online.target以确保网络就绪后再启动这些服务。经过以上步骤你的Ubuntu 20.04服务器就应该能够稳定地运行在双网卡NAT桥接模式下并且可以通过两个IP地址进行远程SSH管理。这种配置在混合网络环境、开发测试、服务隔离等场景下非常实用。关键点始终在于理解路由表的工作原理并清晰地规划每张网卡的职责。如果在配置过程中遇到本指南未覆盖的奇怪问题多使用ip route get 目标IP命令来追踪数据包的实际路径这是最直接的诊断工具。