折腾起源

把自己从csdn上写的文章搬过来了喵!
最近偶然发现宿舍网虽然没ipv4,但是有ipv6地址,查了相关资料,还问了客服,发现宿舍里ipv6的地址能直接从公网访问。

default_name_b75a3607.png

客服回答

还有这种好事?好时代来临辣!

我随便建了个测速网站试了试,发现可以直接通过公网ip地址+端口访问,格式为[xxx:xxx:xxx:xx]:xxxx,如图

default_name_fc5d8823.png

ipv6地址格式

default_name_d6fff108.png

ipv6访问的speedtest

当然我还得考虑本机当然可以直接访问这个网页,我用手机开5G流量试了一下,自然也是可

以连通 (现在开4G或者5G流量一般都自带ipv6)

default_name_29449cb4.png

这里测试结果就不放了,本人只是小小的宿舍50M带宽,放出来怕丢人。

既然公网IP来了,这不得弄个ddns伺候一下?

直接设置华硕DDNS,虽然会有ipv6地址ddns绑定,但是他会优先ipv4访问,我的ipv4地址是内网,这里只能想办法用单栈DDNS绑定的域名,于是开始折腾

设置ipv6

本来有点想略过ipv6设置的,但是因为本人也是小白,刚接触的时候找资料很麻烦,这里顺便一起写了吧。

首先简单的进路由器后台不用说了吧,好假设你不知道,win+r,输入cmd回车

default_name_a57c025f.png

输入

ipconfig

找到你的默认网关

default_name_5d4b31d5.png

这就是你路由器后台的地址,这里以我的路由器ac68u为例

打开浏览器输入192.168.50.1

default_name_736a1e2c.png

输入账号密码以后进入路由器后台

default_name_fac2a431.png

点ipv6的设置

default_name_030bdeff.png

这里有两种,一种是你是光猫桥接,路由器拨号,一种是光猫拨号。

如果你是第二种,最好改光猫工作模式为桥接,省去后面不必要的麻烦,接下来以我这种校园网为例

我的校园网是第一种,但是之前我有试过这个路由器当二级路由,也就变成了第二种,这里先说第一种设置方法

default_name_ec0fef58.png

联机类型选Native,接口选ppp,DHCP-PD打开,其他设置默认即可

如果你是第二种,联机类型改成passthrough,其他默认

应用之后随便找个测试ipv6连通性网站,我这里找的是ipw.cn

default_name_a8f033bd.png

这里显示ipv6访问优先就可以了

如果你是第二种,也许不能正常获取ipv6地址,这种情况建议改桥接;或者有ipv6地址显示ipv4优先,这种情况可以尝试先访问ipv6.ipw.cn,如果可以获取到ipv6地址就不要再折腾了,如果不行再尝试如下设置

手动设置dns,我当时设置的是阿里的dns

2400:3200::1
2400:3200:baba::1

或者用这个公共的dns

240c::6666
240c::6644

我这里的网络是设置了以后,有时候连不上网,而且图片加载速度极慢,可能是我设置问题,还是建议改成第一种方案

至此成功获取ipv6地址,接下来开始第二步设置ddns单栈

DDNS设置部分

如果你是openwrt,ddns设置界面应该是有单ipv6的,直接套用就好。

如果你是华硕固件又不想太折腾刷openwrt,那我建议你刷梅林固件,因为梅林固件自带个crond服务,还有他的脚本,可以将代码套用到里面实现ddns

这里路由器的系统真的很让人烦躁,因为所有的东西基本都在tmp文件夹下,包括root文件夹,包括iptables设置,包括crond设置文件。我刚进来的时候真的束手无策,不知道怎么搞。之后我折腾出两种方法,都是基于ssh进入系统后写脚本

打开ssh端口及服务

华硕原固件也是可以打开的,在web管理界面下,高级设置–》系统管理–》系统设置–》启用ssh,默认端口是1025,账号密码默认就是你登陆web的账号密码

进入ssh界面

这里为了方便直接用powershell自带的ssh即可

ssh <你的用户名>@192.168.50.1 -p 1025

之后输入密码就进到后台了

如果想用xshell自己设置一下就行,会用xshell应该不用多说了。

方法一:套用jffs下自带的启动脚本

这个地方我是思路很清晰,但是不知道他自带的启动脚本在哪,百度半天才知道,最小linux系统真的很难用。

目录为:/jffs/scripts

这里我用的是wan-start这个脚本

cd /jffs/scripts
vi ./wan-start

不知道写什么?等会再说,先说方法二,因为按照程序思维这里不能放脚本,这里放了方法二就会报错的,要放在两个方法外面

方法二:在梅林固件默认启动脚本目录下自建脚本

这里是自己一边百度摸出来的,随便乱逛koolshare目录,看到有很多S开头和K开头的文件,熟悉linux的同学应该就知道这里是干啥的了,但是我不知道,我还百度了一下,命名格式一定要对才能自启,目录为:/jffs/.koolshare/init.d

脚本格式为:S+两位数字+任意名字.sh

例如我的:

