sergey vasin

The IT blog

Изменяем поведение IP с помощью параметра SkipAsSource – Hey, Scripting Guy! Blog

leave a comment »

Резюме: Microsoft Support Engineer James Kehr рассказывает об использовании Windows PowerShell для изменения поведения IP при помощи параметра SkipAsSource

Microsoft Scripting Guy, Ed Wilson на связи. Сегодня я представляю вашему вниманию статью, написанную James Kehr, инженером поддержки Microsoft.

James…

Правда ли, что когда никто не смотрит, некоторые IP-адреса не используются?

Одна из частых задач, для которой я недавно написал скрипт, это настройка эмуляции основного (primary) IP-адреса в операционных системах Windows Vista и Windows Server 2008 и новее при помощи параметра SkipAsSource. Для тех, кто все еще использует Windows XP и Windows Server 2008, я объясню. Primary IP-адреса больше не существует. Хотя я подозреваю, что вы об этом уже знаете. Если на сетевом адаптере в Windows Server 2008 указано несколько IP-адресов, то вы больше не можете быть уверены, что адрес, указанный на вкладке General окна свойств IPv4, который всегда считался основным IP-адресом, будет использоваться компьютером для установки сетевых соединений. По умолчанию все адреса регистрируются в DNS и только один из них используется хостом. Обычно это не вызывает проблем, если только у вас не слишком жесткие политики настройки межсетевых экранов.

Если вам по каким-то причинам нужно, чтобы система вела себя как раньше, вам потребуется добавить IP-адреса, используя параметр SkipAsSource. Это то, что вы не можете сделать из графического интерфейса. Для этого вам придется воспользоваться netsh или PowerShell 3.0, в случае, если вы настраиваете Windows Server 2012 или Windows 8. И если IP-адрес уже сконфигурирован на интерфейсе, вам может потребоваться удалить его, а затем добавить с параметром SkipAsSource. Если на вашем сервере всего 2 или 3 IP-адреса – это не проблема. Если количество адресов равно сорока или пятидесяти – это обычно приводит к тому, что админы становятся очень сердитыми и очень быстрыми.

Но здесь нам может помочь Windows PowerShell!

Я не буду здесь объяснять причины изменения работы с IP-адресами, так как другие люди уже сделали это. Вместо этого я дам вам несколько ссылок на статьи, подробно рассматривающие этот вопрос.

http://blogs.technet.com/b/networking/archive/2009/04/25/source-ip-address-selection-on-a-multi-homed-windows-computer.aspx

http://blogs.technet.com/b/rmilne/archive/2012/02/08/fine-grained-control-when-registering-multiple-ips.aspx

http://support.microsoft.com/kb/975808

Принцип работы параметра SkipAsSource довольно прост. Если он установлен в True, то IP-адрес не будет зарегистрирован в DNS и не будет использоваться хостом для установления соединений, кроме тех случаев, когда приложение явным образом его задействует. Установка параметра в False означает, что IP-адрес будет зарегистрирован в DNS и может быть использован системой для коммуникаций. Установка параметра SkipAsSource на одном из нескольких IP-адресов эмулирует поведение основного IP-адреса.

Текущее состояние параметра SkipAsSource для IP-адреса вы можете определить, используя одну из следующих команд:

netsh interface ipv4 show ipaddresses level=verbose

Для PowerShell 3.0 на Windows Server 2012/Windows 8:

Get-NetIPAddress

Как установить параметр SkipAsSource в Windows PowerShell 2.0

В давние времена, а именно 3 месяца назад, когда был только Windows PowerShell 2.0, единственным способом установки параметра SkipAsSource был netsh. Впрочем, ничего особенного, ведь вы можете использовать netsh через PowerShell. Однако, сначала нам нужно собрать некоторую информацию.

Первое, что нам необходимо знать, это какой интерфейс использовать. Для того, чтобы упростить процесс, мы сохраним его имя в переменной.

$netInterface = «Local Area Connection»

