diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c9faf419086453604244e7e46359fa09500130eb..0c8a4472935c11fcd2c900c79b38fa859bb71cb1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -35,18 +35,6 @@ stages:
   - performance
   - cleanup
 
-prepare_secrets:
-  stage: prepare
-  image: alpine:latest
-  script:
-    - cp $ENV_FILE .env # Also provide env file
-  artifacts:
-    paths:
-      - .env
-  only:
-    - branches
-    - tags
-
 prepare_node:
   stage: prepare
   image: node:10
@@ -92,7 +80,7 @@ build:
 
 review:
   variables:
-    HELM_UPGRADE_EXTRA_ARGS: --set service.externalPort=80 --set service.internalPort=80 --set service.commonName= --set ingress.tls.enabled=false --set ingress.annotations.kubernetes\.io/tls-acme="false" --set ingress.annotations.nginx\.ingress\.kubernetes\.io/ssl-redirect="false"
+    HELM_UPGRADE_VALUES_FILE: .gitlab/review-values.yaml
     ROLLOUT_RESOURCE_TYPE: deployment
     
 production:
diff --git a/.gitlab/review-values.yaml b/.gitlab/review-values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..93036cb7fa263d5e55957d157423d305cb4c5e1d
--- /dev/null
+++ b/.gitlab/review-values.yaml
@@ -0,0 +1,17 @@
+service:
+  enabled: true
+  externalPort: 80
+  internalPort: 80
+  commonName: ""
+ingress:
+  tls:
+    enabled: false
+  annotations:
+    kubernetes.io/tls-acme: "false"
+    nginx.ingress.kubernetes.io/ssl-redirect: "false"
+readinessProbe:
+  path: "/healthz"
+  timeoutSeconds: 60
+livenessProbe:
+  path: "/healthz"
+  timeoutSeconds: 60
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index a8dcb97d0ae31a2306d26d9f484bd5c649379c3f..5c91c25150438878c712e72d9c645769acc9b303 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM alpine:3.11.3
+FROM alpine:3
 
 RUN apk add --update \
     nginx \
@@ -21,11 +21,13 @@ RUN apk add --update \
     php7-dom \
     php7-fileinfo \
     php7-redis \
