网络共享

出自 ArchWiki

本文介绍如何将一台机器的互联网连接共享给其他机器。

要求

充当服务器的机器应具有额外的网络设备。该网络设备需要到将要接收互联网访问的机器的功能性数据链路层

  • 为了能够将互联网共享到多台机器,交换机可以提供数据链路层连接。
  • 无线设备也可以共享对多台机器的访问,有关这种情况,请首先参阅 软件无线热点。
  • 如果您仅共享给一台机器,则交叉电缆就足够了。如果两台计算机的以太网卡之一具有 MDI-X 功能,则不需要交叉电缆,可以使用常规以太网电缆。以 root 身份执行 `ethtool interface | grep MDI` 有助于确定这一点。

配置

注意: 本节假设连接到客户端计算机的网络设备名为 net0,而连接到互联网的网络设备为 internet0
提示: 您可以使用 udev#设置静态设备名称 将您的设备重命名为此方案。

所有配置都在服务器计算机上完成,除了最后一步 #为客户端电脑分配 IP 地址

静态 IP 地址

在服务器计算机上,为连接到其他机器的接口分配一个静态 IPv4 地址。此地址的前 3 个字节不能与另一个接口的完全相同,除非两个接口的子网掩码都严格大于 /24。

# ip link set up dev net0
# ip addr add 192.168.123.100/24 dev net0 # arbitrary address

要在启动时分配静态 IP,您可以使用 网络管理器

启用数据包转发

警告: 在没有正确配置 防火墙 的情况下启用 IP 转发是一个安全风险。

要检查当前数据包转发设置,请运行

# sysctl -a | grep forward

您会注意到用于控制默认转发、每个接口转发以及每个接口单独的 IPv4/IPv6 选项的选项。有关所有可用选项的详细描述,请参阅 kernel documentation

要启用 IPv4 和 IPv6 数据包转发,请 配置 sysctl 以设置这些设置

net.ipv4.ip_forward = 1
net.ipv4.conf.all.forwarding = 1
net.ipv6.conf.all.forwarding = 1
提示: 要选择性地为特定接口启用数据包转发,请改用 net.ipv[46].conf.interface_name.forwarding=1
警告

本文或本节已过时。

原因: 很可能已过时。由于 systemd-networkd 256+ 现在支持在每个链接级别设置 IPv4 转发。请在确认后删除此注释和以下警告。(在 Talk:Internet sharing 中讨论)

如果系统使用 systemd-networkd 来控制网络接口,则无法进行每个接口的 IPv4 设置,即 systemd 逻辑会将任何配置的转发传播到 IPv4 的全局(对于所有接口)设置。建议的解决方法是使用防火墙再次禁止在选定的接口上转发。有关更多信息,请参阅 systemd.network(5) 手册页。在之前的 systemd 版本 220/221 中引入的 IPForward=kernel 语义以尊重内核设置不再适用。[1] [2]

要使更改在重启后持久化,请参阅 Sysctl#配置。您可以考虑将设置写入具有描述性文件名的文件,例如 /etc/sysctl.d/30-ipforward.conf

之后,建议在重启后再次检查是否已按要求启用转发。

使用 systemd-networkd 进行数据包转发

本文或本节是与 systemd-networkd#[Network] 合并的候选对象。

注意: 对于通用示例,任意文件命名没有意义。没有 [Match] 部分的 .network 文件没有意义。只需说明需要设置什么并链接到 systemd-networkd#[Network] 页面。(在 Talk:Internet sharing 中讨论)

如果您使用 systemd-networkd 来管理您的网络配置,您也可以在重启后持久化这些设置

/etc/systemd/network/20-lan.network
[Network]
IPv4Forwarding=yes
...

这实际上设置了与上一节中提到的相同的 net.ipv[46].conf.interface_name.forwarding=1。对于 IPv6,配置为 IPv6Forwarding=yes

注意: 从 systemd 256 开始,IPv6Forwarding 选项的行为与文档不符,请参阅 [3]

这仅为特定接口设置数据包转发。为了使互联网共享正常工作,您需要在应该在两者之间路由流量的两个(所有)接口上启用数据包转发。通常是您的 lanwan 接口。

另请参阅 systemd-networkd#[Network]

启用 NAT

使用 iptables

安装 iptables 软件包。使用 iptables 启用 NAT

# iptables -t nat -A POSTROUTING -o internet0 -j MASQUERADE
# iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -A FORWARD -i net0 -o internet0 -j ACCEPT
注意: 当然,这也适用于移动宽带连接(在路由 PC 上通常称为 ppp0)。

如果您安装了 docker,请使用 -I DOCKER-USER 而不是 -A FORWARD[4]

# iptables -t nat -A POSTROUTING -o internet0 -j MASQUERADE
# iptables -I DOCKER-USER 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -I DOCKER-USER 2 -i net0 -o internet0 -j ACCEPT

如果通过 PPPoE 连接,请将 mss 钳制为 pmtu 以防止分片

# iptables -t mangle -A FORWARD -o ppp0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

阅读 iptables 文章以获取更多信息(尤其是在启动时保存规则并自动应用它)。还有一个关于 iptables 简单状态防火墙 的优秀指南。

使用 nftables

安装 nftables 软件包。要使用 nftables 启用 NAT,您必须在新表/现有表中创建 postrouting

# nft add table inet nat
# nft add chain inet nat postrouting '{ type nat hook postrouting priority 100 ; }'

之后,您必须为 internet0 伪装 net0 地址

# nft add rule inet nat postrouting oifname internet0 masquerade

许多防火墙配置,例如默认的 /etc/nftables.conf,将 'filter' 表的 'forward' 链的默认策略设置为 'drop'。在这种情况下,您将需要规则来允许转发 NAT 流量

# nft add rule inet filter forward ct state related,established accept
# nft add rule inet filter forward iifname net0 oifname internet0 accept

您可以在 nftables Wiki 中找到有关 nftables 中 NAT 的更多信息。如果您想使这些更改永久生效,请按照 nftables 上的说明进行操作。

使用 firewalld

安装 firewalld 软件包。firewalld 是一个防火墙守护进程,它依赖于 nftablesiptables。首先更改网络接口的 firewalld 区域

# firewall-cmd --zone=external --change-interface=internet0 --permanent
# firewall-cmd --zone=internal --change-interface=net0 --permanent

然后添加新策略以允许流量在内部区域和外部区域之间流动

# firewall-cmd --permanent --new-policy int2ext
# firewall-cmd --permanent --policy int2ext --add-ingress-zone internal
# firewall-cmd --permanent --policy int2ext --add-egress-zone external
# firewall-cmd --permanent --policy int2ext --set-target ACCEPT
# firewall-cmd --reload
提示: 您可以使用比裸 ACCEPT 更严格的策略规则,如 firewalld 概念页面的 防火墙规则 部分所示 [5]

例如,要仅允许 192.168.2.0/24 中的节点访问互联网,请执行

firewall-cmd --permanent --policy int2ext --add-rich-rule='rule family=ipv4 source address=192.168.2.0/24 accept' 不要忘记之后重新加载规则

firewall-cmd --reload

为客户端电脑分配 IP 地址

如果您计划定期让多台机器使用此机器共享的互联网,那么安装 DHCP 服务器是一个好主意。有关可用选项,请参阅 路由器#DNS 和 DHCP。然后在每台客户端 PC 上配置 DHCP 客户端,请参阅 网络配置#网络管理器

本文或本节需要语言、Wiki 语法或风格改进。请参阅 帮助:风格 以供参考。

原因: 这不是 iptables 指南。使用 iptables -I 扩展链可能会跳过其他重要规则;如果您需要为此编写 ON/OFF 开关脚本,请使用自定义链,并将跳转小心地放置在 INPUT 链中。(在 Talk:Internet sharing 中讨论)

必须允许 DHCP 服务器的 UDP 端口 67 的入站连接。还需要允许 DNS 请求的 UDP/TCP 端口 53 的入站连接。

# iptables -I INPUT -p udp --dport 67 -i net0 -j ACCEPT
# iptables -I INPUT -p udp --dport 53 -s 192.168.123.0/24 -j ACCEPT
# iptables -I INPUT -p tcp --dport 53 -s 192.168.123.0/24 -j ACCEPT

或者使用 firewalld

# firewall-cmd --zone=internal --permanent --add-service dns
# firewall-cmd --zone=internal --permanent --add-service dhcp
# firewall-cmd --zone=internal --permanent --add-service dhcpv6

如果您不打算定期使用此设置,您可以改为手动为每个客户端添加 IP。

手动添加 IP

除了使用 DHCP 之外,还可以手动配置静态 IP 地址和通过 192.168.123.100 的默认路由。有许多工具可用于相应地配置网络。这种工具的一个突出示例是 ip(8),请参阅 网络配置#网络管理。或者,可以使用 .network 文件,请参阅 Systemd-networkd#使用静态 IP 的有线适配器 来设置静态 IP。

为每个客户端配置 DNS 服务器,有关详细信息,请参阅 域名解析

就是这样。客户端电脑现在应该可以上网了。

故障排除

如果您能够连接两台电脑但无法发送数据(例如,如果客户端电脑向服务器电脑发出 DHCP 请求,服务器电脑收到请求并向客户端提供 IP,但客户端不接受,而是超时),请检查您是否没有其他 iptables 规则 干扰

客户端无法访问互联网或无法连接

症状可能还包括:客户端在 ping 主机时收到 host is down,在 ping LAN 外部的设备时收到 no route to host(应该由 NAT 转发),DHCP 提供的地址未跨越桥接,...

已知 docker 可能会导致这些问题。只需禁用 docker.servicedocker.socket 即可解决此问题。

docker github 问题.

连接的第二台电脑无法使用桥接 LAN

第一台电脑有两个 LAN。第二台电脑有一个 LAN 并连接到第一台电脑。让第二台电脑在桥接接口后提供对 LAN 的所有访问权限

本文或本节需要扩充。

原因: 解释这些设置的实际作用。(在 Talk:Internet sharing 中讨论)
# sysctl net.bridge.bridge-nf-filter-pppoe-tagged=0
# sysctl net.bridge.bridge-nf-filter-vlan-tagged=0
# sysctl net.bridge.bridge-nf-call-ip6tables=0
# sysctl net.bridge.bridge-nf-call-iptables=0
# sysctl net.bridge.bridge-nf-call-arptables=0

参见