路由器

来自 Arch Linux 中文维基
(重定向自Router

此文章是将一台电脑配置为一台网关/路由器的指南。为加强安全性,不应在此机器上运行对外服务。对于局域网(LAN),只运行特定的网关服务而不运行httpd、ftpd、samba、nfsd等属于局域网服务器的服务,因为这样会带来风险。

此文章不涉及如何设置两台PC用交叉网线进行网络连接共享。简单网络连接共享,参见Internet sharing

注意: 在本文中,intern0extern0是网络接口的名称。进一步说明参见#网络接口名称约定.

硬件需求[编辑 | 编辑源代码]

  • 至少 1GB 硬盘空间。基本安装约需 500MB 硬盘空间,如果使用web代理缓存还需额外预留缓存空间。
  • 至少两个实体网络接口:网关要将两个网络彼此连通(实际上路由器可以用一个物理网络接口实现两个VLAN接口并连接到VLAN交换机,这称为单臂路由/router-on-a-stick,但本文不讨论这种情况)。需要将两个网络连接到同一台实体机器,其中一个网口连接到外部网络,另一个连接内部网络。其中一个接口必须连接到外部网络,其他接口连接到内部网络。
  • 一个集线器、交换机或UTP线缆:将其他机器连接到网关。

网络接口配置[编辑 | 编辑源代码]

网络接口名称约定[编辑 | 编辑源代码]

Systemd 会自动为网口选择唯一接口名称。命名是持续不变的,直到重启。你可能希望更改接口名称,以便标记不同的网络接口。在以下的说明中,我们约定使用以下名称:

  • intern0:连接到局域网(LAN)的网络接口。真实名称可能是 enp2s0、enp1s1 等等。
  • extern0:连接到外部网络或广域网的网络接口。真实名字可能是 enp2s0、enp1s1 等等。

你可以通过Systemd-networkd#Renaming an interface中说明的方法使用Systemd-networkd的配置文件,或通过网络配置#Change interface name中说明的方法使用udev规则重新分配设备名称。由于本文是示例性质,使用以上约定名称。

IP 配置[编辑 | 编辑源代码]

首先需要配置网络接口。配置网络接口最好的方式是编辑 netctl 配置文件。下面需要创建两个配置文件。

注意: 如果仅通过PPPoE连接到互联网(只有一个广域网接口),则不要设置或启用外网口配置文件(extern0-profile)。参见#PPPoE配置
  • /etc/netctl/extern0-profile
Description='Public Interface.'
Interface=extern0
Connection=ethernet
IP='dhcp'
  • /etc/netctl/intern0-profile
Description='Private Interface'
Interface=intern0
Connection=ethernet
IP='static'
Address=('10.0.0.1/24')
注意: 上面示例中假定路由器面向整个子网。如果只要面向少数几台机器,可以修改 CIDR 后缀缩减范围。例如 /27 是限定范围在 10.0.0.110.0.0.30。有很多在线CIDR计算器可用,例如sipcalc

下一步是用 netctl 启用网络接口配置。

# netctl enable extern0-profile
# netctl enable intern0-profile

ADSL连接/PPPoE[编辑 | 编辑源代码]

可以用 rp-pppoe 将防火墙的 extern0 接口连接到ADSL modem并管理该连接。确认已将modem设置为桥接(或半桥接或RFC1483)模式,否则modem工作于路由器模式。安装 rp-pppoe 包。

需要注意的是:如果仅能通过PPPoE连接到互联网(除了能连接modem之外没有其它广域网接口),则不必启用 extern0-profile ,因为此时外网口使用名为 ppp0 的伪接口。

PPPoE配置[编辑 | 编辑源代码]

可以使用 netctl 设置 pppoe 连接。首先,

# cp /etc/netctl/examples/pppoe /etc/netctl/

然后编辑它。选择连接到modem的接口并配置。如果你仅仅通过PPPoE连接到互联网,这就是 extern0 接口。其他字段填入ISP的信息。详情参阅 netctl.profile(5) 手册。

DNS 和 DHCP[编辑 | 编辑源代码]

可以使用专为小型站点设计的 dnsmasq 为局域网提供DNS和DHCP服务。安装 dnsmasq 包即可。

Dnsmasq 要配置为DHCP服务器。编辑 /etc/dnsmasq.conf

/etc/dnsmasq.conf
interface=intern0 # 使dnsmasq只侦听来自内网口(intern0,即局域网)的请求
expand-hosts      # 为 /etc/hosts 中的主机名添加一个域名
domain=foo.bar    # 允许DHCP主机的完全限定域名(需要启用“expand-hosts”)
dhcp-range=10.0.0.2,10.0.0.255,255.255.255.0,1h # 定义局域网中DHCP地址范围:从 10.0.0.2 至10.0.0.255,子网掩码为 255.255.255.0,DHCP 租期为 1 小时 (可按需修改)

下面将看到,只能添加静态DHCP租约。例如,分配一个IP地址给局域网中某一台指定MAC地址的机器。这样,无论这台机器何时请求DHCP,都获得同一个IP地址。对于需要DNS记录的网络服务来说这非常有用。这也可以拒绝特定MAC的机器获取IP地址。

现在 启动 dnsmasq.service 服务。

连接共享[编辑 | 编辑源代码]

现在可以连通两个网络接口。

Manual[编辑 | 编辑源代码]

首先,需要允许数据包从一个网络接口跳转到另一个网络接口。这样需要通过内核中的 sysctl(8) 功能启用包转发功能。详情参阅 Internet sharing#Enable packet forwarding

假设 net.**forwarding 设置正确(即设置为 1),数据包仍需要正确地发送和接收。因此,必须在外部网路和内部子网之间转换IP地址。这种技术称为“伪装”(masquerading)。还需要两个转发规则保持连接,并使LAN能够转发到WAN。为此,我们可以使用iptables

/etc/iptables/iptables.rules
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o extern0 -j MASQUERADE
COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i intern0 -o extern0 -j ACCEPT
COMMIT

如果通过PPPoE连接,还需要将 mss 钳制到 pmtu,防止产生碎片:

/etc/iptables/iptables.rules

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A FORWARD -o ppp0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
COMMIT

Startenable iptables.service。路由器现在应该完全正常运行,并路由数据。但是,要面向公共Internet使用,还需要通过Simple stateful firewall进行额外的保护。

用shorewall共享连接[编辑 | 编辑源代码]

详细配置说明参见Shorewall

IPv6说明[编辑 | 编辑源代码]

很有用的参考: IPv6wikipedia:IPv6

唯一本地地址[编辑 | 编辑源代码]

即使ISP没有提供IPv6地址,仍然可以将路由器设置为IPv6模式。除非禁用IPv6,否则所有接口都会分配唯一的 fe80::/10 地址。

Tango-view-fullscreen.png这篇文章的某些内容需要扩充。Tango-view-fullscreen.png

原因: 添加脱机方式生成ULA。 (在 Talk:路由器 中讨论)

对于内部网络,已保留地址块 fc00::/7。这些地址保证是唯一的,且不可从开放的互联网路由。属于 fc00::/7 的地址称为 Unique Local Addresses。要在内部网络生成和使用 generate a ULA /64 block,如希望使用 fd00:aaaa:bbbb:cccc::/64,我们首先要在内部接口上分配静态IPv6地址。修改上面的 intern0-profile,添加以下一行:

 Address6=('fd00:aaaa:bbbb:cccc::1/64')

这样将ULA添加到内部网络接口。就路由器而言,这是唯一需要配置的地方。

全局单播地址[编辑 | 编辑源代码]

如果ISP或WAN网络可以访问IPv6 Internet,则可以将全局链路地址分配给路由器,并通过 SLAAC传播到内部网络。全局单播前缀通常是静态或通过前缀委派提供的。

静态IPv6前缀[编辑 | 编辑源代码]

如果ISP提供静态前缀,则编辑 /etc/netctl/extern0-profile配置文件,简单添加IPv6地址和前缀即可:

 Address6=('2002:1:2:3:4:5:6:7/64')

可以在使用上述ULA地址之外,同时使用此功能。

通过DHCPv6-PD获取IPv6前缀[编辑 | 编辑源代码]

如果ISP通过前缀委派处理IPv6,则可以按照main IPv6 article中的说明进行操作。按照本说明的约定,WAN接口为 extern0(或如果通过PPPoE连接时是 ppp0),LAN接口为 intern0

路由通告与无状态自动配置(SLAAC)[编辑 | 编辑源代码]

要向网络客户端正确分发IPv6,需要使用通告守护进程。按照 main IPv6 article 中关于如何设置 radvd的说明进行操作。按照本说明的约定,LAN接口是 intern0。可以通告所有前缀,或选择哪些前缀分配给本地网络。

可选附加功能[编辑 | 编辑源代码]

UPnP[编辑 | 编辑源代码]

上述 shorewall 的配置不包含 UPnP 支持。尽管可能使路由器遭到来自局域网内部的攻击,然而某些应用要求必须使用UPnP。

要在路由器上启用UPnP,需要安装一个UPnPInternet Gateway Device (IGD) protocol。可从官方仓库安装 miniupnpd

更详细信息请查阅 Shorewall guide on UPnP

远程管理[编辑 | 编辑源代码]

OpenSSH 可用于远程管理路由器,十分适合运行在“无头”模式(无显示器或输入设备)的机器。

缓存网页代理[编辑 | 编辑源代码]

参阅 Squid 如何配置代理为网页浏览加速和/或添加额外的安全层。

时间服务器[编辑 | 编辑源代码]

将路由器用作一台时间服务器,参阅System time#Time synchronization,配置网络时间协议(NTP)服务器。

然后配置 shorewall 或者 iptables 允许 NTP 流量流出。

内容过滤[编辑 | 编辑源代码]

如果需要内容过滤,可以安装配置 DansGuardian 或者 Privoxy

流量共享[编辑 | 编辑源代码]

流量共享很有用,尤其当局域网中不止一台机器时。基本思路是为不同类型的流量分配优先级。交互型流量(ssh、在线游戏等)可能需要高优先级,而 P2P 流量可分配低优先级。其他流量介于二者之间。

参阅[编辑 | 编辑源代码]