Skip to content

Instantly share code, notes, and snippets.

@mikesparr
Created March 29, 2024 18:35
Show Gist options
  • Save mikesparr/c902f6979a6752f1d62c7dba87befdee to your computer and use it in GitHub Desktop.
Save mikesparr/c902f6979a6752f1d62c7dba87befdee to your computer and use it in GitHub Desktop.
Experiment using Google Cloud Secure Web Proxy and Cloud NAT
#!/usr/bin/env bash
#####################################################################
# REFERENCES
# - https://cloud.google.com/secure-web-proxy/docs/initial-setup-steps
# - https://cloud.google.com/certificate-manager/docs/deploy-google-managed-regional
# - https://cloud.google.com/secure-web-proxy/docs/quickstart
# - https://cloud.google.com/secure-web-proxy/docs/enable-tls-inspection (OPTIONAL)
#####################################################################
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_USER=$(gcloud config get-value core/account) # set current user
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
export IDNS=${PROJECT_ID}.svc.id.goog # workflow identity domain
export GCP_REGION="us-central1" # CHANGEME (OPT)
export GCP_ZONE="us-central1-a" # CHANGEME (OPT)
export NETWORK_NAME="default"
# enable apis
gcloud services enable compute.googleapis.com \
storage.googleapis.com \
certificatemanager.googleapis.com \
networksecurity.googleapis.com \
networkservices.googleapis.com
# configure gcloud sdk
gcloud config set compute/region $GCP_REGION
gcloud config set compute/zone $GCP_ZONE
############################################################
# Networking
############################################################
export NETWORK_NAME="demo-network"
export RESERVED_RANGE_NAME="google-managed-services"
export PROXY_SUBNET_NAME="secure-proxy"
export PROXY_SUBNET_RANGE="192.168.0.0/23"
export TEST_SUBNET_NAME="test-vms"
export TEST_SUBNET_RANGE="10.201.0.0/24"
export AUTHORIZATION_NAME="cert-auth-dns"
export DOMAIN_NAME="proxy.msparr.com" # CHANGEME
export CERTIFICATE_NAME="proxy-cert"
# create network (custom-mode)
gcloud compute networks create $NETWORK_NAME \
--subnet-mode=custom
# create ssh firewall rule
gcloud compute firewall-rules create allow-ssh \
--direction=INGRESS \
--priority=1000 \
--network=$NETWORK_NAME \
--action=ALLOW \
--rules=tcp:22 \
--source-ranges=0.0.0.0/0
# create proxy subnet
gcloud compute networks subnets create $PROXY_SUBNET_NAME \
--purpose=REGIONAL_MANAGED_PROXY \
--role=ACTIVE \
--region=$GCP_REGION \
--network=$NETWORK_NAME \
--range=$PROXY_SUBNET_RANGE \
--enable-private-ip-google-access
# create vm subnet
gcloud compute networks subnets create $TEST_SUBNET_NAME \
--region=$GCP_REGION \
--network=$NETWORK_NAME \
--range=$TEST_SUBNET_RANGE \
--enable-private-ip-google-access
# create dns authorization for regional managed cert
gcloud certificate-manager dns-authorizations create $AUTHORIZATION_NAME \
--domain="$DOMAIN_NAME" \
--type=PER_PROJECT_RECORD \
--location=$GCP_REGION
# describe dns auth to get CNAME for updating records
gcloud certificate-manager dns-authorizations describe $AUTHORIZATION_NAME \
--location=$GCP_REGION
# update your DNS records to add CNAME as this example:
# - cname: _acme-challenge_tprcqly2gkqiluqe.proxy.msparr.com
# - data: b7f8c0a6-3637-47ec-ba93-6f1c0bbbf267.2.us-central1.authorize.certificatemanager.goog.
# create regional managed certificate
gcloud certificate-manager certificates create $CERTIFICATE_NAME \
--domains=$DOMAIN_NAME \
--dns-authorizations=$AUTHORIZATION_NAME \
--location=$GCP_REGION
############################################################
# Secure Web Proxy
############################################################
export INSTANCE_NAME="swp-test-vm"
export POLICY_NAME="policy1"
export POLICY_FILE_NAME="policy.yaml"
export RULE_NAME="allow-wikipedia-org"
export RULE_FILE_NAME="rule.yaml"
export GATEWAY_NAME="swp1"
export GATEWAY_FILE_NAME="gateway.yaml"
export GATEWAY_ADDRESSES="[10.201.0.200]"
export GATEWAY_PORTS="[443]"
# create policy file (skipped TLS inspection / CA setup for simplicity)
cat > $POLICY_FILE_NAME << EOF
description: basic Secure Web Proxy policy
name: projects/$PROJECT_ID/locations/$GCP_REGION/gatewaySecurityPolicies/$POLICY_NAME
EOF
# create the swp policy
gcloud network-security gateway-security-policies import $POLICY_NAME \
--source=$POLICY_FILE_NAME \
--location=$GCP_REGION
# create swp rules file (skipped TLS inspection / CA setup for simplicity)
cat > $RULE_FILE_NAME << EOF
name: projects/$PROJECT_ID/locations/$GCP_REGION/gatewaySecurityPolicies/$POLICY_NAME/rules/$RULE_NAME
description: Allow wikipedia.org
enabled: true
priority: 1
basicProfile: ALLOW
sessionMatcher: host() == 'wikipedia.org'
EOF
# create the swp rule
gcloud network-security gateway-security-policies rules import $RULE_NAME \
--source=$RULE_FILE_NAME \
--location=$GCP_REGION \
--gateway-security-policy=$POLICY_NAME
# create the gateway config file
cat > $GATEWAY_FILE_NAME << EOF
name: projects/$PROJECT_ID/locations/$GCP_REGION/gateways/$GATEWAY_NAME
type: SECURE_WEB_GATEWAY
addresses: $GATEWAY_ADDRESSES
ports: $GATEWAY_PORTS
certificateUrls: ["projects/$PROJECT_ID/locations/$GCP_REGION/certificates/$CERTIFICATE_NAME"]
gatewaySecurityPolicy: projects/$PROJECT_ID/locations/$GCP_REGION/gatewaySecurityPolicies/$POLICY_NAME
network: projects/$PROJECT_ID/global/networks/$NETWORK_NAME
subnetwork: projects/$PROJECT_ID/regions/$GCP_REGION/subnetworks/$TEST_SUBNET_NAME
scope: samplescope
EOF
# create the gateway
gcloud network-services gateways import $GATEWAY_NAME \
--source=$GATEWAY_FILE_NAME \
--location=$GCP_REGION
############################################################
# Testing the proxy
############################################################
export INSTANCE_NAME="swp-test-vm"
# create a VM instance for testing (doesn't use proxy-only subnet which is reserved per region)
gcloud compute instances create $INSTANCE_NAME \
--subnet=$TEST_SUBNET_NAME \
--zone=$GCP_ZONE \
--image-project=debian-cloud \
--image-family=debian-11
# test the connection (allowed)
gcloud compute ssh $INSTANCE_NAME \
--zone $GCP_ZONE \
-- curl -x https://10.201.0.200:443 https://wikipedia.org --proxy-insecure
# test the connection (denied)
gcloud compute ssh $INSTANCE_NAME \
--zone $GCP_ZONE \
-- curl -x https://10.201.0.200:443 https://yahoo.com --proxy-insecure
# next steps (optional):
# - https://cloud.google.com/secure-web-proxy/docs/use-tags
# - https://cloud.google.com/secure-web-proxy/docs/use-url-list
# - https://cloud.google.com/secure-web-proxy/docs/assign-static-ip-addresses-for-egress-traffic
@mikesparr
Copy link
Author

Cloud NAT Automatic Provisioning

Cloud NAT was provisioned automatically when I set up the Secure Web Proxy above.

Screenshot 2024-03-29 at 12 56 41 PM

It was in "automatic" mode (preferred if no static IPs needed) to allow Google Cloud to handle scaling IPs and ports as needed.

Screenshot 2024-03-29 at 12 56 53 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment