[实例] Python一键切换路由器配置

router-with-python

因为有不同的使用场景,自用的路由器每天都需要在“中继”和“网桥”之间切换。
手工操作的步骤是这样的:

  1. 手动设置IPv4地址、子网掩码、网关地址
  2. 在浏览器中进入路由器管理页并登录
  3. 切换路由器工作模式
    • 若为中继,每次都需要设置WAN口为无线接入,并在连接状态里点击一次“连接”按钮,等待其连接成功
  4. 切换回DHCP

分析以上过程:1和4可以通过Mac的位置(Location)功能实现网络配置的快速切换;2和3都是Post数据的过程

进一步可以得知,Location的切换可以在终端中用scselect命令实现,在Python中可以使用os.system()函数来调用它;同时Python的urllib模块,也可以很方便地模拟浏览器来提交数据

知道原理后,马上来抓包分析一下具体的细节:

live-http-headers

可以清楚地看到,HTTP Header有一个Authorization来验证用户是否获得授权

查阅网络后得知,这是将用户名和密码以“USERNAME:PASSWORD”的形式Base64加密后的结果

所以我们只要向 http://路由器IP/opmode_StatusSet.cgi 提交一个POST请求,发送的数据为“opmode=1”(并非所有参数都是必要的,处女座可以逐个测试看看),并在头部添加Authorization 即可实现切换路由器工作模式

其他功能(设置WAN口接入方式、连接上一级Wi-Fi、重启路由器)也同理,先对手工操作的过程抓包,然后更改一下Post的地址和数据即可

自动切换

需要在网络偏好中添加一个新的Location,如“Router”,小窍门是添加两次网络接口,IP设置为手动,这样既可以获取上级路由器的DHCP,又可以连通不在同一网关的网桥模式的路由器

system-preferences-network

有两个地方需要思考:

  1. 路由器URL在网络建立的情况才下有效,而切换Location会导致网络重连,如何判断网络是否已经连上?
    • 解决方法是 try..except.. 不断尝试直至成功(在本实例中打印”.”)
  2. 在提交的过程中,有一些不稳定因素会导致程序在某个步骤卡死,如何保证其稳定性?
    • 判断每个步骤的执行时间,若尝试时间过长,则中断之-使用signal模块(在本实例中打印”..”)

另外即使中途用 Ctrl+C 中断,也别忘了用 try..finally.. 来切换回原来的Location

根据以上思路,代码在GitHub

 

如何跨设备使用?

其实移动设备占了使用场景的一半以上,首先scselect肯定是不能用了

Python官方wiki提供了一个在Android上编写(运行)Python的推荐APP列表:https://wiki.python.org/moin/Android

我选择的是QPython,优点是提供Google Play版本,方便可靠;另外可以将任一.py文件直接作为图标添加到启动器页面,这样我们就可以直接点击图标来一键执行切换

screenshot-of-qpython

非越狱的iOS则有一个叫pythoni的可用,不过网上讨论不多,而且UI看起来怪怪的