如何使用 PowerShell 和/或 Python 重新啟動路由器?

如何使用 PowerShell 和/或 Python 重新啟動路由器?

如何使用PowerShell重新啟動路由器?

我的電腦使用網路線連接到路由器,路由器充當數據機,它透過 PPPoE 連接到 ISP,我的電腦位於 NAT 之後。

我的路由器型號:華為HS8545M,區域網路位址:192.168.1.1,網頁管理員登入名稱:CMCCAdmin,網頁管理員密碼:aDm8H%MdA。

我必須執行以下操作才能重新啟動路由器(總共點擊 7 次,瀏覽器會記住登入名稱和密碼):

在此輸入影像描述

在此輸入影像描述

步驟太多了。

我嘗試過使用這種方法:

$ie = New-Object -ComObject 'internetExplorer.Application'
$ie.Navigate "https://192.168.1.1"

但不久之後連線遺失,.Document為空,嘗試刷新會導致此錯誤:

OperationStopped: The RPC server is unavailable. (0x800706BA)

我正在使用 Windows 10 20H2,我禁用了遠端桌面、遠端協助、遠端註冊表、Windows 遠端管理和許多其他功能,我禁用了遠端功能,因為它們對安全性構成威脅,我認為它們與此相關;順便說一句,RPC服務正在運行。

誰能幫我?


第一頁原始碼:第1頁.html

第二頁原始碼:page2.html

這應該很簡單,登入192.168.1.1,建立一個cookie,然後使用cookie進入192.168.1.1/index.asp,提交Restart_button,工作完成,但是我不太熟悉處理網路的命令...


我目前正在尋找Python的方式,我使用的是Python 3.9.1 amd64,我很早就把它放在PATH中,我已經透過pip安裝了Selenium和Twill。下載GeckoDriver.exe並將其解壓縮到Python安裝資料夾中;

我知道 selenium、twill、urllib、urllib2、cookielib 和 webbot,都能夠做到這一點,我目前正在嘗試找出如何以最好的方式做到這一點。


我已經成功透過 twill 在 Python 中登入路由器,但我不知道下一步該怎麼做:

from twill.commands import *
go('http://192.168.1.1')
showforms()
fv("1","txt_Username","CMCCAdmin")
fv("1","txt_Password","aDm8H%MdA")
showforms()
submit('btnSubmit')
go("http://192.168.1.1/index.asp")

在此輸入影像描述

按鈕:

<input type="button" name="Restart_button" id="Restart_button" class="submit" style="width:98px" onclick="Reboot()" value="重启">

它位於:

html.body.#container.#center.#content.table.tbody.tr.td.#frameContent.html.body.div.#Restart_button

