本文從授權和撤銷安全性群組規則、加入和移出安全性群組講解Elastic Compute Service的安全性群組最佳實務。

網路類型

阿里雲的網路類型分為傳統網路和Virtual Private Cloud,對安全性群組支援不同的設定規則:

  • 如果是傳統網路,您可以設定內網入方向、內網出方向、公網入方向和公網出方向的安全性群組規則。
  • 如果是Virtual Private Cloud,您可以設定內網入方向和內網出方向的安全性群組規則。

安全性群組是區分網路類型的,一台傳統網路類型的ECS執行個體只能加入傳統網路的安全性群組。一台Virtual Private Cloud類型的ECS執行個體只能加入本VPC的安全性群組。

安全性群組內網通訊的概念

本文開始之前,您應知道以下幾個安全性群組內網通訊的概念:

  • 預設只有同一個安全性群組的ECS執行個體可以網路互連。即使是同一個賬戶下的ECS執行個體,如果分屬不同安全性群組,內網網路也是不通的。這個對於傳統網路和Virtual Private Cloud都適用。所以,傳統網路類型的ECS執行個體也是內網安全的。
  • 如果您有兩台ECS執行個體,不在同一個安全性群組,您希望它們內網不互連,但實際上它們卻內網互連,那麼,您需要檢查您的安全性群組內網規則設定。如果內網協議存在下面的協議,建議您重新設定。
    • 允許所有連接埠。
    • 授權對象為CIDR網段(SourceCidrIp):0.0.0.0/0或者10.0.0.0/8的規則。如果是傳統網路,上述協議會造成您的內網暴露給其它的訪問。
  • 如果您想實現在不同安全性群組的資源之間的網路互連,您應使用安全性群組方式授權。對於內網訪問,您應使用源安全性群組授權,而不是CIDR網段授權。

安全規則的屬性

安全規則主要是描述不同的存取權限,包括如下屬性:

  • Policy:授權策略,參數值可以是accept(接受)或drop(拒絕)。
  • Priority:優先順序,根據安全性群組規則的建立時間降序排序匹配。規則優先順序可選範圍為1-100,預設值為1,即最高優先順序。數字越大,代表優先順序越低。
  • NicType:網路類型。如果只指定了SourceGroupId而沒有指定SourceCidrIp,表示通過安全性群組方式授權,此時,NicType必須指定為intranet
  • 規則描述:
    • IpProtocol:IP協議,取值:tcpudpicmpgreall。all表示所有的協議。
    • PortRange:IP協議相關的連接埠號碼範圍:
      • IpProtocol取值為tcpudp時,連接埠號碼取值範圍為1~65535,格式必須是“開始端點口號/終止連接埠號碼”,如“1/200”表示連接埠號碼範圍為1~200。如果輸入值為“200/1”,介面調用將報錯。
      • IpProtocol取值為icmpgreall時,連接埠號碼範圍值為-1/-1,表示不限制連接埠。
    • 如果通過安全性群組授權,應指定SourceGroupId,即源安全性群組ID。此時,根據是否跨帳號授權,您可以選擇設定源安全性群組所屬的帳號SourceGroupOwnerAccount。
    • 如果通過CIDR授權,應指定SourceCidrIp,即源IP位址區段,必須使用CIDR格式。

授權一條入網請求規則

在控制台或者通過API建立一個安全性群組時,入網方向預設deny all,即預設情況下您拒絕所有入網請求。這並不適用於所有的情況,所以您要適度地配置您的入網規則。

比如,如果您需要開啟公網的80連接埠對外提供HTTP服務,因為是公網訪問,您希望入網儘可能多訪問,所以在IP網段上不應做限制,可以設定為0.0.0.0/0,具體設定可以參考以下描述,其中,括弧外為控制台參數,括弧內為OpenAPI參數,兩者相同就不做區分。

  • 網卡類型(NicType):公網(internet)。如果是Virtual Private Cloud類型的只需要填寫intranet,通過EIP實現公網訪問。
  • 授權策略(Policy):允許(accept)。
  • 規則方向(NicType):入網。
  • 協議類型(IpProtocol):TCP(tcp)。
  • 連接埠範圍(PortRange):80/80。
  • 授權對象(SourceCidrIp):0.0.0.0/0。
  • 優先順序(Priority):1。
说明 上面的建議僅對公網有效。內網請求不建議使用CIDR網段,請參見傳統網路的內網安全性群組規則不要使用 CIDR 或者 IP 授權

禁止一個入網請求規則

