husseinnasser.
com
Introduction to NGINX
NGINX Web Server / Reverse Proxy
Agenda
● What is NGINX?
● Current & Desired Architecture
● Layer 4 and Layer 7 Proxying in NGINX
● TLS Termination vs TLS Passthrough
● Timeouts in NGINX
● Example
○ NGINX as a Web Server, Layer 7 and Layer 4 Proxy
○ Enable HTTPS, TLS 1.3 & HTTP/2 on NGINX
● Summary
What is NGINX?
What is NGINX?
● Web Server
○ Serves web content
● Reverse Proxy
○ Load Balancing
○ Backend Routing
○ Caching
○ API Gateway
Current vs Desired
Architecture
Current Architecture
GET /employees
JSON { }
GET /employees
JSON { }
GET /employees
JSON { } db:5432
http:3001
Desired Architecture
GET /employees
http:3001
JSON { }
GET /employees
JSON { }
GET /employees http:3002
NGINX
HTTPS:443 db:5432
JSON { }
h/2
Frontend Backend
http:3003
NGINX Layer 4 vs
Layer 7 proxying
Layer 4 and Layer 7
● Layer 4/7 refers to OSI model layers
● In Layer 4 we see TCP/IP stack only nothing about the app, we have access to
○ Source IP, Source Port
○ Destination IP, Destination Port
○ Simple packet inspection (SYN/TLS hello)
● In Layer 7 we see the application, HTTP/ gRPC etc..
○ We have access to more context
○ I know where the client is going, which page they are visiting
○ Require decryption
Layer 4 and Layer 7 proxying in NGINX
● NGINX can operate in Layer 7 (e.g. http) or Layer 4 (tcp)
● Layer 4 proxying is useful when NGINX doesn’t
understand the protocol (MySQL database protocol)
● Layer 7 proxying is useful when NGINX want to share
backend connections and cache results
● Using stream context it becomes a layer 4 proxy
● Using http context it becomes a layer 7 proxy
TLS Termination vs
TLS Passthrough
TLS
● TLS stands for Transport Layer Security
● It is a way to establish end-to-end encryption between one another
● Symmetric encryption is used for communication (client/server has the
same key)
● Asymmetric encryption is used initially to exchange the symmetric key
(diffie hellman)
● Server (sometimes even the client) need to authenticate themselves
by supplying a certificate signed by a certificate authority
TLS Termination
● NGINX has TLS (e.g. HTTPS) backend is not ( HTTP )
● NGINX terminates TLS and decrypts and send unencrypted.
● NGINX is TLS and backend is also TLS ( HTTPS )
● NGINX terminates TLS, decrypted, optionally rewrite and then
re-encrypt the content to the backend.
● NGINX NGINX can look at the L7 data, re-write headers, cache but
needs to share the backend certificate or at least has its own
TLS Passthrough
● Backend is TLS
● NGINX proxies/streams the packets directly to the backend.
● The TLS handshake is forwarded all the way to the backend.
● Just like a tunnel
● No caching, L4 check only, but more secure, NGINX doesn’t need
the backend certificate.
NGINX Timeouts
NGINX Timeouts
Frontend Timeouts Backend Timeouts
● client_header_timeout ● proxy_connect_timeout
● client_body_timeout ● proxy_send_timeout
● send_timeout ● proxy_read_timeout
● keepalive_timeout ● keepalive_timeout
● lingering_timeout ● proxy_next_upstream_timeout
● resolver_timeout
Frontend Timeouts
● client_header_timeout
NGINX Frontend ●
●
client_body_timeout
send_timeout
Timeouts ●
●
keepalive_timeout
lingering_timeout
● resolver_timeout
client_header_timeout
GET / HTTP/1.1
content-length:13
... > 60 s
Close connection
content-type:app/json
Defines a timeout for reading client request header. If a client does not transmit the entire header within this time, the request is terminated with the 408 (Request
Time-out) error. Default 60s
client_body_timeout
POST / HTTP/1.1
content-length:1M
content-type :text
body:this is a
A very large file..
... > 60 s
Close connection
I’m going to take time..
Defines a timeout for reading client request body. The timeout is set only for a period between two successive read operations, not for the transmission of the
whole request body. If a client does not transmit anything within this time, the request is terminated with the 408 (Request Time-out) error. Default 60s
P/1.1
send_timeout /H T T
GET nt-length xt
:13
e te
cont nt-type :
e
GET / HTTP/1.1 cont .
content-length:13
r y v ery..
e
content-type :text is the v
Here e t h at...
r e s pons
Here is the very very... large
Large response that.
ile..
... > 60 s k e a wh
tt a
Migh
Close connection
Sets a timeout for transmitting a response to the client. The timeout is set only between two successive write operations, not for the transmission of the whole
response. If the client does not receive anything within this time, the connection is closed. (Default 60s)
keepalive_timeout
GET / HTTP/1.1
Connection: keep-alive
... > 75 s
Close connection
The first parameter sets a timeout during which a keep-alive client connection will stay open on the server side. The zero value disables keep-alive client connections.
The optional second parameter sets a value in the “Keep-Alive: timeout=time” response header field. Two parameters may differ. (default 75 seconds)
lingering_timeout
Close connection
GET /
... > 60 s
Physical close FIN
When lingering_close is in effect, this directive specifies the maximum waiting time for more client data to arrive. If data are not received during this time, the
connection is closed. Otherwise, the data are read and ignored, and nginx starts waiting for more data again. The “wait-read-ignore” cycle is repeated, but no longer
than specified by the lingering_time directive.
resolver_timeout
GET / HTTP/1.1
Connection: keep-alive What is the IP of
server1.test.com?
server1.test.com
... > 30 s
Sets a timeout for name resolution, 30 seconds
Backend Timeouts
● proxy_connect_timeout
NGINX Backend ●
●
proxy_send_timeout
proxy_read_timeout
Timeouts ●
●
keepalive_timeout
proxy_next_upstream_timeout
proxy_connect_timeout
Connecting to server1.test.com
... > 60 s
server1.test.com
Defines a timeout for establishing a connection with a proxied server. It should be noted that this timeout cannot usually exceed 75 seconds.
proxy_send_timeout
POST / HTTP/1.1
POST / HTTP/1.1
content-length:1M
content-length:1M
content-type :text
content-type :text
body:this is a
body:this is a
A very large file..
A very large file..
server1.test.com
... > 60 s
I’m going to take time.. Close connection
Note (body_timeout may trigger before) so we don’t
even bother the backend..
Sets a timeout for transmitting a request to the proxied server. The timeout is set only between two successive write operations, not for the transmission of the whole
request. If the proxied server does not receive anything within this time, the connection is closed.
proxy_read_timeout GET / HTTP/1.1
content-length:13
GET / HTTP/1.1 content-type :text
content-length:13
content-type :text Here is the very very...
Here is the very very... large response that...
Large response that.
... > 60 s
... Close connection
Might take a while..
Note (send_timeout may trigger before or after)
Defines a timeout for reading a response from the proxied server. The timeout is set only between two successive read operations, not for the transmission of the
whole response. If the proxied server does not transmit anything within this time, the connection is closed.
proxy_next_upstream_timeout
/
GET
GET /
GET /
When to stop?
GET
/
>6
0s
Limits the time during which a request can be passed to the next server. The 0 value turns off this limitation. Default 0
Keepalive_timeout (Backend)
Connect
idle.. > 60 s
Close connection
Sets a timeout during which an idle keepalive connection to an upstream server will stay open.
Example
● Install NGINX (mac)
● NGINX as a Web Server
● NGINX as a Layer 7 Proxy
○ Proxy to 4 backend NodeJS services (docker)
○ Split load to multiple backends (app1/app2)
○ Block certain requests (/admin)
● NGINX as a Layer 4 Proxy
● Enable HTTPS on NGINX (lets encrypt)
● Enable TLS 1.3 on NGINX
● Enable HTTP/2 on NGINX
Summary
● What is NGINX?
● Current & Desired Architecture
● Layer 4 and Layer 7 Proxying in NGINX
● TLS Termination vs TLS Passthrough
● Timeouts in NGINX
● Example
○ NGINX as a Web Server, Layer 7 Proxy & Layer 4 Proxy
○ Enable HTTPS, TLS 1.3 & HTTP/2 on NGINX
● Summary