De Wiki inetshell
Saltar a: navegación, buscar

NGINX PHP-FPM Chroot

https://gist.github.com/corburn/9ad9d07535d59b478159

Adjusting child processes for PHP-FPM (Nginx)

Permitir underscore/guion bajo en headers

https://stackoverflow.com/questions/19751313/forward-request-headers-from-nginx-proxy-server

https://stackoverflow.com/questions/22856136/why-underscores-are-forbidden-in-http-header-names

https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/?highlight=disappearing%20http%20headers#missing-disappearing-http-headers

underscores_in_headers on;

Permitir muchos server_name

https://nginx.org/en/docs/http/server_names.html

https://nginx.org/en/docs/hash.html

Al utilizar muchos server_name, puede llegar a aparecer cualquiera de estos dos errores:

could not build the server_names_hash,
you should increase server_names_hash_bucket_size: 32


could not build the server_names_hash,
you should increase either server_names_hash_max_size: 512
or server_names_hash_bucket_size: 32

Esto se resuelve aumentando el tamaño de la tabla de hash:

server_names_hash_bucket_size 128;
server_names_hash_max_size 4096;

Rate limit

http://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req

https://www.nginx.com/blog/rate-limiting-nginx/

https://www.freecodecamp.org/news/nginx-rate-limiting-in-a-nutshell-128fe9e0126c/

DNS resolver

https://distinctplace.com/2017/04/19/nginx-resolver-explained/

server {
  listen        80;
  server_name   example.com;

  location / {

    resolver 172.16.0.23;

    set $upstream_endpoint http://service-999999.eu-west-2.elb.amazonaws.com;

    proxy_pass $upstream_endpoint$request_uri;
  }
}

Generar configuracion

https://nginxconfig.io/

Location

http://nginx.org/en/docs/http/ngx_http_core_module.html#location

https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms

A location can either be defined by a prefix string, or by a regular expression. Regular expressions are specified with the preceding “~*” modifier (for case-insensitive matching), or the “~” modifier (for case-sensitive matching). To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered. Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then the configuration of the prefix location remembered earlier is used.

Confirmar regex

https://www.regextester.com/94055

Obtener IP de cliente detras de proxy

server {
 ...
 set_real_ip_from 10.0.0.0/8;
 real_ip_header X-Forwarded-For;
...
}

Too many open files

https://www.scalescale.com/tips/nginx/nginx-accept-failed-24-too-many-open-files/#

Rewrite

https://www.nginx.com/blog/creating-nginx-rewrite-rules/

https://forum.nginx.org/read.php?2,213799,213799

Proxy

https://www.liaohuqiu.net/posts/nginx-proxy-pass/

