百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程文章 > 正文

玩转NAS第3期-基于crontab的公网IP变更通知

qiyuwang 2024-10-19 08:54 17 浏览 0 评论

前言

外网访问对于广大NAS玩家而言可以算的上是刚需了,我目前采用的方案是使用将光猫桥接到路由上获取动态公网IP,再在路由配置端口转发实现NAS的外网访问。该方案配合DDNS(动态域名解析)可以很方便的实现外网访问,但在国内想要正常使用需要对域名和服务都进行备案,由于备案较为繁琐我省去了该环节通过公网IP直接访问NAS,也因此对于公网IP的变更较为敏感。简单调研后自己写了一IP监测个脚本,通过NAS的crontab定时调用该脚本监测公网IP,当IP发生变化时通过微信和邮件自动通知。

脚本编写

  • 监测公网IP
  • 微信通知
  • 邮件通知
  • homarr配置修改

我是用的NAS运行的群晖DSM7.2系统,该系统上已经安装了python3.8,因此采用python语言作为IP监测脚本开发语言,代码如下:

import requests
import logging
import smtplib
import json
import re
from email.mime.text import MIMEText

log_file_name = "ip-notify.log"  #日志文件名
ip_record_file_name = "ip.txt"   #记录ip文件名
xts_token = ""                   #虾推啥token
email = ""      #邮箱地址
email_auth_code = ""             #邮箱smtp授权码
email_smtp_addr = "smtp.qq.com"             #邮箱smtp地址
homarr = "/volume1/@appdata/Homarr/data/configs/default.json"                      #homarr配置文件路径


#初始化日志
def init_log():
    logging.basicConfig(filename=log_file_name
                        ,format="%(asctime)s - %(name)s - %(levelname)-9s - %(filename)-8s : %(lineno)s line - %(message)s"
                        ,filemode='a'
                        ,level=logging.INFO)


#通过soho接口获取公网IP地址
def get_public_ip_sohu():
    '''通过sohu提供的接口获取公网IP地址'''
    try:
        logging.info("start getting IP by soho")
        res_content = requests.get("http://txt.go.sohu.com/ip/soip").text
        ip_public = re.findall(r'\d+.\d+.\d+.\d+', res_content)[0]
        logging.info("getting IP success:"+ip_public+" sohu API")
        return ip_public
    except:
        logging.error("getting IP failed-soho API")
        return '0.0.0.0'

#通过ipip获取公网IP地址
def get_public_ip_ipip():
    try:
        logging.info("start getting IP by ipip")
        res_content = requests.get("http://myip.ipip.net").text
        ip_public = re.findall(r'\d+.\d+.\d+.\d+', res_content)[0]
        logging.info("getting IP success:" + ip_public + " ipip API")
        return ip_public
    except:
        logging.error("getting IP failed-ipip API")
        return '0.0.0.0'

def check_ip(ipaddress):
    ip = ''
    #读取ip.txt文件判断是否一直
    try:
        logging.info("start reading ip_record_file")
        fr = open(ip_record_file_name,'r')
        ip = fr.read()
        if ip==ipaddress['ip']:
            logging.info("IP not change")
            ipaddress['ischanged'] = False
            return ipaddress
        logging.info("recorded ip address:"+ip)
        fr.close()
    except:
        logging.error("ip_record_file don`t exist")
        ipaddress['ischanged'] = True

    #ip发生变化将ip写入ip_record_file_name文件中
    with open(ip_record_file_name, 'w+') as file:
        logging.info('start checking IP into ip.txt')
        if ip == '' or ip !=ipaddress['ip']:
            logging.warning('IP changed, writting into ip_record_file, original IP: '+ip+" new IP: "+ipaddress['ip'])
            ipaddress['ischanged'] = True
            file.write(ipaddress['ip'])
        else:
            ipaddress['ischanged'] = False
    file.closed
    return ipaddress


#获取IP地址
def check_ip_change():
    #从两个渠道获取公网IP地址
    ipaddress = {}
    ipaddress['status'] = False
    ip1 = get_public_ip_sohu()
    ip2 = get_public_ip_ipip()
    if ip1 !='0.0.0.0':
        ipaddress['ip'] = ip1
        ipaddress['status'] = True
    elif ip2 != '0.0.0.0':
        ipaddress['ip'] = ip2
        ipaddress['status'] = True
    else:
        ipaddress['ip'] = '0.0.0.0'
        ipaddress['status'] = False

    #判断IP地址是否发生变化
    if ipaddress['status'] == True:
        ipaddress = check_ip(ipaddress)
    return ipaddress