-    && rm -rf /var/cache/apk/*
+    && rm -rf /var/cache/apk/* \
+    && update-ca-certificates
 
 WORKDIR /html
 
-RUN sed -i 's/;error_log = log\/php7\/error.log/error_log = \/dev\/stderr/g' /etc/php7/php-fpm.conf && \
+RUN wget -O /etc/ssl/cacert.pem "https://curl.haxx.se/ca/cacert.pem" && \
+    sed -i 's/;error_log = log\/php7\/error.log/error_log = \/dev\/stderr/g' /etc/php7/php-fpm.conf && \
     sed -i 's/;daemonize = yes/daemonize = no/g' /etc/php7/php-fpm.conf && \
     sed -i 's/listen = 127.0.0.1:9000/listen = 9000/g' /etc/php7/php-fpm.d/www.conf && \
     sed -i 's/;request_terminate_timeout = 0/request_terminate_timeout = 30/g' /etc/php7/php-fpm.d/www.conf && \
@@ -50,6 +52,7 @@ RUN sed -i 's/;error_log = log\/php7\/error.log/error_log = \/dev\/stderr/g' /et
     sed -i 's/;opcache.max_wasted_percentage=5/opcache.max_wasted_percentage=5/g' /etc/php7/php.ini && \
     sed -i 's/;opcache.validate_timestamps=1/opcache.validate_timestamps=1/g' /etc/php7/php.ini && \
     sed -i 's/;opcache.revalidate_freq=2/opcache.revalidate_freq=300/g' /etc/php7/php.ini && \
+    sed -i 's/;curl.cainfo =/curl.cainfo ="\/etc\/ssl\/cacert.pem"/g' /etc/php7/php.ini && \
     ln -s /dev/null /var/log/nginx/access.log && \
     ln -s /dev/stdout /var/log/nginx/error.log && \
     cp /usr/share/zoneinfo/Europe/Berlin /etc/localtime && \
diff --git a/DockerfileDev b/DockerfileDev
index 555ddd722a3344dfa514ff33368e209a06f8322d..4fe5df9f8fae668fdc84d784ade60ae31ec2c5ad 100644
--- a/DockerfileDev
+++ b/DockerfileDev
@@ -26,7 +26,8 @@ RUN apk add --update \
 
 WORKDIR /html
 
-RUN sed -i 's/;error_log = log\/php7\/error.log/error_log = \/dev\/stderr/g' /etc/php7/php-fpm.conf && \
+RUN wget -O /etc/ssl/cacert.pem "https://curl.haxx.se/ca/cacert.pem" && \
+    sed -i 's/;error_log = log\/php7\/error.log/error_log = \/dev\/stderr/g' /etc/php7/php-fpm.conf && \
     sed -i 's/;daemonize = yes/daemonize = no/g' /etc/php7/php-fpm.conf && \
     sed -i 's/listen = 127.0.0.1:9000/listen = 9000/g' /etc/php7/php-fpm.d/www.conf && \
     sed -i 's/;request_terminate_timeout = 0/request_terminate_timeout = 900/g' /etc/php7/php-fpm.d/www.conf && \
@@ -43,6 +44,7 @@ RUN sed -i 's/;error_log = log\/php7\/error.log/error_log = \/dev\/stderr/g' /et
     sed -i 's/group = www-data/group = nginx/g' /etc/php7/php-fpm.d/www.conf && \
     sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php7/php.ini && \
     sed -i 's/expose_php = On/expose_php = Off/g' /etc/php7/php.ini && \
+    sed -i 's/;curl.cainfo =/curl.cainfo ="\/etc\/ssl\/cacert.pem"/g' /etc/php7/php.ini && \
     sed -i 's/;zend_extension=xdebug.so/zend_extension=xdebug.so/g' /etc/php7/conf.d/xdebug.ini && \
     echo "xdebug.remote_enable = 1" >> /etc/php7/conf.d/xdebug.ini && \
     echo "xdebug.remote_autostart = 1" >> /etc/php7/conf.d/xdebug.ini && \
diff --git a/app/Document.php b/app/Document.php
index b3ceb31e9d3fb6e3cd821da099e100d955083187..39f2a277bc539ca94aba67693fd13df532eb02ba 100644
--- a/app/Document.php
+++ b/app/Document.php
@@ -2,7 +2,6 @@
 
 namespace App;
 
-use Illuminate\Http\Request;
 use URL;
 
 abstract class Document
@@ -16,46 +15,43 @@ abstract class Document
         $this->baseUrl  = $base;
     }
 
-    public function proxifyUrl($url, $topLevel)
-    {
-        // Only convert valid URLs
+    public function proxifyFormAction($url){
         $url = trim($url);
-
         if (stripos($url, "javascript:") === 0) {
             return "";
         }
 
-        if (strpos($url, "http") !== 0 || strpos($url, URL::to('/')) === 0) {
+        // Deny Loading internal URLs and check if URL syntax is correct
+        $host = parse_url($url, PHP_URL_HOST);
+        $selfHost = \Request::getHttpHost();
+        if (strpos($url, "http") !== 0 || $host === false || $host === $selfHost) {
             return $url;
         }
 
-        $urlToProxy = base64_encode(str_rot13($url));
-        $urlToProxy = str_replace("/", "<<SLASH>>", $urlToProxy);
-        $urlToProxy = urlencode($urlToProxy);
-        
-        if ($topLevel) {
-            $params = \Request::all();
-            
-            # Password
-            $pw         = md5(env('PROXY_PASSWORD') . $url);
-            $urlToProxy = base64_encode(str_rot13($url));
-            $urlToProxy = urlencode(str_replace("/", "<<SLASH>>", $urlToProxy));
+        return \App\Http\Controllers\ProxyController::generateFormgetUrl($url);
+    }
 
-            # Params
-            $params['password'] = $pw;
-            $params['url']      = $urlToProxy;
+    public function proxifyUrl($url, $topLevel)
+    {
+        // Only convert valid URLs
+        $url = trim($url);
 
-            $iframeUrl = action('ProxyController@proxyPage', $params);
-        } else {
-            $params             = \Request::all();
-            $params['password'] = $this->password;
-            $params['url']      = $urlToProxy;
-            $params["id"]       = \Request::route("id");
+        if (stripos($url, "javascript:") === 0) {
+            return "";
+        }
 
-            $iframeUrl = action('ProxyController@proxy', $params);
+        // Deny Loading internal URLs and check if URL syntax is correct
+        $host = parse_url($url, PHP_URL_HOST);
+        $selfHost = \Request::getHttpHost();
+        if (strpos($url, "http") !== 0 || $host === false || $host === $selfHost) {
+            return $url;
         }
 
-        return $iframeUrl;
+        if($topLevel){
+            return \App\Http\Controllers\ProxyController::generateProxyWrapperUrl($url);
+        }else{
+            return \App\Http\Controllers\ProxyController::generateProxyUrl($url);
+        }
     }
 
     protected function convertRelativeToAbsoluteLink($rel)
diff --git a/app/HtmlDocument.php b/app/HtmlDocument.php
index d3db7e7e2b7dc44cfc8fc4c7e9b93f333443c479..b3dffb0336280ab3eabe12835e355bb5856ccc31 100644
--- a/app/HtmlDocument.php
+++ b/app/HtmlDocument.php
@@ -10,7 +10,7 @@ class HtmlDocument extends Document
     private $htmlString;
     private $encoding;
 
-    public function __construct($password, $baseUrl, $htmlString, $encoding)
+    public function __construct($password, $baseUrl, $htmlString, $encoding = null)
     {
         parent::__construct($password, $baseUrl);
         $this->htmlString = $this->convertEncoding($htmlString, $encoding);
@@ -168,7 +168,7 @@ class HtmlDocument extends Document
             }
             #
             # And finally Proxify the Url
-            $action = $this->proxifyUrl($action, true);
+            $action = $this->proxifyFormAction($action);
             $form->setAttribute("action", $action);
         }
 
@@ -179,6 +179,9 @@ class HtmlDocument extends Document
             # Convert all Links to the proxified Version
             # All of this Links should NOT target to the top Level
             $link->setAttribute("href", $this->proxifyUrl($link->getAttribute("href"), false));
+            // We will proxify any File that is linked here which changes its content
+            // Integrity will therefor fail and as we do not know the correct content yet it needs to be removed
+            $link->removeAttribute("integrity");
         }
 
         # All Iframes
diff --git a/app/Http/Controllers/ProxyController.php b/app/Http/Controllers/ProxyController.php
index fc28d7f19d9873ab50529525bf5e52f7617680df..2a409fdb74a5c4f85789e5669acac88d08527a92 100644
--- a/app/Http/Controllers/ProxyController.php
+++ b/app/Http/Controllers/ProxyController.php
@@ -6,32 +6,32 @@ use App\CssDocument;
 use App\HtmlDocument;
 use Cache;
 use finfo;
+use Log;
 use Illuminate\Http\Request;
-use Symfony\Component\HttpFoundation\StreamedResponse;
-use URL;
 use Illuminate\Support\Facades\Redis;
 use App\Console\Commands\RequestFetcher;
-use App\Models\HttpParser;
 use Carbon\Carbon;
 
 class ProxyController extends Controller
 {
     const PROXY_CACHE = 5; # Cache duration in minutes
+    const PROXYLINKVALIDHOURS = 1;
 
-    public function proxyPage(Request $request, $password, $url)
+    public function proxyPage(Request $request)
     {
-        $targetUrl = str_replace("<<SLASH>>", "/", $url);
-        $targetUrl = str_rot13(base64_decode($targetUrl));
-        if (strpos($targetUrl, URL::to('/')) === 0) {
-            return redirect($targetUrl);
+        if(!$request->filled("url") || !$request->filled("password")){
+            if (env("APP_ENV", "") !== "production") {
+                return view("development");
+            } else {
+                return redirect("https://metager.de");
+            }
         }
 
-        // Password already got checked by the middleware:
-
-        $newPW = md5(env('PROXY_PASSWORD') . date('dmy'));
+        $targetUrl = $request->input("url", "https://metager.de");
+        $password = $request->input("password", "");
 
         # Check For URL-Parameters that don't belong to the Proxy but to the URL that needs to be proxied
-        $params = $request->except(['enableJS', 'enableCookies']);
+        $params = $request->except(['url', 'password']);
         if (sizeof($params) > 0) {
             # There are Params that need to be passed to the page
             # Most of the times this happens due to forms that are submitted on a proxied page
@@ -75,83 +75,73 @@ class ProxyController extends Controller
             return redirect($newLink);
         }
 
-        $this->writeLog($targetUrl, $request->ip());
-
-        $toggles = "111000A";
-
-        # Script Toggle Url:
-        $params = $request->all();
-        $scriptsEnabled = false;
-        if ($request->has('enableJS')) {
-            $scriptsEnabled = true;
-            array_forget($params, 'enableJS');
-        } else {
-            $toggles[1] = "0";
-            $params['enableJS'] = "true";
+        // Check Password
+        if(!self::checkPassword($targetUrl, null, $password)){
+            abort(400, "Invalid Request");
         }
 
-        $params['password'] = $password;
-        $params['url'] = $url;
-        $scriptUrl = action('ProxyController@proxyPage', $params);
-        //$scriptUrl          = "javascript:alert('Diese Funktion wurde auf Grund von technischen Problemen vorerst deaktiviert. Sie können JavaScript wieder aktivieren sobald diese behoben wurden.');";
-
-        # Cookie Toggle Url:
-        $params = $request->all();
-        $cookiesEnabled = false;
-        if ($request->has('enableCookies')) {
-            $cookiesEnabled = true;
-            array_forget($params, 'enableCookies');
-        } else {
-            $toggles[0] = "0";
-            $params['enableCookies'] = "true";
+        // Deny Loading internal URLs and check if URL syntax is correct
+        $host = parse_url($targetUrl, PHP_URL_HOST);
+        $selfHost = $request->getHttpHost();
+        // The target URL couldn't be parsed. This is probably a malformed URL
+        if($host === false){
+            abort(404, "Invalid Request");
         }
-
-        $params['password'] = $password;
-        $params['url'] = $url;
-        $cookieUrl = action('ProxyController@proxyPage', $params);
-
-        $settings = "u0";
-        if ($cookiesEnabled && !$scriptsEnabled) {
-            $settings = "O0";
-        } elseif (!$cookiesEnabled && $scriptsEnabled) {
-            $settings = "e0";
-        } elseif ($cookiesEnabled && $scriptsEnabled) {
-            $settings = "80";
+        // The URL to load itself is a URL to our proxy
+        // We will just redirect to that URL
+        if ($host === $selfHost) {
+            return redirect($targetUrl);
         }
 
-        $key = md5($request->ip() . microtime(true));
-        $urlToProxy = $this->proxifyUrl($targetUrl, $newPW, $key, false);
+        $this->writeLog($targetUrl, $request->ip());
+       
+        $urlToProxy = self::generateProxyUrl($targetUrl);
         
         return view('ProxyPage')
-            ->with('key', $key)
             ->with('iframeUrl', $urlToProxy)
-            ->with('scriptsEnabled', $scriptsEnabled)
-            ->with('scriptUrl', $scriptUrl)
-            ->with('cookiesEnabled', $cookiesEnabled)
-            ->with('cookieUrl', $cookieUrl)
             ->with('targetUrl', $targetUrl);
     }
 
-    public function proxy(Request $request, $password, $id, $url)
+    public function proxy(Request $request)
     {
-        $supportedContentTypes = [
-            'text/html',
-        ];
+        if(!$request->filled("url") || !$request->filled("password") || !$request->filled("valid-until")){
+            Log::info("Request with missing url, password or valid-until");
+            abort(400, "Invalid Request");
+        }
+
+        $targetUrl = $request->input("url", "https://metager.de");
+        $password = $request->input("password", "");
+        $validUntil = $request->input("valid-until", "");
+
+        // Check Password
+        if(!self::checkPassword($targetUrl, $validUntil, $password)){
+            Log::info("Password incorrect");
+            abort(400, "Invalid Request");
+        }
 
-        
-        $targetUrl = str_replace("<<SLASH>>", "/", $url);
-        $targetUrl = str_rot13(base64_decode($targetUrl));
-        
         try {
-            $path = parse_url($targetUrl)["path"];
-        } catch (\Exception $e) {
-            $path = "";
+            $validUntil = Carbon::createFromFormat("d-m-Y H:i:s P", $validUntil);
+        } catch (InvalidFormatException $e) {
+            abort(400, "Invalid Request");
+        }
+
+        if ($validUntil->isBefore(Carbon::now()->setTimezone("UTC"))) {
+            Log::info("URL expired");
+            abort(400, "Invalid Request");
+        }
+
+        // Deny Loading internal URLs and check if URL syntax is correct
+        $host = parse_url($targetUrl, PHP_URL_HOST);
+        $selfHost = $request->getHttpHost();
+        // The target URL couldn't be parsed. This is probably a malformed URL
+        // The URL to load itself is a URL to our proxy
+        if($host === false || $host === $selfHost){
+            Log::info("URL to myself");
+            abort(404, "Invalid Request");
         }
 
-        $this->password = $password;
         // Hash Value under which a possible cached file would've been stored
         $hash = md5($targetUrl);
-        $result = [];
         $httpcode = 200;
 
         if (!Cache::has($hash) || env("CACHE_ENABLED") === false) {
@@ -195,8 +185,8 @@ class ProxyController extends Controller
             }
         }
 
-        if ($result === null) {
-            return $this->streamFile($targetUrl);
+        if ($answer === null) {
+            abort(400, "Couldn't fetch response");
         } else {
             $httpcode = $answer["http-code"];
             extract(parse_url($targetUrl));
@@ -216,7 +206,7 @@ class ProxyController extends Controller
                     }
                     
                     $key = md5($request->ip() . microtime(true));
-                    $headerArray[trim($index)] = $this->proxifyUrl($redLink, null, $key, false);
+                    $headerArray[trim($index)] = self::generateProxyUrl($redLink);
                 } elseif (strtolower($index) === "content-disposition") {
                     $headerArray[strtolower(trim($index))] = strtolower(trim($value));
                 } else {
@@ -286,6 +276,9 @@ class ProxyController extends Controller
                 case 'application/zip':
                 case 'binary/octet-stream':
                 case 'application/vnd.android.package-archive':
+                case 'image/svg+xml':
+                case 'font/woff':
+                case 'font/woff2':
                     # Nothing to do with Images: Just return them
                     break;
                 case 'text/css':
@@ -296,6 +289,7 @@ class ProxyController extends Controller
                     break;
                 default:
                     # We have no Parser for this one. Let's respond:
+                    Log::error("Couldn't find parser for content type " . $contentType . " on URL " . $targetUrl);
                     abort(500, $contentType . " " . $targetUrl);
                     break;
             }
@@ -308,100 +302,190 @@ class ProxyController extends Controller
             ->withHeaders($answer["headers"]);
     }
 
-    public function streamFile(Request $request, $password, $id, $url)
-    {
-        /**
-         * Forms of proxied webpages might aswell Post to this URL
-         * Those need to be denied
-         */
-        $check = md5(env('PROXY_PASSWORD') . date('dmy') . $request->ip());
-        if (!$request->filled("force-download") && $request->input("check", "") === $check) {
-            abort(405);
+    /**
+     * This function is called if a proxied page submits a form
+     * It should take the submitted parameters and add them to the url
+     * After that it should redirect to the correct page with the correct parameters
+     */
+    public function formget(Request $request, $password, $validUntil, $url){
+        if(empty($password) || empty($validUntil) || empty($url)){
+            abort(400, "Invalid Request");
         }
-        $targetUrl = str_replace("<<SLASH>>", "/", $url);
-        $targetUrl = str_rot13(base64_decode($targetUrl));
-        if (strpos($targetUrl, URL::to('/')) === 0) {
-            return redirect($targetUrl);
+
+        // Check Password
+        if(!self::checkPassword($url, $validUntil, $password)){
+            abort(400, "Invalid Request");
         }
-        return $this->streamResponse($targetUrl);
-    }
 
-    private function streamResponse($url)
-    {
-        $headers = get_headers($url, 1);
+        try {
+            $validUntil = Carbon::createFromFormat("d-m-Y H:i:s P", $validUntil);
+        } catch (InvalidFormatException $e) {
+            abort(400, "Invalid Request");
+        }
+
+        if ($validUntil->isBefore(Carbon::now()->setTimezone("UTC"))) {
+            abort(400, "Invalid Request");
+        }
+
+        // Deny Loading internal URLs and check if URL syntax is correct
+        $host = parse_url($url, PHP_URL_HOST);
+        $selfHost = $request->getHttpHost();
+        // The target URL couldn't be parsed. This is probably a malformed URL
+        // The URL to load itself is a URL to our proxy
+        if($host === false || $host === $selfHost){
+            abort(404, "Invalid Request");
+        }
 
-        $filename = basename($url);
+        // All Checks passed we can generate a url where the submitted data is included
+        $submittedParameters = $request->all();
 
-        # From the headers we need to remove the first Element since it's the status code:
-        $status = $headers[0];
-        $status = intval(preg_split("/\s+/si", $status)[1]);
-        array_forget($headers, 0);
+        // The URL itself might contain query parameters
+        $containedParameters = array();
+        $parts = parse_url($url);
+        if(!empty($parts["query"])){
+            parse_str($parts["query"], $containedParameters);
+        }
+        $urlParameters = array_merge($submittedParameters, $containedParameters);
 
-        # Add the Filename if it's not set:
-        if (!isset($headers["Content-Disposition"])) {
-            $headers["Content-Disposition"] = "inline; filename=\"" . $filename . "\"";
-        } elseif (preg_match("/filename=\"{0,1}(.*?)(\"|\s|$)/", $headers["Content-Disposition"], $matches)) {
-            $filename = $matches[1];
+        if(empty($parts["scheme"]) || empty($parts["host"])){
+            abort(400, "Invalid Request");
         }
 
-        return response()->streamDownload(function () use ($url) {
-            # We are gonna stream a large file
-            $ch = curl_init();
-            curl_setopt($ch, CURLOPT_URL, $url);
-            curl_setopt($ch, CURLOPT_HEADER, 0);
-            curl_setopt($ch, CURLOPT_BUFFERSIZE, 4096);
-            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-            curl_setopt($ch, CURLOPT_LOW_SPEED_LIMIT, 50000);
-            curl_setopt($ch, CURLOPT_LOW_SPEED_TIME, 5);
-            curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $data) {
-                echo($data);
-            });
-    
-            curL_exec($ch);
-
-            curl_close($ch);
-        }, $filename, $headers);
+        // Build the url
+        $targetUrl = $parts["scheme"] . "://" .
+            ((!empty($parts["user"]) && !empty($parts["pass"])) ? $parts["user"] . ":" . $parts["pass"] . "@" : "") .
+            $parts["host"] .
+            (!empty($parts["port"]) ? ":" . $parts["port"] : "") .
+            (!empty($parts["path"]) ? $parts["path"] : "") .
+            (!empty($urlParameters) ? "?" . http_build_query($urlParameters, "", "&", PHP_QUERY_RFC3986) : "") .
+            (!empty($parts["fragment"]) ? "#" . $parts["fragment"] : "");
+
+        return redirect(self::generateProxyWrapperUrl($targetUrl));
     }
 
-    public function proxifyUrl($url, $password = null, $key, $topLevel)
-    {
-        // Only convert valid URLs
-        $url = trim($url);
-        if (strpos($url, "http") !== 0 || strpos($url, URL::to('/')) === 0) {
-            return $url;
+    /**
+     * This function generates a URL to a proxied page
+     * including the proxy header.
+     */
+    public static function generateProxyWrapperUrl($url){
+        $password = self::generatePassword($url, null);
+
+        $parts = parse_url($url);
+        $host = null;
+        $path = null;
+
+        if(!empty($parts["host"])){
+            $host = $parts["host"];
         }
+        if(!empty($parts["path"])){
+            $path = trim($parts["path"], "/");
+        }
+
+        $parameters = [
+            "host" => $host,
+            "path" => $path,
+            "url" => $url,
+            "password" => $password,
+        ];
+
+        return route('proxy-wrapper-page', $parameters);
+    }
+
+    /**
+     * This function generates a URL to a proxied page
+     * excluding the proxy header.
+     */
+    public static function generateProxyUrl($url){
+
+        $validUntil = self::generateValidUntilDate();
+        $password = self::generatePassword($url, $validUntil);
 
-        if (!$password) {
-            $password = urlencode(\Request::route('password'));
+        $parts = parse_url($url);
+        $host = null;
+        $path = null;
+
+        if(!empty($parts["host"])){
+            $host = $parts["host"];
+        }
+        if(!empty($parts["path"])){
+            $path = trim($parts["path"], "/");
         }
 
-        $urlToProxy = base64_encode(str_rot13($url));
-        $urlToProxy = str_replace("/", "<<SLASH>>", $urlToProxy);
-        $urlToProxy = urlencode($urlToProxy);
+        $parameters = [
+            "host" => $host,
+            "path" => $path,
+            "url" => $url,
+            "valid-until" => $validUntil,
+            "password" => $password,
+        ];
+
+        return route('proxy', $parameters);
+    }
 
-        if ($topLevel) {
-            $params = \Request::all();
+    /**
+     * This function generates a URL to a page that takes submitted form data
+     * excluding the proxy header.
+     */
+    public static function generateFormgetUrl($url){
 
-            # Password
-            $pw = md5(env('PROXY_PASSWORD') . $url);
-            $urlToProxy = base64_encode(str_rot13($url));
-            $urlToProxy = urlencode(str_replace("/", "<<SLASH>>", $urlToProxy));
+        $validUntil = self::generateValidUntilDate();
+        $password = self::generatePassword($url, $validUntil);
 
-            # Params
-            $params['password'] = $pw;
-            $params['url'] = $urlToProxy;
-            
-            $iframeUrl = action('ProxyController@proxyPage', $params);
-        } else {
-            $params = \Request::all();
-            $params['password'] = $password;
-            $params['url'] = $urlToProxy;
-            $params["id"] = $key;
-            
-            $iframeUrl = action('ProxyController@proxy', $params);
+        $parameters = [
+            "url" => $url,
+            "validUntil" => $validUntil,
+            "password" => $password,
+        ];
+
+        return route('proxy-formget', $parameters);
+    }
+
+    /**
+     * This function generates a Date/Time String which is used by our Download Controller
+     * to check if a download link is valid.
+     * This Date/Time is used in the password hash, too to make sure it is not altered
+     */
+    private static function generateValidUntilDate()
+    {
+        $validUntil = Carbon::now()->setTimezone("UTC");
+        $validUntil->addHours(self::PROXYLINKVALIDHOURS);
+
+        return $validUntil->format("d-m-Y H:i:s P");
+    }
+
+    /**
+     * This function generates the password for Download Links
+     * The password is an hmac with the proxy password.
+     * Algo is SHA256
+     * Data is $url . $validUntil or just $url when it should not expire
+     */
+    private static function generatePassword($url, $validUntil)
+    {
+        $data = $url;
+
+        if(!empty($validUntil)){
+            $data .= $validUntil;
         }
 
-        return $iframeUrl;
+        if (!is_string($data) || strlen($data) === 0) {
+            return null;
+        }
+        return hash_hmac("sha256", $data, env("PROXY_PASSWORD", "unsecure_password"));
+    }
+
+    private static function checkPassword($url, $validUntil, $password)
+    {
+        $data = $url;
+
+        if(!empty($validUntil)){
+            $data .= $validUntil;
+        }
+
+        if (!is_string($data) || strlen($data) === 0) {
+            return false;
+        }
+        $excpectedHash = hash_hmac("sha256", $data, env("PROXY_PASSWORD", "unsecure_password"));
+        return hash_equals($excpectedHash, $password);
     }
 
     private function writeLog($targetUrl, $ip)
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index 26548969f8ada798b62cd3c806d75cfc0370621b..da5c03cfed8a6b3a836de6c627d71295139f3537 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -61,7 +61,6 @@ class Kernel extends HttpKernel
         'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
         'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
         'checkpw' => \App\Http\Middleware\CheckPassword::class,
-        'browserverification' => \App\Http\Middleware\Browserverification::class,
     ];
 
     /**
diff --git a/app/Http/Middleware/Browserverification.php b/app/Http/Middleware/Browserverification.php
deleted file mode 100644
index 52a0aa4c607b51b4c7fd5ba3c3b1c61e3ae1c19b..0000000000000000000000000000000000000000
--- a/app/Http/Middleware/Browserverification.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-namespace App\Http\Middleware;
-
-use Closure;
-use Illuminate\Support\Facades\Redis;
-
-class Browserverification
-{
-    /**
-     * Handle an incoming request.
-     *
-     * @param  \Illuminate\Http\Request  $request
-     * @param  \Closure  $next
-     * @return mixed
-     */
-    public function handle($request, Closure $next)
-    {
-        $redis = Redis::connection("central");
-
-        $key = $request->route('id');
-        if (!preg_match("/^[a-f0-9]{32}$/", $key)) {
-            abort(404);
-        }
-
-        $answer = $redis->brpoplpush($key, $key, 3);
-        
-        if ($answer === null) {
-            abort(404);
-        }
-        
-        return $next($request);
-    }
-}
diff --git a/app/Http/Middleware/CheckPassword.php b/app/Http/Middleware/CheckPassword.php
index bfad434cd555f266e4da9e6e73b6fc32c22b7ee2..8ce977d74bd79cbaab53c83ca141f41ec623155d 100644
--- a/app/Http/Middleware/CheckPassword.php
+++ b/app/Http/Middleware/CheckPassword.php
@@ -32,7 +32,7 @@ class CheckPassword
             }
             
             // Check Password:
-            $checkPw  = md5(env('PROXY_PASSWORD') . $targetUrl);
+            $checkPw  = md5(env('PROXY_PASSWORD_OLD') . $targetUrl);
             $password = $request->route('password');
             if ($checkPw === $password) {
                 return $next($request);
diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml
index 66cef14d3fd3a6012059a82210e3c60d8c1eb1d7..228c92625a17b42edd54ff5c79592a590d087a70 100644
--- a/chart/templates/deployment.yaml
+++ b/chart/templates/deployment.yaml
@@ -44,6 +44,10 @@ spec:
     spec:
       imagePullSecrets:
 {{ toYaml .Values.image.secrets | indent 10 }}
+      volumes:
+      - name: env-files
+        secret:
+          secretName: {{ .Values.application.secretName }}
       containers:
       - name: {{ .Chart.Name }}-phpfpm
         image: {{ template "imagename" . }}
@@ -60,6 +64,11 @@ spec:
           value: {{ .Values.gitlab.envName | quote }}
         - name: GITLAB_ENVIRONMENT_URL
           value: {{ .Values.gitlab.envURL | quote }}
+        volumeMounts:
+        - name: env-files
+          mountPath: /html/.env
+          subPath: ENV_FILE
+          readOnly: true
         ports:
         - name: "{{ .Values.service.name }}-phpfpm"
           containerPort: 9000
@@ -130,6 +139,11 @@ spec:
           value: {{ .Values.gitlab.envName | quote }}
         - name: GITLAB_ENVIRONMENT_URL
           value: {{ .Values.gitlab.envURL | quote }}
+        volumeMounts:
+        - name: env-files
+          mountPath: /html/.env
+          subPath: ENV_FILE
+          readOnly: true
         livenessProbe:
           exec:
             command:
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php
index 8d7a9610c7daaf5c50856b363bb27602f9ecdc50..1264ba45ae3baaa67d87c7c48c6b55ced541aada 100644
--- a/resources/views/layouts/app.blade.php
+++ b/resources/views/layouts/app.blade.php
@@ -3,7 +3,6 @@
 <meta charset="utf-8" />
 <title>Proxy - MetaGer</title>
 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
-<link href="/index.css?id={{$key}}" rel="stylesheet" type="text/css" />
 <link href="{{ mix('/css/all.css') }}" rel="stylesheet" type="text/css" />
 </head>
 <body>
diff --git a/routes/web.php b/routes/web.php
index 02a33927647270b875ff3f2882da6329de6eb1f3..8109f5e30e800ce59ea6d4d41ee94dc1e6149644 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -23,28 +23,43 @@ Route::group(['prefix' => 'download'], function () {
     Route::get('/', 'DownloadController@download')->name("download");
 });
 
-Route::get('/', function () {
+// Route for form submissions
+Route::get('formget/{password}/{validUntil}/{url}', 'ProxyController@formget')
+    ->name('proxy-formget')
+    ->where('password', '[A-Fa-f0-9]{64}')
+    ->where('url', '.*');
+// Route without Proxy Header
+Route::get('p/{host?}/{path?}', 'ProxyController@proxy')->name('proxy')->where('host', '[^\.]+(\.[^\.]+)+')->where('path', '(.*)');
+// Route with Proxy Header
+Route::get('{host?}/{path?}', 'ProxyController@proxyPage')->name('proxy-wrapper-page')->where('host', '[^\.]+(\.[^\.]+)+')->where('path', '(.*)');
+
+Route::post('{host?}/{path?}', function (Request $request) {
     if (env("APP_ENV", "") !== "production") {
-        return view("development");
-    } else {
-        return redirect("https://metager.de");
+        $validatedData = $request->validate([
+            'url' => 'required|url|max:255',
+        ]);
+        $url = $request->input('url', 'https://metager.de');
+        return redirect(\App\Http\Controllers\ProxyController::generateProxyWrapperUrl($url));
+    }else{
+        abort(400);
     }
-});
+})->where('host', '[^\.]+(\.[^\.]+)+')->where('path', '(.*)');
 
-Route::get('index.css', 'BrowserVerification@verifyCss');
-
-Route::post('/', function (Request $request) {
-    $validatedData = $request->validate([
-        'url' => 'required|url|max:255',
-    ]);
-    $url = $request->input('url', 'https://metager.de');
-    $password = md5(env('PROXY_PASSWORD') . $url);
-    $url = base64_encode(str_rot13($url));
-    $target = urlencode(str_replace("/", "<<SLASH>>", $url));
-    return redirect(action('ProxyController@proxyPage', ['password' => $password, 'url' => $target]));
-});
+/**
+ * This is our old Proxy route
+ * We will keep it temporarily to help users
+ * migrate to the new ones and redirect to the new one.
+ * 15.01.2021
+ */
+Route::get('{password}/{url}', function(Request $request, $password, $url){
+    $targetUrl = str_replace("<<SLASH>>", "/", $url);
+    $targetUrl = str_rot13(base64_decode($targetUrl));
+    if (strpos($targetUrl, URL::to('/')) === 0) {
+        return redirect($targetUrl);
+    }
 
-Route::get('{password}/{url}', 'ProxyController@proxyPage')->middleware('throttle:60:1')->middleware('checkpw');
+    return redirect(\App\Http\Controllers\ProxyController::generateProxyWrapperUrl($targetUrl));
+})->middleware('throttle:60:1')->middleware('checkpw');
 # Route that triggers streaming of Download
 Route::get('proxy/{password}/{id}/{url}', 'ProxyController@proxy')->middleware('checkpw:true');
 Route::post('proxy/{password}/{id}/{url}', 'ProxyController@streamFile')->middleware('checkpw:true');