...
Il est possible d'avoir des location nested, mais le proxy_pass n'est pas hérité, il faut donc le répéter. Si ajout d'un add_header, ceux des niveaux supérieures sont ignorés.
Il est possible d'utiliser if à la place, notamment pour faire des add_header. nginx vous dira si une directive est autorisé dans un if. C'est aussi indiqué dans la documentation.
...
Par défaut seul le contenu text/html est compressé. Il est conseillé d'ajouter des gzip_types comme fait par défaut sur les apache sous debian.
Il faut aussi s'assurer que gzip on est activé (c'est le cas sur debian, mais pas sur CentOS)
headers avec des "_"
Par défaut, les headers avec des "_" sont bloqués. Pour les autoriser, utiliser underscores_in_headers.
(exemple : nécessaire si l'on veut autoriser "REMOTE_USER")
WebSocket
Il faut s'assurer de passer les headers "Upgrade" et "Connection" de la 1ère requête WebSocket (le handshake).
Nginx va ensuite détecter la réponse d'Upgrade vers WebSocket et établir un tunnel.
Tout est clairement documenté upstream : https://nginx.org/en/docs/http/websocket.html
Monitoring
Par défaut le monitoring nginx est très limité : module stub_status. Ce module est utilisé par /usr/local/bin/monitor-nginx .
...
Limitation de la taille d'upload
Par défaut Apache limite très peu la taille d'upload à 1G (cf LimitRequestBody), laissant le soin aux scripts de limiter.
...
| Bloc de code | ||
|---|---|---|
| ||
client_max_body_size 150M1G; |
Cache
Attention à proxy_cache_key :
...
proxy_cache_key $scheme://$host$request_uri;
Par défaut un Pour faire fonctionner le force-reload ne fonctionne pas avec nginx (?). Solution :
proxy_cache_bypass $http_pragma;
Pour forcer une mise en cache d'un contenu, il faut comprendre ce qu'effectue nginx :
- interrogation du cache avec "proxy_cache_key", en vérifiant les contraintes sur les request headers (voir plus loin)
- si cache trouvé et si évaluation de "proxy_no_cache" répond faux
- utilisation du cache
- sinon
- requesting upstream après effectué "proxy_set_header"
- si réponse n'a pas "Set-Cookie" ou si ignoré par "proxy_ignore_headers"
et si réponse a X-Accel-Expires/Cache-Control/Expires et non ignoré par "proxy_ignore_headers"
ou si "proxy_cache_valid" l'autorise- si response headers contient "Vary" et non ignoré par "proxy_ignore_headers"
- si "Vary: *" ou Vary trop long (plus de 128 chars)
- pas de mise en cache
- sinon mise en cache avec contrainte sur les request headers listé dans "Vary"
- si "Vary: *" ou Vary trop long (plus de 128 chars)
- sinon mise en cache sans contrainte
- si response headers contient "Vary" et non ignoré par "proxy_ignore_headers"
- sinon pas de mise en cache
- dans tous les cas, effectuer "proxy_hide_header" et "add_header"
PS : la durée de mise en cache est définie par X-Accel-Expires/Cache-Control/Expires/proxy_cache_valid (avec cet ordre de priorité)
Buffering
Par défaut nginx bufferise les requêtes et les réponses. Cela peut nécessiter de la place disque.
...
Par défaut, nginx n'a pas de cache de TLS session tickets. Il faut l'activer avec ssl_session_cache.
POST on static pages
nginx autorise uniquement la méthode GET sur les pages statiques.
Solution possible : "error_page 405 =200 $uri;"
Techniques de proxification
Modifier un response header
- Pour forcer une valeur :
proxy_hide_header Content-Security-Policy;
add_header Content-Security-Policy "xxx";
- Pour ajouter une valeur
proxy_hide_header Content-Security-Policy;
add_header Content-Security-Policy "$upstream_http_content_security_policy; xxx";
- Pour modifier une valeur
# NB: doit être fait en scope global ("http")
map $upstream_http_content_security_policy $content_security_policy_allow_bandeau {
'~(.*); script-src (.*)' "$1; script-src ent.univ.fr $2";
'~(.*)' "$1; script-src ent.univ.fr";
}
proxy_hide_header Content-Security-Policy;
add_header Content-Security-Policy $content_security_policy_allow_bandeau;
Proxifier un backend avec SNI
| Bloc de code |
|---|
proxy_pass https://foo.bar;
proxy_ssl_verify on;
proxy_ssl_verify_depth 1;
# le SNI est utilisé par le backend
proxy_ssl_name xxx.univ.fr;
proxy_ssl_server_name on; |
Mais attention si on a besoin d'un deuxième SNI vers le même serveur backend, exemple :
| Bloc de code |
|---|
proxy_pass https://foo.bar;
proxy_ssl_name xxx2.univ.fr; |
=> cela ne fonctionnera pas à cause "proxy_ssl_session_reuse".
Une solution est "proxy_ssl_session_reuse off".
Une autre solution est d'utilisateur un upstream :
| Bloc de code |
|---|
# NB: pour proxy_pass https://xxx.univ.fr, il semble que nginx utilise "xxx.univ.fr" comme clé pour la fonctionnalité proxy_ssl_session_reuse
# En utilisant un upstream, on peut forcer une clé différente pour un même backend
upstream upstream_xxx2 {
server foo.bar:443;
}
server {
...
proxy_pass https://upstream_xxx2;
proxy_ssl_name xxx2.univ.fr;
} |
Sticky sessions avec nginx open source
| Bloc de code |
|---|
upstream prefer_server1 {
server server1:8080;
server server2:8080 backup;
}
upstream prefer_server2 {
server server1:8080 backup;
server server2:8080;
}
...
set $prefered_backend server2;
if ($cookie_JSESSIONID ~ "[.](server1|server2)$") { set $prefered_backend $1; }
proxy_pass http://prefer_$prefered_backend;
include proxy_params; |
Envoyer une requête à tous les backends
Si vous utilisez l'affinité de session pour choisir le backend, deux pbs peuvent se poser :
- CAS Single Logout back-channel : le serveur CAS fait une requête directement au serveur, sans passer par le navigateur. Il n'envoie donc pas de cookie de session qui permettrait de savoir quel backend choisir
- proxy CAS : le serveur CAS envoie le PGT directement à l'application, sans passer par le navigateur. Il est souvent possible de configurer l'application pour fournir à CAS une URL directe, ne passant pas par le balancer.
| Bloc de code |
|---|
upstream prefer_server1 {
server server1:8080;
server server2:8080 backup;
}
upstream prefer_server2 {
server server1:8080 backup;
server server2:8080;
}
server {
...
set $prefered_backend server3;
set $fallback_backend server2;
...
error_page 418 = @broadcast;
set $need_broadcast 0;
if ($remote_addr = 192.1.2.3) { set $need_broadcast 1; }
if ($need_broadcast) { return 418; }
...
location @broadcast {
mirror /@mirror_to_fallback;
mirror_request_body on; # for CAS back-channel Single-Logout
proxy_pass http://${prefered_backend}.univ.fr:8080;
include proxy_params;
}
location /@mirror_to_fallback {
proxy_pass http://${fallback_backend}.univ.fr:8080$request_uri;
include proxy_params;
proxy_set_header User-Agent "Duplicated-$http_user_agent";
}
} |
Shibboleth-SP
Shibboleth-SP fournit un FastCGI authorizer. Nginx ne gère pas cela en standard.
...