Nginx

**HTTP protocol**

* ***partial GET Request*-** GET /documentary.mp4 HTTP/1.1 Host:example.com Range:0-1024

GET /documentary.mp4  I Want to watch only first 20 second of the documentary.mp4 -->

<--- HTTP/1.1 206 Partial Content . Here is first 20 second worth of data

```
        curl -I example.com/partial.txt

        curl --header "Range: bytes=10-20" example.com/partial.txt

```

* ***conditional GET Request**   -* GET /sanple.html HTTP 1.1 Host:example.com If-Modified-Since, 29 Oct 2015 19:43:31 GMT. If is not modified it responds with code 205 not modified

```
 curl -I --header "If-Modified-SInce: Sat, 05 Dec 2015 09:49:22 GMT" example.com/partial.txt

```

* ***HTTP - POST   -**Used* to send some data to the server to be processed in some way.

```
​ Example: POST/login.php HTTP/1.1
 Content-Type: application/x-www-form-urlencoded
 Content-Lenght: 32
 user=admin password=test123

```

* **HTTP-HEAD -**

**Below are HEADER FIELDS from HTTP request**

```
**​** HTTP/1.0 200 OK
        DATE: Fri, 31 Dec 2015 23:59:59 GMT
        Content-Type: text/html
        Content-Lenght:1354
        Cache-Control: public

```

**Below is message body**

```
<html>

<body>

Happy New Millenium!

(more file content)

</body>

</html>

```

**HEAD - Identical to GET request execpt Server should not return message-body in response**

**curl -I example.com**

**Used to find a lot of information about a particular file without downloading it.**

1. Last modified Date
2. Content Lenght, Content type
3. Cache Timings associated with it

* **HTTP TRACE -**

Curl -X "Trace" example.com

* **HTTP -OPTIONS**

​          curl -X OPTIONS http://example.com/login.html -i

Some files like mp3 allow for GET,HEAD and some login.php allow also for POST

* **HTTP Response status Code:**

1. **100-199 - Informational status**
2. **200-299 - Success Status codes**

```
    Indicates that action received by client is: Received, Understood, Accepted, Processed
    For example: 200 OK

```

**3.  300-399 - Redirection Status codes**

```
    Indicates that client must take additional steps to complete the requests. Many of them are used in URL redirection. For example : 301 Moved Permamently, 304 Not Modified

```

**4. 400-499  Client Error Status codes**

```
     Indicates that client seemed to have sent some errored request.

     Example: 401-Unauthorized, 403: Forbidden, 404 - Page Not Found

```

**5. 500-599  Server Error Status codes**

```
     Server failed to fulfill a valid client request.

     Example: 500 - internal server error

```

Nginx

* Is an open source reverse proxy server for HTTP,HTTPS,SMTP,POP3 and IMAP protocol as well as load balancer, HTTP cache and a web server.
* Nginx uses asynchronous event-driver handler for requests. This allows nginx to more accurately provide predictable performance under very high load

Features:

* Handles static files, index files and auto-indexing
* Reverse proxy with caching abilities
* Load balancing of nodes
* Support fault tolerance
* Open SSL support for certficates
* FastCGI, PHP-FPM and SCGI support
* Fully IPv6 compatibile
* Websockets and HTTP/1.1
* Live stream file compression
* URL redirects and rewriting
* Bandwidth throttling
* Geolocations of Ips
* Very low memory footprint - more than 10k concurrent connections with only ~2.5 mb of memory fo keep-alive sessions

	+ include /etc/nginx/vhost.d/\*.conf;
* mkdir -p /var/www/html
* vim /etc/nginx/vhost.d/default

