起因是想把一些服务搬到虚拟机里,因为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