如何使用IPv6远程访问家中服务器??

小甜菜Pro下班买菜

IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。

每一台设备都有一个唯一的地址,才保证了用户在连网的计算机上操作时,能够高效而且方便地从千千万万台计算机中选出自己所需的对象来。

如今IPv4地址已经面临枯竭,IPv4在设计之初并没有考虑到网络的爆炸式发展,总共只有大约43亿个地址,根本不可能让每一台电脑都分配到一个IPv4公网地址,事实上,大部分人用的都是私网IP地址,私网相当于一个大型局域网,用户只是局域网中的一员,普通上网并没有什么问题,但是家里使用NAS或者使用服务器等场景时,还需要内网穿透技术,这就要比公网地址差的多。
https://baijiahao.baidu.com/s?id=1724913660832159677&wfr=spider&for=pc

IPv6是英文“Internet Protocol Version 6”(互联网协议第6版)的缩写,是互联网工程任务组(IETF)设计的用于替代IPv4的下一代IP协议,其地址数量号称可以为全世界的每一粒沙子编上一个地址。

与IPv4相比,IPv6不仅仅具有更大的地址空间,还有更强的组播支持以及对流的控制,这使得网络上的多媒体应用有了长足发展的机会,为服务质量(QoS,Quality of Service)控制提供了良好的网络平台。

同时,在使用IPv6网络中用户可以对网络层的数据进行加密并对IP报文进行校验,在IPV6中的加密与鉴别选项提供了分组的保密性与完整性,极大的增强了网络的安全性。

全球IPv4地址耗尽,其实对大众而言是完全无感的。随着5G、工业互联网等新技术的持续演进,万物互联已成为未来网络发展的主要方向,IPv6网络应用的优势更多体现在工业互联网及智能家居领域,Pv6与工业互联网、物联网、云计算、大数据、人工智能等融合应用将成为未来信息社会的基石。
https://baijiahao.baidu.com/s?id=1664454626878339245&wfr=spider&for=pc

那么我们在家中有小型服务器,或者是自己在家搭建的服务如何使用IPv6公网地址进行外网访问呢?

在这之前首先你要确保家中宽带具有IPv4和IPv6双栈协议,最好光猫使用桥接模式,然后使用路由器进行拨号,IPv6使用复用IPv4链路,并打开DHCPv6功能或者SLAAC功能,这样家中的服务器才可正确获取公网IPv6地址。

同时你使用的外网也必须支持IPv6,并且能正确获取到IPv6公网地址,这样才可以实现外网远程访问。

下面小编来介绍一下自己的远程访问解决方案,大体的思路是(因为IPv6公网IP为了确保安全性,所以会不定期更新):使用Python语言写一个脚本,实现每隔一段时间自动获取服务器公网IPv6地址,如果地址发生了变化则将变化后的IPv6公网地址通过SMTP服务器发送到自己的邮箱中,这样就可以在邮件中收到服务器的IPv6公网地址,最后进行远程访问。Python脚本具体如下:

1、获取本机操作系统平台。此函数可以识别服务器系统是否为Windows或者为Linux,毕竟应该没有人用MacOS进行搭建服务器吧。

def get_platform():
    sys_platform = sys.platform
    platform_list = ["linux""win"]
    result_list = ["linux""windows"]
    for index in range(len(platform_list)):
        if platform_list[index] in sys_platform:
            return result_list[index]
    return "none"

2、获取本机公网IPv6地址。此函数是使用了Linux的ifconfig命令和Windows的ipconfig命令得到IP地址的,如果你的Linux服务器中没有ifconfig命令则需要先使用sudo apt-get install -y net-tools命令进行安装,否则程序运行会出错。

def get_global_ipv6_address():
    platform_list = ["linux""windows"]
    get_ipv6_command = ["ifconfig""ipconfig /all"]
    get_ipv6_command_flag = -1
    for index in range(len(platform_list)):
        if get_platform() == platform_list[index]:
            get_ipv6_command_flag = index
            break
    if get_ipv6_command_flag == -1:
        return "none"
    get_ipv6_process = os.popen(get_ipv6_command[get_ipv6_command_flag])
    output = str(get_ipv6_process.read())
    return re.findall(r"(([a-f0-9]{1,4}:){7}[a-f0-9]{1,4})", output, re.I)[0][0]

3、使用SMTP服务器发送邮件。这里的函数中参数需要设置SMTP服务器主机、SMTP服务器端口、用户名、密码、发送者、接收者、发送方描述、接收方描述、邮件主题和邮件内容,最后返回是否发送成功,需要注意的是,这里的SMTP服务器主机、SMTP服务器端口、用户名和密码需要在自己邮箱的设置中开启SMTP服务器,并正确获取到口令(密码),例如我的邮箱使用网易163邮箱,这里的SMTP服务器主机则为smtp.163.com

def send_email(host, port, user, password, sender, receivers, From, To, Subject, massage):
    massage_obj = MIMEText(massage, 'plain''utf-8')
    massage_obj['From'] = Header(From, 'utf-8')
    massage_obj['To'] = Header(To, 'utf-8')
    massage_obj['Subject'] = Header(Subject, 'utf-8')
    try:
        SMTP_object = smtplib.SMTP()
        SMTP_object.connect(host, port)
        SMTP_object.login(user, password)
        SMTP_object.sendmail(sender, receivers, massage_obj.as_string())
        return "Successful: 邮件发送成功"
    except smtplib.SMTPException:
        return "Error: 无法发送邮件"

4、获取当前系统主机名。

def get_hostname():
    return socket.gethostname()

