起因是想把一些服务搬到虚拟机里,因为Windows的"服务"体验比较差。为了开机可用,不想使用VBox,所以选择Hyper-V。Hyper-V的桥接网络有限问题,会导致Windows自己上不了网。因此,使用NAT+映射端口的方式来完成。
首先参照这篇文章新建一个NAT虚拟交换机。原文是英文系统的名称,本文使用中文系统环境,所以有些内容会对应更改。命令都是用管理员权限的Powershell运行的。名字是NATSwitch,类型是内部:
1
| New-VMSwitch -SwitchName "NATSwitch" -SwitchType Internal
|
原文Windows(下文统一称为主机)的地址是192.168.0.1,但是我的物理LAN网段和它冲突了,所以主机的IP地址设置为192.168.2.1,网络段用192.168.2.0/24,虚拟交换机的名称vEthernet (NATSwitch)。先配置主机的网络:
1
| New-NetIPAddress -IPAddress 192.168.2.1 -PrefixLength 24 -InterfaceAlias "vEthernet (NATSwitch)"
|
然后配置虚拟交换机的网络,注意Name要跟上面的匹配:
1
| New-NetNAT -Name "NATNetwork" -InternalIPInterfaceAddressPrefix 192.168.2.0/24
|
虚拟机使用的是Archlinux,启动之前在设置里把网络适配器更改为NATSwitch。
在主机上配置NATSwitch,先给这个名字是"arch"的虚拟机设置一个静态IP(因为DHCP没法用)。虚拟机的IP是192.168.2.2。下面这个要保存到一个.ps1文件里,然后在管理员权限的Powershell里运行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| Function Set-VMNetworkConfiguration { [CmdletBinding()] Param ( [Parameter(Mandatory=$true, Position=1, ParameterSetName='DHCP', ValueFromPipeline=$true)] [Parameter(Mandatory=$true, Position=0, ParameterSetName='Static', ValueFromPipeline=$true)] [Microsoft.HyperV.PowerShell.VMNetworkAdapter]$NetworkAdapter,
[Parameter(Mandatory=$true, Position=1, ParameterSetName='Static')] [String[]]$IPAddress=@(),
[Parameter(Mandatory=$false, Position=2, ParameterSetName='Static')] [String[]]$Subnet=@(),
[Parameter(Mandatory=$false, Position=3, ParameterSetName='Static')] [String[]]$DefaultGateway = @(),
[Parameter(Mandatory=$false, Position=4, ParameterSetName='Static')] [String[]]$DNSServer = @(),
[Parameter(Mandatory=$false, Position=0, ParameterSetName='DHCP')] [Switch]$Dhcp )
$VM = Get-WmiObject -Namespace 'root\\virtualization\\v2' -Class 'Msvm_ComputerSystem' | Where-Object { $_.ElementName -eq $NetworkAdapter.VMName } $VMSettings = $vm.GetRelated('Msvm_VirtualSystemSettingData') | Where-Object { $_.VirtualSystemType -eq 'Microsoft:Hyper-V:System:Realized' } $VMNetAdapters = $VMSettings.GetRelated('Msvm_SyntheticEthernetPortSettingData')
$NetworkSettings = @() foreach ($NetAdapter in $VMNetAdapters) { if ($NetAdapter.Address -eq $NetworkAdapter.MacAddress) { $NetworkSettings = $NetworkSettings + $NetAdapter.GetRelated("Msvm_GuestNetworkAdapterConfiguration") } }
$NetworkSettings[0].IPAddresses = $IPAddress $NetworkSettings[0].Subnets = $Subnet $NetworkSettings[0].DefaultGateways = $DefaultGateway $NetworkSettings[0].DNSServers = $DNSServer $NetworkSettings[0].ProtocolIFType = 4096
if ($dhcp) { $NetworkSettings[0].DHCPEnabled = $true } else { $NetworkSettings[0].DHCPEnabled = $false }
$Service = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -Namespace "root\\virtualization\\v2" $setIP = $Service.SetGuestNetworkAdapterConfiguration($VM, $NetworkSettings[0].GetText(1))
if ($setip.ReturnValue -eq 4096) { $job=[WMI]$setip.job
while ($job.JobState -eq 3 -or $job.JobState -eq 4) { start-sleep 1 $job=[WMI]$setip.job }
if ($job.JobState -eq 7) { write-host "Success" } else { $job.GetError() } } elseif($setip.ReturnValue -eq 0) { Write-Host "Success" } }
Get-VMNetworkAdapter -VMName arch -Name "网络适配器" | Set-VMNetworkConfiguration -IPAddress 192.168.2.2 -Subnet 255.255.255.0 -DNSServer 114.114.114.114 -DefaultGateway 192.168.2.1
|
接下来启动虚拟机,静态IP可以自己搜索怎么配置,我用dhcpcd就是添加以下到/etc/dhcpcd.conf:
1 2 3 4
| interface eth0 static ip_address=192.168.2.2/24 static routers=192.168.2.1 static domain_name_servers=114.114.114.114
|
关于NAT映射端口,参照这个文章的以下格式:
1
| Add-NetNatStaticMapping -ExternalIPAddress "0.0.0.0/24" -ExternalPort 8118 -Protocol UDP -InternalIPAddress "192.168.2.2" -InternalPort 8118 -NatName NATNetwork
|