S20myddnsd.sh

脚本实现部分

话不多说,先直接上主逻辑

#!bin/sh                                                                                                                                                                                                                                         
                                                                                                                                                                          
                                                                                                                                                                                                                                                 
ip=$(curl ipv6.ipw.cn)                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                 
curl -s -X POST  https://dnsapi.cn/Record.Modify -d 'login_token=123456,asdklqwejlkasczxcd&format=json&record_line=默认&domain_id=123123123&value='$ip'&record_type=AAAA&record_id=123123123&sub_domain=r'

解释一下,这里是先通过访问获取ipv6地址的网站获取ipv6地址,之后调用你域名的api实现ddns,相关api你要去看文档自己去实现,我这里只能以腾讯域名商dnspod为例(8块钱先买一个dns域名一年,这和花生壳的内网穿透域名不一样,这种方法是不限速的,只取决于你自己的带宽)

DDNS实现

dnspod文档网址

API 文档首页 - DNSPod 服务与支持

为了速成,这里先把必要的列出来

default_name_0547cea9.png

首先是每次请求必带的参数

login_token String 用于鉴权的 API Token。

下面是修改必带的参数

domain_id 或 domain Integer 或 String 分别对应域名ID和域名, 提交其中一个即可。
record_id Integer 记录ID。
record_type String 记录类型,通过API记录类型获得,大写英文,比如:A。
record_line String 记录线路,通过API记录线路获得,中文,比如:默认。
value String 记录值, 如 IP:200.200.200.200, CNAME: cname.dnspod.com., MX: mail.dnspod.com. 。
mx {1-20} Integer MX优先级, 当记录类型是 MX 时有效,范围1-20。

mx{1-20}如果你不是MX记录就不必要,这里我们是AAAA记录就不用管它

record_line_id String 线路的ID,通过API记录线路获得,英文字符串,比如:‘10=1’。record_line 和 record_line_id 二者传其一即可,系统优先取 record_line_id。

如果你的shell不支持中文,就把record_type换成record_line_id,默认对应的参数为0

请求网址和方法如下

default_name_38208f65.png

这里为了避免麻烦,我们先创建一个AAAA记录便于之后修改,开始的值可以随便填,按ipv6的格式就行

login_token获取

网页右上角找到API密钥

default_name_0c63ed89.png

default_name_af360132.png

既然他都说了就用DNSPod Token吧

创建密钥后显示如下

default_name_c08d411c.png

注意!login_token一定是ID+逗号+Token的形式写进请求body里,不然一定会返回登陆失败的code

domain_id获取

default_name_be11c0b1.png

record_id获取

先修改一次记录,修改刚才创建好的AAAA记录,在操作日志里可以找到record_id

default_name_da051d3f.png

箭头指向括号内的就是record_id

接下来就简单了,拼接body即可

现成的如下

vi S20myddnsd.sh
#!bin/sh                                                                                                                                                                                                                                         
                                                                                                                                                                          
                                                                                                                                                                                                                                                 
ip=$(curl ipv6.ipw.cn)                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                 
curl -s -X POST  https://dnsapi.cn/Record.Modify -d 'login_token=<数字>,<一串字母>&format=json&record_line=默认&domain_id=<域名id>&value='$ip'&record_type=AAAA&record_id=<你的记录id>&sub_domain=<你想要的域名开头>'

#我本人自己用的的可以往上翻就能看到

:wq保存退出以后记得修改脚本权限

chmod +x S20myddnsd.sh

踩坑阶段

设置好了脚本以后就开始试试能不能用了,先直接运行试试效果

/bin/sh /jffs/.koolshare/init.d/S20myddnsd.sh

由于是路由器直接用脚本发送请求,ipv6对应的地址就是路由器的地址,用手机5G网shell试试域名+端口能不能连

成功连上啦

default_name_c98185b0.png

再试试web远程网页管理,连不上捏😭😭

问题出在哪呢,我第一反应想到防火墙没关,于是关闭了ipv6的防火墙

default_name_eb47854e.png

再试试,还是连不上捏😭😭😭

但是ssh正常外网访问

重启也连不上,这里应该是梅林固件有问题,于是想到去看看ip6tables设置

打开ssh

ip6tables-save

default_name_bf8e0efc.png

很好,没远程管理的端口,加上就解决

ip6tables -I INPUT -p tcp -m tcp --dport 8443 -j ACCEPT
ip6tables-save #查看是否成功加入端口

default_name_f083bfa5.png

注意这里一定要是-I而不是-A 不然会添加到-A INPUT -j DROP后面导致规则无效,除非你删除那条-A INPUT -j DROP

你也可以这样

ip6tables -L INPUT -n --line-number

default_name_5d6576de.png

得到DROP在第15号,删除它

ip6tables -D INPUT 15

再输入命令看看是否删除

ip6tables -L INPUT -n --line-number

default_name_d0f46b53.png

已经成功删掉了

然后再试试连接web管理端

还是失败

原因是梅林固件的web端只对应了ipv4的请求,即TCP4,要将ipv6的请求端口转发到ipv4对应对款上

