菜鸡路由器拼装之路(1):基础IPv4网关构建

买了一个“香蕉派”(BananaPi-R1),功能还是可以的,本来准备一点点改成一个比较好用的综合网关,后来搁置了。最近因为没有实验室可以用,只能在宿舍工作,设备又比较多,学校的接入方式还有点智障,因此又描上了这块盒子。

硬件介绍与基本思路

看上去很美好,然而有点鸡肋。因为:

  • 没有硬NAT,大量报文需要走CPU。
  • CPU和53125之间是一条1Gbps的线路,理论上就没法线速处理报文
  • Wi-Fi驱动对Hostapd支持有问题,难以搭建热点
  • 最重要的是,BCM53125在上电后没有down,而是把所有端口置于同一个VLAN,安全风险极大
  • SATA供电和速率均处于勉强可用的水平

而一些缺陷似乎可以弥补:

  • USB接外置网卡做Hostapd
  • LAN口虽然隔离不好但是毕竟比较多

初步的想法是:

  • 自己的帐号出了点问题,而且配置PPPoE本身也有点麻烦,因此就先用舍友的WiFi接入一段时间公网
  • LAN下的有线和无线设备同处于192.168.40.0/24内,不隔离
  • 没有其他需求

实际就是个简单的网关配置任务。

硬件界面准备

SD卡烧入Bananian Linux后,串口链接到J13的UART0上,插入外置网卡(我用的是一块RTL8188CUS)。

开机,用默认用户名和密码登入后进入系统,修改/etc/udev/rules.d/70-persistent-net.rules,分别将两块网卡(一块自带,一块新装)设定为wlan0wanwlan1lan

WAN接口准备

用以下命令获取配置项:

wpa_passphrase <SSID> <Password>

/etc/network/interfaces中添加:

# Set Wireless WAN network
auto wlan0wan
iface wlan0wan inet static
  wpa-ssid <SSID>
  wpa-psk <The passphrase got before>
  address 192.168.10.20
  netmask 255.255.255.0
  #gateway 192.168.10.233  #这条不要加,知道就好了

重新启动后登陆,理论上这块板子本体应该可以联网了。这时你应该立刻进行系统升级,并减少联网时间,因为此时系统还没有防火墙。

有线LAN接口准备

根据BPI-R1的设计,我们决定将VLAN做如下规划:

  • eth0.100 与wlan1lan桥接,局域网
  • eth0.200 外网PPPoE
  • eth0.300 外网DHCP(暂时不做配置)

首先来修改VLAN。修改/etc/network/if-pre-up.d/swconfig

ifconfig eth0 up
# The swconfig port number are:
# |2|1|0|4|  |3|
# (looking at front of ports)
# Will allocate 3 client ports, 1 PPPoE Ports and 1 DHCP ports
# using vlan 100, 200 and 300
swconfig dev eth0 set reset 1
swconfig dev eth0 set enable_vlan 1
# swconfig dev eth0 vlan 101 set ports '3 8t'
# swconfig dev eth0 vlan 102 set ports '4 0 1 2 8t'
swconfig dev eth0 vlan 300 set ports '3 8t'
swconfig dev eth0 vlan 200 set ports '4 8t'
swconfig dev eth0 vlan 100 set ports '2 1 0 8t'
swconfig dev eth0 set apply 1

注意,8t必须加,否则这个网络和本体是不通信的。此外,如果你能单条执行以上指令,或许能发现一个可以缓解LAN口隔离缺陷的方法,我在后几篇文章中会提到。

不要忘了把相关的配置添加到/etc/network/interfaces中:

auto eth0.100
iface eth0.100 inet manual

auto eth0.200
iface eth0.200 inet manual

auto eth0.300
iface eth0.300 inet manual

无线LAN接口准备

刚才我们配置好了所有的有线接口,现在开始配置无线接口。apt装上dnsmasq之后,首先配置hostapd。编辑配置文件/etc/hostapd/hostapd.conf

...

macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0

...
wpa=3
wpa_key_mgmt=WPA-PSK
#wpa_pairwise=TKIP
rsn_pairwise=CCMP

...
#driver=nl80211
driver=rtl871xdrv

...
device_name=RTL8188CUS
manufacturer=Realtek

# set proper interface
interface=wlan1lan
bridge=br0
hw_mode=g
# best channels are 1 6 11 14 (scan networks first to find which slot is free)
channel=1
# this is the network name
ssid=IAMBACK
# CHANGE THE PASSPHRASE
wpa_passphrase=500InternalError

注意修改相关的密钥管理选项。之后修改/etc/default/hostapd,注释掉配置文件那一行。重启板子,验证一下配置是否正确就可以了。

基础IPv4网关搭建

LAN接口桥接

在执行这一步之前,请确定相关的有线和无线接口工作正常,二层链路工作正常,数据帧收发正常。

我们首先将有线和无线LAN接口桥接起来。apt安装brctl后,在/etc/network/interfaces中添加:

auto br0
iface br0 inet static
  bridge_ports eth0.100 wlan1lan
  hostname seemless
  address 192.168.40.200
  netmask 255.255.255.0

路由服务搭建

重启网络服务,确定br0建立起来,并且有线客户端、无线客户端和机体互通后,LAN工作正常。

接下来启动DHCP服务。修改/etc/dnsmasq.conf

interface=br0
dhcp-range=192.168.40.50, 192.168.40.100,12h
dhcp-option=option:router,192.168.40.200

验证DHCP服务器工作正常,且下发配置正常后,接着修改/etc/sysctl.conf,开启转发:

net.ipv4.ip_forward=1
#net.ipv4.tcp_syncookies=1  # 这一条你也可以取消注释,如果你确定不会有人胆肥到找你来搞事

NAT服务搭建

上面我们实际已经完成了一个路由器的建立。很多人用家用路由器用的比较多后,总是容易把NAT和路由的概念混淆。实际上,这两者的概念是截然不同的。如果我们现在在本机和舍友的无线路由器上分别添加两条路由表项,指定到192.168.40.0/24192.168.1.0/24网段流量的流向后,我们就已经可以上网了。

然而事情常常没那么好,在诸如ADSL的情况下,你是不可能让ISP方添加一条你自己的路由表项的。因此我们接下来要做的就是NAT。与此同时,我们添加一些自己的防火墙项目。

我猜刚才配置好LAN接口后,你已经自己启动了SSH服务了。那么注意,在下面的配置过程中,你最好准备一条串口线,否则万一配错了,就很尴尬。

首先配置一个最基础版本的防火墙,用于我们在启动期间的安全防护:

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i br0 -j ACCEPT

然后记得保存一下

service netfilter-persistent save

接下来写几个辅助函数。我强烈建议你在阅读本文以及其他文章的后续工作之前,仔细阅读Stephen Zhang的这几篇文章。知其然而不知其所以然是很痛苦的一件事情。

按照Stephen文章中分Zone的管理方案,我先写了个这么个东西:

#!/bin/bash
# Some code copied from https://onebitbug.me/2014/06/01/building-a-gateway-iptables/

iptables_cmd=iptables

function iptables_init () {
    local lan_iface=$1
    local lan_iaddr=$2
    # Clear all old rules 
    $iptables_cmd -F
    $iptables_cmd -X
    $iptables_cmd -t nat -F
    $iptables_cmd -t nat -X
    # Build basic inbound rules
    $iptables_cmd -P INPUT DROP
    $iptables_cmd -P OUTPUT ACCEPT
    $iptables_cmd -P FORWARD DROP
    $iptables_cmd -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    $iptables_cmd -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
    # Now all basic inbound rules are configured.
    # We need to define some Zones which are helpful for management.
    # Those things should not be done by me, but I've left some functions here.
}

function iptables_zone_create () {
  local zone_name=$1
  $iptables_cmd -N Zone${zone_name}Input
  $iptables_cmd -N Zone${zone_name}Forward
  $iptables_cmd -t nat -N Zone${zone_name}Postrouting
}

function iptables_zone_member_add () {
    local zone_name=$1;
    shift
    local zone_iface=
    local zone_iaddr=
    for zone_iface in $@; do
        $iptables_cmd -A INPUT -i $zone_iface \
                      -j Zone${zone_name}Input
        $iptables_cmd -A FORWARD -i $zone_iface \
                      -j Zone${zone_name}Forward
        $iptables_cmd -t nat -A POSTROUTING -o $zone_iface \
                      -j Zone${zone_name}Postrouting
    done
}

然后写一个network_wlan_boot.sh

echo Route table processing...
ip route add default dev wlan0wan via 192.168.10.233
echo FW Zone processing...
iptables_init
iptables_zone_create Wan
iptables_zone_create Lan
iptables_zone_member_add Wan wlan0wan
iptables_zone_member_add Lan br0
echo FW Forwarding processing...
iptables -A ZoneLanInput -j ACCEPT
iptables -A ZoneLanForward -j ACCEPT
iptables -t nat -A ZoneWanPostRouting -j MASQUERADE
echo FW Fixing...
iptables -t mangle -X
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

然后在/etc/rc.local里加几行

echo default-on > /sys/class/leds/green:ph24:led1/trigger
bash /root/scripts/network_wlan_boot.sh > /dev/kmsg
echo mmc0 > /sys/class/leds/green:ph24:led1/trigger

重启机器,应该可以了。


以上我们已经完成了最基本的NAT网关的配置。接下来的几篇文章,我会试图实现以下几个目标:

  • PPPoE接入互联网
  • VPN接入国外网络以及流量区分
  • LAN中的IPv6访问
  • 网络和运行状态监视(via HTTP)
  • 启动中关闭LAN交换机
  • 启动时更改WAN接入方式,以及运行状态监视(via LCD)
  • 备用电源供应,RTC时钟和交换机配置保存