Home Forums Support Unable to secure site with SSL with pound reverse proxy server

This topic contains 12 replies, has 2 voices, and was last updated by  Hillel Coren 3 years, 3 months ago.

Viewing 13 posts - 1 through 13 (of 13 total)
  • Author
    Posts
  • #2054

    Anonymous

    Hi everyone!

    After spending almost the entirety of yesterday searching and experimenting with different methods, I am hoping you experts might be able to help me out on this. As some background, I am a tech literate guy, but not to a great extent.

    I have Invoice Ninja running in a Bitnami VM behind a Pound reverse proxy server. When I have this set up and go to any page, my browser (Chrome) states that the website is attempting to run scripts from unauthenticated sources. I have the pound server redirecting all HTTP traffic to the HTTPS address. When I enable the option in the .env file to require HTTPS, I get an error about a redirect loop. When I set this to false, I get the page with almost no styling stating that I am trying to run scripts from unauthenticated sources.

    Some of the things that I tried doing was setting the .env file’s address to use HTTPS, I’ve tried to add the SESSION_ENCRYPT=true and SESSION_SECURE=true lines to the .env file without success.

    If there are any suggestions you can provide, I would be immensely appreciative. This is an amazing project and I hope that I can get this working for production.

    Thank you very much!

    Chris

    #2056

    Hillel Coren
    Keymaster

    Try setting a value for TRUSTED_PROXIES in your .env file.

    Here’s the code from the top of app/Http/Middleware/StartupCheck.php

    // Set up trusted X-Forwarded-Proto proxies
    // TRUSTED_PROXIES accepts a comma delimited list of subnets
    // ie, TRUSTED_PROXIES=’10.0.0.0/8,172.16.0.0/12,192.168.0.0/16′
    if (isset($_ENV[‘TRUSTED_PROXIES’])) {
    Request::setTrustedProxies(array_map(‘trim’, explode(‘,’, env(‘TRUSTED_PROXIES’))));
    }

    #2059

    Anonymous

    Hi Hillel! Thank you for your response! I added TRUSTED_PROXIES=’192.168.1.196/16′ to the .env file and restarted the server and have not had any change. For reference, here’s what my .env file looks like.

    APP_ENV=production
    APP_DEBUG=false
    APP_URL=https://billing.XXX.com
    APP_CIPHER=rijndael-256
    APP_KEY=eKSBhF9xgPMPPR431yIitaYCghIEsI9H

    DB_TYPE=mysql
    DB_STRICT=false
    DB_HOST=localhost
    DB_DATABASE=bitnami_invoiceninja
    DB_USERNAME=bn_invoiceninja
    DB_PASSWORD=XXX

    MAIL_DRIVER=smtp
    MAIL_PORT=587
    MAIL_ENCRYPTION=tls
    MAIL_HOST=smtp.gmail.com
    MAIL_USERNAME=XXX
    MAIL_FROM_ADDRESS=XXX
    MAIL_FROM_NAME=XXX
    MAIL_PASSWORD=XXX

    PHANTOMJS_CLOUD_KEY=’a-demo-eKSBhF9xgPMPPR431yIitaYCghIEsI9H-with-low-quota-per-ip-address’
    LOG=single
    REQUIRE_HTTPS=true

    GOOGLE_CLIENT_ID
    GOOGLE_CLIENT_SECRET
    GOOGLE_OAUTH_REDIRECT=http://ninja.dev/auth/google

    TRUSTED_PROXIES=’192.168.1.196/16′

    SESSION_ENCRYPT=true
    SESSION_SECURE=true

    The login page still just consists of the text boxes without the styling. I checked the source of the page and its still trying to point to the HTTP address of everything. Any other suggestions or am I not understanding this option?

    #2060

    Anonymous

    I also meant to mention that 192.168.1.196 is the reverse proxy server.

    #2061

    Hillel Coren
    Keymaster

    If there’s no styling that makes me think this is a problem with the app itself, not the reverse proxy.

    Can you check either your browser’s console or storage/logs/laravel.log for details on the error.

    #2062

    Anonymous

    The last error block in the laravel.log file is below. It There is one identical error like this earlier but given how often the page is being accessed, it does not look like any relevant errors are popping up in this log. What I notice as interesting is that when I inspect the page source of the login page, I see that all references are being made with HTTP as opposed to HTTPS. Is there a way to hardcode that HTTP so that it is not being dynamically generated?

    [2016-01-19 00:35:03] production.ERROR: exception ‘Illuminate\Session\TokenMismatchException’ in /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php:2550
    Stack trace:
    #0 /opt/bitnami/apps/invoiceninja/htdocs/app/Http/Middleware/VerifyCsrfToken.php(39): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))
    #1 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(9236): App\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))
    #2 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(12416): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
    #3 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(9236): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
    #4 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(11106): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
    #5 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(9236): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
    #6 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(12118): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
    #7 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(9236): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
    #8 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(12066): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
    #9 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(9236): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
    #10 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(2589): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
    #11 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(9236): Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
    #12 [internal function]: Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
    #13 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(9227): call_user_func(Object(Closure), Object(Illuminate\Http\Request))
    #14 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(1996): Illuminate\Pipeline\Pipeline->then(Object(Closure))
    #15 /opt/bitnami/apps/invoiceninja/htdocs/vendor/compiled.php(1983): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
    #16 /opt/bitnami/apps/invoiceninja/htdocs/public/index.php(53): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
    #17 {main}

    #2063

    Anonymous

    When I tell the browser to allow the unsafe scripts to run, the page renders normally. Also, when I direct port 443 to the VM directly, everything works great. It’s only when funneled through the reverse proxy that these issues arise. As I am planning to host other sites, forwarding standard port 443 directly to the VM is not an option.

    #2064

    Hillel Coren
    Keymaster

    To force HTTP you could set REQUIRE_HTTPS=true in your .env file.

    You could try clearing you browser cookies to resolve TokenMismatchException errors.

    #2065

    Anonymous

    Setting REQUIRE_HTTPS=true generates a redirect loop. The HTTPS request comes in through the reverse proxy server, decrypted, and sent via HTTP to the Bitnami VM hosting Invoice Ninja. My guess is that Invoice Ninja sees the funneled decrypted traffic as HTTP and requires HTTPS. This new request loops through the reverse proxy server where it is decrypted into HTTP and hits Invoice Ninja again generating this same loop.

    #2066

    Hillel Coren
    Keymaster

    I’m not sure, you may be find more info online if you search for ‘laravel reverse proxy’.

    #2067

    Anonymous

    Got it! I’m so happy I can barely contain myself! I want to post my configuration here so anyone in my shoes can fix this and maybe help the community out!

    Instead of searching for reverse proxy information specifically with Invoice Ninja, I followed your advise and searched ‘laravel reverse proxy’ like you suggested. That led me to this page: https://kura.io/2011/09/29/load-balancing-httphttps-with-pound-on-debian-6ubuntu/

    This web page told me to add the
    AddHeader "X-Forwarded-Proto: https"
    option to my Pound server configuration. This means that my configuration for pound looks like this:

    ListenHTTPS
            Address 0.0.0.0
            Port    443
            AddHeader "X-Forwarded-Proto: https"
            Cert    "/path/to/cert"
            CAList  "/path/to/cabundle"
    
            Service
                    HeadRequire "Host:.billing.xxx.com.*"
                    BackEnd
                            Address 192.168.1.197
                            Port 80
                    End
            End
    End

    As soon as I implemented this and restarted the server, everything worked beautifully. Thank you so much for your help Hillel and I hope this helps anyone who is running into this issue like me! I look forward to pushing Invoice Ninja into production!

    #2068

    Anonymous

    Oh also, here’s what my .env file ended up looking like:

    APP_ENV=production
    APP_DEBUG=false
    APP_URL=https://billing.xxx.com
    APP_CIPHER=rijndael-256
    APP_KEY=****************************
    
    DB_TYPE=mysql
    DB_STRICT=false
    DB_HOST=localhost
    DB_DATABASE=bitnami_invoiceninja
    DB_USERNAME=*********************
    DB_PASSWORD=*********************
    
    MAIL_DRIVER=smtp
    MAIL_PORT=587
    MAIL_ENCRYPTION=tls
    MAIL_HOST=smtp.gmail.com
    MAIL_USERNAME=xxx
    MAIL_FROM_ADDRESS=xxx
    MAIL_FROM_NAME=xxx
    MAIL_PASSWORD=xxx
    
    PHANTOMJS_CLOUD_KEY='a-demo-key-with-low-quota-per-ip-address'
    LOG=single
    REQUIRE_HTTPS=true
    
    GOOGLE_CLIENT_ID
    GOOGLE_CLIENT_SECRET
    GOOGLE_OAUTH_REDIRECT=http://ninja.dev/auth/google
    
    TRUSTED_PROXIES='192.168.1.196/24'
    
    SESSION_ENCRYPT=true
    SESSION_SECURE=true
    #2069

    Hillel Coren
    Keymaster

    Thanks for sharing your working configuration, happy to hear your time hasn’t been wasted.

    Let us know if you run into any other issues.

Viewing 13 posts - 1 through 13 (of 13 total)

You must be logged in to reply to this topic.

Posted in: