none
[分享]在客戶端/域控重置靜態網絡裏 Windows 7 客戶端 DNS 服務器 IP 的批處理腳本. RRS feed

  • 常规讨论

  •        

    其中在客戶端設置域控 DNS 服務器的腳本有三個, 功能相同, 只是實現有所不同. 工作原理爲, 只要檢查出當前 DNS 服務器 IP 設置(基於字符串匹配), 不同於域管理員的默認設置, 即將其重置.

    雖然在組策略有一個設置 Windows 客戶端 DNS 服務器設置的 GPO, 但僅支持 Windows XP.

    由於正確的 DNS 服務器 IP 對於域環境中 Windows 客戶端日常管理使用至關重要, 所以下面詳細說明一下相關注意事項.

    0. 需要明確知曉, 正確的域控 DNS 服務器 IP 設置, 對於域客戶端來說是非常重要的.
       錯誤或者無效的域控 DNS 服務器設置, 形式上等同於和域控失去聯繫.
       如果出現大範圍域客戶端 DNS 配置錯誤, 修復起來非常麻煩.
       至於修復方法, 最後會提供一個腳本, 這個腳本在域控(或成員服務器)上執行修復操作.

       在生產環境使用任意腳本, 均需自擔風險.

    1. 腳本名爲分別名爲 

       netsh_reset_nt61_dns.bat 
       wmic_reset_nt61_dns.bat
       reg_reset_nt61_dns.bat

       最開始的字符, 表示重置 DNS 用到的具體命令, 實際使用, 可依據具體情況進行更改.

    2. 因爲這三個腳本用在關機/開機腳本, 出於加載速度的考慮, 沒有使用 PowerShell 腳本. 
       在虛擬機中的測試, 簡單的用如下方法測試

       echo begin
       echo %time%
       call \\contoso.com\netlogon\???_reset_nt61_dns.bat
       echo %time%
       echo end

       三個腳本都能在 1 秒內完成檢查和重置. 

       如果想通過 PowerShell 實現, 煩請自行編寫腳本.
       當然用 PowerShell 可能是編寫簡單, 如果有合適 cmdlet 命令的話, 但是執行速度可能會因爲初次加載 powershell 而打折扣.

    3. 因爲是在虛擬機中進行測試, 所以沒有添加太多的客戶端, 理論上 NT6 以及內核更高版本的系統都支持.
       如希望應用在 Windows 8 這些系統, 在部署前, 自行進行充分測試, 畢竟目前只針對 Windows 7 進行了測試.
       但此腳本不支持降級到 NT 5 內核的系統, 因爲裏面用到的那些原生命令一些參數, 只有新版才有,
       此外組策略有針對這個需求的 GPO. 如果一定要使用, 則請手動修改一下 wmic 版的那個腳本, 對 route 部分去掉 -4.

    4. 此腳本只針對 IPv4 靜態網絡.

    5. 這些腳本只針對僅有一個默認網關的情況下, 或者說只針對 metric 最低的那個. 如果同時存在多個網關, 網關之間的
       排序邏輯, 由具體版本的外部命令決定. 同時三個腳本沒有判斷當前環境是否存在多默認網關.

    6. 腳本中如果涉及到配置文件, 處於訪問方便的考慮, 都是和腳本放在一個目錄裏.

    7. 根據自己遇到的一些情況, 通過外部命令的更改 DNS 設置, 可能會遇到更改完成後, 新設置沒有寫入, 而原有設置又丟失的情況, 就是說實際進行的是清空 DNS 服務器 IP 設置的操作. 
       不過在遇到該問題時, 沒有及時記錄, 所以印象中, 遇到過這個問題的是 netsh, 但也不排除其他方法修改不會遇到.
       爲了應對這種情況的發生, 可能需要最佳兩種方式

       netsh+reg
       wmic+reg

       一旦發現沒有設置成功, 就強行用 reg 去改.
       或者改 hosts 文件, 但不推薦這個. 因爲用腳本, 特別是批處理腳本處理起來不夠細緻.

    8. 上面提到的 reg, 除了腳本封裝的外. 還可以考慮
       在執行腳本前, 先

       reg export HKLM\SYSTEM\CurrentControlSet\services\tcpip\Parameters\Interfaces if.txt

       如果執行腳本後, 沒有正確設置, 則

       reg import if.txt

       這樣直接簡單粗暴的把設置全部改回去.
       需要說明的是, 這種全部替換的方法, 沒有經過測試, 所以需要自行測試驗證.
       上述說明已經添加在由 netsh 設置 DNS 的腳本裏.

       下面列出三個重置腳本

       netsh_reset_nt61_dns.bat
       由於 Windows 的網絡適配器名稱可以任意更改, 而批處理處理字符串的能力有限,
       所以腳本用網絡適配器的索引來指定.
       其中 nsOrder.lst 文件的格式爲一個 IP 佔一行

       以下爲 netsh_reset_nt61_dns.bat 的代碼

    @echo off
    
    setlocal enabledelayedexpansion
    
    set args=%1
    set IN=inheritance
    set /a koma=%2
    set nsoFile=nsOrder.lst
    set nsBackup=!WINDIR!\temp\if_para.backup
    set domain=contoso.com
    set validate=no
    
    set /a rc=0
    if /i !rc! equ !IN! (
      set /a rc=!koma!
    ) else (
      call \\!domain!\netlogon\blueghost.bat
      set /a rc=!ERRORLEVEL!
    )
    
    if !rc! neq 61 (goto exit)
    
    set /a if_idx=-1
    for /f "tokens=5" %%n in ('netsh int ip show route ^| find "0.0.0.0/0"') do (
      set /a if_idx=%%n
      goto break
    )
    
    :break
    if !if_idx! equ -1 (goto exit)
    
    dir \\!domain!\netlogon\!nsoFile! /a-d/b 1> nul 2> nul
    if !ERRORLEVEL! neq 0 (goto exit)
    
    reg export HKLM\SYSTEM\CurrentControlSet\services\tcpip\parameters\interfaces !nsBackup! /y
    if !ERRORLEVEL! neq 0 (goto exit)
    
    set /a count=1
    for /f "tokens=1" %%i in ('type \\!domain!\netlogon\!nsoFile!') do (
      if !count! equ 1 (
        netsh int ip set dns !if_idx! static %%i primary !validate!
      ) else (
        netsh int ip add dns !if_idx! %%i index=!count! !validate!
      )
      set /a count=!count!+1
    )
    
    chcp 437
    netsh int ip show dns !if_idx! | find /i "dns servers" | find /i "none" 1> nul 2> nul
    if !ERRORLEVEL! equ 0 (reg import !nsBackup!)
    chcp 936
    
    :exit
    endlocal
       


       以上爲 netsh_reset_nt61_dns.bat 的代碼

       wmic_reset_nt61_dns.bat 
       最後的設置 DNS 代碼並沒有做驗證.

       以下爲 wmic_reset_nt61_dns.bat 的代碼

    @echo off
    
    setlocal enabledelayedexpansion
    
    set args=%1
    set IN=inheritance
    set /a koma=%2
    set nsOrder='192.168.1.4','192.168.1.5'
    set domain=contoso.com
    
    set /a rc=0
    if /i !rc! equ !IN! (
      set /a rc=!koma!
    ) else (
      call \\!domain!\netlogon\blueghost.bat
      set /a rc=!ERRORLEVEL!
    )
    
    if !rc! neq 61 (goto exit)
    
    set ipaddress=""
    for /f "tokens=4" %%n in ('route -4 print ^| find "0.0.0.0"') do (
      set ipaddress=%%n
      goto break
    )
    
    :break
    
    if not defined ipaddress (goto exit)
    
    sc config winmgmt start= auto
    sc start winmgmt
    
    set /a index=-1
    for /f "tokens=2 delims=," %%n in ('wmic nicconfig get index^,ipaddress -format:csv ^| find "!ipaddress!"') do (
      set /a index=%%n
    )
    
    if !index! equ -1 (goto exit)
    
    wmic nicconfig where index=!index! get DNSServerSearchOrder | find "!nsOrder!"
    if !ERRORLEVEL! equ 0 (goto exit)
    
    wmic nicconfig where index=!index! call SetDNSServerSearchOrder (!nsOrder!) | find "= 0;" 1> nul 2> nul
    
    :exit
    endlocal
       


       以上爲 wmic_reset_nt61_dns.bat 的代碼

       以下爲 reg_reset_nt61_dns.bat 的代碼

    @echo off
    
    setlocal enabledelayedexpansion
    
    set args=%1
    set IN=inheritance
    set /a koma=%2
    set nsOrder="192.168.1.4,192.168.1.5"
    set REG_ROOT="HKLM\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces"
    set domain=contoso.com
    
    set /a rc=0
    if /i !rc! equ !IN! (
      set /a rc=!koma!
    ) else (
      call \\!domain!\netlogon\blueghost.bat
      set /a rc=!ERRORLEVEL!
    )
    
    if !rc! neq 61 (goto exit)
    
    set gateway=
    set ipaddress=
    for /f "tokens=3,4" %%a in ('route -4 print ^| find "0.0.0.0"') do (
      set gateway=%%a
      set ipaddress=%%b
      goto break
    )
    
    :break
    
    if not defined gateway (goto exit)
    if not defined ipaddress (goto exit)
    
    set regItem=
    for /f "skip=1 tokens=*" %%n in ('reg query !REG_ROOT! /s /d /f "!ipaddress!" /e') do (
      set regItem=%%n
      goto break2
    )
    
    :break2
    
    if not defined regItem (goto exit)
    
    reg query !regItem! /d /f "!ipaddress!" /e | find /i "IPAddress" 1> nul 2> nul
    if !ERRORLEVEL! neq 0 (goto exit)
    
    reg query !regItem! /d /f "!gateway!" /e | find /i "DefaultGateway" 1> nul 2> nul
    if !ERRORLEVEL! neq 0 (goto exit)
    
    reg query !regItem! /d /f "!nsOrder!" /e | find /i "NameServer" 1> nul 2> nul
    if !ERRORLEVEL! neq 0 (
      reg add !regItem! /v NameServer /t REG_SZ /d "!nsOrder!" /f
      goto exit
    )
    
    :exit
    endlocal

    x

       以上爲 reg_reset_nt61_dns.bat 的代碼

    9. 正如之前提到的那樣, 如果 Windows 7 客戶端的 DNS 服務器 IP 被清空, 只要客戶端的 lanmanserver 服務在
       運行, 且 SMB 445/tcp 端口沒有被防火牆禁用.也有適當可以訪問該客戶端域帳戶, 那麼可以通過遠程
       修改註冊表的方法, 將正確的 DNS 服務器 IP 寫入到客戶端.
       寫入成功後, 手動或通過

       shutdown -m \\client.contoso.com -r -t 0

       重啓該客戶端即可完成修復.

       在測試, 考慮到了 Windows 客戶端在默認設置下, 會緩存用戶憑據, 所以在測試時, 禁用了緩存憑據, 
       但沒有發現存在訪問問題. 但如果這個測試方法有問題, 那要希望通過遠程(批量)修復, 只能另尋他法了.

        以下爲 reset_cli_nt61_dns.bat 的代碼

    @echo off
    
    setlocal enabledelayedexpansion
    
    set client=%1
    set IN=inheritance
    set nsOrder="192.168.1.4,192.168.1.5"
    set REG_ROOT=HKLM\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces
    set domain=contoso.com
    
    
    if not defined client (goto exit)
    
    set /a rc=0
    call \\!domain!\netlogon\blueghost.bat
    set /a rc=!ERRORLEVEL!
    
    if !rc! lss 9 (goto exit)
    
    set regItem=
    for /f "tokens=* skip=1" %%n in ('reg query \\!client!\!REG_ROOT! /s /f !domain! /d') do (
      set regItem=%%n
      goto break
    )
    
    :break
    
    if not defined regItem (goto exit)
    
    reg query \\!client!\!regItem! /v Domain /t REG_SZ | find /i "!domain!" 1> nul 2> nul
    if !ERRORLEVEL! neq 0 (goto exit)
    
    echo reg add \\!client!\!regItem! /v NameServer /t REG_SZ /d !nsOrder! /f
    reg add \\!client!\!regItem! /v NameServer /t REG_SZ /d !nsOrder! /f
    
    :exit
    endlocal

       以上爲 reset_cli_nt61_dns.bat 的代碼



    Folding@Home

    2017年6月2日 0:30