Proxy bandwidth to / from backend server - nginx

I am using NGINX with the OpenResty framework.
I have a server acting as a reverse proxy between users and multiple sites. I am interested in logging 4 different types of bandwidth use.
Bytes from users to proxy
Bytes from proxy to users
Bytes from proxy to site server
Bytes from site server to proxy
Currently I have access to the NGINX variables $bytes_sent and $bytes_received that are trivially provided on the http://nginx.org/en/docs/stream/ngx_stream_core_module.html documentation page. I believe these only provide half the story I am interested in.
What is not made clear is how these variables interact when measured in conjunction with proxy_pass http://$site_ip:$site_port$request_uri;
Is there some way I can calculate the 4 cases of bandwidth I am interested in without modification to NGINX? I am able to use computational solutions if such a thing could be written via the lua hooks provided by OpenResty.
Thanks!

Related

Docker, nginx and several sites on one server

I have server with nginx and one working app. I want to add several apps to this servers. I would like to assimilate a few things for myself.
What is the difference between load balancer and reverse proxy?
In which situations should I use the first, and in which situations should I use the second?
What should I use if my sites are static, and what if not static?
And additionally it would be a big plus to hear about containers in the context of several sites for nginx
Differences between load balancer and reverse proxy
A reverse proxy accepts a request from a client, forwards it to a server that can fulfill it, and returns the server’s response to the client.
A load balancer distributes incoming client requests among a group of servers, in each case returning the response from the selected server to the appropriate client.
Taken from nginx docs
TL;DR :
Reverse proxying is about : routing requests to the correct server using the domain name
Load balancing is about : distributing load to multiple instances
What should I use if my sites are static, and what if not static?
You can combine an HTTP reverse proxy + load balancing with both static and non static web apps, so it depends.
And additionally it would be a big plus to hear about containers in the context of several sites for nginx
I recommend one nginx container per app / site + a dynamic reverse proxy, traefik in particular (http://traefik.io)
You need a reverse proxy to route the incoming traffic to the proper application taking into account the content of the original request (and rules that you may define).
When the target application(s) is determined, you will need to load balance them in order to distribute the amount of work across them.
Both tasks can be done by software like classic nginx, apache, haproxy, etc or by those that are designed for the microservices world, like fabio, traefik and others.

How to Eliminate Nginx from the Production Stack via using Cloudflare as a substitutable Reverse Proxy?

Is it possible to use "cloudflare" as a reverse proxy for hosting several websites on the same host machine but on different ports?
Cloudflare can replace some of the features of Nginx, specifically:
Caching resources
Rate limiting and protecting your website
Redirecting access to your website to another server
But you still need Nginx or another web server for the following tasks:
Handling the TCP connections between Cloudflare and the server which generates the response (+ HTTPS should be used)
Generating the actual response, via FastCGI (PHP, Python, Ruby, etc.) or just delivering a file/resource (server and location blocks in Nginx)
Setting the correct headers for the response, for caching and content type (Cloudflare relies on these)
Cloudflare does not support sending your requests to specific ports on the origin host - but that would still not help you much, because Cloudflare has a very specific feature set, and generating responses is not part of them, which is why you need a web server.
If you want to reduce the work needed to maintain Nginx, you can restrict Nginx to only reply to requests by Cloudflare and do the rate limiting and some other tasks in Cloudflare.

Nginx - Allow requests from IP range with no header set

I'm trying to use nginx behind a Compute Engine http load balancer. I would like to allow Health Check requests to come through a port unauthorized and all other requests to be authorized with basic auth.
The Health Check requests come from IP block: 130.211.0.0/22. If I see requests coming from this IP block with no X-forwarded-for header, then it is a health check from the load balancer.
I'm confused on how to set this up with nginx.
Have you tried using Nginx header modules? Googling around I found these:
HttpHeadersMoreModule
Headers
There's also a similar question here.
Alternative. In the past I worked with a software (RT), which had thought of this possibility in the software itself, providing a subdirectory for unauthorized access (/noauth/). Maybe your software might have the same, and you could configure GCE health check to point to something like /noauth/mycheck.html.
Please remember that headers can be easily forged, so an attacker who knows your vulnerability could access your server without auth.

Assign IPs to programs/processes

I need to assign different IP addresses to different processes (mostly PHP & Ruby programs) running on my Linux server. They will be making queries to various servers, including the situation where processes connecting to the same external server should have different IPs.
How this can be achieved?
Any option (system wide, or PHP/Ruby-specific, using proxy servers etc) will suit me.
The processes bind sockets (both incoming and outgoing) to an interface (or multiple interfaces), addressable by IP address, with various ports. In order to have them directly addressable by different IP addresses, you must have them bind their sockets to different NICs (virtual or hardware).
You could point each process to a proxy (configure the hostname of the server to be queried to be a different proxy for each process), in which case the external server will see the different IPs of the proxies. Otherwise, if you could directly configure the processes to use different NICs for their communications, that would be ideal.
You may need to make changes to the code to make this configurable (very often, programmers create outgoing TCP connections with convenience functions without specifying the NIC they will use, as they typically don't care). In PHP, you can use "socket_bind" to bind the endpoint to a nic, e.g. see the first example in the docs for socket_bind.
As per #LeonardoRick request, I'm providing the details for the solution that I ended up with.
Say, I have a server with 172.16.0.1 and 172.16.0.2 IP addresses.
I set up nginx (on the same machine) with the configuration that was looking somewhat like this:
server {
# NEVER EXPOSE THIS SERVER TO THE INTERNET, MAKE SURE PORT 10024 is not available from outside
listen 127.0.0.1:10024;
# block access from outside on nginx level as well
allow 127.0.0.1;
deny all;
# actual proxy rules
location ~* ^/from-172-16-0-1/http(s?)\:\/\/(.*) {
proxy_bind 172.16.0.1;
proxy_pass http$1://$2?$args;
}
location ~* ^/from-172-16-0-2/http(s?)\:\/\/(.*) {
proxy_bind 172.16.0.2;
proxy_pass http$1://$2?$args;
}
}
(Actually I cannot remember all the details now (this code is 'from whiteboard', it's not an actual working one), nevertheless it should represent all the key ideas. Check regexes before deployment).
Double-check that port 10024 is firewalled and not accessible from outside, add extra authentication if necessary. Especially if you are running Docker.
This nginx setup makes it possible to run HTTP requests likehttp://127.0.0.1:10024/from-172-16-0-2/https://example.com/some-URN/object?argument1=something
Once received a request, nginx will fetch the HTTP response from the requested URL using the IP specified by the corresponding proxy_bind directive.
Then - as I was running in-house or open-source software - I simply configured it (or altered its code) so it would perform requests like the one above instead of (original) https://example.com/some-URN/object?argument1=something.
All the management - what IP should be used at the moment - was also done by 'my' software, it simply selected the necessary /from-172-16-0-XXX/ endpoint according to its business logic.
That worked very well for my original question/task. However, this may not be suitable for some other applications, where it could not be possible to alter the request URLs. However, a similar approach with setting some kind of proxy may work for those cases.
(If you are not familiar with nginx, there are some starting guides here and here)

How can I use Lift asychronously with Nginx?

I want to use Nginx as a frontend redirecting requests to Lift application.
In this post
http://scala-programming-language.1934581.n4.nabble.com/Simple-deployment-of-Lift-apps-on-Jetty-Nginx-td1980295.html
David Polak recommends to use nginx as a reverse proxy. But in book "Nginx HTTP Server by Nedelcu C", I read this:"...the reverse proxy mechanism that we are going to describe
in this chapter is not the optimal solution. It should be employed in problematic
cases..." and FastCGI is described as the best choice.
Next option I see is to use Lift with Netty as here: https://github.com/jrwest/lift-and-netty-examples but it seems it just an expirement for now.
Maybe I am missing something?
I am a big fan of Nginx (make sure of that looking at my SO/SF profiles) and my opinion is that Nginx is a perfect fit for many-many uses.
Nginx can be used as a frontend to Lift application via HTTP transport (i.e. proxy_pass directive in Nginx), just like Nginx is used to proxy to Apache, Jetty, Tomcat or any other backend server talking HTTP. fastcgi_pass is designed to proxy to FastCGI backends. I did not see any benchmarks on which transport implementation is more effective, but I guess this difference will be smaller than differences implied by programming language/app server technologies.
One more note. I have no idea how FastCGI transport can be used to implement Comet applications. At the same time, Liftweb's Comet applications work perfectly via Nginx.

Resources