server {

```
 listen 80 default\_server;
 server\_name \_;
 }
location / {
root /var/www/html;
 index index.html index.htm; }

```

* echo "NEW configuration" >> /var/www/html/index.html
* nginx -t to check configuration
* example of new vhost :
	+ mkdir -p /var/www/html/myexample
	+ echo "www.myexample.local >> /var/www/html/myexample/index.html'
	+ echo "private IP www.myexample.local myexample >> /etc/hosts
	+ vim /etc/nginx/vhost.d/www.myexample.local

server {

```
 listen 80;
 root /var/www/html/myexample;
 index index.html index.htm index.php;
 server\_name www.myexample.local myexample;
 }

```

* nginx -t
* systemctl reload nginx
* lynx http://myexample.local

**Location block**

* location ~/greet[0-9] { return 200 'Hello from NGINX case sensitive regex match location block' };
* location \*~/greet[0-9] { return 200 'Hello from NGINX case insensitive regex match location block' }
* location ^~/greet { return 200 'Hello from Nginx match with preference over regex location block!' ;
* Matching order :

1. ​ = Exact match
2. ^~ Preferential Prefix - same as standard match but more important than regex
3. ~&\*~ Regex match
4. no modifier Prefix Match no modifier

**Nginx as reverse proxy, what can do:**

* It hides existence of the orgin backend servers
* Can protect the server from web-based attacks,DOS
* Can provide great Caching functionality
* can optimize content by compressing it
* can act as SSL terminating proxy
* request routing

**Understanding proxy\_pass directive**

* Forwards the request to the proxied serves specified along with this directive
* location / { proxy pass http://192.168.10.50;}
* location /admin { proxy\_pass http:192.168.10.50; }
* location /app { proxy\_pass http://192.168.10.100/application;}

**Need for X-REAL-IP**

* If we request to server1 which is reverse proxy to backed server2 , the backed server only sees that server1 is requesting connection not computer client
* proxy\_set\_header X-Real IP $remote\_addr; after proxy\_pass!
* a in log format we can add "$http\_x\_real\_ip"

**Proxy Host header**

* Client sends request to the nginx reverse proxy as GET/index.html GET/HTTP 1.1 host kp.in
* Nginx reverse proxy remove additional header host kp.in and sends only to backend GET/HTTP 1.1
* This is not problem since backend server serves only one site
* to resolve that add proxy\_set\_header Host $host;

**Example of using upstream module**

* **vim**/etc/nginx/vhost.d/www.mynode.local

upstream mynode {

```
 server localhost:8888;}
 server {
 server\_name www.mynode.local mynode;
 }

 location / {
 proxy\_pass http://mynode;
 }

```

* echo "private IP www.mynode.local mynode >> /etc/hosts
* yum install npm node-js
* mkdir -p /var/www/html/mynode
* touch myserver.js and paste to it code from : https://gist.github.com/ryanflorence/701407
* nodejs myserver.js &
* nginx -t
* systemctl reload nginx
* echo " this is our nodejs html file" >> /var/www/html/nodejs/index.html
* first check with lynx http://localhost:8888
* turn off selinux for while when you have error 502

**Basic load balancing**

* **cp ​**/var/www/html/mynode/myserver.js to myserver2.js
* **cp ​**/var/www/html/mynode/index.html to index2.html
* edit myserver2.js to support 8889 port and index2.html file
* run new server2
* edit /etc/nginx/vhost.d/www.mynode.local. In normal version it would be round robin but we can add weight so server2 will be 4 times more used.
* if we add after ip address directive down; it means that that server won't be used, server 192.169.122.32 down;

upstream mynode {

```
server localhost:8888 weight=1;
 server localhost:8889 weight=4;
}
server { listen 80; server\_name example.com;
}

location / {
proxy\_pass http://mynode;
}

```

**Active health monitoring nginx plus**  - every 5 seconds by default, by defult check uri is /

```
                  location /  { proxy_pass http://backend;

 health\_check interval=10 fails=3 passes=2; uri=/test.txt
match=server\_test; } }

 match server\_test {

 status 200-399;

 body !~maintenence;

 or if body ~ Welcome to nginx

 zone server\_test 64k; --shared memory that worker process will be using

 }

```

* sends interval by two consecutive health check to 10 sec, if fails 3 times, serves is treated as down, after passes two checks server will be considered healthy, uri to check is /test.txt and if in body is not maintence, the server is up and running
* match means if body in /test.txt we find maintence  and status is 200-399 , the server is considered dead
* or if body ~ Welcome to nginx in /test.txt and status is 200-399 , server is considered health

**Passive health monitoring - support in free version**

* max\_fails parameter sets the number of failed attempts that should happen during the specified time to still consider the server unavailable.
* fail\_timeout parameter sets the time during which the specified number of failed attempts should happen and still consider the server unavailable. In other words, the server is unavailable for the interval set by fail\_timeout. So if max\_fails=3 and fail\_timeout=50, server waits 50 sec to check again.
* upstream backend {

```
server 52.4.121.83 max\_fails=3 fail\_timeout=50;
server 52.4.121.82; } bad is that client can wait some more time to request, because first request will be go to bad server, a the next to the good one

```

**Least conn**

* Specifies that a group should use a load balancing method where a request is passed to the server with the least number of active connections, taking into account weights of servers. If there are several such servers, they are tried in turn using a weighted round-robin balancing method.
* upstream backend {

```
 least\_conn;
 server 52.4.121.83 max\_fails=3 fail\_timeout=50;
 server 52.4.121.82; }

```

**Cache**

* **Cache-Control Headers:**

1. max-age=[seconds] — specifies the maximum amount of time that a representation will be considered fresh. Similar to Expires, this directive is relative to the time of the request, rather than absolute. [seconds] is the number of seconds from the time of the request you wish the representation to be fresh for.
2. s-maxage=[seconds] — similar to max-age, except that it only applies to shared (e.g., proxy) caches.
3. public — marks authenticated responses as cacheable; normally, if HTTP authentication is required, responses are automatically private.
4. private — allows caches that are specific to one user (e.g., in a browser) to store the response; shared caches (e.g., in a proxy) may not.
5. no-cache — forces caches to submit the request to the origin server for validation before releasing a cached copy, every time. This is useful to assure that authentication is respected (in combination with public), or to maintain rigid freshness, without sacrificing all of the benefits of caching.
6. no-store — instructs caches not to keep a copy of the representation under any conditions.
7. must-revalidate — tells caches that they must obey any freshness information you give them about a representation. HTTP allows caches to serve stale representations under special conditions; by specifying this header, you’re telling the cache that you want it to strictly follow your rules.
8. proxy-revalidate — similar to must-revalidate, except that it only applies to proxy caches.

location !\.(png) {

root /var/www/website/example;

expires 1h;

add-header Cache-Control max-age=120;

} it means that in the header will be Cache-Control: max-age=3600 and Expires date

```
location !\.(png) {
 root /var/www/website/example;

add_header Cache-Control max-age=120;  it means that it will be cache for 120s , in the private cache

 **add\_header Cache-Control no-store; -means that it no be cached- only in memory**

 **add\_header Cache-Control s-maxage=200; -** it will be cached on intermediate servers(public) for 200s

 **add\_header Cache-Control no-cache; - it means that download fresh, no-cache means that it will be in cache, but it must be revalidate query to back to the server,**

 **add\_header Pragma no-cache;**

 **add\_header Cache-Control must-revalidate;**

**expires -1; -** means that it will be no-cache

}  - ,check in about:cache,no cache  must-revalidate means Cache should must be revalidate every time for document freshness

```

it means that download fresh, no-cache means that it will be in cache, but it must be revalidate query to back to the server**(public cache)**

**Access Control**

```
 **location /downloads/ {**
      root /var/www/html/example;

 **index index.html;**

 **allow 10.4.4.4;**

 **allow 192.168.10.0/24;**

 **deny all;**

}

```

* **limit connection module**

```
**​** location /downloads {

                /var/www/websites/example;

                limit_rate 50k;  }

```

This below allows for only one connection at time from 1 IP

```
limit_conn_zone $binary_remote_addr zone=addr:10m;

server {
    location /download/ {
        limit_conn addr 1;
    }

```

* **Basic authentication**

**​        yum install httpd-tools**

**htpasswd -c /etc/nginx/.htpasswd fgtuser**

```
 **location /downloads {**

 **auth\_basic " Basic authentication ";**

 **auth\_basic\_user\_file "/etc/nginx/.htpasswd";**
 **}**

```

* **GeoIP**

```
 **http {**

 **geoip\_country /usr/share/GeoIP/GeoIP.dat;**

 **map "$host:$geoip country\_code" $deny\_by country {**

 **-^example.com:(?!PL) 1; -if is not from Poland , this mean that is forbidden**

 **default 0;**

 **}**

 **server {**

 **server\_name example.com;**

 **listen 80;**

 **if ($deny\_by\_country) { return 403; }**

 **location / {**

 **root /var/www/websites/example;**

 **}**

 **}**

 **iso3166 country code**

```

**SSL cerficate management**

```
::::* mkdir /etc/nginx/ssl

```

* cd ssl
* openssl genrsa -des3 -out server.key 1024
* openssl req -new -key server.key -out server.csr
* cp server.key server.key.org
* openssl rsa -in server.key.org -out server.key
* openssl x509 -req -days 365 -i server.csr -signkey server.key -out server.crt
* vim /etc/nginx/vhost.d/www.myexample.local  and add:

server {

listen 443;

root /var/www/html/myexample;

index index.html index.htm index.php;

server\_name www.myexample.local myexample;

ssl on;

ssl\_certificate /etc/nginx/ssl/server.crt;

ssl\_certificate\_key /etc/nginx/ssl/server.key;

}

* systemctl reload nginx
* lynx https://www.myexample.local