Utiliser l'allocation de ports dynamique Cloud NAT

1. Présentation

L'allocation de ports dynamique (DPA) est une nouvelle fonctionnalité de Cloud NAT. Lorsqu'elle est activée, Cloud NAT augmente ou réduit de manière dynamique les allocations de ports pour les instances en fonction de leurs besoins. La DPA est configurée avec des limites de ports minimales et maximales afin qu'elle ne réduise jamais le nombre de ports en dessous du minimum ni ne l'augmente au-delà du maximum. Cela permet à certaines instances situées derrière des passerelles NAT d'augmenter dynamiquement le nombre de connexions sans avoir à allouer davantage de ports à toutes les instances situées derrière Cloud NAT.

Sans allocation de ports dynamique, toutes les instances derrière Cloud NAT se voient attribuer le même nombre de ports, quelle que soit leur utilisation, comme défini par le paramètre minPortsPerVm .

Pour en savoir plus, consultez la section de la documentation sur le DPA NAT .

Points abordés

  • Configurer une passerelle Cloud NAT en vue de la DPA
  • Inspecter les allocations de ports sans DPA
  • Comment activer et configurer la protection des données en transit pour une passerelle NAT.
  • Observer les effets de la protection des données en exécutant des connexions de sortie parallèles.
  • Comment ajouter des règles NAT à une passerelle NAT avec DPA activé.
  • Découvrez le comportement de DPA avec les règles en exécutant des connexions de sortie vers plusieurs destinations.

Prérequis

  • Connaissance de base de Google Compute Engine
  • Connaissance de base de la mise en réseau et des protocoles TCP/IP
  • Connaissances de base de la ligne de commande Unix/Linux
  • Il est utile d'avoir suivi une présentation de la mise en réseau dans Google Cloud, comme l'atelier Mise en réseau dans Google Cloud.
  • Un projet Google Cloud avec l'accès alpha activé.
  • Comprendre les principes de base de Cloud NAT.

2. Utiliser la console Google Cloud et Cloud Shell

Pour interagir avec GCP, nous utiliserons à la fois la console Google Cloud et Cloud Shell tout au long de cet atelier.

Console Google Cloud

La console Cloud est accessible à l'adresse https://console.cloud.google.com.

75eef5f6fd6d7e41.png

