创建管理网络安全组

配置网络安全组和安全规则,以限制到特定服务器的网络流量。 你希望让应用服务器能通过 HTTP 连接到数据库服务器。 不希望数据库服务器通过 HTTP 连接到应用服务器。

image-20231121165732052

变量资源分配

rg=learn-c5547acb-6432-4632-9c2e-17e555ac9e72

在 Azure Cloud Shell 中,将资源组分配给变量通常是为了简化管理任务和自动化脚本中的操作。当你在 Azure Cloud Shell 或任何脚本中运行命令时,经常需要引用资源组名称。如果你有一个变量,比如 $rg,存储了资源组的名称,你就可以在后续的命令中重复使用这个变量,而不是每次都输入完整的资源组名称。

例如,如果你将资源组名称分配给变量 $rg,那么你可以在创建资源、查询资源状态、删除资源等命令中使用这个变量,如下所示:

# 分配资源组名称到变量
rg="your-resource-group-name"

# 使用变量创建一个新的Azure虚拟机
az vm create --resource-group $rg --name MyVm --image UbuntuLTS --generate-ssh-keys

# 列出资源组中的所有资源
az resource list --resource-group $rg

# 删除资源组
az group delete --name $rg --yes --no-wait

这样做有几个好处:

  1. 减少错误:每次输入资源组名称时都有可能出错,尤其是在名称很长或复杂时。使用变量可以减少这种风险。

  2. 提高效率:不需要每次都输入完整的资源组名称,可以快速重复使用变量。

  3. 提高可读性:在脚本中使用变量可以使代码更容易理解,尤其是对于其他可能查看或维护这些脚本的人。

  4. 易于修改:如果资源组名称变更,或者你想要在不同的资源组上执行相同的一系列命令,你只需要在一个地方更新变量的值,而不是修改每一条命令。

  5. 自动化和模板化:在自动化脚本中使用变量可以使脚本更加通用和可配置,这对于创建可复用的脚本模板非常有用。

要在 Azure Cloud Shell 中分配资源组到变量 rg,你可以使用以下命令:

rg=$(az group list --query "[?name=='your-sandbox-resource-group-name'].name" -o tsv)

这个命令使用 az group list 命令列出所有资源组,然后通过 --query 参数结合 JMESPath 查询语言来提取特定名称的资源组名,最后通过 -o tsv 输出为纯文本格式,然后将结果赋值给变量 rg。这样,你就可以在后续的 Azure CLI 命令中使用 $rg 来代表这个资源组名称了。

创建ERP-servers虚拟网络和Applications子网

该命令是用来在Azure云服务中创建一个虚拟网络(Virtual Network,简称VNet)及其子网的。Azure的虚拟网络是一个隔离的网络环境,它允许你在Azure中自定义私有IP地址块、创建子网、配置路由和网络策略。

az network vnet create \  # 调用Azure CLI的命令来创建一个虚拟网络。
--resource-group $rg \ # 指定Azure资源组的名称,该资源组是用来组织和管理Azure资源的容器。这里使用$rg变量来表示资源组名称。
--name ERP-servers \ # 设置虚拟网络的名称为"ERP-servers"。
--address-prefixes 10.0.0.0/16 \ # 定义虚拟网络的IP地址空间。这里使用了CIDR表示法,表示这个虚拟网络可以包含从10.0.0.0到10.0.255.255的IP地址。
--subnet-name Applications \ # 在虚拟网络内创建一个子网,并命名为"Applications"。
--subnet-prefixes 10.0.0.0/24 # 为"Applications"子网定义IP地址范围。这里的范围是10.0.0.0到10.0.0.255。

执行这个命令后,你将在指定的资源组中创建一个名为”ERP-servers”的虚拟网络,该网络拥有一个名为”Applications”的子网。这个子网的地址范围是10.0.0.0/24,这意味着它可以包含256个IP地址(从10.0.0.0到10.0.0.255)。

在实际执行该命令之前,确保你已经设置了$rg变量,它应该包含一个有效的资源组名称。如果$rg变量未设置或为空,命令将会失败。如果你不确定变量的当前值,可以通过以下命令来检查:

echo $rg

如果变量未设置或你想要直接指定资源组名称,可以直接在命令中替换$rg部分,如下所示:

az network vnet create \
--resource-group my-resource-group-name \
--name ERP-servers \
--address-prefixes 10.0.0.0/16 \
--subnet-name Applications \
--subnet-prefixes 10.0.0.0/24

请确保将my-resource-group-name替换为实际使用的资源组名称。

image-20231121220713610

创建Databases子网

为了在已经存在的虚拟网络 ERP-servers 中创建一个新的子网 Databases,你可以使用 az network vnet subnet create 命令。下面是这个命令的详细解释和格式:

az network vnet subnet create \  # 命令用于在Azure中创建一个新的子网
--resource-group $rg \ # 指定子网所属的资源组,这里使用$rg变量来表示资源组名称
--vnet-name ERP-servers \ # 指定虚拟网络的名称,在这个例子中是"ERP-servers"
--address-prefixes 10.0.1.0/24 \ # 定义子网的IP地址范围,这里使用CIDR表示法,表示子网可以包含从10.0.1.0到10.0.1.255的IP地址
--name Databases # 设置子网的名称为"Databases"

在执行这个命令之前,请确保 $rg 变量已经被赋值为你的Azure资源组的名称。如果 $rg 变量没有设置或者你不想使用变量,可以直接在命令中指定资源组的名称,例如:

az network vnet subnet create \
--resource-group my-resource-group-name \
--vnet-name ERP-servers \
--address-prefixes 10.0.1.0/24 \
--name Databases

请将 my-resource-group-name 替换为你的实际资源组名称。

执行这个命令将会在 ERP-servers 虚拟网络中创建一个新的子网 Databases,其IP地址范围是 10.0.1.0/24。这个子网可以用于数据库服务器或相关服务,以保持网络的逻辑分隔和组织。

image-20231121221015180

创建ERP-SERVERS-NSG网络安全组

要在Azure中创建一个新的网络安全组(NSG),可以使用 az network nsg create 命令。网络安全组用于定义入站和出站网络流量的安全规则,以此来控制对Azure虚拟网络中资源的访问。

az network nsg create \  # 命令用于在Azure中创建一个新的网络安全组
--resource-group $rg \ # 指定网络安全组所属的资源组,这里使用$rg变量来表示资源组名称
--name ERP-SERVERS-NSG # 设置网络安全组的名称为"ERP-SERVERS-NSG"

在执行这个命令之前,请确保 $rg 变量已经被赋值为你的Azure资源组的名称。如果 $rg 变量没有设置或者你不想使用变量,可以直接在命令中指定资源组的名称,例如:

az network nsg create \
--resource-group my-resource-group-name \
--name ERP-SERVERS-NSG

请将 my-resource-group-name 替换为你的实际资源组名称。

执行这个命令后,将会在指定的资源组中创建一个名为 ERP-SERVERS-NSG 的网络安全组。创建了NSG之后,你可能还需要创建和关联安全规则来定义允许或拒绝的流量类型。这些规则可以通过 az network nsg rule create 命令来创建。

image-20231121221102757

创建运行Ubuntu的VM

创建两个 VM,名称分别为 AppServer 和 DataServer。 需将 AppServer 部署到 Applications 子网,并将 DataServer 部署到 Databases 子网。 将 VM 网络接口添加到 ERP-SERVERS-NSG 网络安全组。 然后使用这些 VM 测试网络安全组。

AppServer

要生成 AppServer VM,可以使用 az vm create 命令。该命令将创建一个新的虚拟机,并将其配置为使用指定的资源组、虚拟网络、子网、网络安全组等。

