引言
在远程工作环境中,我们经常需要连接到公司内部网络进行开发工作。使用VSCode进行远程开发时,内网穿透成为了一个不可或缺的工具。Cpolar作为一款流行的内网穿透服务,其TCP地址可能会因多种原因发生变化。当地址变化时,手动更新配置不仅效率低下,而且容易出错。为了解决这一问题,我编写了一个Python脚本,能够自动监测Cpolar隧道地址的变化,并通过邮件实时通知我新的地址。
解决方案
为了实现这一目标,我开发了一个Python脚本,该脚本的核心功能如下:
- 地址监测:定期检查Cpolar生成的TCP地址,与预存的地址进行比对。
- 变化检测:一旦检测到地址变化,脚本将触发通知机制。
- 邮件通知:使用SMTP服务,将新的TCP地址通过邮件发送给用户
实现细节
地址信息获取
自动登录cploar页面。地址如下:https://dashboard.cpolar.com/login。
登录之后在选择状态,其中tcp对应的就是我们需要获取的地址
这里实现的代码如下所示
def fetch_info_from_website(login_url, info_url, credentials):
with requests.Session() as session:
# 获取登录页面以抓取csrf token
login_page = session.get(login_url)
login_page_soup = BeautifulSoup(login_page.text, 'html.parser')
# 提取csrf token
csrf_token = login_page_soup.find('input', {'name': 'csrf_token'})['value']
credentials['csrf_token'] = csrf_token
# 登录
login_response = session.post(login_url, data=credentials)
# 检查是否登录成功
if login_response.url == login_url:
print("登录失败,请检查您的凭据。")
# print("响应内容:", login_response.text)
return None
else:
print("登录成功。")
# 获取信息页面
response = session.get(info_url)
response.raise_for_status()
# 解析页面
soup = BeautifulSoup(response.text, 'html.parser')
for i in soup.find_all('th'):
if i.find('a'):
info=i.get_text()
if info.split(':')[0]=='tcp':
return info
邮件发送
这里我使用的是QQ邮箱,需要在QQ邮箱中设置权限,获取授权码
获取授权码之后写入代码中
# 发送邮件
def send_email(subject, body, to_email):
from_email = 'youmail@qq.com'
# 考虑使用环境变量或其他安全措施来存储密码
from_password = '授权码'
# 创建MIMEText邮件对象,可以是'plain'或'html',根据邮件内容选择
msg = MIMEText(body, 'plain', 'utf-8')
msg['From'] = Header(from_email)
msg['To'] = Header(to_email)
msg['Subject'] = Header(subject)
# 连接到SMTP服务器并发送邮件
try:
with smtplib.SMTP('smtp.qq.com', 587) as server:
server.starttls() # 启用安全传输模式
server.login(from_email, from_password)
server.sendmail(from_email, [to_email], msg.as_string())
print("邮件发送成功")
except smtplib.SMTPException as e:
print("邮件发送失败", e)
地址变更监测
定义last_info变量,用于存储之前的地址,判断当前获取的地址是否发生变化
def check_for_changes_and_send_email(info, to_email):
global last_info
if info != last_info: # 如果数据有变化
print("检测到数据变化,发送邮件通知...")
last_info = info # 更新历史数据
send_email('Data Change Notification', info, to_email)
else:
print("没有检测到数据变化。")
定时发送
每隔1个小时监测一下页面上的tcp地址是否变化,使用apscheduler库实现定时,先构建一个scheduled_job函数,将前面的函数调用包装起来,再进行定时调度
def scheduled_job():
login_url = "https://dashboard.cpolar.com/login"
info_url = "https://dashboard.cpolar.com/status"
credentials = {
'login': 'cploar用户名',
'password': 'cploar账号密码'
}
info = fetch_info_from_website(login_url, info_url, credentials)
# 使用示例
to_email = "youmail@qq.com"
check_for_changes_and_send_email(info, to_email)
定时调度代码如下
scheduler = BackgroundScheduler()
four_hours_in_seconds = 4 * 60 * 60
scheduler.add_job(scheduled_job, 'interval', hours=1, misfire_grace_time=four_hours_in_seconds )
# scheduler.add_job(scheduled_job, 'interval', seconds =60, misfire_grace_time=four_hours_in_seconds )
scheduler.start()
# 为了防止主线程退出,这里使用一个无限循环
try:
while True:
time.sleep(2)
except (KeyboardInterrupt, SystemExit):
# 关闭调度器
scheduler.shutdown()
print("调度器关闭。")
完整的代码
import requests
from bs4 import BeautifulSoup
from email.mime.text import MIMEText
from email.header import Header
import smtplib
from apscheduler.schedulers.background import BackgroundScheduler
import time
last_info = None
# 登录网站并获取页面内容
def fetch_info_from_website(login_url, info_url, credentials):
with requests.Session() as session:
# 获取登录页面以抓取csrf token
login_page = session.get(login_url)
login_page_soup = BeautifulSoup(login_page.text, 'html.parser')
# 提取csrf token
csrf_token = login_page_soup.find('input', {'name': 'csrf_token'})['value']
credentials['csrf_token'] = csrf_token
# 登录
login_response = session.post(login_url, data=credentials)
# 检查是否登录成功
if login_response.url == login_url:
print("登录失败,请检查您的凭据。")
# print("响应内容:", login_response.text)
return None
else:
print("登录成功。")
# 获取信息页面
response = session.get(info_url)
response.raise_for_status()
# 解析页面
soup = BeautifulSoup(response.text, 'html.parser')
for i in soup.find_all('th'):
if i.find('a'):
info=i.get_text()
if info.split(':')[0]=='tcp':
return info
# 发送邮件
def send_email(subject, body, to_email):
from_email = 'youmail@qq.com'
# 考虑使用环境变量或其他安全措施来存储密码
from_password = '授权码'
# 创建MIMEText邮件对象,可以是'plain'或'html',根据邮件内容选择
msg = MIMEText(body, 'plain', 'utf-8')
msg['From'] = Header(from_email)
msg['To'] = Header(to_email)
msg['Subject'] = Header(subject)
# 连接到SMTP服务器并发送邮件
try:
with smtplib.SMTP('smtp.qq.com', 587) as server:
server.starttls() # 启用安全传输模式
server.login(from_email, from_password)
server.sendmail(from_email, [to_email], msg.as_string())
print("邮件发送成功")
except smtplib.SMTPException as e:
print("邮件发送失败", e)
def check_for_changes_and_send_email(info, to_email):
global last_info
if info != last_info: # 如果数据有变化
print("检测到数据变化,发送邮件通知...")
last_info = info # 更新历史数据
send_email('Data Change Notification', info, to_email)
else:
print("没有检测到数据变化。")
def scheduled_job():
login_url = "https://dashboard.cpolar.com/login"
info_url = "https://dashboard.cpolar.com/status"
credentials = {
'login': 'cploar账号',
'password': 'cploar密码'
}
info = fetch_info_from_website(login_url, info_url, credentials)
# 使用示例
to_email = "youmail@qq.com"
check_for_changes_and_send_email(info, to_email)
if __name__ == '__main__':
scheduler = BackgroundScheduler()
four_hours_in_seconds = 4 * 60 * 60
scheduler.add_job(scheduled_job, 'interval', hours=1, misfire_grace_time=four_hours_in_seconds )
# scheduler.add_job(scheduled_job, 'interval', seconds =60, misfire_grace_time=four_hours_in_seconds )
scheduler.start()
# 为了防止主线程退出,这里使用一个无限循环
try:
while True:
time.sleep(2)
except (KeyboardInterrupt, SystemExit):
# 关闭调度器
scheduler.shutdown()
print("调度器关闭。")
结语
通过这个脚本,我能够确保在Cpolar隧道地址发生变化时,第一时间得到通知,从而避免了手动检查和更新的繁琐过程。这不仅提高了工作效率,也减少了因地址变更导致的潜在中断。
请注意,上述示例代码中的邮件发送部分需要你根据自己的邮件服务提供商进行相应的配置和替换。同时,确保在实际部署中处理好邮件发送的安全性和隐私问题。