From 78904a4d17fa888f272256085f68ee41862126ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andre=CC=81=20R?= <ar@ez.no>
Date: Wed, 24 Jan 2018 14:56:24 +0100
Subject: [PATCH] Make it possible to inject port to SSL and Varnihs proxy

In order to get symfony to use the right docker port:
- make it possible to pass it from parent to Varnihs VCL in a trusted way
- make it possible to dynamicaly inject port to ssl proxy image (using pear module in this case)
---
 doc/docker/Dockerfile-nginx-ssl-proxy        |  2 +-
 doc/docker/entrypoint/ssl-proxy/nginx.conf   |  9 ++++++++-
 doc/docker/entrypoint/varnish/parameters.vcl |  5 +++++
 doc/docker/varnish.yml                       |  2 ++
 doc/varnish/vcl/parameters.vcl               |  5 +++++
 doc/varnish/vcl/varnish4_xkey.vcl            | 12 +++++++-----
 6 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/doc/docker/Dockerfile-nginx-ssl-proxy b/doc/docker/Dockerfile-nginx-ssl-proxy
index efe934f908..852e5c3ad4 100644
--- a/doc/docker/Dockerfile-nginx-ssl-proxy
+++ b/doc/docker/Dockerfile-nginx-ssl-proxy
@@ -1,4 +1,4 @@
-FROM nginx:stable
+FROM nginx:stable-perl
 # Based on: https://github.com/clamorisse/nginx-ssl-container
 
 RUN mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
diff --git a/doc/docker/entrypoint/ssl-proxy/nginx.conf b/doc/docker/entrypoint/ssl-proxy/nginx.conf
index d50525b642..901f1e9f05 100644
--- a/doc/docker/entrypoint/ssl-proxy/nginx.conf
+++ b/doc/docker/entrypoint/ssl-proxy/nginx.conf
@@ -4,6 +4,10 @@ worker_processes  1;
 error_log  /var/log/nginx/error.log warn;
 pid        /var/run/nginx.pid;
 
+load_module /etc/nginx/modules/ngx_http_perl_module.so;
+
+# To pass in the public facing forward port we want to set
+env X_FORWARD_PORT;
 
 events {
     worker_connections  1024;
@@ -17,6 +21,9 @@ http {
     tcp_nodelay         on;
     keepalive_timeout   15;
 
+    # Get SSL port to use from X_FORWARD_PORT env variable, or fallback to 443
+    perl_set $x_forward_port 'sub { return $ENV{"X_FORWARD_PORT"} || 443; }';
+
     server {
         listen 443 ssl http2;
 
@@ -36,7 +43,7 @@ http {
             proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
             proxy_set_header X-Forwarded-Proto $scheme;
             proxy_set_header X-Forwarded-Host  $host;
-            proxy_set_header X-Forwarded-Port  443;
+            proxy_set_header X-Forwarded-Port  $x_forward_port;
             proxy_set_header Host              $host;
 
             proxy_pass http://varnish:80;
diff --git a/doc/docker/entrypoint/varnish/parameters.vcl b/doc/docker/entrypoint/varnish/parameters.vcl
index c3f40c97e4..4a708edb10 100644
--- a/doc/docker/entrypoint/varnish/parameters.vcl
+++ b/doc/docker/entrypoint/varnish/parameters.vcl
@@ -16,3 +16,8 @@ acl debuggers {
     "127.0.0.1";
     "172.16.0.0"/20;
 }
+
+// ACL for trusted proxies IP
+acl proxies {
+    "ssl";
+}
diff --git a/doc/docker/varnish.yml b/doc/docker/varnish.yml
index 755b455a85..6248d17259 100644
--- a/doc/docker/varnish.yml
+++ b/doc/docker/varnish.yml
@@ -35,6 +35,8 @@ services:
       dockerfile: Dockerfile-nginx-ssl-proxy
     ports:
      - "8443:443"
+    environment:
+     - X_FORWARD_PORT=8443
     depends_on:
      - varnish
     networks:
diff --git a/doc/varnish/vcl/parameters.vcl b/doc/varnish/vcl/parameters.vcl
index 00820f64c6..bf36a22f10 100644
--- a/doc/varnish/vcl/parameters.vcl
+++ b/doc/varnish/vcl/parameters.vcl
@@ -19,3 +19,8 @@ acl debuggers {
     "127.0.0.1";
     "192.168.0.0"/16;
 }
+
+// ACL for trusted proxies IP
+acl proxies {
+    "127.0.0.1";
+}
diff --git a/doc/varnish/vcl/varnish4_xkey.vcl b/doc/varnish/vcl/varnish4_xkey.vcl
index 981e2a8b00..24683b269d 100644
--- a/doc/varnish/vcl/varnish4_xkey.vcl
+++ b/doc/varnish/vcl/varnish4_xkey.vcl
@@ -30,11 +30,13 @@ sub vcl_recv {
     // To be removed in Symfony 3.3
     unset req.http.Forwarded;
 
-    // Ensure that the Symfony Router generates URLs correctly with Varnish
-    if (req.http.X-Forwarded-Proto == "https" ) {
-        set req.http.X-Forwarded-Port = "443";
-    } else {
-        set req.http.X-Forwarded-Port = "80";
+    // Ensure that the Symfony Router generates URLs correctly with Varnish, if port is not set by trusted proxy already
+    if (! req.http.X-Forwarded-Port || ! client.ip ~ proxies) {
+        if (req.http.X-Forwarded-Proto == "https" ) {
+            set req.http.X-Forwarded-Port = "443";
+        } else {
+            set req.http.X-Forwarded-Port = "80";
+        }
     }
 
     // Trigger cache purge if needed