Возможности коммутатора Hyper-V: защита от ARP Spoofing и контроль IP адресов ВМ

Я часто общаюсь с хостинг провайдерами, активно использующими виртуализацию Hyper-V. Одним из недостатков, периодически называемым мне, является отсутствие контроля IP адреса виртуальной машины со стороны виртуального коммутатора администратором виртуальной инфраструктуры. Также заказчики боятся атак типа ARP Spoofing. Последние несколько недель данная тема активно обсуждалась в Microsoft, результатом чего стали появляться статьи и рекомендации. Интересно, что функционал, о котором пойдёт речь, есть не только в первом пакете обновления (Hyper-V R2 Service Pack 1), но даже доступен в виде LDR обновления для оригинального Hyper-V R2 (доступно лишь через службу поддержки, номер обновления 2144850). Итак, что же интеллектуального есть в Hyper-V Virtual Switch, чего не настраивается в графическом интерфейсе?

Для каждого порта виртуального сетевого коммутатора Hyper-V (читай как «для каждого сетевого интерфейса виртуальной машины, соединённого с коммутатором») можно включить опцию фильтрации следующих пакетов:

  • ARP request (opcode=1)
  • ARP reply (opcode=2)
  • ICMP Redirect (type=5)
  • ICMP Router Advertisement (type=9)
  • Neighbor Solicitation (ICMPv6 type=135)
  • Neighbor Advertisement (ICMPv6 type=136)
  • Router Redirect (ICMPv6 type=137)
  • Router Advertisement (ICMPv6 type=134)

Также данная опция позволяет чётко указать, какой IP адрес должен иметь сетевой интерфейс, подключенный к этому порту коммутатора. Запросы от других IP адресов к этому порту обрабатываться не будут.

Как же включить данный функционал? Вам потребуется использовать PowerShell. Рассмотим пример скрипта, включающего данную опцию и задающего явно IP требуемый адрес для виртуальной машины, а также скрипт, выключающий опцию и возвращающий настройки контроля IP по умолчанию.

Пример скрипта, включающего опцию PreventIPSpoofing для виртуальной машины TestVM, и требующего IP адрес 192.168.0.1 для этой машины:

$VmName = "TestVm"
$Msvm_ComputerSystem = (Get-WmiObject -Namespace root\virtualization -Class Msvm_ComputerSystem -Filter "ElementName='$VmName'")

#Retrieve all Msvm_SyntheticEthernetPort's associated with this VM - there will be one per Synthetic NIC
$Msvm_SyntheticEthernetPortCollection = $Msvm_ComputerSystem.GetRelated("Msvm_SyntheticEthernetPort")
#This will get the last object in a collection or if the collection has one object just that object
$Msvm_SyntheticEthernetPort = $Msvm_SyntheticEthernetPortCollection | % {$_}

#There will only ever be one Msvm_VmLANEndpoint per Msvm_SyntheticEthernetPort
$Msvm_VmLANEndpointCollection = $Msvm_SyntheticEthernetPort.GetRelated("Msvm_VmLANEndpoint")
$Msvm_VmLANEndpoint = $Msvm_VmLANEndpointCollection | % {$_}

#There will only ever be one Msvm_SwitchPort per Msvm_VmLANEndpoint
$Msvm_SwitchPortCollection = $Msvm_VmLANEndpoint.GetRelated("Msvm_SwitchPort")
#This will get the last object in a collection or if the collection has one object just that object
$Msvm_SwitchPort = $Msvm_SwitchPortCollection | % {$_}

$Msvm_SwitchPort.PreventIPSpoofing=$true
$Msvm_SwitchPort.AllowedIPv4Addresses= (, "192.168.0.1")
$Msvm_SwitchPort.Put()

 

Пример скрипта, включающего опцию PreventIPSpoofing для виртуальной машины TestVM с несколькими сетевыми картами, и требующего IP адрес 192.168.0.1 для сетевой карты этой машины с заданным MAC адресом :

$VmName = "TestVm"
$MacAddress = “00155D2D480A” #this can be obtained for a VM using WMI
$Msvm_ComputerSystem = (Get-WmiObject -Namespace root\virtualization -Class Msvm_ComputerSystem -Filter "ElementName='$VmName'")