Configuration de l'environnement au rythme de chacun

  1. Connectez-vous à la console Google Cloud, puis créez un projet ou réutilisez un projet existant. (Si vous ne possédez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.)

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • Le nom du projet est le nom à afficher pour les participants au projet. Il s'agit d'une chaîne de caractères qui n'est pas utilisée par les API Google, et que vous pouvez modifier à tout moment.
  • L'ID du projet doit être unique sur l'ensemble des projets Google Cloud et doit être immuable (vous ne pouvez pas le modifier une fois que vous l'avez défini). Cloud Console génère automatiquement une chaîne unique dont la composition importe peu, en général. Dans la plupart des ateliers de programmation, vous devrez référencer l'ID du projet (généralement identifié comme PROJECT_ID), donc s'il ne vous convient pas, générez-en un autre au hasard ou définissez le vôtre, puis vérifiez s'il est disponible. Il est ensuite "gelé" une fois le projet créé.
  • La troisième valeur est le numéro de projet, utilisé par certaines API. Pour en savoir plus sur ces trois valeurs, consultez la documentation.
  1. Vous devez ensuite activer la facturation dans Cloud Console afin d'utiliser les ressources/API Cloud. L'exécution de cet atelier de programmation est très peu coûteuse, voire sans frais. Pour arrêter les ressources afin d'éviter qu'elles ne vous soient facturées après ce tutoriel, suivez les instructions de nettoyage indiquées à la fin de l'atelier. Les nouveaux utilisateurs de Google Cloud peuvent participer au programme d'essai sans frais pour bénéficier d'un crédit de 300$.

Démarrer Cloud Shell

Bien que Google Cloud puisse être utilisé à distance depuis votre ordinateur portable, nous allons nous servir de Google Cloud Shell pour cet atelier de programmation, un environnement de ligne de commande exécuté dans le cloud.

Depuis la console GCP, cliquez sur l'icône Cloud Shell de la barre d'outils située dans l'angle supérieur droit :

bce75f34b2c53987.png

Le provisionnement et la connexion à l'environnement prennent quelques instants seulement. Une fois l'opération terminée, le résultat devrait ressembler à ceci :

f6ef2b5f13479f3a.png

Cette machine virtuelle contient tous les outils de développement nécessaires. Elle comprend un répertoire d'accueil persistant de 5 Go et s'exécute sur Google Cloud, ce qui améliore nettement les performances du réseau et l'authentification. Vous pouvez réaliser toutes les activités de cet atelier dans un simple navigateur.

3. Mettre en place l'atelier

Pour cet atelier, vous allez utiliser un projet et créer deux VPC avec un sous-réseau dans chacun d'eux. Vous allez réserver des adresses IP externes, puis créer et configurer une passerelle Cloud NAT (avec un routeur Cloud Router), deux instances de producteur et deux instances de consommateur. Après avoir validé le comportement par défaut de Cloud NAT, vous allez activer l'allocation de ports dynamique et valider son comportement. Enfin, vous configurerez également des règles NAT et observerez l'interaction entre la DPA et les règles NAT.

Présentation de l'architecture réseau :

a21caa6c333909d8.png

4. Réserver des adresses IP externes

Réservons toutes les adresses IP externes à utiliser dans cet atelier. Cela vous aidera à écrire toutes les règles NAT et de pare-feu pertinentes dans les VPC du consommateur et du producteur.

Depuis Cloud Shell :

gcloud compute addresses  create nat-address-1 nat-address-2 \
 producer-address-1 producer-address-2 --region us-east4

Résultat :

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-1].
Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-2].
Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-1].
Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-2].

Renseignez les adresses IP réservées en tant que variables d'environnement.

export natip1=`gcloud compute addresses list --filter name:nat-address-1 --format="get(address)"`
export natip2=`gcloud compute addresses list --filter name:nat-address-2 --format="get(address)"`
export producerip1=`gcloud compute addresses list --filter name:producer-address-1 --format="get(address)"`
export producerip2=`gcloud compute addresses list --filter name:producer-address-2 --format="get(address)"`

Aucun résultat n'est attendu, mais vous pouvez vérifier que les adresses ont été correctement renseignées. Affichons les valeurs de toutes les variables d'environnement.

env | egrep '^(nat|producer)ip[1-3]'

Résultat :

producerip1=<Actual Producer IP 1>
producerip2=<Actual Producer IP 2>
natip1=<NAT IP 1>
natip2=<NAT IP 2>

5. Configuration du VPC et des instances du producteur.

Nous allons maintenant créer les ressources pour les ressources du producteur. Les instances exécutées dans le VPC du producteur proposeront le service accessible sur Internet à l'aide de deux adresses IP publiques, "producer-address-1" et "producer-address-2" .

Commençons par créer le VPC. Depuis Cloud Shell :

gcloud compute networks create producer-vpc --subnet-mode custom

Résultat :

Created [https://www.googleapis.com/compute/v1/projects/<Project-ID>/global/networks/producer-vpc].
NAME      SUBNET_MODE  BGP_ROUTING_MODE  IPV4_RANGE  GATEWAY_IPV4
producer-vpc  CUSTOM       REGIONAL

Instances on this network will not be reachable until firewall rules
are created. As an example, you can allow all internal traffic between
instances as well as SSH, RDP, and ICMP by running:

$ gcloud compute firewall-rules create <FIREWALL_NAME> --network producer-vpc --allow tcp,udp,icmp --source-ranges <IP_RANGE>
$ gcloud compute firewall-rules create <FIREWALL_NAME> --network producer-vpc --allow tcp:22,tcp:3389,icmp

Créez ensuite le sous-réseau dans us-east4. Depuis Cloud Shell :

gcloud compute networks subnets create prod-net-e4 \
   --network producer-vpc --range 10.0.0.0/24 --region us-east4

Résultat :

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/prod-net-e4].
NAME         REGION    NETWORK       RANGE        STACK_TYPE  IPV6_ACCESS_TYPE  IPV6_CIDR_RANGE  EXTERNAL_IPV6_CIDR_RANGE
prod-net-e4  us-east4  producer-vpc  10.0.0.0/24  IPV4_ONLY