#虾推啥微信通知
def wechat_notify(ipaddress):
    if(xts_token == ""):
        logging.error("wechat notify failed, xts_token is null")
    else:
        push_url = "http://wx.xtuis.cn/{token}.send".format(token=xts_token)
        message={
            'text':"IP变动通知",
            'desp':"{ip}".format(ip=ipaddress['ip'])
        }
        try:
            requests.get(push_url,data=message)
            logging.info("wechat notify success")
        except:
            logging.error("wechat notify failed, xts API failed")
    return

#email通知
def email_notify(ipaddress):
    if email == "" or email_auth_code == "":
        logging.error("email notify failed, email or email_auth_code is null")
    else:
        smtp = smtplib.SMTP()
        smtp.connect(email_smtp_addr, '25')
        smtp.login(email,email_auth_code)

        mail = MIMEText("IP changed, the new IP is: {ip}".format(ip=ipaddress['ip']))
        mail['Subject'] = "IP变化通知"
        mail['From'] = email
        mail['To'] = email

        smtp.sendmail(email, email, mail.as_string())
        logging.info("email notify success")


#homarr修改
def rewrite_homarr_config(ipaddress):
    if homarr == "":
        logging.error("homarr config change failed, homarr is null")
    else:
        #读取homarr配置文件
        config = ''
        try:
            file = open(homarr,'r', encoding="utf-8")
            config = json.load(file)

            #修改homarr文件
            for app in config['apps']:
                app['behaviour']['externalUrl'] = re.sub(r'\d+.\d+.\d+.\d+', ipaddress['ip'], app['behaviour']['externalUrl'])
            file.close()
        except:
            logging.error("can not open homarr config file")
            return

        with open(homarr, 'w+') as fr:
            if config != '':
                json.dump(config, fr)
                logging.info("homarr config change success")
        fr.closed
    return

#程序入口
if __name__ == '__main__':
    init_log()
    logging.info('###################start running script########################')
    res = check_ip_change()
    if res['status'] == True and res['ischanged'] == True:
        wechat_notify(res) #微信通知
        email_notify(res) #邮箱通知
        rewrite_homarr_config(res) #修改homarr中各应用外网地址

    logging.info('###################script end########################')

主要功能如下:

  • 公网IP监测:分别通过调用soho和ipip提供的接口获取,同时从两个接口获取可以有效避免出现单点故障
  • 微信通知:使用虾推啥提供的API接口,只需在微信关注该服务即可免费获取token,每天限制推送500条,每分钟最高10条,对于一般用户来说足够了。
  • 邮件通知:需要设置自己的邮箱地址、smtp服务器地址以及smtp授权码,这些都可以根据自己邮箱账户查到
  • Homarr配置修改:IP变更时自动修改homarr上配置的各应用外网访问地址,这样只需记住homarr的端口就可访问其他所有服务

软件部署

脚本写好后还需要将其部署到NAS上并设置定时运行。这里需要借助linux的crontab来实现(群晖DSM7.2是在linux的基础上改造而来,因此也具备该功能),我们可以在固定的间隔时间执行指定的系统指令或 shell script脚本,时间间隔的单位可以是分钟、小时、日、月、周及以上的任意组合。

将写好的脚本命名为ipcheck.py并将其上传到NAS,我将其上传到了/volume1/homes/scripts/

上传完成后,打开控制面板进入终端机和SNMP页面,勾选启用SSH功能

使用计算机上的SSH软件连接到群晖,并执行sudo su命令进入管理员模式,密码和群晖登录密码一致。

执行vim /etc/crontab命令编辑crontab,添加0 5 * * * root /usr/bin/python /volume1/homes/scripts/ipcheck.py到最后一行,该命令意思为每天五点指定调用python执行ipcheck.py脚本,如果你想使用不同的定时执行策略可百度了解crontab配置方法。

编辑完成后执行synosystemctl restart crond命令重启crontab即可完成配置。

脚本第一次执行时默认发送IP变动通知,我们就可通过微信或邮箱查看到当前公网IP了。

最后

