Padavan 路由器开启 IPv6,使外网通过 IPv6 访问子网树莓派上的网站 | 陶熔鼓铸
步骤:
一、获取公网 IPv6 地址并在树莓派上构建 Web 服务器
二、设置阿里 DNS 域名解析
三、更改树莓派获取 IPv6 地址的方式
四、更改 Padavan 防火墙的设置
一、获取公网 IPv6 地址并在树莓派上构建 Web 服务器
首先需要确定的是,您的运营商支持 IPv6。您可以通过以下配置尝试是否可以获取到 IPv6。
在 IPv6 的设置页面,按上图进行设置。如果运营商已经支持 IPv6 网络,那么设置完成后,在网络地图中的 “ IPv6 地址:WAN ”和“ IPv6 地址:LAN ”中,都会获取到 IPv6 地址,如下图所标示位置:
将树莓派连入网络中,使用 ifconfig 命令检查是否获取到 IPv6 地址。一般接口为 eth0,如果您打开了 wlan,同时查看相应接口是否也获取到 IPv6 地址。
注意:
1、即便 eth0 和 wlan0 连接到了不同路由器,两个接口也都会获取到 IPv6。
2、以 fe80 开头的 IPv6 地址为链路本地连接地址,并不是公网 IPv6 地址。您可以简单地把它理解为 IPv4 中类似 192.168.x.x 这类私有地址。
使用 ping6 命令可以检查网络的连通性,如下图:
网络连通了以后,您可以在树莓派上安装 Web 服务器,例如 Apache 或 Nginx。具体方法本文不再赘述,请查阅相关资料。安装完成后,请保持默认配置即可,即,所有 IP 地址(IPv4 和 IPv6)都可以通过浏览器访问。您也可以根据自己的需要进行设置。
当您做好了以上准备,就可以进行下一步了。
二、设置阿里 DNS 域名解析
通过以上操作,树莓派已经可以连接到 IPv6 网络,并实现外部访问了。
现在的问题是:
我们是以 PPPoE 方式上网,所获取的 IPv6 地址是动态的,即,每次路由器重启,IPv6 地址就会改变,树莓派重启,它的 IPv6 地址也会改变。这样一来,我们在树莓派上搭建 Web 服务器的话,就需要频繁的更改 IPv6 地址来访问。
为了便于记忆,我们使用域名解析到它的 IPv6 地址。在此只介绍使用阿里 DNS 来进行解析的办法。在设置之前,您需要在阿里云购买了一个域名并进行了实名认证。
1、登录阿里云网站并进入控制台,在右上角个人资料中,选择 AccessKey 管理。
2、出现以下提示时,选择“开始使用子用户 AccessKey”。
3、依次填写用户信息、显示名称,并将访问方式设置为“编程访问”。
4、验证手机后,会显示 AccessKeyID 和 AccessKey Secret,该信息页面关闭后无法再次显示,请妥善保存该信息。
5、在左侧的菜单中,点击“用户”,对刚才添加的用户进行添加授权。在搜索栏输入“dns”,点击下部筛选结果中的“AliyunDNSFullAccess”以将其添加到右侧列表中。点击确定以完成。
6、切换至阿里云域名管理设置界面,对您使用的域名进行解析操作,以初始化记录。在此,您需要解析一个记录类型为“AAAA”的主机,将其 IPv6 地址手动的设置为你树莓派上 eth0 口的 IPv6 地址,主机名称任选,如下图,保存并等待其生效。
至此,阿里云端的操作结束。
7、下面转到树莓派的本地设置。
由于路由器或树莓派本身的重启都会导致树莓派IPv6 地址的变化,我们就需要在树莓派的 IPv6 地址发生变化时,将新的 IPv6 地址信息传递给阿里云,进行 DNS 记录的更改。为便于操作,我们使用 Python 脚本实现这一功能,同时,为了尽量保证中断的时间尽可能短,我们使用计划任务每 10 分钟执行一次这个脚本。
该脚本来源于网络搜集,由 BG3MDO、BH4DQX 进行了编辑改写,对源脚本的问题进行了修正和处理。
请在树莓派的用户目录中,建立一个名称为 xxx.py 的文件,并将以下脚本内容复制过去:
#coding:utf-8
from __future__ import print_function
from aliyunsdkcore import client
from aliyunsdkalidns.request.v20150109 import DescribeDomainsRequest,DescribeDomainRecordsRequest,UpdateDomainRecordRequest
import json,urllib,re
import subprocess
#替换以下参数
ID="这里填写你从阿里云获取的AccessKeyID"
Secret="这里填写你从阿里云获取的AccessKeySecret"
RegionId="cn-hangzhou"
DomainName="这里填写你的域名,不带主机名,如:abc.com"
#想要自动修改的主机名和域名类型
HostNameList = ['这里填写你的主机名']
Types = "AAAA"
clt = client.AcsClient(ID,Secret,RegionId)
#获取公网ip
def GetLocalIP():
ips = subprocess.check_output(["hostname", "-I"])
#ip = subprocess.check_output(["curl", "-s", "https://api-ipv6.ip.sb/ip"])
ip = ips.split()[-1]
print(ip)
return ip
#获取域名列表
def GetDomainList():
DomainList = DescribeDomainsRequest.DescribeDomainsRequest()
DomainList.set_accept_format('json')
DNSListJson = json.loads(clt.do_action(DomainList))
print(DNSListJson)
#更新域名ip
def EditDomainRecord(HostName, RecordId, Types, IP):
UpdateDomainRecord = UpdateDomainRecordRequest.UpdateDomainRecordRequest()
UpdateDomainRecord.set_accept_format('json')
UpdateDomainRecord.set_RecordId(RecordId)
UpdateDomainRecord.set_RR(HostName)
UpdateDomainRecord.set_Type(Types)
UpdateDomainRecord.set_TTL('600')
UpdateDomainRecord.set_Value(IP)
UpdateDomainRecordJson = json.loads(clt.do_action(UpdateDomainRecord))
print("Edit Domain Record returns:")
print(UpdateDomainRecordJson)
#获取域名信息
def GetAllDomainRecords(DomainName, Types, IP):
DomainRecords = DescribeDomainRecordsRequest.DescribeDomainRecordsRequest()
DomainRecords.set_accept_format('json')
DomainRecords.set_DomainName(DomainName)
DomainRecordsJson = json.loads(clt.do_action(DomainRecords))
for HostName in HostNameList:
for x in DomainRecordsJson['DomainRecords']['Record']:
RR = x['RR']
Type = x['Type']
if RR == HostName and Type == Types:
RecordId = x['RecordId']
print("Record ID is: " + RecordId)
print("Hostname: " + HostName)
print("Types: " + Types)
print("IP: " + str(IP))
print("-"*32)
EditDomainRecord(HostName, RecordId, Types, IP)
IP = GetLocalIP()
print("-"*32)
GetDomainList()
print("-"*32)
GetAllDomainRecords(DomainName, Types, IP)
8、需要树莓派中的 Python 版本为 2.7 以上,使用 pip 安装 SDK:
sudo pip install aliyun-python-sdk-alidns
通过 install 完成升级:
sudo pip install aliyun-python-sdk-alidns --upgrade
9、建立定时任务:
crontab -e
在打开的文件最后一行添加:
* /10 * * * * /usr/bin/python2 /home/xxx.py
至此,阿里 DNS 功能设置完毕。该脚本每 10 分钟向阿里云提交一次更改请求,以保障服务的连续性。
三、更改树莓派获取 IPv6 地址的方式
我们先讨论一下从运营商网络获取 IPv6 地址(Global Address)的方式,然后再说为什么要更改树莓派获取 IPv6 地址的方式。
生成“全球单播地址”,有两种方式:即手动配置和自动配置,我们只讨论自动配置。
自动配置根据获取方式,分为:无状态(Stateless)和有状态(Stateful)。
无状态:根据路由通告报文 RA(Router Advertisement)包含的 Prefix 前缀信息自动配置 IPv6 地址,组成方式是:Prefix + (EUI64 或者 随机)。Stateless 也可称为 SLAAC(Stateless address autoconfiguration)。
有状态:通过 DHCPv6 方式获取 IPv6 地址。
其中,“有状态”又分为两种情况:有状态 DHCPv6(Stateful DHCPv6)和无状态 DHCPv6(Stateless DHCPv6)。
有状态 DHCPv6:IPv6 地址、其它参数(如DNS)均通过 DHCPv6 获取。
无状态 DHCPv6:IPv6 地址依然通过路由通告 RA 方式生成,其它参数(如DNS)通过 DHCPv6获取。
现在我们回过头来再说为什么要更改树莓派 IPv6 地址的获取方式。
内网设备(本例中的树莓派)的 IPv6 地址,前半部分是 IPv6 前缀,是运营商分配的,宽带重新连接后会发生变化。
后半部分,有两种情况,一种是随机,这样的话也会有变化。另一种是 EUI64,与 MAC 地址相关,不会变化,除非更换网卡。
如果整个 IPv6 的前后两个部分都会变,那么防火墙规则就没办法写了。除非全网放行(内网目标地址掩码填 ::/0 或 any)。
所以,将树莓派 IPv6 地址的后半部分设置为 EUI64,防火墙的目标地址掩码填写 ::xxxx:xxxx:xxxx:xxxx/::FFFF:FFFF:FFFF:FFFF,这样就比较安全了。因为 IPv6 地址掩码比 IPv4 灵活,IPv6 可以掩前面,也可以掩后面,而 IPv4 就只能掩前面。
需要注意的是,这里的例子,默认的掩码为/64,如果您的网络分配的掩码不是64,则需要调整掩码位数。
目的很简单,更改树莓派的 IPv6 地址后半部分的获取方式为 EUI64,可以让我们有办法在防火墙上做相应设置。
步骤如下:
vi /etc/dhcpcd.conf
在此配置文件中,查找 slaac ,将其默认的 slaac private 注释掉,将默认注释掉的 slaac hwaddr 启用即可。更改后重新获取 IPv6 地址,再用 ifconfig 命令验证,其 IPv6 地址后六位与对应的 MAC 地址后六位相同并且不变。
四、更改 Padavan 防火墙的设置
在路由器设置中,开启防火墙,此时搭建在树莓派上的 IPv6 网站无法从外网访问。
在路由器配置界面中,打开“自定义设置”——“脚本”。在“在防火墙规则启动后执行”一项中,填入以下内容:
ip6tables -A INPUT --ipv6 -p tcp -d ::xxxx:xxxx:xxxx:xxxx/::FFFF:FFFF:FFFF:FFFF -j ACCEPT
ip6tables -A OUTPUT --ipv6 -p tcp -d ::xxxx:xxxx:xxxx:xxxx/::FFFF:FFFF:FFFF:FFFF -j ACCEPT
ip6tables -A FORWARD --ipv6 -p tcp -d ::xxxx:xxxx:xxxx:xxxx/::FFFF:FFFF:FFFF:FFFF -j ACCEPT
ip6tables -A INPUT --ipv6 -p tcp -d ::nnnn:nnnn:nnnn:nnnn/::FFFF:FFFF:FFFF:FFFF -j ACCEPT
ip6tables -A OUTPUT --ipv6 -p tcp -d ::nnnn:nnnn:nnnn:nnnn/::FFFF:FFFF:FFFF:FFFF -j ACCEPT
ip6tables -A FORWARD --ipv6 -p tcp -d ::nnnn:nnnn:nnnn:nnnn/::FFFF:FFFF:FFFF:FFFF -j ACCEPT
上述代码中,::xxxx:xxxx:xxxx:xxxx 是 eth0 端口的 IPv6 地址的后半部分,而 ::nnnn:nnnn:nnnn:nnnn 是 wlan0 端口的 IPv6 地址的后半部分。这样,当树莓派既连接了有线又连接了无线时,不管树莓派使用 eth0 还是 wlan0 端口的 IPv6 地址向阿里 DNS 提交解析数据时,都可以实现从外网到此树莓派的访问。
如果您的内网主机设备有多个网络接口,可以参照上述配置添加所有接口的防火墙规则。由于我们没有固定的 IPv6 地址,所以无法在 Web 服务器中绑定一个地址(或者,通过脚本实现起来非常麻烦)。
至此,树莓派可以实现从使用 IPv6 的外网通过域名访问了。其实,之所以使用 ipv6 来搭建,主要的原因有二,一是,部分运营商没有公网 IPv4,但提供了公网 IPv6;二是,貌似所有运营商早已将 IPv4 的 80 端口封锁,而 IPv6 可能尚未封锁。
我这里搭建好的访问地址是:http://pi.liyajun.top,欢迎测试。如果您接入了 IPv6 网络,打开这个网址,您将会看到一个树莓派 Dashboard 页面。