En caso se que el puerto sea distinto, usar $http_host en lugar de $host:

    location / {
        proxy_pass http://172.17.0.5:80;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }


Location con diagonales y sin ellas

https://serverfault.com/questions/376162/how-can-i-create-a-location-in-nginx-that-works-with-and-without-a-trailing-slas

location ~ ^/phpmyadmin(?:/(.*))?$ {
    alias /home/phpmyadmin/$1;
}


TCP Proxy

https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-tcp/

https://docs.nginx.com/nginx/admin-guide/security-controls/securing-tcp-traffic-upstream/

https://docs.nginx.com/nginx/admin-guide/security-controls/controlling-access-proxied-tcp/

stream {
  log_format basic '$remote_addr [$time_local] '
                   '$protocol $status $bytes_sent $bytes_received '
                   '$session_time';

  server {
    listen 8443;
    access_log /var/log/nginx/access.log basic;
    error_log /var/log/nginx/error.log;
    proxy_pass backend;
    proxy_ssl on

    allow 127.0.0.1;
    deny all;
  }

  upstream backend{
    server myserver.com:8443;
  }
}

FastCGI

https://www.digitalocean.com/community/tutorials/understanding-and-implementing-fastcgi-proxying-in-nginx

Como probar FastCGI

  1. Configurar NGINX para que apunte a puerto de pruebas en el host deseado. En este ejemplo se usa 9001/TCP.
    location / {
        root /var/www/html;
        include fastcgi_params;
        fastcgi_pass 10.0.0.1:9001;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_buffers 256 128k;
        fastcgi_connect_timeout 300s;
        fastcgi_send_timeout 300s;
        fastcgi_read_timeout 300s;
    }
  1. Iniciar un proceso de netcat escuchando en el mismo puerto y leer con strings la salida
# nc -l -p 9001 -v | strings

listening on [any] 9001 ...
connect to [10.0.0.1] from nginx-test [10.0.0.2] 48264
QUERY_STRING
REQUEST_METHODGET
CONTENT_TYPE
CONTENT_LENGTH
SCRIPT_NAME/test/test.php
REQUEST_URI/test/test.php
DOCUMENT_URI/test/test.php
DOCUMENT_ROOT/var/www/html
SERVER_PROTOCOLHTTP/1.1
REQUEST_SCHEMEhttp
GATEWAY_INTERFACECGI/1.1
SERVER_SOFTWAREnginx/1.13.10
REMOTE_ADDR192.168.0.1
REMOTE_PORT5871
SERVER_ADDR10.0.0.2
SERVER_PORT80
SERVER_NAME
REDIRECT_STATUS200
SCRIPT_FILENAME/var/www/html/test/test.php
HTTP_HOSTwww.test.com:10080
HTTP_CONNECTIONkeep-alive
HTTP_CACHE_CONTROLmax-age=0
HTTP_UPGRADE_INSECURE_REQUESTS1
UHTTP_ACCEPTtext/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
HTTP_ACCEPT_ENCODINGgzip, deflate
HTTP_ACCEPT_LANGUAGEes-ES,es;q=0.9

Secure Link

http://nginx.org/en/docs/http/ngx_http_secure_link_module.html?_ga=2.81049108.2074973945.1524495402-782923656.1520539754

https://www.nginx.com/blog/securing-urls-secure-link-module-nginx-plus/

Basic

Agregar lo siguiente a la configuracion de NGINX. Usando secure_link_secret y la clave enigma:

server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;

    location / {
        index  index.html index.htm;
    }

    location /secret {
        secure_link_secret enigma;
        if ($secure_link = "") { return 403; }
        if ($secure_link = "0") { return 410; }
        rewrite ^ /private/$secure_link;
    }
    
    location /private {
        internal;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Para generar la clave:

SECRET=`echo -n 'secret/data.txtenigma777' | openssl md5 -hex  | cut -d " " -f 2`
curl -s http://192.168.0.1/secret/$SECRET/secret/data.txt

Expire

Agregar lo siguiente a la configuracion de NGINX. Usando secure_link_secret y la clave enigma:

server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;

    location / {
        index  index.html index.htm;
    }
    
    location /private {
        secure_link $arg_md5,$arg_expires;
        secure_link_md5 "$secure_link_expires enigma";
        if ($secure_link = "") { return 403; }
        if ($secure_link = "0") { return 410; }
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Agregar un script PHP con lo siguiente:

<?php
/**
 * FROM: https://gist.github.com/bftanase/cbae1f9fc69bb4f9cb86
 * @param $baseUrl - non protected part of the URL including hostname, e.g. http://example.com
 * @param $path - protected path to the file, e.g. /downloads/myfile.zip
 * @param $secret - the shared secret with the nginx server. Keep this info secure!!!
 * @param $ttl - the number of seconds until this link expires
 * @param $userIp - ip of the user allowed to download
 * @return string
 */
function buildSecureLink($baseUrl, $path, $secret, $ttl, $userIp)
{
    $expires = time() + $ttl;
    $md5 = md5("$expires $secret", true);
    $md5 = base64_encode($md5);
    $md5 = strtr($md5, '+/', '-_');
    $md5 = str_replace('=', '', $md5);
    return $baseUrl . $path . '?md5=' . $md5 . '&expires=' . $expires;
}

// example usage
$secret = 'enigma';
$baseUrl = 'http://<SERVER_IP';
$path = '/private/data.txt';
$ttl = 30; //no of seconds this link is active
//$userIp = $_SERVER['REMOTE_ADDR'];

$redirect = buildSecureLink($baseUrl, $path, $secret, $ttl, $userIp);
header("Location: $redirect");
die();
?>

Python

  • nginx:
server {
    listen       80;
    server_name  _;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    root   /usr/share/nginx/html;

    location / {
        index  index.html index.htm;
    }

    location /insecure {
        autoindex on;
        alias /usr/share/nginx/html/media;
    }

    location /media {
        alias /usr/share/nginx/html/media;
        secure_link $arg_token;
        secure_link_md5 "$uri password";
        if ($secure_link = "") { return 403; }
        if ($secure_link = "0") { return 410; }
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}
  • python code
import hashlib
import base64
secret = "password"
media_uri = "/media/dir/data.txt"
m = hashlib.md5()
m.update("{uri} {secret}".format(uri=media_uri, secret=secret))
print(base64.b64encode(m.digest()).replace("+","-").replace("=",""))
  • curl
curl http://example.com/media/dir/data.txt?token=tphEgJBcPqftoVRwT7YHsw

Python

  • nginx:
server {
    listen       80;
    server_name  _;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    root   /usr/share/nginx/html;

    location / {
        index  index.html index.htm;
    }

    location /insecure {
        autoindex on;
        alias /usr/share/nginx/html/media;
    }

    location /media {
        alias /usr/share/nginx/html/media;
        secure_link $arg_token;
        secure_link_md5 "$uri password";
        if ($secure_link = "") { return 403; }
        if ($secure_link = "0") { return 410; }
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}
  • python code
import hashlib
import base64
secret = "password"
media_uri = "/media/dir/data.txt"
m = hashlib.md5()
m.update("{uri} {secret}".format(uri=media_uri, secret=secret))
print(base64.b64encode(m.digest()).replace("+","-").replace("=",""))
  • curl
curl http://example.com:8443/media/dir/data.txt?token=tphEgJBcPqftoVRwT7YHsw

Bash

  • nginx:
server {
    listen       80;
    server_tokens  off;

    root   /usr/share/nginx/html;

    location / {
        index  index.html index.htm;
    }

    location /secure {
        secure_link $arg_token,$arg_expires;
        secure_link_md5 "$secure_link_expires $uri enigma777";
        if ($secure_link = "") { return 403; }
        if ($secure_link = "0") { return 410; }
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
  • bash:

Basado en http://nginx.2469901.n2.nabble.com/Cannot-get-secure-link-with-expires-to-work-td7604167.html

#!/bin/bash

SECRET="enigma777"
DURATION=60
URI="/secure/backup.tgz"
SERVER="http://server.local:80"
TOKEN_FORMAT="%s %s %s" # must match format of secure_link_md5
NOW=$( date +%s )
EXPIRES=$(( ${NOW} + ${DURATION} ))
TOKEN=$(printf "${TOKEN_FORMAT}" ${EXPIRES} ${URI} ${SECRET} | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d = )
URL="${SERVER}${URI}?token=${TOKEN}&expires=${EXPIRES}"
curl ${URL}

Docker

Redireccion TCP

https://github.com/jetbrains-infra/docker-nginx-tcp-proxy

Redireccion HTTP a HTTPS