WebSocket server on managed VM not properly exposed trough GAE URL - google-app-engine

A normal webserver in a ManagedVM can listen on 0.0.0.0:8080 and properly serve requests dispatched through the GAE URL: http://xx.appspot.com:80
Instead of a normal webserver, try serving websocket connections and things no longer work. No connection gets handled anymore when connecting on: ws://xx.appspot.com:80
This (http://stackoverflow.com/questions/27827752/websocket-support-in-managed-vm) SO topic suggests exposing port 8080 to the Internet from the GCE network settings and using the IP of the GCE instance directly. That works indeed, but is not helpful as the IP changes on every new deployment.
If this is indeed the way to go, then it's not documented anywhere.
The only clue I've seen is that a Google employee also uses IP discovery to connect to the right GCE instance that hosts a websocket server:
https://github.com/proppy/cacophon/blob/master/frontend/api/controllers/DiscoveryController.js
I'm hoping for a proper fix that doesn't require me to use introspection for gather IPs of the VM instances hosting websocket servers.

With reference to Google issue tracker,
Since this thread was opened more than two years ago, I would like to check with you that if you're still hoping for the fix/FR about WebSocket server on Flex not properly exposed through GAE ULR?
for more update you can check Google issue tracker

Related

intermediate hops in nginx reverse proxy

I am new to nginx and doing full stack development for the first time. Could you please help me understand the below logic
Lets say we are building a chatting app. We have 3 servers (EC2 instances)
server_nginx - ec2 running a nginx server working as reverse proxy
server_react - ec2 running a react project through nginx as web server
server_spring - ec2 running a spring boot project through nginx as web server
My reverse proxy is running through SSL/https. Initially everything was happening on same machine, so I made my spring boot service also ssl because I could not initiate a http connection over https. Now the I started separating out the instance as mentioned above (3 ec2 instances). I was expecting that the connection to my backend would fail. Reason :
user connects to reverse proxy through https domain (lets say mydomain.com).
The request comes to server_nginx(mydomain.com).
From here this proxies this to server_react (which is running on simple http). This is the server where my react code is hosted
This react code tries to initiate a web socket connection to server_spring where I have enabled the CORS for mydomain.com. So I was expecting that the connection would fail here as this is a different IP now. But surprisingly all the apis are getting the response as if I am hitting it from mydomain.com
So can anyone please help me understand why is the behaviour like this
Thanks.

NextJs connecting to third party API which requires whitelisting of an IP address

I am building a full-stack nextjs app where the majority of the functionality is coming from a third-party API connection that requires whitelisting of an IP address to connect and make calls to the API and bring the data back to the user.
Everything works in dev (as usual) considering that i have a dedicated IP through a VPN, but i have attempted to push the production version to vercel and heroku and whitelisted the IP ranges applicable to those platforms domain servers but i still am getting "Access Denied" and cannot run any calls.
Can my expert peers please help me understand what the best way to get this to work in production is? Do i need a proxy server or do i need the backend to be on an express server and just keep the front end static (would prefer to keep everything the way that it is).
Thank you all in advance for the support

Cloud Run static outbound IP address does not go through Google App Engine firewall

I have a python (flask) application running on Google App Engine (flex); the application is protected by the GAE firewall where:
Default rule is 'Deny' all ingress
There is a whitelist of IP addresses from which traffic is allowed.
I have some microservices deployed on Cloud Run (fully managed) which:
Receive requests from the GAE app (e.g. for heavy duty tasks)
Send the results of whatever they process as http requests back to handlers/endpoints in the GAE app
Thus the GAE app is the main point of interaction with clients and a dispatcher of heavy tasks, while the processing of those tasks is carried out by the microservices. I have set up a static outbound IP address of the Cloud Run hosted service which verfiedly works and traffic is routed through the NAT gateway as required in the documentation. The respective NAT IP address is on the firewall whitelist.
The problem is that the firewall still does not let in the Cloud Run >>> GAE app requests which bounce back with 403 statuses (of course, if I change the default firewall rule to 'Allow', traffic goes through). If I host the same microservice in a docker container on a GCE VM with a static IP address like this everything works flawlessly. This makes me hypothesize that albeit Cloud Run outbound traffic is indeed routed through the static IP address when traffic is towards addressees outside GCP, when I try to ping an internal (project-wise) asset it still goes though some dynamically selected IP (i.e. the static IP solution simply does not work). Unfortunately the logs don't show the 403-ed attempt so I can't see from what IP addresses those request seem to come (from a GAE standpoint).
I would be very grateful for ideas how this can be fixed as it greatly diminishes the value of the otherwise wonderful idea to have static outbound IP addresses for Cloud Run.
First, thank you both for your help and suggestions, they are very helpful. I found the solution with some kind help from Google:
When the Cloud Run microservice and the GAE app are hosted in the same project traffic is still routed through internal channels and appears to come from IP address 0.0.0.0 which can be whitelisted (so it would work) as long as one considers this address encompasses GCP assets which are parts of other projects too (to the best of my understanding)
A more robust solution seems to be setting up an externally facing load balancer as described here and putting it in front of the GAE app; in such a case, Cloud Run will indeed consistently use its static outbound IP address as described in the documentation
You are correct saying that the static IP is not honoured when packets are routed internally to GCP.
I think this is what you want. You have to allow in the firewall one of the IPs mentioned there (not sure which one right now).
Just as you and #Ema mentioned, this is an expected behavior having in mind that the traffic from Cloud Run to App Engine is intern.
When you use Cloud Nat to send all traffic there, it does happen. If you create a container and ping, let's say to www.github.com. You will find that the traffic goes through the IP you set. On the other hand, if you ping to www.google.com, given that the traffic is intern, and the site to reach out is in the same infrastructure, the request doesn't even goes through public internet.
Additionally, just to keep in mind Static outbound IP address is still in Beta and it is not recommended to use Beta features/products in production environments.
As you mentioned and as it is stated in Allowing requests from your services:
Creating a rule for IP 0.0.0.0 will apply to all Compute Engine instances with Private Google Access enabled, not only the ones you own. Similarly, allowing requests from 0.1.0.40 or 10.0.0.1 will allow any App Engine app to make URL Fetch requests to your app.
This questions might be of your interest:
What are the outbound IP ranges for GCP managed Cloud Run?
Possible to get static IP address for Google Cloud Functions?

What is the equivalent of a hosts file mapping for AppEngine?

Our AppEngine app is connecting to a remote service which requires a VPN and also required me to add entries to the hosts file on my local machine in order to connect to their endpoints.
e.g.
10.200.30.150 foo.bar.com
This is working fine when running the app locally, but I can't figure out how to set this up on Google Cloud to work once deployed.
I can't use the IP addresses directly because it errors that the IP is not on the cert's list.
How do I map the host names to the IPs in Google Cloud so that AppEngine can use them?
From the error mentioned in the comment I suspect connecting directly through the IP fails because the certificate doesn't recognize the IP to DNS mapping as valid and therefore the secure connection setup breaks. Based on the requirements of connecting to the API by VPN and tweaking the hosts mapping there are few things you may try.
The simplest approach that may work would be using a Google Compute Engine VM instance, since there you would able to manipulate the etc/hosts file and replicate the local machine setup. This VM could be used either as the main app service or as a proxy from App Engine to the 3rd party API endpoint. To go that route I would suggest taking a look at these two posts which explain how to change the etc/hosts file on GCE (Changing the file once wouldn't work as the VM periodically overrides it, see the posts for cronjob like workaround).
Separately, as your app runs in App Engine flexible environment there is the chance to provide a docker container with the app packaged. It may be possible to set the workaround above in the docker file and have it working in App Engine too.

How to do API calls with Google App Engine or Cloud Composer when the API only allows restricted IPs

I have jobs and APIs hosted on cloud composer and App Engine that works fine. However for one of my job I would need to call an API that is IP restricted.
As far as I understand, I see that there's no way to have a fixed IP for app engine and cloud composer workers and I don't know what is the best solution then.
I thought about creating a GCE with a fixed IP that would be switched on/off by the cloud composer or app engine and then the API call would be executed by the startup-script. However, it restrains this to only asynchronous tasks and it seems to add a non desired step.
I have been told that it is possible to set up a proxy but I don't know how to do it and I did not find comprehensive docs about it.
Would you have advice for this use-case ?
Thanks a lot for your help
It's probably out of scope to you, but you could whitelist the whole range of app engine ip by performing a lookup on _cloud-netblocks.googleusercontent.com
In this case you are whitelisting any app engine applications, so be sure this api has another kind of authorization and good security. More info on the App Engine KB.
What I would do is install or implement some kind of API proxy on GCE. It's a bummer to have a VM on 24/7 for this kind of task so you could also use an autoscaler to scale to 0 (not sure about this one).
As you have mentioned: you can set up a TCP or UDP proxy in GCE as a relay, and then send requests to the relay (which then forwards those requests to the IP-restricted host).
However, that might be somewhat brittle in some cases (and introduces a single point of failure). Therefore, another option you could consider is creating a private IP Cloud Composer environment, and then using Cloud NAT for public IP connectivity. That way, all requests from Airflow within Composer will look like they are originating from the IP address of the NAT gateway.

Resources