Ensuite, créons des règles de pare-feu VPC pour permettre aux adresses IP NAT d'atteindre les instances de producteur sur le port 8080.

Pour la première règle, depuis Cloud Shell :

gcloud compute firewall-rules create producer-allow-80 \
  --network producer-vpc --allow tcp:80 \
  --source-ranges $natip1,$natip2

Résultat :

Creating firewall...⠹Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/firewalls/producer-allow-80].
Creating firewall...done.
NAME                 NETWORK       DIRECTION  PRIORITY  ALLOW     DENY  DISABLED
producer-allow-80    producer-vpc  INGRESS    1000      tcp:80          False

L'étape suivante consiste à créer les deux instances de producteur.

Les instances de producteur exécuteront un déploiement de proxy nginx simple.

Pour provisionner rapidement les instances avec tous les logiciels requis, nous allons les créer avec un script de démarrage qui installe nginx à l'aide du gestionnaire de packages Debian APT.

Pour pouvoir écrire des règles NAT, nous allons provisionner chaque instance avec une adresse IP réservée différente.

Créez la première instance. Depuis Cloud Shell :

gcloud compute instances create producer-instance-1 \
--zone=us-east4-a --machine-type=e2-medium \
--network-interface=address=producer-address-1,network-tier=PREMIUM,subnet=prod-net-e4 \
--metadata startup-script="#! /bin/bash
sudo apt update
sudo apt install -y nginx
mkdir /var/www/html/nginx/
cat <<EOF > /var/www/html/nginx/index.html
<html><body><h1>This is producer instance 1</h1>
</body></html>
EOF"

Résultat :

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/producer-instance-1].
NAME                 ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
producer-instance-1  us-east4-a  e2-medium                  10.0.0.2     <Producer IP1>  RUNNING

Créez ensuite la deuxième instance. Depuis Cloud Shell :

gcloud compute instances create producer-instance-2 \
--zone=us-east4-a --machine-type=e2-medium \
--network-interface=address=producer-address-2,network-tier=PREMIUM,subnet=prod-net-e4 \
--metadata startup-script="#! /bin/bash
sudo apt update
sudo apt install -y nginx
mkdir /var/www/html/nginx/
cat <<EOF > /var/www/html/nginx/index.html
<html><body><h1>This is producer instance 2</h1>
</body></html>
EOF"

Résultat :

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/producer-instance-2].
NAME                 ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
producer-instance-2  us-east4-a  e2-medium                  10.0.0.3     <Producer IP2>  RUNNING

6. Configurer le VPC consommateur, Cloud NAT et les instances

Maintenant que vous avez créé le service de producteur, il est temps de créer le VPC consommateur et sa passerelle Cloud NAT.

Après avoir créé le VPC et le sous-réseau, nous allons ajouter une règle de pare-feu d'entrée simple pour autoriser les plages d'adresses IP sources IAP pour TCP. Cela nous permettra d'établir une connexion SSH aux instances du consommateur directement à l'aide de gcloud.

Nous allons ensuite créer une passerelle Cloud NAT simple en mode d'allocation manuelle et l'adresse réservée "nat-address-1" qui y est associée. Dans les parties suivantes de l'atelier de programmation, nous mettrons à jour la configuration de la passerelle pour activer l'allocation dynamique de ports, puis nous ajouterons des règles personnalisées.

Commençons par créer le VPC. Depuis Cloud Shell :

gcloud compute networks create consumer-vpc --subnet-mode custom

