Internet sharing (简体中文)

From ArchWiki
翻译状态:本文是 Internet sharing翻译。上次翻译日期:2017-06-28。如果英文版本有所更改,则您可以帮助同步翻译。

Tango-preferences-desktop-locale.png本文或本节需要翻译。要贡献翻译,请访问简体中文翻译团队Tango-preferences-desktop-locale.png

附注: 初创页面,尚未翻译(在 Talk:Internet sharing (简体中文)# 中讨论)

这篇文章解释了如何从一台机器向其他机器分享网络连接。

依赖

作为服务器的机器应该有一个额外的网络设备。这个网络设备需要一个数据链路层来连接到将要获得网络访问的机器:

  • 如果想给若干台机器分享网络连接,交换机可以提供数据连接。
  • 一个无线设备同样可以给若干台机器分享网络访问,参见Software access point
  • 如果只需分享网络给一台机器,一根交叉网线就可以了。 如果两台电脑的网卡支持MDI-X,交叉网线也不是必须的,一根普通直连网线也可以。 运行 ethtool interface | grep MDI 确认网卡是否支持MDI-X。

配置

这个章节假定,连接到客户机的网络设备被命名为 net0而连接到互联网的网络设备被命名为internet0

提示: 为了此事,你可以使用Udev#Setting static device names所述的方法重命名你的设备。

所有的配置都是在服务器计算机上完成的,除了最后一步#给客户机分配IP地址.

静态IP地址

在服务器计算机上,给要连接到其他机器的网卡分配一个静态的IP地址。IP地址的前3个字节不能和其他网卡的一模一样,除非两个网卡都有一个严格大于/24的子网掩码。

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

为了使你的静态IP在启动时被分配,你可以使用network manager

启用包转发

检查当前的包转发设置:

# sysctl -a | grep forward

你将会注意到控制每个默认值,每个网卡的包转发的选项都是存在的,同时每个网卡的IPv4和IPv6选项都是分开的。

输入这条命令以在运行时临时启用包转发:

# sysctl net.ipv4.ip_forward=1
提示: 要想选择性地为某一个具体的网卡提供包转发,使用sysctl net.ipv4.conf.interface_name.forwarding=1来代替。
警告: 如果系统使用了systemd-networkd来控制网卡,就不可能为单个网卡配置IPv4的设置,换言之,systemd的操作规则会将所有配置过的转发发送到一个全局(针对所有网卡)的IPv4的设置。建议的变通方法是使用防火墙在选中的网卡上禁止转发。参考systemd.network(5)手册页以获取更多信息。在之前的systemd发行版本220/221中引入的执行内核设置的IPForward=kernel已不再适用。[1] [2]

编辑/etc/sysctl.d/30-ipforward.conf来使得之前的改变可以永久地应用于所有接口上:

/etc/sysctl.d/30-ipforward.conf
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1

这之后,仍然建议在重启之后再次检查,以确认转发已经按需求启用。

启用 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
注意: 当然了,这对移动宽带连接(一般在电脑上叫做ppp0)也有用。

阅读iptables的文章以获取更多信息(特别是关于保存规则并在重启之后应用的东西)。 还有一篇关于iptables的很好的文章:Simple stateful firewall

使用 nftables

安装 nftables包。要通过nftables启用NAT,你必须在一个新的或者现有的表中创建prerouting和postrouting链(即使它们是空的你也还是需要这两个链):

# nft add table ip nat
# nft add chain ip nat prerouting { type nat hook prerouting priority 0 \; }
# nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
注意: 如果想要使用IPv6,你需要将所有的ip替换为ip6

然后,你还要将net0的地址转换为internet0的地址(这里就是网络地址转换NAT了):

# nft add rule nat postrouting oifname internet0 masquerade

你可能还向在forwarding链上添加更多的防火墙显示(加入filter表已经存在,就像Nftables#Server中配置的那样):

# nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop}
# nft add rule filter forward ct state related,established accept
# nft add rule filter forward iifname net0 oifname internet0 accept


你可以在nftables Wiki找到更多的关于nftables中的NAT的信息。如果你想要持久化这些更改,照着nftables (简体中文)说的做。

给客户机分配IP地址

如果你计划经常要有几台机器使用这台电脑共享的网络,那么建议你安装一个DHCP服务器,比如dhcpd (简体中文) 或者 dnsmasq (简体中文)。然后在每一台连这个网的电脑上配置DHCP客户端(比如说dhcpcd (简体中文))。

Tango-edit-clear.pngThis article or section needs language, wiki syntax or style improvements. See Help:Style for reference.Tango-edit-clear.png

Reason: This is not an iptables guide. Expanding the chain with iptables -I might skip other important rules; if you need to script an ON/OFF switch for this, use custom chain with a jump placed carefully in the INPUT chain. (Discuss in Talk:Internet sharing (简体中文))

必须把67端口的UDP传入连接开给DHCP服务器。为了允许DNS请求,还要打开53端口的UDP/TCP传入连接。

# 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

如果你不打算经常使用这套配置,你也可以手动给每台电脑配置IP。

手动添加IP地址

Tango-edit-clear.pngThis article or section needs language, wiki syntax or style improvements. See Help:Style for reference.Tango-edit-clear.png

除了使用DHCP,你还可以在每台客户端电脑上添加IP地址和默认网关:

# ip addr add 192.168.123.201/24 dev eth0  # 地址随便填,但是网段和子网掩码必须和服务端在这个子网的配置一样
# ip link set up dev eth0
# ip route add default via 192.168.123.100 dev eth0   # 服务端的地址

为每一个客户端电脑配置DNS服务器, 细节位于resolv.conf (简体中文)

搞定。客户端电脑现在应该有网了。

问题解决

如果你可以连接两台电脑但没法传输数据(比如说,客户端发送了DHCP请求给服务器,服务器受到了并且给了一个IP,但是客户端没收到,最后超时了),检查以确保你没有其他Iptables (简体中文)规则在干扰

客户端无法连接Wi-Fi或者无法上网

问题还包括:很久都拿不到ip,DHCP offer穿不过虚拟网桥,设备ping电脑的时候得到"host is down", ping外部网络的时候得到"no route to host"……

目前已知docker可能导致这个问题。禁用docker.service和docker.socket就可以解决了。

在github上的issue

另请参见