#Retreve all Msvm_SyntheticEthernetPort's associated with this VM - there will be one per Synthetic NIC
$Msvm_SyntheticEthernetPortCollection = $Msvm_ComputerSystem.GetRelated("Msvm_SyntheticEthernetPort")
#This will get the last object in a collection or if the collection has one object just that object
$Msvm_SyntheticEthernetPort = $Msvm_SyntheticEthernetPortCollection |  Where-Object -FilterScript {$_.PermanentAddress -eq "$MacAddress"}

#There will only ever be one Msvm_VmLANEndpoint per Msvm_SyntheticEthernetPort
$Msvm_VmLANEndpointCollection = $Msvm_SyntheticEthernetPort.GetRelated("Msvm_VmLANEndpoint")
$Msvm_VmLANEndpoint = $Msvm_VmLANEndpointCollection | % {$_}

#There will only ever be one Msvm_SwitchPort per Msvm_VmLANEndpoint
$Msvm_SwitchPortCollection = $Msvm_VmLANEndpoint.GetRelated("Msvm_SwitchPort")
#This will get the last object in a collection or if the collection has one object just that object
$Msvm_SwitchPort = $Msvm_SwitchPortCollection | % {$_}

$Msvm_SwitchPort.PreventIPSpoofing=$true
$Msvm_SwitchPort.AllowedIPv4Addresses= (, "192.168.0.1")
$Msvm_SwitchPort.Put()

Пример скрипта, выключающего опцию PreventIPSpoofing для виртуальной машины TestVM, и разрешающего произвольный IP адрес для неё:

$VmName = "TestVm"
$Msvm_ComputerSystem = (Get-WmiObject -Namespace root\virtualization -Class Msvm_ComputerSystem -Filter "ElementName='$VmName'")

#Retrieve all Msvm_SyntheticEthernetPort's associated with this VM - there will be one per Synthetic NIC
$Msvm_SyntheticEthernetPortCollection = $Msvm_ComputerSystem.GetRelated("Msvm_SyntheticEthernetPort")
#This will get the last object in a collection or if the collection has one object just that object
$Msvm_SyntheticEthernetPort = $Msvm_SyntheticEthernetPortCollection | % {$_}

#There will only ever be one Msvm_VmLANEndpoint per Msvm_SyntheticEthernetPort
$Msvm_VmLANEndpointCollection = $Msvm_SyntheticEthernetPort.GetRelated("Msvm_VmLANEndpoint")
$Msvm_VmLANEndpoint = $Msvm_VmLANEndpointCollection | % {$_}

#There will only ever be one Msvm_SwitchPort per Msvm_VmLANEndpoint
$Msvm_SwitchPortCollection = $Msvm_VmLANEndpoint.GetRelated("Msvm_SwitchPort")
#This will get the last object in a collection or if the collection has one object just that object
$Msvm_SwitchPort = $Msvm_SwitchPortCollection | % {$_}

$Msvm_SwitchPort.PreventIPSpoofing=$false
$Msvm_SwitchPort.AllowedIPv4Addresses= $null
$Msvm_SwitchPort.Put()

Итого, задать для каждого интерфейса можно три параметра:

boolean PreventIPSpoofing - для блокировки указанных в начале заметки типов запросов

string AllowedIPv4Addresses[] - для указания разрешенных IPv4 адресов с данного сетевого интерфейса (с данного MAC адреса на данный порт коммутатора). Указывается в двойных кавычках. В случае разрешения нескольких адресов, они разделяются запятыми.

string AllowedIPv6Addresses[] - для указания разрешенных IPv6 адресов с данного сетевого интерфейса (с данного MAC адреса на данный порт коммутатора)

Данные скрипты корректно работают с кластеризованными виртуальными машинами, однако вам следует обновить (Refresh) ресурс Virtual Machine Configuration в консоли кластера после выполнения скрипта. Следует также понимать, что этот функционал не связан с настройкой MAC Spoofing, доступной в интерфейсе Hyper-V Manager R2.