这里使用socat实现

socat TCP6-LISTEN:8442,reuseaddr,fork TCP4:192.168.50.1:8443&
#&为后台运行

尝试从公网访问

这下终于成功了!

接下来重启路由器试试

路由器重启完毕直接兴冲冲的连接web管理端,发现又不行了,这是怎么一回事呢

手动排查一下

ps

没有socat的进程

ip6tables-save

没有发现防火墙开启的端口8442

经过半天折腾后终于知道原因如下:

1.这个自启脚本启动的时候还是没有网的,自然也就获取不到ipv6地址,更别说调用api了,而且ip6tables服务也没有完全启动

2.socat的端口监听需要占用一个shell,关闭shell的同时也就关闭了socat端口转发

于是在重新创建一个脚本S20bindport.sh添加个延时命令,在下面添加端口并且执行S20myddnsd.sh解决这个问题,S20bindport.sh如下

#!/bin/sh

socat TCP6-LISTEN:8442,reuseaddr,fork TCP4:192.168.50.1:8443&

sleep 1m

/jffs/.koolshare/S23myddnsd.sh

ip6tables -I INPUT -p tcp --dport 8442 -j ACCEPT

同样:wq保存退出并且添加权限x

chmod +x S20bindport.sh

这里考虑到S20myddnsd.sh放在init.d下可能会重复执行,于是把S20myddnsd.sh改名为S23myddnsd.sh,并将它移入上一级目录/jffs/.koolshare/下

cd /jffs/.koolshare/init.d
cp S20myddnsd.sh /jffs/.koolshare/S23myddnsd.sh
rm -rf S20myddnsd.sh

重启路由器试试

https端口8842访问web端

default_name_33f56d73.png

终于成功啦

锦上添花一:用crond服务定时更新ddns

ipv6地址可能在一段时间内会变化,这里直接用crond实现就好了

这里已经测试过脚本加载不用延时直接可以添加任务,于是直接在sleep 1m前面加上一句即可

echo '1 * * * * /bin/sh /jffs/.koolshare/S23myddnsd.sh'|cat >/tmp/var/spool/cron/crontabs/<你的登陆用户名>  &

crontab这里也是在tmp目录下的,每次重启都会重置,折腾死我了,后边自己摸索出来的这个方法,先echo然后管道链接cat写入文件

锦上添花二:远程开机

电脑在没开机之前是没有ipv6公网ip的,可以通过路由器转发udp实现

windows设置如下:

打开设备管理器

default_name_0c8c54df.png

找到网卡

default_name_24d8a496.png

bios设置,以我微星主板为例,PCIE设备唤醒设置为允许,唤醒事件管理设置为BIOS

default_name_8f2417cc.png

路由器转发设置如下,在/jffs/.koolshare/init.d/S20bindport.sh中sleep 1m前面添加如下语句

socat UDP6-LISTEN:2333,reuseaddr,fork UDP4:192.168.50.59:9&


arp -s 192.168.50.59 d8:bb:c1:3f:d5:dd

这里d8:bb:c1:3f:d5:dd是我本机的mac地址,192…168.50.59是我路由器设置的静态ip地址

如果少了一条arp绑定,只在web管理页面设置绑定,可能在第一次开机之前没法唤醒,路由器需要等电脑开机一次才能匹配ip和mac,但是web界面能直接唤醒,使用别的软件不行

路由器设置如下

default_name_79335d4f.png

default_name_0c7b64de.png

default_name_ae8a0940.png

手机上随便下一个WOL软件,设置如下

default_name_faacbcc9.png

尝试开机

成功啦

default_name_05760810.png

脚本源码部分

S20bindport.sh

socat TCP6-LISTEN:8442,reuseaddr,fork TCP4:192.168.50.1:8443&

socat UDP6-LISTEN:2333,reuseaddr,fork UDP4:192.168.50.59:9&

echo '1 * * * * /bin/sh /jffs/.koolshare/S23myddnsd.sh'|cat >/tmp/var/spool/cron/crontabs/xxx  &



arp -s 192.168.50.59 d8:bb:c1:3f:d5:dd

sleep 1m

/jffs/.koolshare/S23myddnsd.sh

ip6tables -I INPUT -p udp --dport 2333 -j ACCEPT

ip6tables -I INPUT -p tcp --dport 8442 -j ACCEPT

S23myddnsd.sh

#!bin/sh                                                                                                                                                                                                                                         
                                                                                                                                                                          
                                                                                                                                                                                                                                                 
ip=$(curl ipv6.ipw.cn)                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                 
curl -s -X POST  https://dnsapi.cn/Record.Modify -d 'login_token=xxx,xxxxxxxxxx&format=json&record_line=默认&domain_id=xxxxxx&value='$ip'&record_type=AAAA&record_id=xxx&sub_domain=xxxx'

后记

谢谢你能够耐心看完,这是我第一次写博客,如果发现什么问题,欢迎批评指正。写这篇博客的初衷是为了记录,如果能顺便帮到你,我会很开心的。