菜鸡路由器拼装之路(3):基于某网络现状的IPv6方案

长夜漫漫,等待Chrome源码编译,顺手写一下。

上一篇文章中,我们基本上把IPv4的网络配置好了,这篇文章就来说说IPv6的一些基础配置。同IPv4相比,IPv6给我们的本地网络配置带来了很多方便,为网间通信提出了一些新的方式,但是这并不意味着我们可以高枕无忧,因为很多时候,新特性你是用不上的……

不说废话,开搞。

总体思路

首先要说,IPv6下的网络配置思路是和IPv4有所不同的。上一代网络中我们进行网络配置的时候,由于ISP分配的地址数量有限,因此我们通常都是按照内网联通-外网联通-NAT的思路来配置的。但是由于IPv6中有众多可用的地址,ISP通常可不以地址为单位进行分配,而可以为每位用户分配一个字网前缀,网内的主机使用Stateles或Stateful的地址自动配置方案,与公网之间通过防火墙隔离。这样做有很多好处,比如:

  • 硬件设计更容易,硬转发更容易
  • 路由表设计更简单
  • 减少了性能延迟

因此,对于IPv6网络,通常直接在启用转发功能后向网内主机通报一个前缀,之后的事情就不用处理了。

然而,对于我所在的IPv6环境,事情变得有点复杂。我们的接入系统并不会分配一个地址前缀,而是分配单个地址。即使你要求ISP分配一个前缀,返回的地址也是无法正常路由的。因此,我们不得不回到NAT的老路上……

内网配置

内网准备使用Stateful Autoconfiguration。为了维护方便,仍然用dnsmasq作为DHCPv6服务端,我们在dnsmasq中添加一行:

dhcp-option=option6:dns-server,[::]

之后,我们去Unique Local IPv6 Generator获取一个随机的字网前缀,这样得到的前缀不太容易和其他人相同。假设我们拿到了fdeb:6802:6817::/48,那我现在打算设定子网为fdeb:6802:6817:1433::/64,于是给br0分一个地址。修改/etc/network/interfaces,加入:

iface br0 inet6 static
  # use prefix fdeb:6802:6817:1433::/64
  address fdeb:6802:6817:1433::1
  netmask 64

现在可以配置RA了。安装RA服务端apt install radvd后,编辑/etc/radvd.conf

interface br0
{
  AdvSendAdvert on;
  AdvManagedFlag on;
  AdvOtherConfigFlag on;
  MinRtrAdvInterval 5;
  MaxRtrAdvInterval 15;
  prefix fdeb:6802:6817:1433::/64 {
   AdvOnLink on;
   AdvAutonomous on;
  };
  RDNSS fdeb:6802:6817:1433::1 {
  };
};

此外,还需要做一些防火墙的配置。我们把之前的iptables_helper复制一份为ip6tables_helper,并做一些修改。之后,在启动脚本中添加这么几行:

ip6tables_zone_member_add Wan tun0
ip6tables_zone_member_add Wan wlan0wan

这几行的目的就不说啦,熟门熟路的。现在在所有终端的防火墙上加一条规则:

ip6tables -I INPUT -s eth0 -p ipv6-icmp -j ACCEPT

这是因为RA依赖ICMPv6。现在重启所有路由和终端的网络服务,看看所有设备能否获得我们设定的子网前缀的地址,能否互相连通。

外网和NAT配置

接下来我们开始配置转发和NAT,不过在此之前,先从rc.local中注释掉所有的命令,因为要升级内核到4.4.34版本,这是因为Linux在3.9.0版本后才从内核支持NATv6,而我的发行版在3系并没有支持到3.9。

升级后记得调整你的所有脚本,确定正常工作之后,就可以尝试配置转发了。首先我们调整一个参数:

net.ipv6.conf.all.accept_ra=2
net.ipv6.conf.default.accept_ra=2

为什么要调整这个参数呢?我们来看下文档中对这个参数的说明:

accept_ra - INTEGER
 Accept Router Advertisements; autoconfigure using them.

 It also determines whether or not to transmit Router
 Solicitations. If and only if the functional setting is to
 accept Router Advertisements, Router Solicitations will be
 transmitted.

 Possible values are:
  0 Do not accept Router Advertisements.
  1 Accept Router Advertisements if forwarding is disabled.
  2 Overrule forwarding behaviour. Accept Router Advertisements
    even if forwarding is enabled.

 Functional default: enabled if local forwarding is disabled.
       disabled if local forwarding is enabled.

由于我的网络是依靠RA下发地址的,而我还要做转发,所以必须这样设置。当然,dnsmasq中要做好处理,不要让错误的ra扩散到WAN接口上去。此外别忘了:

net.ipv6.conf.all.forwarding=1
net.ipv6.conf.default.forwarding=1

从而启用转发。

IPv6的外网配置在第一篇文章中就说过一部分了,现在你的IPv6外网实际应该处于连通状态,因此不再细谈如何配置接入,而是要看看如何配置防火墙。还记得之前的0001pppoe_ipv4_start吗?我们去ip6-up.d新建一个0001pppoe_ipv6_start:

#!/bin/bash

# Import scripts
SCRIPT_ROOT=/root/scripts
source $SCRIPT_ROOT/ip6tables_helper

#echo Interface: $1 > /dev/kmsg
#echo Local IP:  $4 > /dev/kmsg
#echo Remote IP: $5 > /dev/kmsg

# Base rules
ip6tables_init

# Create zones
ip6tables_zone_create Wan
ip6tables_zone_create Lan

ip6tables_zone_member_add Wan $1
ip6tables_zone_member_add Lan br0

ip6tables -A ZoneWanInput -p ipv6-icmp -j ACCEPT

ip6tables -A ZoneLanInput -j ACCEPT
ip6tables -A ZoneLanForward -j ACCEPT
ip6tables -t nat -A ZoneWanPostrouting -j MASQUERADE

# fix mss problems
ip6tables -t mangle -X
ip6tables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

注意我们允许了WAN上的ICMP,理由同上。现在再次重新启动所有终端,检查:

  • 所有终端可以自动获得fdeb:6802:6817:1433::/64下的地址
  • 所有终端可以用fdeb:6802:6817:1433::/64的地址与路由器fdeb:6802:6817:1433::1通信
  • 测试curl -6nvLI ipv6.google.com应该返回正常结果(如果你认真配置了DNS的话)

现在去测试一下:

img

img

至此,网络相关的所有主要配置都结束了。回顾一下我们的目标:

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

后几个都需要一些软硬件改动才能实现,因此更新速度会很慢。

等不起编译了,睡觉。