禁止一條規則時,您只需要配置一條拒絕策略,並設定較低的優先順序即可。這樣,當有需要時,您可以配置其它高優先順序的規則覆蓋這條規則。例如,您可以採用以下設定拒絕6379連接埠被訪問。

  • 網卡類型(NicType):內網(intranet)。
  • 授權策略(Policy):拒絕(drop)。
  • 規則方向(NicType):入網。
  • 協議類型(IpProtocol):TCP(tcp)。
  • 連接埠範圍(PortRange):6379/6379。
  • 授權對象(SourceCidrIp):0.0.0.0/0。
  • 優先順序(Priority):100。

傳統網路的內網安全性群組規則不要使用CIDR或者IP授權

對於傳統網路類型的ECS執行個體,阿里雲預設不開啟任何內網的入規則。內網的授權一定要謹慎。
说明 為了安全考慮,不建議開啟任何基於CIDR網段的授權。

對於彈性計算來說,內網的IP經常變化,另外,這個IP的網段是沒有規律的,所以,建議您通過安全性群組授權對傳統網路內網的訪問。

例如,您在安全性群組sg-redis上構建了一個redis的叢集,為了只允許特定的機器(如sg-web)訪問這個redis的伺服器編組,您不需要配置任何CIDR,只需要添加一條入規則:指定相關的安全性群組ID即可。

  • 網卡類型(NicType):內網(intranet)。
  • 授權策略(Policy):允許(accept)。
  • 規則方向(NicType):入網。
  • 協議類型(IpProtocol):TCP(tcp)。
  • 連接埠範圍(PortRange):6379/6379。
  • 授權對象(SourceGroupId):sg-web。
  • 優先順序(Priority):1。

對於Virtual Private Cloud類型的執行個體,如果您已經通過多個VSwitch規劃好自己的IP範圍,您可以使用CIDR設定作為安全性群組入規則。但是,如果您的Virtual Private Cloud網段不夠清晰,建議您優先考慮使用安全性群組作為入規則。

將需要互相通訊的ECS執行個體加入同一個安全性群組

一個ECS執行個體最多可以加入5個安全性群組,而同一安全性群組內的ECS執行個體之間是網路互連的。如果您在規劃時已經有多個安全性群組,而且,直接設定多個安全規則過於複雜的話,您可以建立一個安全性群組,然後將需要內網通訊的ECS執行個體加入這個新的安全性群組。

這裡也不建議您將所有的ECS執行個體都加入一個安全性群組,這將會使得您的安全性群組規則設定變成夢魘。對於一個中大型應用來說,每個伺服器編組的角色不同,合理地規劃每個伺服器的入方向請求和出方向請求是非常有必要的。

在控制台上,您可以根據文檔加入安全性群組的描述將一台執行個體加入安全性群組。

如果您對阿里雲的OpenAPI非常熟悉,您可以參見弹性管理ECS实例,通過OpenAPI進行大量操作。對應的Python片段如下。

def join_sg(sg_id, instance_id):
    request = JoinSecurityGroupRequest()
    request.set_InstanceId(instance_id)
    request.set_SecurityGroupId(sg_id)
    response = _send_request(request)
    return response
# send open api request
def _send_request(request):
    request.set_accept_format('json')
    try:
        response_str = clt.do_action(request)
        logging.info(response_str)
        response_detail = json.loads(response_str)
        return response_detail
    except Exception as e:
        logging.error(e)

將ECS執行個體移除安全性群組

如果ECS執行個體加入不合適的安全性群組,將會暴露或者Block您的服務,這時您可以選擇將ECS執行個體從這個安全性群組中移除。但是在移除安全性群組之前必須保證您的ECS執行個體已經加入其它安全性群組。

说明 將ECS執行個體從安全性群組移出,將會導致這台ECS執行個體和當前安全性群組內的網路不通,建議您在移出之前做好充分的測試。

對應的Python片段如下。

def leave_sg(sg_id, instance_id):
    request = LeaveSecurityGroupRequest()
    request.set_InstanceId(instance_id)
    request.set_SecurityGroupId(sg_id)
    response = _send_request(request)
    return response
# send open api request
def _send_request(request):
    request.set_accept_format('json')
    try:
        response_str = clt.do_action(request)
        logging.info(response_str)
        response_detail = json.loads(response_str)
        return response_detail
    except Exception as e:
        logging.error(e)

定義合理的安全性群組名稱和標籤

合理的安全性群組名稱和描述有助於您快速識別當前複雜的規則群組合。您可以通過修改名稱和描述來協助自己識別安全性群組。

您也可以通過為安全性群組設定標籤分組管理自己的安全性群組。您可以在控制台直接設定標籤,也可以通過API設定標籤。

刪除不需要的安全性群組

安全性群組中的安全規則類似於一條條白名單和黑名單。所以,請不要保留不需要的安全性群組,以免因為錯誤加入某台ECS執行個體而造成不必要的麻煩。