5、新建文本文件并写入内容或在已存在的文本文件中追加新内容。创建该函数是为了方便实现后续操作执行时进行文件的写操作。

def textfile_create(path, text):
    with open(file=path, mode="a+", encoding="utf-8"as file:
        file.write(str(text))

6、获得指定路径下所有目录及文件。

def get_path_dirs_files(path):
    for root, dirs, files in os.walk(path):
        return [dirs, files]

7、获取文本文件最后一行内容。此函数是为了使用一个日志文件判断IPv6地址是否重复,如果日志文件中最后一行的公网IPv6地址与当前系统的公网IPv6地址不相同,则程序会自动发送一个变化后的公网IPv6地址邮件;如果相同则继续在日志文件中追加一行日志内容并不发送邮件。

def get_text_last_line(textfile):
    file_size = os.path.getsize(textfile)
    block_size = 1024
    dat_file = open(textfile, 'rb')
    last_line = ""
    if file_size > block_size:
        max_seek_point = (file_size // block_size)
        dat_file.seek((max_seek_point - 1) * block_size)
    elif file_size:
        dat_file.seek(00)
    lines = dat_file.readlines()
    if lines:
        last_line = lines[-1].strip()
    dat_file.close()
    return last_line

8、创建目录(如果不存在), 可以创建多层路径。

def mkdirs(path):
    if not os.path.exists(path):
        os.makedirs(path)

9、最后是程序入口。首先设置一些必要参数,这里需要注意receivers参数必须为列表类型,列表中每一个元素为一个接收者,可以设置多个接收者;log_file_path参数是用来保存生成的日志文件,最好使用绝对路径,如果使用相对路径则可能发生错误(日志文件不一定会在相对路径的正确位置),并且该程序生成的日志文件不要随意删除,如果删除则会导致一直发送邮件,这是因为每次都是依据生成的日志文件进行判断IPv6地址是否重复,删除后则判断为真就会自动发送邮件。并且建议每次开机后(程序已经执行一次后)不要删除,但是刚开机的时候(开机后还没有执行过这个脚本的时候)可以删除。

if __name__ == '__main__':
    # ================== 参数设置 ==================
    SMTP_host = "smtp.xxx.com"
    SMTP_user = "xxxxxxxx@xxx.com"
    SMTP_password = "xxxxxxxxxxxxxxxx"
    sender = "xxxxxxxx@xxx.com"
    receivers = ["xxxxxxxx@xxx.com"]
    log_file_path = "/usr/local/script/logs"
    # ================== 可选参数 ==================
    SMTP_port = 25
    From = get_hostname()
    To = "none"
    Subject = get_hostname() + " IPv6地址"
    # ================= 参数设置结束 ================
    mkdirs(log_file_path)
    global_ipv6_address = get_global_ipv6_address()
    now_time = str(datetime.now()).split(".")[0]
    log_file = log_file_path + "/get_ipv6_to_email.log"
    # 判断`text_file_path`路径下是否有生成的日志文件, 若没有则进行创建
    if "get_ipv6_to_email.log" not in get_path_dirs_files(log_file_path)[1]:
        textfile_create(path=log_file, text="IPv6\tmessage\tdate")
    # 判断日志文件最后一行是否与当前获取的IPv6地址一致
    # 若不一致则生成一条日志并发送邮件"当前系统IPv6地址为: XXXXXXXXXX"; 若一致则生成一条日志并不发送邮件
    last_line_ipv6_address = get_text_last_line(log_file).decode("utf-8").split("\t")[0]
    if last_line_ipv6_address != global_ipv6_address:
        message = get_hostname() + " 当前系统IPv6地址为: " + global_ipv6_address
        log = send_email(SMTP_host, SMTP_port, SMTP_user, SMTP_password, sender, receivers, From, To, Subject, message)
        textfile_create(log_file, "\n" + global_ipv6_address + "\t" + log + "\t" + now_time)
    else:
        textfile_create(log_file, "\n" + global_ipv6_address + "\t" + "当前IPv6公网地址不变\t" + now_time)

将以上脚本放到服务器中/usr/local/script路径下,然后执行python3 /usr/local/script/get_ipv6_to_email.py命令即可,也可以使用anaconda中的python程序执行,例如小编的服务器中anaconda安装在了/usr/local/anaconda3路径下,因此执行/usr/local/anaconda3/bin/python3 /usr/local/script/get_ipv6_to_email.py命令也是可以的。

实现每一分钟自动执行一次则只需运行crontab -e命令,在其中追加一行*/1 * * * * /usr/local/anaconda3/bin/python3 /usr/local/script/get_ipv6_to_email.py即可(具体crontab语法自行百度),假如你的服务器中安装了宝塔面板,那么在宝塔面板的计划任务中新增一条每分钟运行/usr/local/anaconda3/bin/python3 /usr/local/script/get_ipv6_to_email.py的shell命令就可以了。

当程序执行完毕后可使用cat /usr/local/script/logs/get_ipv6_to_email.log命令查看日志是否执行成功

最后如果大家需要这个脚本,请在公众号后台回复关键字20221231免费获取,如有什么不懂的地方欢迎在公众号后台留言,感谢观看!


声明:
1.转载本公众号中的文章请注明原文链接和作者,否则产生的任何版权纠纷均与本公众号无关。

2.本文中部分文章与图片均来自公开网络,仅供学习交流使用,不会用于任何商业用途,如果出处标注有误或侵犯到原著作者权益,请向邮箱xiaotiancaipro@163.com联系删除,谢谢。