在crontab和python脚本的加持下除了IP变动通知还可以做一些其他更有意思的事情,后续有机会我也会展示给大家。

如果您喜欢我的文章请点一个小小的赞,这对我真的很重要。

相关推荐

# 安装打开 ubuntu-22.04.3-LTS 报错 解决方案

#安装打开ubuntu-22.04.3-LTS报错解决方案WslRegisterDistributionfailedwitherror:0x800701bcError:0x80070...

利用阿里云镜像在ubuntu上安装Docker

简介:...

如何将Ubuntu Kylin(优麒麟)19.10系统升级到20.04版本

UbuntuKylin系统使用一段时间后,有新的版本发布,如何将现有的UbuntuKylin系统升级到最新版本?可以通过下面的方法进行升级。1.先查看相关的UbuntuKylin系统版本情况。使...

Ubuntu 16.10内部代号确认为Yakkety Yak

在正式宣布Ubuntu16.04LTS(XenialXerus)的当天,Canonical创始人MarkShuttleworth还非常开心的在个人微博上宣布Ubuntu下个版本16.10的内...

如何在win11的wsl上装ubuntu(怎么在windows上安装ubuntu)

在Windows11的WSL(WindowsSubsystemforLinux)上安装Ubuntu非常简单。以下是详细的步骤:---...

Win11学院:如何在Windows 11上使用WSL安装Ubuntu

IT之家2月18日消息,科技媒体pureinfotech昨日(2月17日)发布博文,介绍了3中简便的方法,让你轻松在Windows11系统中,使用WindowsSubs...

如何查看Linux的IP地址(如何查看Linux的ip地址)

本头条号每天坚持更新原创干货技术文章,欢迎关注本头条号"Linux学习教程",公众号名称“Linux入门学习教程"。...

怎么看电脑系统?(怎么看电脑系统配置)

要查看电脑的操作系统信息,可以按照以下步骤操作,根据不同的操作系统选择对应的方法:一、Windows系统通过系统属性查看右键点击桌面上的“此电脑”(或“我的电脑”)图标,选择“属性”。在打开的...

如何查询 Linux 内核版本?这些命令一定要会!

Linux内核是操作系统的核心,负责管理硬件资源、调度进程、处理系统调用等关键任务。不同的内核版本可能支持不同的硬件特性、提供新的功能,或者修复了已知的安全漏洞。以下是查询内核版本的几个常见场景:...

深度剖析:Linux下查看系统版本与CPU架构

在Linux系统管理、维护以及软件部署的过程中,精准掌握系统版本和CPU架构是极为关键的基础操作。这些信息不仅有助于我们深入了解系统特性、判断软件兼容性,还能为后续的软件安装、性能优化提供重要依据。接...

504 错误代码解析与应对策略(504错误咋解决)

在互联网的使用过程中,用户偶尔会遭遇各种错误提示,其中504错误代码是较为常见的一种。504错误并非意味着网站被屏蔽,它实际上是指服务器在规定时间内未能从上游服务器获取响应,专业术语称为“Ga...

猎聘APP和官网崩了?回应:正对部分职位整改,临时域名可登录

10月12日,有网友反映猎聘网无法打开,猎聘APP无法登录。截至10月14日,仍有网友不断向猎聘官方微博下反映该情况,而猎聘官方微博未发布相关情况说明,只是在微博内对反映该情况的用户进行回复,“抱歉,...

域名解析的原理是什么?域名解析的流程是怎样的?

域名解析是网站正常运行的关键因素,因此网站管理者了解域名解析的原理和流程对于做好域名管理、解决常见解析问题,保障网站的正常运转十分必要。那么域名解析的原理是什么?域名解析的流程是怎样的?接下来,中科三...

Linux无法解析域名的解决办法(linux 不能解析域名)

如果由于误操作,删除了系统原有的dhcp相关设置就无法正常解析域名。  此时,需要手动修改配置文件:  /etc/resolv.conf  将域名解析服务器手动添加到配置文件中  该文件是DNS域名解...

域名劫持是什么?(域名劫持是什么)

域名劫持是互联网攻击的一种方式,通过攻击域名解析服务器(DNS),或伪造域名解析服务器(DNS)的方法,把目标网站域名解析到错误的地址从而实现用户无法访问目标网站的目的。说的直白些,域名劫持,就是把互...

取消回复欢迎 发表评论: