分享

Padavan 路由器开启 IPv6,使外网通过 IPv6 访问子网树莓派上的网站 | 陶熔鼓铸

 laq6 2021-03-08

步骤:
一、获取公网 IPv6 地址并在树莓派上构建 Web 服务器
二、设置阿里 DNS 域名解析
三、更改树莓派获取 IPv6 地址的方式

四、更改 Padavan 防火墙的设置

一、获取公网 IPv6 地址并在树莓派上构建 Web 服务器

首先需要确定的是,您的运营商支持 IPv6。您可以通过以下配置尝试是否可以获取到 IPv6。

Padavan 路由器开启 IPv6,使外网通过 IPv6 访问子网树莓派上的网站

在 IPv6 的设置页面,按上图进行设置。如果运营商已经支持 IPv6 网络,那么设置完成后,在网络地图中的 “ IPv6 地址:WAN ”和“ IPv6 地址:LAN ”中,都会获取到 IPv6 地址,如下图所标示位置:

Padavan 路由器开启 IPv6,使外网通过 IPv6 访问子网树莓派上的网站

将树莓派连入网络中,使用 ifconfig 命令检查是否获取到 IPv6 地址。一般接口为 eth0,如果您打开了 wlan,同时查看相应接口是否也获取到 IPv6 地址。
注意:
1、即便 eth0 和 wlan0 连接到了不同路由器,两个接口也都会获取到 IPv6。
2、以 fe80 开头的 IPv6 地址为链路本地连接地址,并不是公网 IPv6 地址。
您可以简单地把它理解为 IPv4 中类似 192.168.x.x 这类私有地址。

Padavan 路由器开启 IPv6,使外网通过 IPv6 访问子网树莓派上的网站

使用 ping6 命令可以检查网络的连通性,如下图:

Padavan 路由器开启 IPv6,使外网通过 IPv6 访问子网树莓派上的网站

网络连通了以后,您可以在树莓派上安装 Web 服务器,例如 Apache 或 Nginx。具体方法本文不再赘述,请查阅相关资料。安装完成后,请保持默认配置即可,即,所有 IP 地址(IPv4 和 IPv6)都可以通过浏览器访问。您也可以根据自己的需要进行设置。
当您做好了以上准备,就可以进行下一步了。

二、设置阿里 DNS 域名解析

通过以上操作,树莓派已经可以连接到 IPv6 网络,并实现外部访问了。
现在的问题是:
我们是以 PPPoE 方式上网,所获取的 IPv6 地址是动态的,即,每次路由器重启,IPv6 地址就会改变,树莓派重启,它的 IPv6 地址也会改变。这样一来,我们在树莓派上搭建 Web 服务器的话,就需要频繁的更改 IPv6 地址来访问。
为了便于记忆,我们使用域名解析到它的 IPv6 地址。在此只介绍使用阿里 DNS 来进行解析的办法。在设置之前,您需要在阿里云购买了一个域名并进行了实名认证。

1、登录阿里云网站并进入控制台,在右上角个人资料中,选择 AccessKey 管理。

Padavan 路由器开启 IPv6,使外网通过 IPv6 访问子网树莓派上的网站

2、出现以下提示时,选择“开始使用子用户 AccessKey”。

Padavan 路由器开启 IPv6,使外网通过 IPv6 访问子网树莓派上的网站

3、依次填写用户信息、显示名称,并将访问方式设置为“编程访问”。

Padavan 路由器开启 IPv6,使外网通过 IPv6 访问子网树莓派上的网站

4、验证手机后,会显示 AccessKeyID 和 AccessKey Secret,该信息页面关闭后无法再次显示,请妥善保存该信息。

5、在左侧的菜单中,点击“用户”,对刚才添加的用户进行添加授权。在搜索栏输入“dns”,点击下部筛选结果中的“AliyunDNSFullAccess”以将其添加到右侧列表中。点击确定以完成。

Padavan 路由器开启 IPv6,使外网通过 IPv6 访问子网树莓派上的网站

6、切换至阿里云域名管理设置界面,对您使用的域名进行解析操作,以初始化记录。在此,您需要解析一个记录类型为“AAAA”的主机,将其 IPv6 地址手动的设置为你树莓派上 eth0 口的 IPv6 地址,主机名称任选,如下图,保存并等待其生效。
至此,阿里云端的操作结束。

Padavan 路由器开启 IPv6,使外网通过 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"])
    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.,欢迎测试。如果您接入了 IPv6 网络,打开这个网址,您将会看到一个树莓派 Dashboard 页面。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多