9.3.2 多 WAN 口路由器拨号

之前我们简单地讲解了内网路由器断线重启的方法,但大家也许会注意到一点:粗暴地重启路由器会引发内网网络通信的中断,不仅仅影响网络程序的运行,也容易对其他用户的工作学习造成不便。

因此,我们必须避免在单 WAN 口路由器,以及正常工作日频繁进行路由器重启。这里我们以多 WAN 口路由器为例,进行 ADSL 拨号。

1. 准备工作

在开始之前,请务必阅读上一节内容,对路由器抓包相关内容有所了解。

2. 拨号问题记录

进行路由器宽带拨号,需要进行反复的试验。目前出现的问题主要有一下几点:

问题       解决方案
ip 更换过快,引发 ip 更换失败 降低 ip 切换频率
部分应用连接中断报错 1、降低切换频率;
2、如果是浏览器,进行刷新、等待与重试;
3、如果有可能,把数据库应用放在本地,设置 host 为 localhost

3. 实例演示

配置文件:

# settings.py
import base64


ip = '192.168.1.1'
username = 'your_name'
pwd = 'your_password'

auth = username + ':' + pwd
auth = auth.encode('utf8')
key = base64.b64encode(auth).decode('utf8')

headers = {
    'Host': ip,
    'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:56.0) Gecko/20100101 Firefox/56.0',
    'Accept': '*/*',
    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
    'Accept-Encoding': 'gzip, deflate',
    'Content-Type': 'application/x-www-form-urlencode',
    'X-Requested-With': 'XMLHttpRequest',
    'Referer': 'http://' + ip,
    'Content-Length': '18',
    'Authorization': 'Basic ' + key,
    'Connection': 'keep-alive',
}

运行文件:

import time
import logging
from urllib import request

import requests

from settings import *

__all__ = ['run']

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
    datefmt='%a, %d %b %Y %H:%M:%S',
    filename='/tmp/adsl.log',
    filemode='w'
)


class Dial(object):

    def __init__(self):
        self.s = requests.session()
        # 请求的拨号接口
        self.url = 'http://192.168.1.1/router/wan_status_set.cgi'

    @staticmethod
    def pause_ip():
        outer_ip = request.urlopen("http://ip.6655.com/ip.aspx").read().decode()
        logging.debug(outer_ip)
        time.sleep(120)

    def wan_operator(self, wan, status_code):
        params = {
            'wanid': wan,
            'statu': status_code,
        }
        post_request = self.s.post(self.url, data=params, headers=headers)
        logging.info(post_request.text)

    def run(self):
        number = 1
        try:
            Dial.pause_ip()
            self.wan_operator(wan='WAN1', status_code=0)
            self.wan_operator(wan='WAN1', status_code=1)
            Dial.pause_ip()
            self.wan_operator(wan='WAN2', status_code=0)
            self.wan_operator(wan='WAN2', status_code=1)
        except Exception as e:
            number = number - 1
            logging.warning(e.args)
            time.sleep(60)
            if number > 0:
                self.run()


if __name__ == '__main__':
    adsl = Dial()
    adsl.run()

这里简单演示了双 WAN 口版本,可以通过 crontab 设置夜间运行。当代码执行时间为工作日之时,可以切换为单 WAN 口拨号,并通过执行 shell 脚本进行 ip release。以下为相应的执行脚本。

#!/bin/bash
PUBLIC_IP=`wget http://ipecho.net/plain -O - -q ; echo`
echo $PUBLIC_IP
sudo dhclient -r
sudo dhclient
sudo dhclient

ifconfig enp3s0 | grep "inet"

results matching ""

    No results matching ""