wget -N https://raw.githubusercontent.com/MicrosoftDocs/mslearn-secure-and-isolate-with-nsg-and-service-endpoints/master/cloud-init.yml && \
az vm create \
--resource-group $rg \ # 指定虚拟机所属的资源组,这里使用$rg变量来表示资源组名称
--name AppServer \ # 设置虚拟机的名称为"AppServer"
--vnet-name ERP-servers \ # 指定虚拟机所属的虚拟网络名称
--subnet Applications \ # 指定虚拟机所属的子网名称
--nsg ERP-SERVERS-NSG \ # 指定虚拟机所使用的网络安全组的名称
--image Ubuntu2204 \ # 指定虚拟机的映像(操作系统),这里使用Ubuntu 22.04
--size Standard_DS1_v2 \ # 指定虚拟机的大小/性能配置
--generate-ssh-keys \ # 自动生成SSH密钥对用于远程登录
--admin-username azureuser \ # 指定管理员用户名
--custom-data cloud-init.yml \ # 指定自定义数据(用于配置虚拟机)
--no-wait \ # 不等待虚拟机创建完成,立即返回
--admin-password <password> # 指定管理员密码,将 <password> 替换为复杂的密码

在执行这个命令之前,请确保 $rg 变量已经被赋值为你的Azure资源组的名称,并将 <password> 替换为你希望设置的复杂密码。

此命令还使用 wget 命令从指定的URL下载 cloud-init.yml 文件。该文件包含了自定义数据,用于在虚拟机创建过程中配置虚拟机。请确保可以从 Cloud Shell 访问该 URL。

执行这个命令后,将会创建一个名为 AppServer 的虚拟机,并将其配置为使用指定的资源组、虚拟网络、子网、网络安全组等。虚拟机将使用指定的映像(Ubuntu 22.04)和大小(Standard_DS1_v2)。管理员用户名为 azureuser,密码为你设置的复杂密码。虚拟机创建过程中将使用 cloud-init.yml 文件进行配置。

请注意,命令中的 --no-wait 参数将使命令立即返回,而不等待虚拟机创建完成。如果希望等待虚拟机创建完成后再返回,请删除 --no-wait 参数。

你可以根据需要修改命令中的参数来适应你的环境和需求。

image-20231121221302267

DataServer

要生成 DataServer VM,可以使用 az vm create 命令。该命令将创建一个新的虚拟机,并将其配置为使用指定的资源组、虚拟网络、子网、网络安全组等。

az vm create \
--resource-group $rg \ # 指定虚拟机所属的资源组,这里使用$rg变量来表示资源组名称
--name DataServer \ # 设置虚拟机的名称为"DataServer"
--vnet-name ERP-servers \ # 指定虚拟机所属的虚拟网络名称
--subnet Databases \ # 指定虚拟机所属的子网名称
--nsg ERP-SERVERS-NSG \ # 指定虚拟机所使用的网络安全组的名称
--size Standard_DS1_v2 \ # 指定虚拟机的大小/性能配置
--image Ubuntu2204 \ # 指定虚拟机的映像(操作系统),这里使用Ubuntu 22.04
--generate-ssh-keys \ # 自动生成SSH密钥对用于远程登录
--admin-username azureuser \ # 指定管理员用户名
--custom-data cloud-init.yml \ # 指定自定义数据(用于配置虚拟机)
--no-wait \ # 不等待虚拟机创建完成,立即返回
--admin-password <password> # 指定管理员密码,将 <password> 替换为复杂的密码

在执行这个命令之前,请确保 $rg 变量已经被赋值为你的Azure资源组的名称,并将 <password> 替换为你希望设置的复杂密码。

执行这个命令后,将会创建一个名为 DataServer 的虚拟机,并将其配置为使用指定的资源组、虚拟网络、子网、网络安全组等。虚拟机将使用指定的映像(Ubuntu 22.04)和大小(Standard_DS1_v2)。管理员用户名为 azureuser,密码为你设置的复杂密码。虚拟机创建过程中将使用 cloud-init.yml 文件进行配置。

请注意,命令中的 --no-wait 参数将使命令立即返回,而不等待虚拟机创建完成。如果希望等待虚拟机创建完成后再返回,请删除 --no-wait 参数。

image-20231121173541435

image-20231121221508537

检查运行状态

要确认 VM 是否正在运行,可以使用 az vm list 命令。该命令将列出指定资源组中的虚拟机,并显示其详细信息,包括虚拟机的名称、部署状态和电源状态。