Résultat :

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/networks/consumer-vpc].
NAME          SUBNET_MODE  BGP_ROUTING_MODE  IPV4_RANGE  GATEWAY_IPV4
consumer-vpc  CUSTOM       REGIONAL

Instances on this network will not be reachable until firewall rules
are created. As an example, you can allow all internal traffic between
instances as well as SSH, RDP, and ICMP by running:

$ gcloud compute firewall-rules create <FIREWALL_NAME> --network consumer-vpc --allow tcp,udp,icmp --source-ranges <IP_RANGE>
$ gcloud compute firewall-rules create <FIREWALL_NAME> --network consumer-vpc --allow tcp:22,tcp:3389,icmp

Ensuite, créons un sous-réseau dans us-east4. Depuis Cloud Shell :

gcloud compute networks subnets create cons-net-e4 \
   --network consumer-vpc --range 10.0.0.0/24 --region us-east4

Résultat :

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/cons-net-e4].
NAME         REGION    NETWORK       RANGE        STACK_TYPE  IPV6_ACCESS_TYPE  IPV6_CIDR_RANGE  EXTERNAL_IPV6_CIDR_RANGE
cons-net-e4  us-east4  consumer-vpc  10.0.0.0/24  IPV4_ONLY

Ensuite, créons des règles de pare-feu VPC pour autoriser les plages d'adresses IAP à atteindre les instances de consommateur sur le port 22.

Pour la première règle de pare-feu, exécutez la commande suivante dans Cloud Shell :

gcloud compute firewall-rules create consumer-allow-iap \
  --network consumer-vpc --allow tcp:22 \
  --source-ranges 35.235.240.0/20

Résultat :

Creating firewall...⠹Created [https://www.googleapis.com/compute/v1/projects/<Project-ID>/global/firewalls/consumer-allow-iap].
Creating firewall...done.
NAME                 NETWORK       DIRECTION  PRIORITY  ALLOW     DENY  DISABLED
consumer-allow-iap  consumer-vpc  INGRESS    1000      tcp:22        False

Avant de créer une passerelle NAT, nous devons d'abord créer une instance Cloud Router (nous utilisons un numéro ASN privé, mais cela n'a pas d'importance pour les activités de cet atelier). Depuis Cloud Shell :

gcloud compute routers create consumer-cr \
--region=us-east4 --network=consumer-vpc \
 --asn=65501

Résultat :

Creating router [consumer-cr]...done.
NAME         REGION       NETWORK
consumer-cr  us-east4  consumer-vpc

Créez ensuite l'instance de passerelle NAT. Depuis Cloud Shell :

gcloud compute routers nats create consumer-nat-gw \
    --router=consumer-cr \
    --router-region=us-east4 \
    --nat-all-subnet-ip-ranges \
    --nat-external-ip-pool=nat-address-1

Résultat :

Creating NAT [consumer-nat-gw] in router [consumer-cr]...done.

Notez que, par défaut, la passerelle Cloud NAT est créée avec minPortsPerVm défini sur 64.

Créez les instances de test du consommateur. Nous renseignons ici les adresses IP de producteurs réservées pour pouvoir y faire référence ultérieurement dans l'instance. Depuis Cloud Shell :

gcloud compute instances create consumer-instance-1 --zone=us-east4-a \
--machine-type=e2-medium --network-interface=subnet=cons-net-e4,no-address \
--metadata=producer-service-ip1=$producerip1,producer-service-ip2=$producerip2

gcloud compute instances create consumer-instance-2 --zone=us-east4-a \
--machine-type=e2-medium --network-interface=subnet=cons-net-e4,no-address \
--metadata=producer-service-ip1=$producerip1,producer-service-ip2=$producerip2

Résultat :

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/consumer-instance-1].
NAME                ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP  STATUS
consumer-instance-1  us-east4-a  e2-medium                  10.0.0.2                  RUNNING

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/consumer-instance-2].
NAME                ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP  STATUS
consumer-instance-2  us-east4-a  e2-medium                  10.0.0.3                  RUNNING

