===== Obtener IP origen sin terminar conexión SSL ===== En este escenario: * Edge router. Es el nginx que recibe la conexión del cliente, y expone a la DMZ los puertos TCP 443 y TCP 80. Si recibe la conexión al puerto TCP 443 lo redirige (capa 4) a "behind edge" usando proxy protocol para poder proporcionarle la IP origen * Behind edge. Servidor que expone puertos TCP 443 y TCP 80 a 'edge router'. Cuando recibe la conexión TCP 443, por protocolo 'proxy protocol', termina la conexión SSL, y por tanto entrega los certificados (autorfirmados) SSL. Tanto por TCP 80 como por TCP 443 redirige las conexiones a 'php' * Php. Pinta las cabeceras que recibe Requisitos: * Docker instalado * Docker compose instalados * El servidor tiene que tener una IP pública * Nombre DNS (en este ejemplo "example.com") que apunte a la IP pública del servidor 1. Edge router 1.1. Crear directorio: mkdir edge 1.2. Crear 'default.conf': vim edge/default.conf Con el siguiente contenido: proxy_set_header X-Real-IP $proxy_protocol_addr; proxy_set_header X-Forwarded-For $remote_addr; # To avoid 404. Credits: # https://serverfault.com/a/407983/570054 proxy_set_header Host $host:$server_port; server { listen 80; location / { proxy_pass http://behind_edge; } error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html/; internal; } } 1.3. Crear 'nginx.conf': vim edge/nginx.conf Con el siguiente contenido: user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; upstream behind_edge { # Docker container named 'behind_edge' sharing same docker network server behind_edge:80; } } stream { server { listen 443; proxy_pass behind_edge_ssl; proxy_protocol on; } upstream behind_edge_ssl { # Docker container named 'behind_edge' sharing same docker network server behind_edge:443; } log_format basic '$remote_addr - [$time_local] ' '$status ' ''; access_log /var/log/nginx/access.log basic; } 2. Behind edge 2.1. Crear directorio: mkdir behind_edge 2.2. Crear 'default.conf': vim behind_edge/default.conf Con el siguiente contenido: proxy_set_header X-Real-IP $proxy_protocol_addr; proxy_set_header X-Forwarded-For $remote_addr; # To avoid 404. Credits: # https://serverfault.com/a/407983/570054 proxy_set_header Host $host:$server_port; proxy_set_header X-Custom-IP $proxy_protocol_addr; proxy_set_header X-Custom-Port $proxy_protocol_port; server { listen 80; location / { proxy_pass http://php; } } server { listen 443 ssl proxy_protocol; location / { proxy_pass https://php_ssl; } ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; } 2.3. Crear 'nginx.conf': vim behind_edge/nginx.conf Con el siguiente contenido: user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; upstream php { # Docker container named 'php' sharing same docker network server php:80; } upstream php_ssl { # Docker container named 'php' sharing same docker network server php:443; } } 2.4. Crear: vim behind_edge/Dockerfile Con el siguiente contenido: FROM nginx RUN apt-get update && apt-get install -y \ ssl-cert 3. Php **NOTA**: de hecho la parte de SSL en el contenedor PHP ya no es necesaria, pero bueno... 3.1. Crear directorio: mkdir php 3.2. Crear: vim php/index.php Con el siguiente contenido: $value) { echo "$name: $value
\n"; } ?>
3.3. Crear: vim php/Dockerfile Con el siguiente contenido: FROM php:7-apache RUN apt-get update && apt-get install -y \ ssl-cert RUN a2enmod \ remoteip \ ssl RUN a2ensite default-ssl.conf COPY index.php /var/www/html/ 4. Crear: vim docker-compose.yml Con el siguiente contenido: services: behind_edge: build: context: ./behind_edge container_name: behind_edge volumes: - "/home/debian/behind_edge/nginx.conf:/etc/nginx/nginx.conf:ro" - "/home/debian/behind_edge/default.conf:/etc/nginx/conf.d/default.conf:ro" edge: container_name: edge image: nginx ports: - 80:80 - 443:443 volumes: - "/home/debian/edge/nginx.conf:/etc/nginx/nginx.conf:ro" - "/home/debian/edge/default.conf:/etc/nginx/conf.d/default.conf:ro" php: build: context: ./php container_name: php version: "3.3" Ajustar las rutas a los archivos, en este ejemplo "/home/debian". Resumen: . ├── behind_edge │   ├── default.conf │   ├── Dockerfile │   └── nginx.conf ├── docker-compose.yml ├── edge │   ├── default.conf │   └── nginx.conf └── php ├── Dockerfile └── index.php 5. Probar. Ejecutar: curl -s -k https://example.com Resultado esperado similar a: X-Real-IP: 8.8.8.8
X-Forwarded-For: 172.25.0.3
Host: php_ssl
Connection: close
User-Agent: curl/7.74.0
Accept: */*
Vemos que la cabecera 'X-Real-IP' contiene la IP pública del cliente que ha enviado la petición, en este caso '8.8.8.8'