另外,inputfields第一頁的 (http://192.168.1.1):

PS C:\Windows\System32> $html.inputfields

outerHTML : <input name="txt_Username" type="text" id="txt_Username" style="float:left;padding:0;width:218px;height:38px;line-height:38px;text-indent:0.5em;border:0 solid green;background-color:transparent;" maxlength="31"/>
tagName   : INPUT
name      : txt_Username
type      : text
id        : txt_Username
style     : float:left;padding:0;width:218px;height:38px;line-height:38px;text-indent:0.5em;border:0 solid green;background-color:transparent;
maxlength : 31

outerHTML : <input name="txt_Password" type="password" id="txt_Password" maxlength="127" style="float:left;padding:0;width:218px;height:38px;line-height:38px;text-indent:0.5em;border:0 solid green;background-color:transparent;"
            maxlength="31"/>
tagName   : INPUT
name      : txt_Password
type      : password
id        : txt_Password
maxlength : 31
style     : float:left;padding:0;width:218px;height:38px;line-height:38px;text-indent:0.5em;border:0 solid green;background-color:transparent;

outerHTML : <input type="button" id="btnSubmit" name="btnSubmit" value="确定" onclick="SubmitForm();" class="button_css"/>
tagName   : INPUT
type      : button
id        : btnSubmit
name      : btnSubmit
value     : 确定
onclick   : SubmitForm();
class     : button_css

outerHTML : <input type="reset" name="Submit2" value="取消" onclick="canceltext();" class="button_css"/>
tagName   : INPUT
type      : reset
name      : Submit2
value     : 取消
onclick   : canceltext();
class     : button_css

我已經得到了重置頁面的源代碼:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Pragma" content="no-cache" />
<link rel="stylesheet"  href='../../../../Cuscss/frame.css?2020070716413845-1425773353' type='text/css'>
<script language="JavaScript" src="../../../resource/common/util.js?2020070716413845-1425773353"></script>
<script language="JavaScript" type="text/javascript">

function LoadFrame()
{
}


function Reboot()
{
if(ConfirmEx("确定要重启设备吗?"))
{
setDisable('Restart_button',   1);
setDisable('Restore_button',    1);
setDisable('btnRestoreDftCfg', 1);
var Form = new webSubmitForm();

Form.setAction('set.cgi?x=' + 'InternetGatewayDevice.X_HW_DEBUG.SMP.DM.ResetBoard'
 + '&RequestFile=html/ssmp/devmanage/cmccdevicereset.asp');
Form.addParameter('x.X_HW_Token', getValue('onttoken'));
Form.submit();
}
}

</script>
</head>
<body class="mainbody" onLoad="LoadFrame();">

<div class="func_spread"></div>
<div class="title_with_desc">
<label id="Title_reboot_lable">设备重启</label>
</div>
<div class="title_01" style="padding-left:10px;" width="100%">
<label id="Title_reboot_tips_lable">点击如下按钮重启路由器。</label>
</div>
<div class="button_spread"></div>
<div align="right">
<input type="hidden" name="onttoken" id="hwonttoken" value="de0f5f98c4d4a77239ccb981cd5c4bf3">
<input type='button' name="Restart_button" id="Restart_button" class="submit" style="width:98px" onClick='Reboot()' value="重启">
</div>
</body>
</html>

它位於地址:

http://192.168.1.1/html/ssmp/devmanage/cmccdevicereset.asp

另外我真的不知道Submit('btnSubmit')我是否登錄,我不完全確定......

儘管這可行,但 Firefox 的初始化速度非常慢。


我終於弄清楚如何透過 telnet 方式做到這一點:

telnet 192.168.1.1
root
adminHW
reset

如何使其成為自動輸入命令的腳本?

答案1

SSH 方式

如果您的路由器支援 SSH 存取(您可能需要在路由器設定中啟用它),您可以嘗試透過 SSH 發出命令來重新啟動它。

它可能是類似ssh USERNAME@ROUTER_ADDRESS reboot或 的東西ssh USERNAME@ROUTER_ADDRESS "sudo reboot"

  1. 首先,您需要啟用 SSH 存取。透過鍵入以下命令確保它有效ssh USERNAME@ROUTER_ADDRESS(如果有效,系統將要求您輸入密碼,輸入正確的密碼後,進入路由器的命令提示字元)。
  2. 然後確定需要在路由器的命令提示字元中輸入哪個命令來重新啟動它。可能只是reboot。但您可能還需要指定確切的路徑,如/sbin/reboot、或/usr/sbin/reboot等。sudo COMMANDsu -c 'COMMAND' root
  3. 如果前面的兩個步驟都已完成,您可以將登入 SSH ( ssh USERNAME@ROUTER_ADDRESS) 和發出重新啟動命令(例如sudo reboot)合併為一個命令(例如ssh USERNAME@ROUTER_ADDRESS "sudo reboot")。每次仍然會要求您輸入密碼,但這是可以避免的(如果您到達此步驟並希望避免輸入密碼,請在評論中告訴我)。

HTTP方式

在瀏覽器中開啟網路監視器(例如,在 Firefox 中為Shift+ Ctrl+ E),並在確認重新啟動時嘗試確定到底發出了哪個 Web 請求(例如,在 Firefox 中,您可以看到請求的全部資料)。

答案2

根據使用者 Ligeti 的說法,對於類似的模型:https://jalalsela.com/accessing-hg8245q-shell/

  • 透過 SSH/Telnet 連接到設備
  • 登入身份root
  • 您可以列出可用的命令/?

從這裡您可以嘗試找到一個命令,例如reboot重新啟動,或shell訪問更多 bash 命令,或shutdown -r/help?那裡。如果它說您沒有某些權限,他會提供您自己進行超級管理的步驟,但我認為沒有必要。

答案3

最後我做到了,我發現這很容易。

我使用了 Python 3.9.1、Internet Explorer、Selenium 和 IEDriverServer.exe(32 位元)。

代碼:

    import selenium
    from selenium import webdriver
    ie = webdriver.Ie()
    ie.get('http://192.168.1.1')
    ie.find_element_by_id('txt_Username').send_keys("CMCCAdmin")
    ie.find_element_by_id('txt_Password').send_keys("aDm8H%MdA")
    ie.find_element_by_id('btnSubmit').click()
    ie.get('http://192.168.1.1/html/ssmp/devmanage/cmccdevicereset.asp')
    ie.find_element_by_id('Restart_button').click()
    ie.switch_to.alert.accept()

我保存為RebootModem.py,它運行良好,只是路由器重新啟動後它不會自動關閉窗口,並且代碼執行只是掛起ie.switch_to.alert.accept()並且不會退出,需要我手動關閉 IE 窗口...

我在控制台中嘗試了程式碼,發現在路由器完成重新啟動之前控制台不會接受命令...

我目前正在嘗試找到 webbot、urllib(2)、cookielib 和 twill 方法來執行此操作,我認為依賴瀏覽器不是非常有效。


我已經讓它自動關閉 IE 視窗和腳本:

    start-process -filepath python -argumentlist $PSScriptRoot\RebootModem.py
    start-sleep -seconds 15
    get-process -name iexplore | stop-process
    get-process -name IEDriverServer| stop-process

另存為RebootModem.ps1,在同一目錄下RebootModem.py,執行RebootModem.ps1開始執行RebootModem.py,15秒後會自動關閉IE視窗和Python.exe(改名為IEDriverServer.exe)...


為了概括程式碼,只需將 elementid 替換為路由器網頁的 elementid,您可以透過Ctrl+ Shift+取得它們I,並將位址替換為您找到的位址(儘管您可能不需要更改 192.168.1.1),我透過「檢視訊框來源「取得用於重新啟動調變解調器的頁面位址。


PS我用來重置所有網路設定的完整程式碼:

devcon disable *dev_8168*
devcon enable *dev_8168*
start-sleep -seconds 3
netsh winsock reset
netsh winhttp reset proxy
netsh http flush log buffer
net start dot3svc
netsh lan reconnect
net stop dot3svc
start-sleep -seconds 3
netsh int ip reset
netsh int ipv4 reset
netsh int ipv6 reset
netsh int httpstunnel reset
netsh int portproxy reset
netsh int tcp reset
start-sleep -seconds 3
ipconfig /release
ipconfig /all
ipconfig /flushdns
ipconfig /registerdns
ipconfig /renew

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 
RunDll32.exe InetCpl.cpl,ResetIEtoDefaults
Start-Sleep -Seconds 1
[System.Windows.Forms.SendKeys]::SendWait("{Tab}")
[System.Windows.Forms.SendKeys]::SendWait(" ")
[System.Windows.Forms.SendKeys]::SendWait("R")
Start-Sleep -Seconds 2
[System.Windows.Forms.SendKeys]::SendWait("C")

start-process -filepath python -argumentlist $PSScriptRoot\RebootModem.py
start-sleep -seconds 15
get-process -name iexplore | stop-process
get-process -name IEDriverServer| stop-process

Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name "ProxyEnable" -Type DWord -Value 1
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name "ProxyOverride" -Type String -Value "login.live.com;account.live.com;clientconfig.passport.net;wustat.windows.com;*.windowsupdate.com;*.wns.windows.com;*.hotmail.com;*.outlook.com;*.microsoft.com;*.msftncsi.com;<local>"

答案4

我已經做到了……再一次!

PowerShell + VBScript + Telnet 的方式來做到這一點:

set router = CreateObject ("WScript.Shell")
router.run("Telnet")
WScript.Sleep 750
router.sendkeys("Open 192.168.1.1")
router.sendkeys("{Enter}")
WScript.Sleep 750
router.sendkeys("root")
router.sendkeys("{Enter}")
WScript.Sleep 750
router.sendkeys("adminHW")
router.sendkeys("{Enter}")
WScript.Sleep 750
router.sendkeys("reset")
router.sendkeys("{Enter}")

另存為RebootModem.vbs

Start-Process -Filepath cscript.exe -Argumentlist $PSScriptRoot\RebootModem.vbs
Start-Sleep -Seconds 6
Get-Process -Name Telnet | Stop-Process

另存為RebootModem.ps1

運行RebootModem.ps1透過Telnet重新啟動數據機,並在6秒後自動關閉Telnet.exe。


純PowerShell方法:

    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    Start-Process -Filepath Telnet.exe -Argumentlist 192.168.1.1
    Start-Sleep -Seconds 1
    [System.Windows.Forms.SendKeys]::SendWait("root")
    [System.Windows.Forms.SendKeys]::SendWait("{Enter}")
    [System.Windows.Forms.SendKeys]::SendWait("adminHW")
    [System.Windows.Forms.SendKeys]::SendWait("{Enter}")
    [System.Windows.Forms.SendKeys]::SendWait("reset")
    [System.Windows.Forms.SendKeys]::SendWait("{Enter}")
    Get-Process -Name Telnet | Stop-Process

它可以在 3 秒內完成工作。我確定這確實是最有效的方法。

相關內容