尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Linux双网卡配置NAT网关:十分钟实现网络共享与隔离

Linux双网卡配置NAT网关:十分钟实现网络共享与隔离 1. 项目缘起一个被忽视的Linux网络“超能力”最近在折腾一台闲置的旧笔记本想把它改造成一个轻量级的家庭服务器跑点小服务。这台机器有两个网口一个有线eth0连家里的主路由器另一个有线eth1是空着的。我的需求很简单能不能让这台服务器变成一个“小路由器”把eth0接到的互联网通过NAT网络地址转换共享给eth1这样我就可以把另一台设备比如一台没有无线网卡的台式机或者一个需要有线调试的开发板插在eth1上让它也能上网这个需求听起来像是家用无线路由器的本职工作但很多时候我们手头并没有多余的路由器或者临时需要一个网络隔离的测试环境。这时候Linux内核自带的iptables/netfilter框架配合简单的系统配置就能让任何一台双网卡的Linux机器瞬间变身为一台功能完整的NAT网关。这个功能非常实用无论是搭建临时的测试网络、实现网络隔离还是作为复杂网络拓扑中的一个节点都是运维和开发人员工具箱里的必备技能。很多人觉得配置NAT和防火墙规则很复杂其实核心步骤就那么几条理解了背后的原理十分钟就能搞定。2. 核心概念扫盲NAT、双网卡与iptables到底是什么在动手之前我们得先搞清楚几个关键概念这能帮你理解每一步操作的目的而不是机械地敲命令。2.1 NAT让内网设备“借用”公网身份上网你可以把NAT想象成一个公司的前台总机。公司对外只有一个公开的电话号码公网IP比如203.0.113.1。内部每个员工内网设备都有一个分机号内网IP比如192.168.100.10。当内部分机192.168.100.10的员工想给外面的客户打电话访问互联网时他先拨通总机。总机接听后会用公司的公开号码203.0.113.1替这位员工拨出电话。对于外面的客户来说他接到的来电显示就是203.0.113.1他并不知道实际打电话的是分机100的员工。当客户回电时电话打到总机203.0.113.1总机再根据之前的通话记录把电话转接到对应的分机100。在计算机网络中这个过程就是NAT。我们的Linux服务器就是那个“总机”。它有一个连接外网的网卡比如eth0IP是192.168.1.100这是你家路由器分配的内网IP但相对于服务器背后的设备来说它就是“公网侧”和一个连接内网的网卡比如eth1IP是192.168.100.1。插在eth1上的设备IP如192.168.100.10要上网时数据包到达服务器服务器会修改数据包的源IP地址从192.168.100.10改成自己的外网IP192.168.1.100然后发出去。回来的数据包目标IP是192.168.1.100服务器再根据NAT表记录把目标IP改回192.168.100.10转发给内网设备。这样内网设备就“隐形”了安全地共享了同一个出口IP上网。2.2 双网卡的角色划分WAN口与LAN口要让NAT工作两个网卡必须扮演不同的角色这和我们买的路由器一样WAN口 (Wide Area Network)连接外部网络通常是互联网。在我们的场景里就是连接主路由器的那个网卡例如eth0。这个口需要从上层网络你的家庭路由器获取IP地址通常是DHCP自动获取也可以是静态配置。它的任务是“对外”。LAN口 (Local Area Network)连接内部网络为我们想要共享网络的设备提供接入。这个网卡例如eth1需要配置一个固定的内网IP地址并充当这个内网的网关和DHCP服务器如果需要。它的任务是“对内”。关键点这两个网卡必须位于不同的IP网段。例如WAN口eth0的IP可能是192.168.1.100/24网段是192.168.1.0那么LAN口eth1就必须配置成另一个网段比如192.168.100.1/24网段是192.168.100.0。如果它们在同一网段路由就会混乱NAT也无法正确工作。2.3 iptablesLinux内核的“交通警察”与“翻译官”iptables是用户空间的一个工具用于配置Linux内核中的netfilter防火墙框架。你可以把它理解成一套极其强大的规则集控制着进出服务器的每一个数据包。对于我们实现NAT共享主要用到它的两个功能过滤 (Filter)决定哪些数据包允许通过哪些需要丢弃就像防火墙。地址转换 (NAT)修改数据包的源或目标IP地址就是我们需要的NAT功能。iptables的规则被组织成“表”(Tables)和“链”(Chains)。我们最常打交道的是三张表filter表默认表负责过滤数据包包含INPUT发往本机的包、FORWARD需要本机转发的包、OUTPUT从本机发出的包链。nat表负责网络地址转换包含PREROUTING路由前修改目标IP用于DNAT、POSTROUTING路由后修改源IP用于SNAT和MASQUERADE、OUTPUT链。mangle表用于修改数据包内容如TTL我们本次不涉及。为了实现双网卡共享上网我们需要做两件事允许数据包在两张网卡之间转发配置filter表以及修改转发数据包的源IP地址配置nat表。3. 实战配置一步步搭建你的Linux NAT网关假设我们的环境如下服务器系统Ubuntu 22.04 LTS其他发行版如CentOS、Debian命令类似主要是网络配置文件和软件包管理工具不同外网网卡enp3s0(连接主路由器相当于之前的eth0)内网网卡enp4s0(连接需要上网的设备相当于之前的eth1)外网网段192.168.1.0/24网关是192.168.1.1计划的内网网段192.168.100.0/24网关即服务器的内网IP设为192.168.100.1注意现代Linux系统网卡命名可能是enpXsY或ensX等形式使用ip link或ifconfig需安装net-tools命令查看你的实际网卡名称。3.1 第一步配置双网卡的IP地址首先我们需要为两张网卡配置正确的IP地址。这里以使用netplanUbuntu 18.04为例。编辑网络配置文件例如/etc/netplan/01-netcfg.yamlnetwork: version: 2 renderer: networkd ethernets: enp3s0: # 外网网卡通过DHCP从主路由器获取IP dhcp4: yes optional: true # 允许此接口不存在时系统正常启动 enp4s0: # 内网网卡配置静态IP addresses: - 192.168.100.1/24 # 内网网卡不需要配置网关和DNS因为它不直接连接外网。 # 但可以设置DHCP服务器如dnsmasq为内网设备提供这些信息。 # 这里我们先配好IPDHCP服务稍后设置。保存文件后应用配置sudo netplan apply。验证配置使用ip addr show命令应该能看到enp3s0有一个类似192.168.1.100的IP而enp4s0的IP是192.168.100.1。3.2 第二步开启Linux内核的IP转发功能默认情况下Linux内核不会转发来自一个网卡去往另一个网卡的数据包。我们需要打开这个“路由器”的核心开关。临时生效重启后失效sudo sysctl -w net.ipv4.ip_forward1永久生效编辑/etc/sysctl.conf文件找到或添加一行net.ipv4.ip_forward1然后执行sudo sysctl -p使配置立即生效。为什么必须开启这个参数控制着内核是否处理并转发不是发给本机的IP数据包。关闭时服务器只处理目的地是自己IP的包开启后它才会查看路由表决定将包从哪个接口转发出去这是实现网关功能的基础。3.3 第三步配置iptables实现NAT与转发规则这是最核心的一步。我们将设置三条关键的iptables规则。规则1设置POSTROUTING链的MASQUERADE动态源地址转换这条规则的作用是对所有从内网enp4s0发出经由本机转发到外网enp3s0的数据包在它们离开外网接口之前将其源IP地址修改为本机外网接口enp3s0的IP地址。MASQUERADE是SNAT静态源地址转换的一种特殊形式它自动获取出口接口的IP地址非常适合在出口IP是动态获取如DHCP的情况下使用。sudo iptables -t nat -A POSTROUTING -o enp3s0 -j MASQUERADE-t nat指定操作nat表。-A POSTROUTING在POSTROUTING链末尾追加规则。-o enp3s0匹配出口设备是enp3s0的数据包。-j MASQUERADE跳转到MASQUERADE目标执行地址伪装。规则2允许已建立连接及相关连接的数据包通过这是一条防火墙安全规则放在filter表的FORWARD链。它允许所有属于已建立连接或与已建立连接相关的数据包通过转发。这确保了内网设备发起的请求其回应包能被顺利返回。sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT-A FORWARD在filter表的FORWARD链追加规则。-m conntrack使用conntrack连接跟踪模块。--ctstate RELATED,ESTABLISHED匹配状态为RELATED相关连接如FTP的数据连接或ESTABLISHED已建立连接的数据包。-j ACCEPT允许通过。规则3允许从内网接口发起的转发这条规则允许从内网接口enp4s0进入需要转发出去的流量。sudo iptables -A FORWARD -i enp4s0 -o enp3s0 -j ACCEPT-i enp4s0匹配入口设备是enp4s0内网口。-o enp3s0匹配出口设备是enp3s0外网口。-j ACCEPT允许通过。保存iptables规则至关重要以上通过命令添加的规则在重启后会丢失。为了永久生效我们需要保存它们。不同发行版保存方式不同Ubuntu/Debian安装iptables-persistent包。sudo apt update sudo apt install iptables-persistent在安装过程中它会询问是否保存当前IPv4和IPv6规则选择“是”。之后每次修改规则后使用以下命令保存sudo netfilter-persistent save # 或者 sudo iptables-save /etc/iptables/rules.v4 sudo ip6tables-save /etc/iptables/rules.v6RHEL/CentOS 7使用以下命令保存。sudo iptables-save /etc/sysconfig/iptables # 对于Firewalld开启的系统可能需要先停止firewalld启用iptables服务比较复杂。建议在明确使用iptables的系统中操作。3.4 第四步可选为内网设备配置DHCP与DNS现在你的Linux网关已经可以转发和NAT数据包了。连接到enp4s0的设备如果你手动给它配置静态IP如192.168.100.10、子网掩码255.255.255.0、网关192.168.100.1和DNS服务器可以填192.168.100.1或公共DNS如8.8.8.8它应该就能上网了。但为了方便我们通常希望内网设备能自动获取IP。可以在网关上安装一个轻量级DHCP服务器比如dnsmasq。安装dnsmasqsudo apt update sudo apt install dnsmasq配置dnsmasq首先备份原配置然后编辑/etc/dnsmasq.conf在文件末尾添加# 只监听内网接口 interfaceenp4s0 # 不监听lo回环接口 no-dhcp-interfacelo # 分配的IP地址范围及租期 dhcp-range192.168.100.50,192.168.100.150,255.255.255.0,24h # 指定网关 dhcp-optionoption:router,192.168.100.1 # 指定DNS服务器这里设置为网关本身由网关转发DNS查询或直接使用如8.8.8.8 dhcp-optionoption:dns-server,192.168.100.1 # 如果你希望网关提供DNS解析可以取消注释并修改下一行否则dnsmasq仅转发DNS查询。 # 取消注释以启用本地DNS缓存/转发 # cache-size1000重启dnsmasq服务并设置开机自启sudo systemctl restart dnsmasq sudo systemctl enable dnsmasq注意如果系统原本有systemd-resolved服务在监听53端口会和dnsmasq冲突。可能需要先停止并禁用systemd-resolvedsudo systemctl stop systemd-resolved sudo systemctl disable systemd-resolved然后修改/etc/resolv.conf指向一个公共DNS如nameserver 8.8.8.8。这是一个常见的坑点。4. 问题排查与深度优化指南配置完成后内网设备可能还是无法上网。别急按照以下链路一步步排查这是定位网络问题的标准思路。4.1 基础连通性测试从内网设备开始检查IP获取在内网设备上确认是否通过DHCP获得了192.168.100.0/24网段的IP以及网关是否是192.168.100.1。在Linux客户端用ip addr在Windows客户端用ipconfig查看。ping网关在内网设备上尝试ping 192.168.100.1。如果不通说明到网关的物理链路或二层就有问题。检查网线、网卡状态、防火墙是否屏蔽了ICMPping包。在网关上可以临时关闭防火墙测试sudo iptables -P INPUT ACCEPT sudo iptables -P FORWARD ACCEPT测试后记得恢复或重新配置。检查网关的路由表在网关上执行ip route show或route -n。你应该能看到一条类似192.168.100.0/24 dev enp4s0 proto kernel scope link src 192.168.100.1的路由这表示发往192.168.100.0/24网段的包会从enp4s0口发出。同时应该有一条默认路由default via 192.168.1.1 dev enp3s0指向你的主路由器。4.2 NAT与转发功能验证确认IP转发已开启在网关上执行cat /proc/sys/net/ipv4/ip_forward输出应为1。查看NAT规则执行sudo iptables -t nat -L -v -n。在POSTROUTING链中你应该能看到那条MASQUERADE all -- * enp3s0的规则并且pkts和bytes计数器在增长当有流量经过时。查看FORWARD规则执行sudo iptables -L FORWARD -v -n。确认那两条ACCEPT规则存在并且计数器在增长。跟踪数据包路径高级在内网设备上尝试ping一个外网IP如8.8.8.8。同时在网关上使用tcpdump抓包分析在enp4s0口抓包sudo tcpdump -i enp4s0 icmp应该能看到来自内网设备IP的echo request。在enp3s0口抓包sudo tcpdump -i enp3s0 icmp应该能看到源IP变成了网关的enp3s0口IP的echo request以及对应的echo reply。 如果enp4s0有请求但enp3s0没有问题出在转发或NAT规则。如果enp3s0有请求但没有回复可能是网关的外网连接有问题或者上游防火墙屏蔽了ICMP。4.3 常见故障点与解决方案iptables规则顺序错误iptables规则是按顺序匹配的。如果你的FORWARD链默认策略是DROP并且有其他拒绝规则放在我们添加的ACCEPT规则之前那么数据包可能被提前丢弃。可以用sudo iptables -L FORWARD -n --line-numbers查看规则顺序和编号用sudo iptables -D FORWARD 规则编号删除错误规则或用-I插入而非-A追加来确保规则在正确位置。FORWARD链默认策略使用sudo iptables -L FORWARD -n查看链的默认策略第一行Chain FORWARD (policy ACCEPT)。如果是DROP你需要确保我们的ACCEPT规则能匹配到所有需要转发的流量或者更简单地将策略改为ACCEPT仅用于测试sudo iptables -P FORWARD ACCEPT。生产环境建议保持DROP并精心配置规则。DNS解析失败内网设备能ping通外网IP如8.8.8.8但打不开网页。这通常是DNS问题。检查内网设备的DNS服务器设置是否正确。如果你用网关192.168.100.1做DNS确保网关上的DNS转发服务如dnsmasq或systemd-resolved正常工作并且网关自己能解析域名nslookup baidu.com。外网接口防火墙干扰有些系统如Ubuntu默认的ufw可能会在外网接口上启用防火墙阻止转发流量。可以暂时禁用ufw测试sudo ufw disable。如果问题解决需要为ufw配置正确的转发和NAT规则或者改用纯iptables管理。4.4 进阶优化与安全加固基础功能实现后可以考虑以下优化状态化防火墙我们之前配置的-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT就是状态化防火墙的基础。它比单纯基于端口开关的防火墙更安全高效。确保这条规则在FORWARD链中位于允许新连接规则的前面。限制内网访问可以在FORWARD链中添加规则限制内网设备只能访问某些端口或IP。例如只允许访问80和443端口网页sudo iptables -A FORWARD -i enp4s0 -o enp3s0 -p tcp -m multiport --dports 80,443 -j ACCEPT sudo iptables -A FORWARD -i enp4s0 -o enp3s0 -p udp --dport 53 -j ACCEPT # 允许DNS # 然后设置FORWARD链默认策略为DROP sudo iptables -P FORWARD DROP注意设置DROP前必须确保所有必要的流量都有对应的ACCEPT规则包括我们之前加的RELATED,ESTABLISHED规则。端口转发DNAT如果你想让外网访问内网服务器上的某个服务比如将网关的2222端口转发到内网一台机器的22端口可以添加DNAT规则sudo iptables -t nat -A PREROUTING -i enp3s0 -p tcp --dport 2222 -j DNAT --to-destination 192.168.100.100:22 sudo iptables -A FORWARD -i enp3s0 -o enp4s0 -p tcp --dport 22 -d 192.168.100.100 -j ACCEPT使用nftables替代从RHEL/CentOS 8 和 Ubuntu 22.04 开始nftables正在逐步取代iptables作为默认的防火墙后端。它的语法更简洁性能更好。如果你在新系统上学习nftables是更面向未来的选择。不过iptables命令目前通常作为兼容层存在我们上面的命令在多数新系统上依然有效。5. 从iptables到nftables一次平滑的认知迁移虽然当前绝大多数教程和现有系统仍在使用iptables但了解其继任者nftables很有必要。nftables统一了之前iptables、ip6tables、arptables、ebtables等多个工具的功能拥有更高效的语法和内核实现。如果你在较新的系统上执行iptables -V可能会看到iptables v1.8.7 (nf_tables)这表示它正在使用nftables内核API但提供了iptables的兼容命令行接口。一个等效于我们之前NAT和转发配置的nftables配置脚本可能如下所示保存为/etc/nftables.conf#!/usr/sbin/nft -f flush ruleset table inet filter { chain forward { type filter hook forward priority 0; policy drop; # 默认拒绝转发 ct state established,related accept # 允许已建立和相关的连接 iifname enp4s0 oifname enp3s0 accept # 允许从内网到外网的流量 # 可以在这里添加更多限制规则例如 # iifname enp4s0 oifname enp3s0 tcp dport { 80, 443 } accept } } table ip nat { chain postrouting { type nat hook postrouting priority 100; policy accept; oifname enp3s0 masquerade # 在出口enp3s0上进行MASQUERADE } }然后使用sudo nft -f /etc/nftables.conf加载配置。nftables的语法更接近编程语言表table、链chain、规则rule的层次关系更清晰。对于新项目建议直接学习nftables。配置完成后最让我有成就感的时刻是看到内网设备成功获取IP并打开第一个网页。整个过程就像搭积木从物理连接到IP配置再到内核转发和防火墙规则每一步都清晰可控。这种对网络流量的精细掌控是使用现成路由器无法比拟的体验。它不仅仅是一个共享网络的功能更是一次对Linux网络栈的深度探索。下次当你需要临时组网、创建隔离测试环境或者仅仅是想更透彻地理解数据包是如何在你的机器中流动时不妨再打开终端从配置这两块网卡开始。
返回列表