az vm list \
--resource-group $rg \ # 指定要列出虚拟机的资源组,这里使用$rg变量来表示资源组名称
--show-details \ # 显示详细信息,包括部署状态和电源状态
--query "[*].{Name:name, Provisioned:provisioningState, Power:powerState}" \ # 使用JMESPath查询语法指定要显示的属性
--output table # 以表格形式输出结果

在执行这个命令之前,请确保 $rg 变量已经被赋值为你的Azure资源组的名称。

执行这个命令后,将会列出指定资源组中的虚拟机,并显示其名称、部署状态和电源状态。如果虚拟机正在运行,你将看到 Power 列的值为 VM running

检查默认连接

直接在shell里面使用SSH,

要列出分配给虚拟机的 IP 地址,以便连接到 VM,可以使用 az vm list 命令。该命令将列出指定资源组中的虚拟机,并显示其名称、私有 IP 地址和公共 IP 地址。

az vm list \
--resource-group $rg \ # 指定要列出虚拟机的资源组,这里使用$rg变量来表示资源组名称
--show-details \ # 显示详细信息,包括私有 IP 地址和公共 IP 地址
--query "[*].{Name:name, PrivateIP:privateIps, PublicIP:publicIps}" \ # 使用JMESPath查询语法指定要显示的属性
--output table # 以表格形式输出结果

在执行这个命令之前,请确保 $rg 变量已经被赋值为你的 Azure 资源组的名称。

执行这个命令后,将会列出指定资源组中的虚拟机,并显示其名称、私有 IP 地址和公共 IP 地址。你可以使用公共 IP 地址来连接到相应的虚拟机。

image-20231121221602944

公共IP地址分配给变量

当你运行以下命令时:

APPSERVERIP="$(az vm list-ip-addresses \
--resource-group $rg \
--name AppServer \
--query "[].virtualMachine.network.publicIpAddresses[*].ipAddress" \
--output tsv)"

DATASERVERIP="$(az vm list-ip-addresses \
--resource-group $rg \
--name DataServer \
--query "[].virtualMachine.network.publicIpAddresses[*].ipAddress" \
--output tsv)"

这些命令会执行两个 az vm list-ip-addresses 命令,每个命令获取一个虚拟机的公共 IP 地址。

  • 对于 AppServer,命令如下:
    • --resource-group $rg:指定资源组的名称,这里使用 $rg 变量表示资源组名称。
    • --name AppServer:指定虚拟机的名称,这里是 AppServer。
    • --query "[].virtualMachine.network.publicIpAddresses[*].ipAddress":使用 JMESPath 查询语法指定要提取的公共 IP 地址。
    • --output tsv:以制表符分隔的值格式输出结果。
  • 对于 DataServer,命令类似于上述命令,只是虚拟机的名称改为 DataServer。

这些命令会将每个虚拟机的公共 IP 地址分配给相应的变量:

  • APPSERVERIP 变量将保存 AppServer 的公共 IP 地址。
  • DATASERVERIP 变量将保存 DataServer 的公共 IP 地址。

通过将公共 IP 地址保存到变量中,你可以在后续的操作中更方便地使用这些 IP 地址,比如用于 SSH 连接到虚拟机。

若要检查能否连接到 AppServer VM,请在 Shell 中运行以下命令:

ssh azureuser@$APPSERVERIP -o ConnectTimeout=5

将会收到一条 Connection timed out 消息。

若要检查能否连接到 DataServer VM,请在 Cloud Shell 中运行以下命令:

ssh azureuser@$DATASERVERIP -o ConnectTimeout=5

将会收到同样的连接失败消息。

请记住,默认规则会拒绝所有进入虚拟网络的入站流量,除非该流量来自同一虚拟网络。 “拒绝所有入站”规则阻止了刚刚尝试的入站 SSH 连接。

image-20231121203649284

image-20231121221741123

为SSH创建安全规则

创建一个新的入站安全规则,允许 SSH 访问。请在 Cloud Shell 中运行以下命令:

az network nsg rule create \  # 创建网络安全组规则的 Azure CLI 命令
--resource-group $rg \ # 指定资源组的名称,这里使用 $rg 变量表示资源组名称
--nsg-name ERP-SERVERS-NSG \ # 指定网络安全组的名称,这里是 ERP-SERVERS-NSG
--name AllowSSHRule \ # 指定新规则的名称,这里是 AllowSSHRule
--direction Inbound \ # 指定规则的方向为入站
--priority 100 \ # 指定规则的优先级为 100
--source-address-prefixes '*' \ # 指定源地址前缀为任意地址
--source-port-ranges '*' \ # 指定源端口范围为任意端口
--destination-address-prefixes '*' \ # 指定目标地址前缀为任意地址
--destination-port-ranges 22 \ # 指定目标端口范围为 22(SSH 端口)
--access Allow \ # 指定允许访问
--protocol Tcp \ # 指定协议为 TCP
--description "Allow inbound SSH" # 指定规则的描述为 "Allow inbound SSH"

在执行这个命令之前,请确保以下事项:

  • $rg 变量已经被设置为你的 Azure 资源组的名称。
  • ERP-SERVERS-NSG 是你要添加规则的网络安全组的名称。你可以根据实际情况修改该名称。

这个命令将创建一个名为 AllowSSHRule 的新规则,它允许从任何来源(*)通过 TCP 协议(端口 22)访问目标地址(任何地址)。该规则的优先级为 100,方向为入站,并设置访问权限为允许(Allow)。描述字段提供了关于规则的说明,这里是 “Allow inbound SSH”。

执行这个命令后,将会创建一个新的安全规则,允许 SSH 连接到相应的虚拟机。请确保根据你的网络安全需求和实际情况修改命令中的参数。

image-20231121221817769

检查是否连接

ssh azureuser@$APPSERVERIP -o ConnectTimeout=5

现在应该可以进行连接。 在 Are you sure you want to continue connecting (yes/no)? 消息后,输入 yes。

image-20231121221947123

创建安全规则防止Web访问

image-20231121215338383

创建新的入站安全规则来拒绝端口 80 上的 HTTP 访问

az network nsg rule create \  # 创建网络安全组规则的 Azure CLI 命令
--resource-group $rg \ # 指定资源组的名称,这里使用 $rg 变量表示资源组名称
--nsg-name ERP-SERVERS-NSG \ # 指定网络安全组的名称,这里是 ERP-SERVERS-NSG
--name httpRule \ # 指定新规则的名称,这里是 httpRule
--direction Inbound \ # 指定规则的方向为入站
--priority 150 \ # 指定规则的优先级为 150
--source-address-prefixes 10.0.1.4 \ # 指定源地址前缀为 10.0.1.4
--source-port-ranges '*' \ # 指定源端口范围为任意端口
--destination-address-prefixes 10.0.0.4 \ # 指定目标地址前缀为 10.0.0.4
--destination-port-ranges 80 \ # 指定目标端口范围为 80
--access Deny \ # 指定访问权限为拒绝
--protocol Tcp \ # 指定协议为 TCP
--description "Deny from DataServer to AppServer on port 80" # 指定规则的描述为 "Deny from DataServer to AppServer on port 80"

image-20231121222017283

测试虚拟机之间的HTTP连接

检查新的规则是否生效。 AppServer 应该能通过 HTTP 与 DataServer 进行通信。 DataServer 应无法通过 HTTP 与 AppServer 进行通信。

APP - Data

通过 SSH 连接到 AppServer VM,并检查是否可以通过 HTTP 与 DataServer 进行通信。请在 Cloud Shell 中运行以下命令:

ssh -t azureuser@$APPSERVERIP 'wget http://10.0.1.4; exit; bash'

在执行这个命令之前,请确保以下事项:

  • $APPSERVERIP 变量已经被设置为你的 AppServer VM 的公共 IP 地址。确保该变量已经正确设置。
  • azureuser 是 AppServer VM 上的用户名。如果你在创建 VM 时使用了不同的用户名,请相应地修改命令中的用户名。