7. Vérifier le comportement par défaut de Cloud NAT

À ce stade, les instances consommatrices utilisent le comportement Cloud NAT par défaut, qui utilise la même adresse IP réservée "nat-address-1" pour communiquer avec toutes les adresses externes. Cloud NAT n'a pas encore activé le DPA.

Validons les ports que Cloud NAT a attribués à nos instances consommatrices en exécutant la commande suivante :

gcloud  compute routers get-nat-mapping-info consumer-cr --region=us-east4

Exemple de sortie

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Consumer IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Consumer IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
---
instanceName: consumer-instance-2
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1056-1087
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3
- natIpPortRanges:
  - <NAT Address IP1>:32800-32831
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3

Comme vous pouvez le voir dans le résultat ci-dessus, Cloud NAT a alloué 64 ports par instance à partir de la même adresse IP externe nat-address-1.

Avant d'activer DPA, validons le nombre de connexions que nous pouvons ouvrir en parallèle.

Connectez-vous en SSH à la première instance de consommateur. Depuis Cloud Shell :

gcloud compute ssh consumer-instance-1 --zone=us-east4-a

Vous devriez maintenant être dans le shell de l'instance.

Exemple de résultat (résultat complet tronqué pour plus de concision)

External IP address was not found; defaulting to using IAP tunneling.
...
...
<username>@consumer-instance-1:~$

Depuis l'instance consommateur, récupérons d'abord les adresses IP du producteur et renseignons-les en tant que variables d'environnement.

export producerip1=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip1" -H "Metadata-Flavor: Google"`

export producerip2=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip2" -H "Metadata-Flavor: Google"`

Ensuite, essayez d'envoyer une requête curl aux deux instances de producteur pour vous assurer que vous pouvez les atteindre.

<username>@consumer-instance-1:~$ curl http://$producerip1/nginx/
<html><body><h1>This is producer instance 1</h1>
</body></html>
<username>@consumer-instance-1:~$ curl http://$producerip2/nginx/
<html><body><h1>This is producer instance 2</h1>
</body></html>

Essayons maintenant de créer de nombreuses connexions parallèles à l'une des instances de producteur en exécutant curl dans une boucle. Rappelez-vous que Cloud NAT n'autorise pas la réutilisation des sockets fermés pendant deux minutes. Ainsi, tant que nous pouvons parcourir toutes les tentatives de connexion en deux minutes, nous pouvons simuler des connexions parallèles de cette manière.

Exécutez la commande suivante dans la session SSH de l'instance.

while true; do for i in {1..64}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

Vous devriez pouvoir ouvrir 64 connexions parallèles et le script devrait afficher le résultat suivant :

Connection # 64 successful

Loop Done, Sleeping for 150s
Connection # 64 successful

Loop Done, Sleeping for 150s

Pour vérifier que nous ne pouvons pas dépasser 64 connexions parallèles, attendez d'abord deux minutes pour que tous les anciens sockets soient effacés. Modifiez ensuite la même ligne de commande comme suit et réexécutez-la.

while true; do for i in {1..70}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

Vous devriez maintenant obtenir le résultat suivant :

Connection # 64 successful
Connection # 65 failed
Connection # 66 failed
Connection # 67 failed
Connection # 68 failed
Connection # 69 failed
Connection # 70 failed

Loop Done, Sleeping for 150s

Cela indique que les 64 premières connexions ont réussi, mais que les 6 autres ont échoué en raison de l'indisponibilité des ports.

Alors, agissons ! Quittons le shell SSH et activons DPA dans la section suivante.

8. Activer DPA et valider son comportement

Exécutez la commande gcloud suivante, qui active la DPA, définit l'allocation de ports minimale par VM sur 64 et l'allocation de ports maximale sur 1 024.

gcloud alpha compute routers nats update consumer-nat-gw --router=consumer-cr \
--region=us-east4 --min-ports-per-vm=64 --max-ports-per-vm=1024 \
--enable-dynamic-port-allocation

qui produit ce qui suit

Updating nat [consumer-nat-gw] in router [consumer-cr]...done.

Exécutons à nouveau get-nat-mapping-info pour vérifier que les deux instances ne disposent toujours que de 64 ports alloués.

gcloud  compute routers get-nat-mapping-info consumer-cr --region=us-east4

Exemple de résultat (tronqué par souci de concision)

---
instanceName: consumer-instance-1
...
  - <NAT Consumer IP1>:1024-1055
  numTotalNatPorts: 32
...
- natIpPortRanges:
  - <NAT Consumer IP1>:32768-32799
  numTotalNatPorts: 32
...
---
instanceName: consumer-instance-2
...
  - <NAT Address IP1>:1056-1087
  numTotalNatPorts: 32
...
  - <NAT Address IP1>:32800-32831
  numTotalNatPorts: 32
...

Peu de choses ont changé en termes d'allocation de ports, car l'instance n'en utilise pas encore activement.

Reconnectons-nous en SSH à l'instance :

gcloud compute ssh consumer-instance-1 --zone=us-east4-a

Réexportez les variables d'environnement de l'adresse IP du producteur.

export producerip1=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip1" -H "Metadata-Flavor: Google"`

export producerip2=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip2" -H "Metadata-Flavor: Google"`

Réexécutez la boucle précédente pour simuler des connexions parallèles :

while true; do for i in {1..70}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

Vous devriez maintenant obtenir le résultat suivant :

Connection # 64 successful
Connection # 65 failed

Connection # 66 failed
Connection # 70 successful
Loop Done, Sleeping for 150s

Que s'est-il passé ? Cloud NAT augmente l'allocation de ports en fonction de l'augmentation de l'utilisation des ports, mais cela prend un certain temps pour être programmé dans la couche réseau. Nous constatons donc 1 à 3 dépassements du délai de connexion avant de réussir à effectuer le reste des tentatives de connexion.

Nous avons spécifié un délai d'attente agressif pour curl (5 secondes), mais les applications avec des délais d'attente plus longs devraient pouvoir établir des connexions avec succès pendant que DPA augmente les allocations de ports.

Ce comportement de montée en charge est plus visible lorsque nous exécutons la boucle pour 1 024 tentatives de connexion, comme suit :

while true; do for i in {1..1024}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

Nous devrions maintenant voir le résultat suivant :

Connection # 64 successful
Connection # 65 failed

Connection # 66 failed
Connection # 129 successful
Connection # 130 failed

Connection # 131 failed
Connection # 258 successful
Connection # 259 failed

Connection # 260 failed
Connection # 515 successful
Connection # 516 failed

Connection # 1024 successful
Loop Done, Sleeping for 150s

Étant donné que Cloud NAT alloue des ports par puissances de 2, en doublant essentiellement les allocations à chaque étape, nous constatons que les délais d'inactivité de connexion sont mis en évidence autour des puissances de 2 entre 64 et 1 024.

Comme nous avons défini maxPortsPerVM sur 1 024, nous ne nous attendons pas à pouvoir établir plus de 1 024 connexions. Pour le vérifier, nous pouvons relancer la boucle curl avec un nombre supérieur à 1 024 (après avoir attendu deux minutes pour réinitialiser les ports obsolètes).

while true; do for i in {1..1035}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

Comme prévu, la sortie montre que les connexions au-delà de 1 024 commencent à échouer.

<truncated output>
...
Connection # 1028 successful
Connection # 1029 failed
Connection # 1030 failed
Connection # 1031 failed
Connection # 1032 failed
Connection # 1033 failed
Connection # 1034 failed
Connection # 1035 failed
...
Loop Done, Sleeping for 150s

En définissant maxPortsPerVM sur 1024, nous avons indiqué à Cloud NAT de ne jamais dépasser 1024 ports par VM.

Si nous quittons la session SSH et réexécutons get-nat-mapping-info suffisamment rapidement, nous pouvons voir les ports supplémentaires alloués.

