Python实现清华校园网登录与DDNS
前言
因为疫情的缘故,经常需要在家远程使用学校的计算机,但是有时候会由于电脑重启、停电以及一些莫名其妙的原因导致校园网下线、IP变化,结果就不能远程了。为了解决这个问题,想了一个相对好一点的办法就是,实现校园网的自动联网和DDNS,这样就可以通过URL来远程计算机了。
总体思路
前提条件
这是篇受众明确的短文,不过可以供具有类似条件的读者参考:
- 具有公网IP,需要通过登录认证系统联网(这一点可以排除大多数人了,不过很多校园网应该是类似的);
- 拥有一个域名,可以通过API进行DNS解析的操作(从阿里云、腾讯云等主流DNS服务商购买的应该都可以)。
流程设计
整个流程其实非常简单,如下图所示:
graph LR id1[获取本机IP]-->id2[筛选校园网IP]-->id3[校园网登录]-->id4[更新DNS解析记录]-->id5[结束]
下面我们按照这个顺序分别介绍其实现。
获取本机IP
本机IP的获取其实并不难,使用Python其实有好几种方法,我在这里稍做总结:
1. 基于socket
-
单网卡
- 通过
gethostname()
获取主机名,再用gethostbyname()
将主机名转换为IP地址:
1
2
3
4
5
6
7import socket
# 查看当前主机名
print('当前主机名称为 : ' + socket.gethostname())
# 根据主机名称获取当前IP
print('当前主机的IP为: ' + socket.gethostbyname(socket.gethostname()))
# Mac下测试上述方法也可以获得IP地址- 通过使用socket中的
getaddrinfo()
中的函数获取IP
1
2
3
4
5
6
7
8
9
10
11# 下方代码为获取当前主机IPV4 和IPV6的所有IP地址(所有系统均通用)
addrs = socket.getaddrinfo(socket.gethostname(),None)
for item in addrs:
print(item)
# 仅获取当前IPV4地址
print('当前主机IPV4地址为:' + [item[4][0] for item in addrs if ':' not in item[4][0]][0])
# 同上仅获取当前IPV4地址
for item in addrs:
if ':' not in item[4][0]:
print('当前主机IPV4地址为:' + item[4][0])
break - 通过
-
多网卡
通过使用
socket.gethostbyname_ex()
获取主机IP地址列表:1
2
3
4
5
6try:
hostname = socket.gethostname()
ips = socket.gethostbyname_ex(hostname)[2]
except socket.gaierror:
logging.warning('failed to resolve host %s', hostname)
ips = []
2. 基于UDP
利用 UDP 协议生成一个UDP包,把自己的 IP 放如到 UDP 协议头中,然后从UDP包中获取本机的IP:
1 | import socket |
3. 基于netifaces
基于第三方库netifaces
获取网卡信息:
1 | import netifaces |
4. 基于psutil
基于第三方库psutil
获取网卡信息:
1 | import psutil |
在以上几种方式中,为了只使用python的原生库,我们选择使用了第一种方式。
筛选校园网IP
在多网卡的情况下,经常会获得多个无效的IP,所以需要筛选其中真正的校园网IP。
清华网段
从网上查了一下清华的IP段,不一定完全准确,仅供参考:
1 | 59.66.0.0/16 |
判断IP是否位于网段内
使用Python自带的ipaddress
库来判断,具体代码如下:
1 | import ipaddress |
清华校园网登录
关于清华校园网的联网认证,可以从网上找到许多大神的实现,我比较感兴趣的有以下三个:
- https://github.com/yuantailing/tunet-python
- https://github.com/WhymustIhaveaname/TsinghuaTunet
- https://github.com/Berrysoft/tunet-rust
在这里,我使用了第一个项目——“tunet-python”,用的时候遇到了SSL证书的问题,所以把HTTPS的网址改为了HTTP,对安全性有要求的读者可以自行修改。
1 | # 导入https://github.com/yuantailing/tunet-python的tunet.py |
DDNS解析
动态DNS(英语:Dynamic DNS,简称DDNS)是域名系统(DNS)中的一种自动更新名称服务器(Name server)内容的技术。根据互联网的域名订立规则,域名必须跟从固定的IP地址。但动态DNS系统为动态网域提供一个固定的名称服务器(Name server),透过即时更新,使外界用户能够连上动态用户的网址。
阿里云DNS解析
如前所述,我们需要一个域名来做解析。以阿里云的域名解析为例,阿里云提供了线程的SDK,以及实现DDNS的示例,但是为了让脚本尽可能简单,我使用Python自带的urllib
发起修改DNS的请求,主要包括以下几种:
在发起API请求之前,首先需要从阿里云获得AccessKey
和AccessSecret
。
更新部分代码示例如下:
1 |
|
需要注意的是,如果要自己实现阿里云的API请求,需要自己完成计算签名、构造URL等操作。
程序部署与运行
写完Python的程序以后,目前不需要使用任何第三方的库,为了让程序自动运行,需要添加定时任务:
- 在Windows下,使用任务计划程序:
- 在MacOS下,使用Launchd;
- 在Linux下,使用crontab。
注意事项
最需要注意的就是安全。包括但不限于:
- Windows远程桌面的RDP端口、SSH端口、MacOS的VNC端口,不建议使用默认端口;
- Tunet认证最好使用HTTPS;
- 妥善保管用户名和密码,包括Tunet的用户名密码、DNS服务商的AccessID和AccessSecret。
下一步工作
- 增加设置定时任务的功能;
- 增加非明文保存密码的功能;
- 增加更多DNS服务商(如DNSPod)的支持;
- 增加对IPv6等Tunet认证的支持;
- 是否考虑有路由器情况的端口转发呢?
小结
本文以清华校园网为例,介绍了如何自动化实现认证登录、DDNS的集成功能,以后远程连接就不用那么费事了。由于代码写得比较简陋,就先不公开了。欢迎交流。