这个命令将通过 SSH 连接到指定的 AppServer VM,并执行以下操作:

  1. 使用 wget 命令尝试从 DataServer VM 的 IP 地址 10.0.1.4 下载一个文件(这里是默认的 HTTP 请求)。
  2. 执行完 wget 命令后,退出 SSH 连接。
  3. 如果连接成功并且可以通过 HTTP 访问 DataServer VM,那么你将进入本地的 Bash shell。

Data - APP

通过 SSH 连接到 DataServer VM,并检查是否可以通过 HTTP 与 AppServer 进行通信。请在 Cloud Shell 中运行以下命令:

ssh -t azureuser@$DATASERVERIP 'wget http://10.0.0.4; exit; bash'

在执行这个命令之前,请确保以下事项:

  • $DATASERVERIP 变量已经被设置为你的 DataServer VM 的公共 IP 地址。确保该变量已经正确设置。
  • azureuser 是 DataServer VM 上的用户名。如果你在创建 VM 时使用了不同的用户名,请相应地修改命令中的用户名。

这个命令将通过 SSH 连接到指定的 DataServer VM,并执行以下操作:

  1. 使用 wget 命令尝试从 AppServer VM 的 IP 地址 10.0.0.4 下载一个文件(这里是默认的 HTTP 请求)。
  2. 执行完 wget 命令后,退出 SSH 连接。
  3. 如果连接成功并且可以通过 HTTP 访问 AppServer VM,那么你将进入本地的 Bash shell。
  4. 因为已阻止端口 80 上的访问,所以此访问应该不会成功。 几分钟后,会收到一条 Connection timed out 消息。 若要在超时之前中止命令,请按 Ctrl+C。

部署应用安全组

创建应用安全组 “ERP-DB-SERVERS-ASG”:

az network asg create \
--resource-group $rg \ # 资源组的名称
--name ERP-DB-SERVERS-ASG # 应用安全组的名称

将 DataServer 与应用安全组关联:

az network nic ip-config update \
--resource-group $rg \ # 资源组的名称
--application-security-groups ERP-DB-SERVERS-ASG # 应用安全组的名称
--name ipconfigDataServer # NIC 配置的名称
--nic-name DataServerVMNic # NIC 的名称
--vnet-name ERP-servers # 虚拟网络的名称
--subnet Databases # 子网的名称

更新网络安全组中的 HTTP 规则:

az network nsg rule update \
--resource-group $rg \ # 资源组的名称
--nsg-name ERP-SERVERS-NSG # 网络安全组的名称
--name httpRule # 规则的名称
--direction Inbound # 流量方向为入站
--priority 150 # 规则的优先级
--source-address-prefixes "" # 源地址前缀为空,表示任意源地址
--source-port-ranges '*' # 源端口范围为任意端口
--source-asgs ERP-DB-SERVERS-ASG # 源应用安全组为 "ERP-DB-SERVERS-ASG"
--destination-address-prefixes 10.0.0.4 # 目标地址前缀为 DataServer 的 IP 地址
--destination-port-ranges 80 # 目标端口范围为 80
--access Deny # 访问权限为拒绝
--protocol Tcp # 使用 TCP 协议
--description "Deny from DataServer to AppServer on port 80 using application security group" # 规则的描述

第一个命令将创建一个名为 “ERP-DB-SERVERS-ASG” 的应用安全组。
第二个命令将关联 DataServer VM 的网络接口配置(NIC)与应用安全组。
第三个命令将更新 ERP-SERVERS-NSG 网络安全组中的 HTTP 规则,将源地址设置为空,源端口设置为任意,源应用安全组设置为 “ERP-DB-SERVERS-ASG”,目标地址设置为 DataServer 的 IP 地址(10.0.0.4),目标端口设置为 80,并将访问权限设置为拒绝。

image-20231121222134518

应用安全组确认了网络安全组规则能正常运行,并且与使用源 IP 地址时相同。 如果我们添加了其他数据服务器,可以通过将新的服务器添加到 ERP-DB-SERVERS-ASG 来轻松地确保这些服务器具备适当的网络安全。