gcloud  compute routers get-nat-mapping-info consumer-cr --region=us-east4

Observez le résultat suivant :

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  - <NAT Address IP1>1088-1119
  -<NAT Address IP1>:1152-1215
  - <NAT Address IP1>:1280-1407
  - <NAT Address IP1>:1536-1791
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 512
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  - <NAT Address IP1>:32832-32863
  - <NAT Address IP1>:32896-32959
  - <NAT Address IP1>:33024-33151
  - <NAT Address IP1>:33536-33791
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 512
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
---
instanceName: consumer-instance-2
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1056-1087
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3
- natIpPortRanges:
  - <NAT Address IP1>:32800-32831
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3

Notez que 1 024 ports sont alloués à consumer-instance-1, mais seulement 64 à consumer-instance-2. Auparavant, cela n'était pas possible facilement. Cela illustre parfaitement la puissance de DPA pour Cloud NAT.

Si vous attendez deux minutes avant de réexécuter la commande get-nat-mapping-info, vous remarquerez que consumer-instance-1 est revenu à sa valeur minimale de seulement 64 ports alloués. Cela illustre non seulement la capacité de DPA à augmenter les allocations de ports, mais aussi à les libérer lorsqu'elles ne sont pas utilisées pour une utilisation potentielle par d'autres instances derrière la même passerelle NAT.

9. Tester les règles Cloud NAT avec DPA

Nous avons également récemment lancé la fonctionnalité de règles NAT pour Cloud NAT, qui permet aux clients d'écrire des règles utilisant des adresses IP NAT spécifiques pour certaines destinations externes. Pour en savoir plus, veuillez consulter la page de documentation sur les règles NAT.

Dans cet exercice, nous allons observer l'interaction entre les règles DPA et NAT. Commençons par définir une règle NAT pour utiliser nat-address-2 lors de l'accès à producer-address-2.

Exécutez la commande gcloud suivante, qui crée la règle NAT à l'aide de

gcloud alpha compute routers nats rules create 100 \
 --match='destination.ip == "'$producerip2'"' \
 --source-nat-active-ips=nat-address-2 --nat=consumer-nat-gw \
 --router=consumer-cr --router-region=us-east4

Vous devriez obtenir le résultat suivant :

Updating nat [consumer-nat-gw] in router [consumer-cr]...done.

Exécutons maintenant à nouveau get-nat-mapping-info pour voir l'effet de la nouvelle règle NAT.

gcloud alpha compute routers get-nat-mapping-info consumer-cr --region=us-east4

qui devrait produire ce qui suit

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1024-1055
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32768-32799
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2

Notez que des ports supplémentaires (également au nombre de 64, le minimum spécifié) sont désormais alloués spécifiquement à nat-address-2 sous la hiérarchie ruleMappings.

Que se passe-t-il si une instance ouvre de nombreuses connexions vers la destination spécifiée par la règle NAT ? Vérifions-le dès maintenant.

Reconnectons-nous en SSH à l'instance :

gcloud compute ssh consumer-instance-1 --zone=us-east4-a

Réexportez les variables d'environnement de l'adresse IP du producteur.

export producerip1=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip1" -H "Metadata-Flavor: Google"`

export producerip2=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip2" -H "Metadata-Flavor: Google"`

Maintenant, réexécutons la boucle curl sur producerip2.

while true; do for i in {1..1024}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip2/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

Vous devriez obtenir un résultat semblable à celui-ci :

Connection # 64 successful
Connection # 65 failed

Connection # 66 failed
Connection # 129 successful
Connection # 130 failed

Connection # 131 failed
Connection # 258 successful
Connection # 259 failed

Connection # 260 failed
Connection # 515 successful
Connection # 516 failed

Connection # 1024 successful
Loop Done, Sleeping for 150s

Il s'agit d'un test identique au précédent. Quittons la session SSH de l'instance et examinons à nouveau les mappages NAT.

gcloud alpha compute routers get-nat-mapping-info consumer-cr --region=us-east4

