Tuesday, June 19, 2018

Nginx Reverse Proxy


Introduction
------------

- proxy server servers content in behalf of another server
- proxy servers are used to hide the identity of other servers
- a proxied request means that the client request was redirected to a backend
  server
- when nginx proxies a request, it sends it to the proxied server, fetches the
  response, and sends the response back to the client
- examples of proxied servers are:
    a. another Nginx server
    b. any kind of HTTP server
    c. a non-HTTP server w/c can run applications built on python, php, etc..
- nginx proxies request using any specified protocol like:
    a. FastCGI
    b. uwsgi
    c. SCGI
    d. memcached
- a proxied server is also known as backend/upstream server
- common use of reverse proxy is to provide load balancing
- a proxied request has a "Via" header field

Ways of proxying requests
-------------------------

Simple way of passing a request
to an HTTP proxied server
server {
  listen 80;
  server_name proxy.example.com;

  location /backend/ {
    proxy_pass http://backend.example.com/;
      # this will proxy the request by re-writing the url
      # from:
      # to:
    ...
  }

  location /proxy2 {
    proxy_pass http://proxy2.example.com/;
      # this version is valid
  }


  location ~ /proxy3/? {
    proxy_pass http://proxy3.example.com/;
      # this version is also valid
  }


  location /proxy4 {
    proxy_pass http://proxy4.example.com;
      # this doesn't work correctly
      # in my testing (nginx/1.10.2)
  }
}
If using a regex to specify
location, appending `/` or
`/any/path` at the end of the
proxied host is not allowed

related error:
"proxy_pass" cannot have URI part
in location given by regular
expression
location ~ /notes/? {
    proxy_pass http://www.example.com;
}
A proxied server can also be set
as an IP:PORT combination
location ~ \.php {
    proxy_pass http://127.0.0.1:8000;
      # I'm encoutering "failed (13: Permission denied)
      # while connecting to upstream" on this (nginx/1.10.2)
}

location /notes/ {
      # I'm encoutering "failed (13: Permission denied)
      # while connecting to upstream" on this (nginx/1.10.2)
}

Protocols for proxying a request
--------------------------------

fastcgi_pass   -- passes a request to a FastCGI server
uwsgi_pass     -- passes a request to a uwsgi server
scgi_pass      -- passes a request to an SCGI server
memcached_pass -- passes a request to a memcached server

Passing request Headers
-----------------------

- by default, nginx redefines 2 headers: "Host" and "Connection"
- nginx eliminate empty header fields
- "Host" is set to $proxy_host
- "Connection" is set to "close"

Example of HTTP headers:


To redefine value for a header
location /some/path/ {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass http://localhost:8000;
}
To prevent a header from being
passed to the proxied server,
set it to empty string
location /some/path/ {
    proxy_set_header Accept-Encoding "";
    proxy_pass http://localhost:8000;
}

Buffering
---------

- by default, a response from proxied servers is put into internal buffers and
  is not sent to client until the whole response is received
- this allows the proxied server to process response quickly
- `proxy_buffering` is set to on by default
- `proxy_buffers` sets the size and number of buffers allocated per request
- `proxy_buffer_size` controls the size of the 1st part of the response from
   the proxied server which usually contains smaller response header compared
   to the rest of the response
- if buffering is disabled, the response from the proxied server is sent
  synchronously to client while being received by the proxy server (this
  behaviour is desirable for clients who needs to get response as soon as
  possible)

Size of the buffer for the first
part is set smaller (2k) compared
to the size of buffers for the
rest of the response (4k)
location /some/path/ {
    proxy_buffers 16 4k;
    proxy_buffer_size 2k;
    proxy_pass http://localhost:8000;
}
Disables buffering on a specific
location
location /some/path/ {
    proxy_buffering off;
    proxy_pass http://localhost:8000;
}

Choosing an outgoing address
----------------------------

- if a proxy server has multiple IPs, you can choose an IP for connecting to the
  proxied server by using `proxy_bind` directive
- useful if the proxied server can only accept connections from an IP range

Sets different IPs in connecting
to proxied server
location /app1/ {
    proxy_bind 127.0.0.1;
    proxy_pass http://example.com/app1/;
}

location /app2/ {
    proxy_bind 127.0.0.2;
    proxy_pass http://example.com/app2/;
}
IP address can also be a variable
location /app3/ {
    proxy_bind $server_addr;
    proxy_pass http://example.com/app3/;
}

No comments:

Post a Comment