Затем, нам нужно знать наш основной IP-адрес и его маску подсети. Для этого примера в качестве основного (primary) адреса я выберу адрес 10.0.0.2 из диапазона 50 адресов, заканчивающегося адресом 10.0.0.51. Маска нашего основного адреса будет 255.0.0.0 (в представлении CIDR — /8).

$primaryIP = «10.0.0.2»

$primarySNM = «255.0.0.0»

Обычно на этом месте я начинаю рассказывать о необходимости валидации вводимых данных. Но в этот раз я скажу просто – если вы не доверяете своим пользователям (в действительности этого вообще не стоит делать), вы можете проверять вводимые IP-адреса с помощью следующего метода. Метод возвращает значения True или False.

$isIpValid = [System.Net.IPAddress]::tryparse([string]$primaryIP, [ref]»1.1.1.1″)

Кроме того, нам нужен список IP-адресов интерфейса. А здесь все уже несколько сложнее. Как вы знаете, для того, чтобы добавить IP-адрес через netsh, вам нужно указать его маску подсети. Хотя в нашем примере для всех адресов используется одна и та же маска подсети, в реальности все может быть и по-другому. Для того, чтобы получить пары IP-адрес/маска, мы воспользуемся WMI.

Но и здесь не все так просто. Метод WMI возвращает все адреса интерфейса, включая IPv6. В нашем примере мы рассматриваем только адреса IPv4, поэтому нам нужно исключить адреса IPv6. И так как я хочу, чтобы код был максимально эффективным, нужно также исключить из списка и основной IP-адрес, чтобы потом нам не пришлось использовать выражения навроде if и foreach.

Для решения всех этих задач нам нужно выполнить три шага. Сначала мы получим объект Win32_NetworkAdapter, соответствующий $netInterface.

$netAdapter = Get-WmiObject Win32_NetworkAdapter -Filter «NetConnectionID = ‘$netInterface'»

Далее, мы получим информацию о конфигурации этого сетевого адаптера. Для этого мы сопоставим индекс объекта $netAdapter индексу соответствующего объекта Win32_NetworkAdapterConfiguration. На этом шаге мы получаем IP-адреса, настроенные на интерфейсе.

$netNAC = Get-WmiObject Win32_NetworkAdapterConfiguration -Filter «Index = ‘$($netAdapter.Index)'»

И, наконец, мы сохраним пары IP-адрес/маска подсети в виде массива объектов PSObject. При этом мы исключим из результирующего набора основной адрес и адреса IPv6 при помощи командлета Where-Object и операторов сравнения.

0..($netNAC.IPAddress.count — 1) | Where-Object {$netNAC.IPAddress[$_].ToString() -ne $primaryIP -and $netNAC.IPAddress[$_].ToString() -like «*.*.*.*»} | ForEach-Object {

$temp = New-Object PSObject -Property @{

IPAddress = $netNAC.IPAddress[$_].ToString()

IPSubnet = $netNAC.IPSubnet[$_].ToString()

}

$IPs += $temp

}

Итак, переходим к нашей основной задаче – установке параметра SkipAsSource. Для большей эффективности я разделю весь процесс на две части: устанавливаем SkipAsSource=false для основного IP-адреса и SkipAsSource=true для всех остальных адресов. Во втором случае мы воспользуемся foreach.

# удаляем основной адрес. Это необходимо для того, чтобы убедиться, что для него SkipAsSource установлен в false.

# так как я не могу сказать, установлен ли для основного адреса параметр SkipAsSource в Windows Server 2008 и Windows Vista, я делаю это на всякий случай, если вдруг для него по каким-то причинам SkipAsSource установлен в True.

netsh int ipv4 delete address «$netInterface» $primaryIP

# добавляем основной IP-адрес с параметром SkipAsSource=false.

netsh int ipv4 add address «$netInterface» $primaryIP $primarySNM skipassource=false

Также мы удаляем все остальные IP-адреса на интерфейсе и добавляем их с установленным параметром SkipAsSource.

# обрабатываем каждый из IP-адресов в массиве