qui devrait produire ce qui suit

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1024-1055
    - <NAT Address IP2>:1088-1119
    - <NAT Address IP2>:1152-1215
    - <NAT Address IP2>:1280-1407
    - <NAT Address IP2>:1536-1791
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 512
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32768-32799
    - <NAT Address IP2>:32832-32863
    - <NAT Address IP2>:32896-32959
    - <NAT Address IP2>:33024-33151
    - <NAT Address IP2>:33280-33535
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 512
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
---
instanceName: consumer-instance-2
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1056-1087
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1056-1087
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3
- natIpPortRanges:
  - <NAT Address IP1>:32800-32831
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32800-32831
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1024-1055
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32768-32799
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2

Comme vous pouvez le voir ci-dessus, l'adresse IP NAT par défaut de consumer-instance-1 ( adresse IP pour nat-address-1) ne dispose toujours que de 64 ports alloués, tandis que l'adresse IP de la règle NAT (adresse IP pour nat-address-2) dispose de 1 024 ports alloués. Pendant ce temps, consumer-instance-2 a conservé ses allocations par défaut de 64 ports pour toutes les adresses IP NAT.

Pour vous entraîner, vous pouvez tester le cas inverse. Laissez Cloud NAT libérer tous les ports supplémentaires, puis exécutez la boucle curl sur producerip1 et observez les effets sur la sortie de get-nat-mapping-info.

10. Étapes de nettoyage

Pour éviter les frais récurrents, vous devez supprimer toutes les ressources associées à cet atelier de programmation.

Commencez par supprimer toutes les instances.

Depuis Cloud Shell :

gcloud compute instances delete consumer-instance-1 consumer-instance-2 \
 producer-instance-1 producer-instance-2 \
 --zone us-east4-a --quiet

Résultat attendu :

Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/consumer-instance-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/consumer-instance-2].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/producer-instance-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/producer-instance-2].

Supprimez ensuite le routeur Cloud Router. Depuis Cloud Shell :

gcloud compute routers delete consumer-cr \
 --region us-east4 --quiet

Vous devriez obtenir le résultat suivant :

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/routers/consumer-cr].

Libérez toutes les adresses IP externes. Depuis Cloud Shell :

gcloud compute addresses delete nat-address-1 \
 nat-address-2 producer-address-1 \
 producer-address-2 --region us-east4 --quiet

Vous devriez obtenir le résultat suivant :

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-2].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-3].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-2].

Supprimez les règles de pare-feu VPC. Depuis Cloud Shell :

gcloud compute firewall-rules delete consumer-allow-iap \
 producer-allow-80 --quiet

Vous devriez obtenir le résultat suivant :

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/firewalls/consumer-allow-iap].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/firewalls/producer-allow-80].

Supprimez les sous-réseaux. Depuis Cloud Shell :

gcloud compute networks subnets delete cons-net-e4 \
 prod-net-e4 --region=us-east4 --quiet

Vous devriez obtenir le résultat suivant :

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/cons-net-e4].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/prod-net-e4].

Enfin, supprimons les VPC. Depuis Cloud Shell :

gcloud compute networks delete consumer-vpc \
 producer-vpc --quiet

Vous devriez obtenir le résultat suivant :

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/networks/consumer-vpc].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/networks/producer-vpc].

11. Félicitations !

Vous avez terminé l'atelier sur le DPA Cloud NAT.

Sujets abordés

  • Configurer une passerelle Cloud NAT en vue de la DPA
  • Inspecter les allocations de ports sans DPA
  • Comment activer et configurer la protection des données en transit pour une passerelle NAT.
  • Observer les effets de la protection des données en exécutant des connexions de sortie parallèles.
  • Comment ajouter des règles NAT à une passerelle NAT avec DPA activé.
  • Découvrez le comportement de DPA avec les règles en exécutant des connexions de sortie vers plusieurs destinations.

Étapes suivantes

©Google, Inc. ou ses sociétés affiliées. Tous droits réservés. Ne pas diffuser.