Meteor and cloudflare with causes loop of xhr requests - meteor

I am writing a Meteor application that has two components - a frontend meteor app, hosted on one server, and a chat app hosted on another. The chat application uses socket.io to do the actual messaging (because I wanted to use redis pub-sub and that isn't supported by Meteor yet), and of course sockjs for the rest.
I am hosting the two on Kubernetes. At their network IPs, websockets are working.
However, I want to use Cloudflare, where websockets won't work, so I have the DISABLE_WEBSOCKETS env variable set to 1. Additionally, the transports for socket.io should have just defaulted to xhr polling.
The only problem is this:
when I get the conversations, the app hangs because the frontend web app is making a huge number of repeated "xhr" requests to the chat app.
after a while, the chat app is able to respond and send down the information after about 10 seconds, when it should have taken less than 0.5 seconds.
there are a huge number of sockjs xhr requests being made, whereas the number of sockjs xhr requests to the normal frontend app is small.
on development, this issue doesn't arise even with DISABLE_WEBSOCKETS set to 1.
On Cloudflare, I tried the following (from this page: https://modulus.desk.com/customer/portal/articles/1929796-cloudflare-configuration-with-meteor-xhr-polling):
- Set "Pseudo IPv4" to "Overwrite Headers"
Is there a special Meteor configuration I need to get xhr working with cloudflare? Additionally, I have another service on the app as well, but it works completely fine. Could socket.io somehow be interfering with sockjs in the chat service?

Related

Fargate errors when frontend service tries to communicate with backend service via Service Discovery

I have a frontend app in Fargate (ECS) in a private subnet exposed to internet through an Application Load Balancer. My frontend makes API calls to my backend apps, also in Fargate, same VPC.
Users calls to my frontend are made via HTTPS, but my frontend communicates with my backend via HTTP (AWS Service Discovery - AWS Cloud Map). This way, the user browser is showing the error "blocked: mixed content" since half of the communication is made via HTTPS and the other half uses HTTP.
infra here
As far as I know and had been searching, it is not possible to use a SSL/TLS certificate with Service Discovery.
I've made a lot of researches and couldn't find something really useful. I also tried to create an internal load balancer for each backend service but the communication is timing out, it only works when I have a VPN connected.
What am I missing here? Do I need an internal load balancer in front of each backend service to attach a certificate between frontend and backend? What is the best approach to solve this?
Users calls to my frontend are made via HTTPS, but my frontend communicates with my backend via HTTP (AWS Service Discovery - AWS Cloud Map). This way, the user browser is causing the error "blocked: mixed content" since half of the communication is made via HTTPS and the other half uses HTTP.
The user's browser wouldn't know anything about this if the communication was happening between the front-end server and the back-end server. Apparently you have front-end client JavaScript code running in the user's web browser trying to access the backend server directly.
If you want to access the backend server directly from the user's web browser, then service discovery won't work, because service discovery is only for traffic that is inside the VPC. And of course by trying to use service discovery in this way you are also causing a security issue which the browser is correctly blocking you from doing. You will need to add another load balancer, or another listener on your current load balancer, that exposes the backend API to the Internet.
Alternatively you could use a reverse proxy like Nginx on your front-end server to send backend API requests to the backend service, and then have your client-side JavaScript code send all requests to the front-end server.

Authenticating NGINX forwarded requests to upstream servers using Cognito

I have the following setup:
{Client App} --[HTTP]--> {NGINX} --[HTTPS]--> {API Gateway}
I need such a setup since API Gateway does not support HTTP (it only supports HTTPS) and my client apps are old/obsolete and do not talk HTTPS. So far it works perfectly fine. Now I need to make sure not just any requests are accepted by my API Gateways. I know how to protect API Gateways using Cognito (if I leave the NGINX out of the equation). The process plays as follows in action:
1.
{Consumer Server} --[Credentials]--> {Cognito}
<--[JWT Token]--
2.
{Consumer Server} --[JWT Token]--> {API Gateway}
...
To make sure there's no misunderstanding, the credential sent in step 1 is NOT an email. This is not for authenticating human users, but rather a machine-to-machine communication. And in my case, the client machine is an NGINX instance.
Having set up the scene, this is what I'm trying to achieve. I want my client app to communicate with my API gateway in HTTP. For that, I have to introduce an NGINX in between. But now, I want to make sure that only my designated NGINX instances can do so. So I need to authenticate the requests coming in from the NGINX. That means that NGINX needs to follow the second diagram and asks for JWT tokens from Cognito. And this is not a one-time process. Tokens expire and once they do, NGINX has to refresh them by sending another request to Cognito.
Does anyone know if there's a ready-made solution for this? Or an easy way to implement it?

How to encrypt values sent in DispatchBrowserEvent in blazor Server Side

Recently we deployed a Blazor application to one of our clients. When their internal team did a WARP test, we got a finding "ClearText transmission of Sensitive Information". When we analyzed it we found that the Blazor heartbeat is sending values typed in every input field to the server via "DispatchBrowserEvent". Given below is a screenshot of the same.
DispatchBrowserEvent
I need a solution to either
Encrypt the value being sent in the DispatchBrowserEvent or
To Stop the transmission of the values until its manually posted.
Blazor Server uses SignalR as the communication mechanism so data is sent back and forth to the server. It should be on an encrypted channel using SSL/TLS, so I assume your site has SSL enabled?
Login credentials have to be sent from the browser to the server in a POST to validate them. This is the same for all web applications. You just have to ensure that the requests are done over SSL so that only the client and the server can read them. This is not a security issue if this the case.
Secondly, the preferred mechanism SignalR/Blazor-Server uses is WebSockets. If your app was using a WebSocket connection you would not see the traffic you are seeing - this is because SignalR will fall back down to alternative methods if WebSockets are not available.
You should check your server to see if WebSockets is enabled - I suspect that is the cause.

R-Shiny script timeout behind a load-balancer

I am testing one Shiny script on an instance in GCP. The instance resides behind a load-balancer that serves as a front end with a static IP address and SSL certificate to secure connections. I configured the GCP instance as part of a backend service to which the load-balancer forwards the requests. The connection between the load-balancer and the instance is not secured!
The issue:
accessing the Shiny script via the load-balancer works, but the web browser's screen gets grayed (time-out) on the client-side after a short time of initiating the connection!! When the browser screen grayed out, I have to start over!!
If I try to access the Shiny script on the GCP instance directly (not through the load-balancer), the script works fine. I suppose that the problem is in the load-balancer, not the script.
I appreciate any help with this issue.
Context: Shiny uses a websocket (RFC 6455) for its constant client-server communication. If, for whatever reason, this websocket connection gets dicsonnected, the user experience is the described "greying out". Fortunately GCP supports websockets.
However, it seems that your load balancer has an unexpected http time out value set.
Depending on what type of load balancer you are using (TCP, HTTPS) this can be configured differently. For their HTTPS offering:
The default value for the backend service timeout is 30 seconds. The full range of timeout values allowed is 1-2,147,483,647 seconds.
Consider increasing this timeout under any of these circumstances:
[...]
The connection is upgraded to a WebSocket.
Answer:
You should be able to increase the timeout for your backend service with the help of this support document.
Mind you, depending on your configuration there could be more proxies involved which might complicate things.
Alternatively you can try to prevent any timeout by adding a heartbeat mechanism to the Shiny application. Some ways of doing this have been discussed in this issue on GitHub.

Where to host SignalR when long-running service via WCF is backend

I'm sure that was a confusing enough title.
I have a long running Windows service dealing with things happening in the world. This service is my canonical source of truth for the rest of my system. Now I want to slap a web interface onto this so the clients can see what is actually going on. At first this would simply be a MVC5 application with some Web API stuff. Then I plan to use SignalR 2.0 and Ember.js to make this application more interactive and "realtime".
The client communicates with the Windows Service over named pipes using WCF. A client (such as a web app) could request an instance of for example IEventService, would be given a WCF proxy client, and could read about events through this interface. Simple enough.
However, a web application basically just exists in the sense that it responds to requests from the user. The way I understand it, this is not the optimal environment for a long lived WCF client proxy to raise events in, and thus I wonder how to host my SignalR stuff. Keep in mind that a user would log in to the MVC5 site, but through the magic of SignalR, they will keep interacting with the service without necessarily making further requests to the website.
The way I see it, there are two options:
1) Host SignalR stuff as part of the web app. Find a way to keep it "long-running" while it has active clients, so that it can react to events on the WCF client proxy by passing information out to the connected web users.
2) Host SignalR stuff as part of my Windows service. This is already long-running, but I know nada about OWIN and what this would mean for my project. Also the SignalR client will have to connect to a different port than where the web app was served from, I assume.
Any advice on which is the right direction to go in? Keep in mind that in extreme cases, a web user would log in when they get to work in the morning, and only have signalr traffic going back and forth (i.e. no web requests) for a full work day, before logging out. I need them to keep up with realtime events all that time.
Any takers? :)
The benefit of self-hosting as part of your Windows service is that you can integrate the calls to clients directly with your existing code and events. If you host the SignalR server separately, you'd have another layer of communication between your service and the SignalR server.
If you've already decided on using WCF named pipes for that, then it probably won't make a difference whether you self-host or host in IIS (as long as it's on the same machine). The SignalR server itself is always "long-running" in the sense that as long as a client is connected, it will receive updates. It doesn't require manual requests from the user.
In any case, you'll probably need a web server to serve the HTML, scripts and images.
Having clients connected for a day shouldn't be a problem either way, as far as I can see.

Resources