路由器

出自 Arch Linux 中文维基

此文章是將一台電腦配置為一台網關/路由器的指南。為加強安全性,不應在此機器上運行對外服務。對於區域網(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 地址。

這篇文章的某些內容需要擴充。

原因: 添加脫機方式生成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 如何配置代理為網頁瀏覽加速和/或添加額外的安全層。

時間伺服器[編輯 | 編輯原始碼]

將路由器用作一台時間伺服器,參閱系統時間#時間同步,配置網絡時間協議(NTP)伺服器。

然後配置 shorewall 或者 iptables 允許 NTP 流量流出。

內容過濾[編輯 | 編輯原始碼]

如果需要內容過濾,可以安裝配置 DansGuardian 或者 Privoxy

流量共享[編輯 | 編輯原始碼]

流量共享很有用,尤其當區域網中不止一台機器時。基本思路是為不同類型的流量分配優先級。交互型流量(ssh、在線遊戲等)可能需要高優先級,而 P2P 流量可分配低優先級。其他流量介於二者之間。

參閱[編輯 | 編輯原始碼]