1.1. 序言
众所周知,中国移动宽带没有给家庭用户分配一个ipv4的公网账号,但是会给一个动态的公网IPV6账号,我们接下来就用这个IPV6搭建一个家庭服务器了
1.2. 查看公网IPV6信息
1.2.1. 打开cmd查看IPV6信息
在cmd中使用命令`ipconfig`查看IPV6,可以看到有一个临时 IPV6 地址
为了验证我的猜想是正确的,我们打开网站 (https://test-ipv6.com/index.html.zh_CN%20) ,此处可使用各类测试ipv6测试网站
上方显示我是有IPV6公网IP的
需要提醒:如果你用的是移动宽带,且还是没法得到IPV6地址,可能原因是你的路由器不支持IPV6协议,此时需要将电脑网线直连到光猫上,进行测试IPV6是否可以获取
1.2.2. 购买腾讯云或者阿里云域名
可以在域名商城购买一些比较便宜的域名,当然购买域名后需要进行实名认证等,会有一些步骤
1.2.3. 配置域名
上述步骤完成后,可在工作台,域名列表中所购买的域名信息了
将域名和IPV6地址进行绑定,绑定完成后,即可使用域名访问自己的主机了
访问测试主机,如果能ping通,则代表配置成功
需要提醒:阿里云或者腾讯云dns配置完成后需要等待一段时间使配置生效,在此期间可能无法ping通主机;此外因为IPV4和IPV6协议不兼容,因此如果想让其它电脑也能测试,需要保证其它电脑也有独立的IPV6地址,一般情况下,手机使用**移动数据网络**时其有IPV6地址,可用手机进行测试,或者手机开热点给笔记本进行测试,这说目前尚未解决的问题。
1.2.4. 动态域名绑定
因为前面提到的家庭IPV6地址是变动的,我们不可能每隔一段时间就配置一次域名,这样太麻烦了,此时我们可以使用阿里云或者腾讯云提供的SDK进行动态修改域名配置信息
1.2.5. 获取本机IPV6地址
判断获取的ipv6是否发生变化
/**
* @return 如果ip发生改变,返回true 如果没有则false
*/
public static boolean getIpV6ChangeStatus() {
boolean startLineFlag = false;
//判断服务器类型
OsInfo osInfo = SystemUtil.getOsInfo();
if (osInfo.isWindows()) {
List<String> list = RuntimeUtil.execForLines("ipconfig");
for (int i = 0; i < list.size(); i++) {
String line = list.get(i);
if (StrUtil.isEmpty(line)) {
continue;
}
if (StrUtil.contains(line, IP_ADAPTER_NAME)) {
startLineFlag = true;
continue;
}
if (startLineFlag) {
if ((!StrUtil.contains(line, ". . :")) && startLineFlag) {
break;
}
List<String> splitList = StrUtil.split(line, ". . :");
if (CollUtil.isEmpty(splitList)) {
continue;
}
if (splitList.size() < 2) {
continue;
}
String name = splitList.get(0);
String value = splitList.get(1);
if (name.contains("临时 IPv6 地址")) {
if (currentIp.equalsIgnoreCase(value)) {
//IP地址没有改变,不用更新
return false;
} else {
//IP改变
currentIp = value;
return true;
}
}
}
}
}
if (osInfo.isLinux()) {
//直接获取第四行数据
List<String> list = RuntimeUtil.execForLines("ifconfig");
if (CollUtil.isEmpty(list) || list.size() < 4) {
System.err.println("从linux上获取ipv6地址失败");
return false;
}
String ipv6Line = list.get(3);
if (ipv6Line.contains("inet6") && ipv6Line.contains("global")) {
ipv6Line = ipv6Line.trim();
ipv6Line = StrUtil.removePrefix(ipv6Line, "inet6 ");
ipv6Line = StrUtil.removeSuffix(ipv6Line, " prefixlen 64 scopeid 0x0<global>");
if (currentIp.equalsIgnoreCase(ipv6Line)) {
//IP地址没有改变,不用更新
return false;
} else {
//IP改变
currentIp = ipv6Line;
return true;
}
}
}
return false;
}
获取电脑或者服务器上的IPV6地址信息
public static String getCurrentIp() {
if (StrUtil.isEmpty(currentIp)) {
getIpV6ChangeStatus();
}
return currentIp;
}
将ipv6地址发送钉钉上
/**
* 发送ipv6到dingding
*
* @param ip
*/
public static void sendIPToDingDing(String ip) {
JSONObject root = new JSONObject();
root.set("msgtype", "text");
JSONObject object = new JSONObject();
object.set("content", "我的IP是:" + ip);
root.set("text", object);
HttpRequest.post(WEB_HOOK_URL)
.header("Content-Type", "application/json; charset=utf-8")
.body(root.toString())
.execute()
.body();
}
开启定时任务,如果ipv6地址发生变化,将消息发送到dingding和修改aliyun上的dns信息
public static void getIpV6Server() {
ThreadUtil.execute(() -> {
while (true) {
boolean changeFlag = getIpV6ChangeStatus();
//ip发生改变,把改变的发送到钉钉
if (changeFlag) {
//将消息发送到钉钉上
sendIPToDingDing(getCurrentIp());
//将消息同步到aliyun上
IAcsClient client = AliyunDnsUtils.getIAcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET);
String recordId = AliyunDnsUtils.uploadIpv6ToAliyun(client, getCurrentIp(), DOMAIN_NAME);
System.err.println("更新完成...");
}
ThreadUtil.sleep(1000 * 60);
}
});
}