4

This is related to the following questions, which are outdated

Currently GCP has VPC Serverless Connector that allows you to route all traffic through a VPC Connector and set up Cloud NAT to get static IP addresses.

I have followed the following guide https://cloud.google.com/functions/docs/networking/network-settings#associate-static-ip using the region us-east4 but external requests from my cloud function always timed out.

I'm not sure this is a bug or I have missed something.

Edit: To make sure I have followed everything, I did all the steps using gcloud, command where possible. These commands are copied from the guides from GCP.

  1. Setting project id for future use
PROJECT_ID=my-test-gcf-vpc-nat
  1. Go to Console and enable billing

  2. Set up a VPC and a test VM to test Cloud NAT

gcloud services enable compute.googleapis.com \
  --project $PROJECT_ID

gcloud compute networks create custom-network1 \
  --subnet-mode custom \
  --project $PROJECT_ID

gcloud compute networks subnets create subnet-us-east-192 \
  --network custom-network1 \
  --region us-east4 \
  --range 192.168.1.0/24 \
  --project $PROJECT_ID

gcloud compute instances create nat-test-1 \
  --image-family debian-9 \
  --image-project debian-cloud \
  --network custom-network1 \
  --subnet subnet-us-east-192 \
  --zone us-east4-c \
  --no-address \
  --project $PROJECT_ID

gcloud compute firewall-rules create allow-ssh \
  --network custom-network1 \
  --source-ranges 35.235.240.0/20 \
  --allow tcp:22 \
  --project $PROJECT_ID
  1. Created IAP SSH permissions using Console

  2. Test network config, the VM should not have internet access without Cloud NAT

gcloud compute ssh nat-test-1 \
  --zone us-east4-c \
  --command "curl -s ifconfig.io" \
  --tunnel-through-iap \
  --project $PROJECT_ID

command responded with connection timed out

  1. Set up Cloud NAT
gcloud compute routers create nat-router \
  --network custom-network1 \
  --region us-east4 \
  --project $PROJECT_ID

gcloud compute routers nats create nat-config \
  --router-region us-east4 \
  --router nat-router \
  --nat-all-subnet-ip-ranges \
  --auto-allocate-nat-external-ips \
  --project $PROJECT_ID
  1. Test network config again, the VM should have internet access with Cloud NAT
gcloud compute ssh nat-test-1 \
  --zone us-east4-c \
  --command "curl -s ifconfig.io" \
  --tunnel-through-iap \
  --project $PROJECT_ID

command responded with IP address

  1. Created VPC Access Connector
gcloud services enable vpcaccess.googleapis.com \
  --project $PROJECT_ID

gcloud compute networks vpc-access connectors create custom-network1-us-east4 \
  --network custom-network1 \
  --region us-east4 \
  --range 10.8.0.0/28 \
  --project $PROJECT_ID

gcloud compute networks vpc-access connectors describe custom-network1-us-east4 \
  --region us-east4 \
  --project $PROJECT_ID
  1. Added permissions for Google Cloud Functions Service Account
gcloud services enable cloudfunctions.googleapis.com \
  --project $PROJECT_ID

PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:service-$PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com \
  --role=roles/viewer

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:service-$PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com \
  --role=roles/compute.networkUser
  1. There are suggestions I should add additional firewall rules and service account permissions
# Additional Firewall Rules
gcloud compute firewall-rules create custom-network1-allow-http \
  --network custom-network1 \
  --source-ranges 0.0.0.0/0 \
  --allow tcp:80 \
  --project $PROJECT_ID

gcloud compute firewall-rules create custom-network1-allow-https \
  --network custom-network1 \
  --source-ranges 0.0.0.0/0 \
  --allow tcp:443 \
  --project $PROJECT_ID


# Additional Permission, actually this service account has an Editor role already.
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:$PROJECT_ID@appspot.gserviceaccount.com \
  --role=roles/compute.networkUser
  1. Deployed test Cloud Functions

index.js

const publicIp = require('public-ip')

exports.testVPC = async (req, res) => {
  const v4 = await publicIp.v4()
  const v6 = await publicIp.v6()
  console.log('ip', [v4, v6])
  return res.end(JSON.stringify([v4, v6]))
}
exports.testNoVPC = exports.testVPC
# Cloud Function with VPC Connector
gcloud functions deploy testVPC \
  --runtime nodejs10 \
  --trigger-http \
  --vpc-connector custom-network1-us-east4 \
  --egress-settings all \
  --region us-east4 \
  --allow-unauthenticated \
  --project $PROJECT_ID

# Cloud Function without VPC Connector
gcloud functions deploy testNoVPC \
  --runtime nodejs10 \
  --trigger-http \
  --region us-east4 \
  --allow-unauthenticated \
  --project $PROJECT_ID

The Cloud Function without VPC Connector responded with IP address https://us-east4-my-test-gcf-vpc-nat.cloudfunctions.net/testNoVPC

The Cloud Function with VPC Connector timed out https://us-east4-my-test-gcf-vpc-nat.cloudfunctions.net/testVPC

thammada.ts
  • 5,065
  • 2
  • 22
  • 33
  • 1
    Hi, have you solved this issue? I've tried for 2 days and still nothing :( https://stackoverflow.com/questions/64711513/how-to-set-external-ip-to-google-cloud-functions – dev_huesca Nov 06 '20 at 08:58
  • Yes, I have, please follow my comments on the answer below, the issue was that the package `public-ip` doesn't work as expected, you can try other methods to get static IP – thammada.ts Nov 06 '20 at 10:11
  • It does not matter what I use, the function can't seem to connect to the internet (in my particular case is trying to connect to an ftp server to drop some files) – dev_huesca Nov 06 '20 at 10:17

2 Answers2

6
  1. Configure a sample Cloud NAT setup with Compute Engine. Use the Compute Engine to test if your settings for Cloud NAT were done successfully.

  2. Configuring Serverless VPC Access. Make sure you create the VPC connector on the custom-network1 made in step 1.

  3. Create a Google Cloud Function

a.Under Networking choose the connector you created on step 2 and Route all traffic through the VPC connector.


import requests
import json

from flask import escape

def hello_http(request):

    response = requests.get('https://stackoverflow.com')

    print(response.headers)    
    return 'Accessing stackoverflow from cloud function:  {}!'.format(response.headers)

The Region for Cloud Nat, Vpc Connector and Cloud Function is us-central1

4.Test the function to see if you have access to internet:

Accessing stackoverflow from cloud function:  {'Cache-Control': 'private', 'Content-Type': 'text/html; charset=utf-8', 'Content-Encoding': 'gzip', 'X-Frame-Options': 'SAMEORIGIN', 'X-Request-Guid': 'edf3d1f8-7466-4161-8170-ae4d6e615d5c', 'Strict-Transport-Security': 'max-age=15552000', 'Feature-Policy': "microphone 'none'; speaker 'none'", 'Content-Security-Policy': "upgrade-insecure-requests; frame-ancestors 'self' https://stackexchange.com", 'Content-Length': '26391', 'Accept-Ranges': 'bytes', 'Date': 'Sat, 28 Mar 2020 19:03:17 GMT', 'Via': '1.1 varnish', 'Connection': 'keep-alive', 'X-Served-By': 'cache-mdw17354-MDW', 'X-Cache': 'MISS', 'X-Cache-Hits': '0', 'X-Timer': 'S1585422197.002185,VS0,VE37', 'Vary': 'Accept-Encoding,Fastly-SSL', 'X-DNS-Prefetch-Control': 'off', 'Set-Cookie': 'prov=78ecd1a5-54ea-ab1d-6d19-2cf5dc44a86b; domain=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly'}!

Success, now you can specify a static IP address for NAT

marian.vladoi
  • 7,663
  • 1
  • 15
  • 29
  • It's really strange, I have created a new project and followed steps 1-4 you suggested, I have enabled required API's, configured required permissions, but I got the same result. I can confirm the test in step 1. worked, Cloud NAT was set up correctly. The only things I've set up differently than the guides are just the names, and the region `asia-east2` instead of `us-central1`, but I also configured my cloud function to deploy to `asia-east2`. Either I missed something, or the documentation is missing something. – thammada.ts Mar 29 '20 at 13:54
  • did you grant to your service account that runs as your cloud function, (in my case the default App Engine service account) the `compute network user` role? – marian.vladoi Mar 29 '20 at 17:06
  • Also, I do not know if it makes a difference, these are my firewall on nat `rules:allow-ssh Ingress Apply to all IP ranges: 35.235.240.0/20 tcp:22 Allow 1000 custom-network1-allow-http Ingress http-server IP ranges: 0.0.0.0/0 tcp:80 Allow 1000 custom-network1-allow-https Ingress https-server IP ranges: 0.0.0.0/0 tcp:443 Allow 1000 Equivalent REST`, also is your connector on the same region? – marian.vladoi Mar 29 '20 at 17:15
  • Hi, I have added the reproduction steps, I have added your suggestion at step 10. – thammada.ts Mar 30 '20 at 04:03
  • 1
    Hi, I know it might sound crazy, but with python code I have access to internet, with node.js I do not. I do not know what I am doing wrong , but I tested with your code and I got timed out . – marian.vladoi Mar 30 '20 at 17:10
  • 1
    This is very helpful. It's because of the package `public-ip`, when I tried `request.get('https://ifconfig.co/ip')` instead it works correctly. Thank you!! – thammada.ts Mar 30 '20 at 20:29
  • Have you had any luck with getting this working with nodejs functions? I'm trying to get a static ip on a firebase function, have followed the instructions in the docs to the letter several times, and every time my function has no access to the internet. – Mark Flegg May 27 '20 at 14:14
  • @MarkFlegg Yes, I have. With firebase functions you will need to enable the VPC Connector from the console. You can post a new question with your details. I might be able to help – thammada.ts May 28 '20 at 13:14
  • @thammada Thanks! As it turns out, I just needed to wait a longer time before testing the functions' access. I left one overnight and the next morning it was good! – Mark Flegg Jun 17 '20 at 15:06
  • I've setup cloud NAT properly also internet connection has been established in compute VM instance. but I found it always taking 0.0.0.0 as internet broadcast IP \, not the static IP which I've patched on cloud Nat. Can you help me to fix it. – Sougata Jun 20 '20 at 19:46
  • @marian.vladoi can you help? https://stackoverflow.com/questions/64711513/how-to-set-external-ip-to-google-cloud-functions – dev_huesca Nov 06 '20 at 08:57
0

Check if the cloud nat routers were created in the same VPC used by the Serverless VPC Access.

Also check if the Cloud Function is deployed in the same region of the Cloud Routers used by the Cloud Nat.

Nakilon
  • 34,866
  • 14
  • 107
  • 142