菜鸡路由器拼装之路(1):基础IPv4网关构建
买了一个“香蕉派”(BananaPi-R1),功能还是可以的,本来准备一点点改成一个比较好用的综合网关,后来搁置了。最近因为没有实验室可以用,只能在宿舍工作,设备又比较多,学校的接入方式还有点智障,因此又描上了这块盒子。
硬件介绍与基本思路
- 全志A20+1GB RAM+BCM53125
- 2.4GHz Wifi
- 5xGbE Ports
- 1xUSB 2.0, 1xRF, 1xHDMI
- 1xSATA
看上去很美好,然而有点鸡肋。因为:
- 没有硬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
,分别将两块网卡(一块自带,一块新装)设定为wlan0wan
和wlan1lan
。
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/24
和192.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时钟和交换机配置保存