foreach ($ip in $IPs) {

# удаляем IP-адрес

Invoke-Expression «netsh int ipv4 delete address `»$interface`» $($ip.IPAddress)»

# добавляем IP-адрес с параметром SkipAsSource=true

Invoke-Expression «netsh int ipv4 add address `»$interface`» $($ip.IPAddress) $($ip.IPSubnet) skipassource`=true»

}

Достаточно просто и понятно, не так ли? Ну, если вы имеете опыт написания скриптов. Я, например, им не обладаю. Для написания этого скрипта потребовалось некоторое количество времени, часть которого ушла на поиск необходимой информации. Если бы только Windows PowerShell 3.0 присутствовал а Windows Server 2008 и Windows Vista…

А теперь то же самое, но в Windows PowerShell 3.0

Вам нравятся фокусы? Мне – очень. Вот вам мой фокус. Ниже представлена версия кода для Windows PowerShell 3.0.

# определяем переменные

$primaryIP = «10.0.0.2»

$netInterface = «Ethernet»

# получаем IP-адреса интерфейса, исключая основной адрес и адреса IPv6

[array]$IPs = Get-NetIPAddress -InterfaceAlias $netInterface | Where-Object {$_.AddressFamily -eq «IPv4» -and $_.IPAddress -ne $primaryIP}

# указываем SkipAsSource=false для основного IP-адреса

Set-NetIPAddress -IPAddress $primaryIP -InterfaceAlias $netInterface -SkipAsSource $false

# для остальных IP-адресов устанавливаем SkipAsSource=true

Set-NetIPAddress -IPAddress $IPs.IPAddress -InterfaceAlias $netInterface -SkipAsSource $true

Прогресс налицо, не правда ли? Нам больше не нужно удалять IP-адреса. Нам не нужно обращаться к WMI. Никаких громоздких циклов и дополнительных команд. Просто небольшой кусочек кода. И для его написания и тестирования мне потребовалось всего 15 минут.

Процесс получения IP-адресов, состоявший из трех шагов в скрипте для Windows PowerShell 2.0 превратился в однострочную команду Get-NetIPAddress. Мне не нужно создавать массив, состоящий из пар IP-адресов и их масок, поскольку результат этой команды — это и есть массив, уже содержащий всю необходимую информацию.

Get-NetIPAddress -InterfaceAlias $netInterface | Where-Object {$_.AddressFamily -eq «IPv4» -and $_.IPAddress -ne $primaryIP}

Благодаря командлету Set-NetIPAddress вам не нужно сначала удалять IP-адрес и затем добавлять обратно. Командлет просто изменяет его свойства. И так как я не добавляю адреса а только изменяю их свойства, мне совсем не нужны их маски.

Поскольку параметр IPAddress способен принимать массив строк, я указываю их, использую новую возможность Windows PowerShell 3.0 – автоматический foreach (я использую $IPs.IPAddress вместо $($IPs | %{$_.IPAddress})).

Set-NetIPAddress -IPAddress $IPs.IPAddress -InterfaceAlias $netInterface -SkipAsSource $true

Как вы понимаете, сейчас пришло время для «Но».

Но все это работает только в Windows Server 2012 и Windows 8. Даже если вы установите Windows PowerShell на Windows Server 2008 R2 или Windows 7, модуль NetTCPIP, содержащий командлеты *-NetIPAddress, не будет вам доступен. Это означает, что теперь у вас добавился еще один повод для перехода на Windows 8 и Windows Server 2012.

~James.

Автор:

Ed Wilson, Microsoft Scripting Guy

Оригинал:

http://blogs.technet.com/b/heyscriptingguy/archive/2013/01/24/use-powershell-to-change-ip-behavior-with-skipassource.aspx


Страницы в социальных сетях:

Twitter: https://twitter.com/vsseth
Facebook: https://fb.com/inpowershell
VKontakte: https://vk.com/inpowershell


Реклама

Written by Сергей Васин

Март 19, 2013 в 13:48

Опубликовано в HeyScriptingGuyBlog, PowerShell

Tagged with ,

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s