Uploaded image for project: 'Moodle'
  1. Moodle
  2. MDL-63770

Moodle doesn't work when external port number doesn't equal internal

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 3.5, 3.10.5, 3.11.1
    • Fix Version/s: 3.10.6, 3.11.2
    • Component/s: General
    • Labels:
    • Affected Branches:
      MOODLE_310_STABLE, MOODLE_311_STABLE, MOODLE_35_STABLE
    • Fixed Branches:
      MOODLE_310_STABLE, MOODLE_311_STABLE
    • Pull from Repository:
    • Pull 3.10 Branch:
      m310_MDL-63770_Allow_Unbalanced_Port_On_Reverse_Proxying
    • Pull 3.11 Branch:
      m311_MDL-63770_Allow_Unbalanced_Port_On_Reverse_Proxying
    • Pull Master Branch:
      m40_MDL-63770_Allow_Unbalanced_Port_On_Reverse_Proxying
    • Difficulty:
      Easy
    • Testing Instructions:
      Hide

      (difficulty: moderate, requires the ability to install the Moodle database using the CLI command and to understand on how the supposed web server port - below Apache, https://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalname and https://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalphysicalport - is evaluated and then passed via PHP into $_SERVER['port'])

      Prepare the test environment

      1. You can use the Moodle Docker Toolbox, by selecting any DB Server - the fastest in your setup - and prepare the Moodle DB:

        # export MOODLE_DOCKER_WWWROOT=/path/to/moodle/moodle/
        # export MOODLE_DOCKER_PHP_VERSION=7.3
        # export MOODLE_DOCKER_DB=mysql
        # export MOODLE_DOCKER_WEB_HOST=<Docker Engine IP/Host e.g. 1.2.3.4, even 127.0.0.1>
        # export MOODLE_DOCKER_WEB_PORT=81
        # cp config.docker-template.php $MOODLE_DOCKER_WWWROOT/config.php
        # bin/moodle-docker-compose up -d
        # Check the public port for the private port 80/tcp binding: it should be 81
        # bin/moodle-docker-compose port webserver 80
        127.0.0.1:81
        

        Due to the localhost binding above - it depends on your Docker environment versions - , if your Docker Host is running on a different host you should apply the following change to moodle-docker code:

        # bin/moodle-docker-compose down -v
        $ git diff
        diff --git a/webserver.port.yml b/webserver.port.yml
        index bff93e6..0edfdb7 100644
        --- a/webserver.port.yml
        +++ b/webserver.port.yml
        @@ -2,6 +2,7 @@ version: "2"
         services:
           webserver:
             environment:
        +      MOODLE_DOCKER_WEB_HOST: "${MOODLE_DOCKER_WEB_HOST}"
               MOODLE_DOCKER_WEB_PORT: "${MOODLE_DOCKER_WEB_PORT}"
             ports:
        -      - "${MOODLE_DOCKER_WEB_PORT}:80"
        +      - "${MOODLE_DOCKER_WEB_HOST}:${MOODLE_DOCKER_WEB_PORT}:80"
        

        and re-apply the sequence of command above to get:

        # bin/moodle-docker-compose port webserver 80
        0.0.0.0:81
        

        Finally:

        # bin/moodle-docker-compose exec webserver php admin/cli/install_database.php --agree-license \
              --fullname="Docker Moodle Test MDL-63770" --shortname="docker_moodle_MDL-63770" \
              --adminpass="test" --adminemail="admin@example.com"
        -------------------------------------------------------------------------------
        == Setting up database ==
        -->System
        [...]
        -->logstore_standard
        ++ Success ++
        Installation completed successfully.
        

      Test

      1. On the same shell (just to preserve the ENV VARs above), issue the following commands:

        # cp config.docker-template.php $MOODLE_DOCKER_WWWROOT/config.php
        # bin/moodle-docker-compose up -d
        # bin/moodle-docker-compose port webserver 80
        0.0.0.0:81
        # bin/moodle-docker-compose exec webserver php admin/cli/install_database.php --agree-license \
              --fullname="Docker Moodle Test MDL-63770" --shortname="docker_moodle_MDL-63770" \
              --adminpass="test" --adminemail="admin@example.com"
        -------------------------------------------------------------------------------
        == Setting up database ==
        -->System
        [...]
        -->logstore_standard
        ++ Success ++
        Installation completed successfully.
        

      2. [EXPECTED] Browse the hostname above, prepending http:// and using the public port above (81): Moodle home appears and you are able to successfully log in as admin/test. Log out and close the browser.
      3. Change the Web Server configuration:

        # bin/moodle-docker-compose exec webserver sh -c 'echo "UseCanonicalName On\nUseCanonicalPhysicalPort On" > /etc/apache2/conf-enabled/usecanonicalphysicalport.conf'
        # bin/moodle-docker-compose restart webserver
        

      4. [EXPECTED] Try browsing the same home: you'll still get an error from your browser telling about too many redirects, like: ERR_TOO_MANY_REDIRECTS
      5. **Allow Port Forwarding by enabling Reverse Proxy setting in Moodle:

        # sed -i '$i ''$CFG->reverseproxy = true;' $MOODLE_DOCKER_WWWROOT/config.php
        

      6. [EXPECTED] Browse again the same target above: no more redirects, the home will appear and you'll be able to log into Moodle
      7. Stop the environment:

        # bin/moodle-docker-compose down -v
        

      Show
      (difficulty: moderate, requires the ability to install the Moodle database using the CLI command and to understand on how the supposed web server port - below Apache,  https://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalname and  https://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalphysicalport - is evaluated and then passed via PHP into $_SERVER ['port'] ) Prepare the test environment You can use the Moodle Docker Toolbox, by selecting any DB Server - the fastest in your setup - and prepare the Moodle DB: # export MOODLE_DOCKER_WWWROOT=/path/to/moodle/moodle/ # export MOODLE_DOCKER_PHP_VERSION=7.3 # export MOODLE_DOCKER_DB=mysql # export MOODLE_DOCKER_WEB_HOST=<Docker Engine IP/Host e.g. 1.2.3.4, even 127.0.0.1> # export MOODLE_DOCKER_WEB_PORT=81 # cp config.docker-template.php $MOODLE_DOCKER_WWWROOT/config.php # bin/moodle-docker-compose up -d # Check the public port for the private port 80/tcp binding: it should be 81 # bin/moodle-docker-compose port webserver 80 127.0.0.1:81 Due to the localhost binding above - it depends on your Docker environment versions - , if your Docker Host is running on a different host you should apply the following change to moodle-docker code: # bin/moodle-docker-compose down -v $ git diff diff --git a/webserver.port.yml b/webserver.port.yml index bff93e6..0edfdb7 100644 --- a/webserver.port.yml +++ b/webserver.port.yml @@ -2,6 +2,7 @@ version: "2" services: webserver: environment: + MOODLE_DOCKER_WEB_HOST: "${MOODLE_DOCKER_WEB_HOST}" MOODLE_DOCKER_WEB_PORT: "${MOODLE_DOCKER_WEB_PORT}" ports: - - "${MOODLE_DOCKER_WEB_PORT}:80" + - "${MOODLE_DOCKER_WEB_HOST}:${MOODLE_DOCKER_WEB_PORT}:80" and re-apply the sequence of command above to get: # bin/moodle-docker-compose port webserver 80 0.0.0.0:81 Finally: # bin/moodle-docker-compose exec webserver php admin/cli/install_database.php --agree-license \ --fullname="Docker Moodle Test MDL-63770" --shortname="docker_moodle_MDL-63770" \ --adminpass="test" --adminemail="admin@example.com" ------------------------------------------------------------------------------- == Setting up database == -->System [...] -->logstore_standard ++ Success ++ Installation completed successfully. Test On the same shell (just to preserve the ENV VARs above), issue the following commands: # cp config.docker-template.php $MOODLE_DOCKER_WWWROOT/config.php # bin/moodle-docker-compose up -d # bin/moodle-docker-compose port webserver 80 0.0.0.0:81 # bin/moodle-docker-compose exec webserver php admin/cli/install_database.php --agree-license \ --fullname="Docker Moodle Test MDL-63770" --shortname="docker_moodle_MDL-63770" \ --adminpass="test" --adminemail="admin@example.com" ------------------------------------------------------------------------------- == Setting up database == -->System [...] -->logstore_standard ++ Success ++ Installation completed successfully. [EXPECTED] Browse the hostname above, prepending http:// and using the public port above ( 81 ): Moodle home appears and you are able to successfully log in as admin / test . Log out and close the browser. Change the Web Server configuration: # bin/moodle-docker-compose exec webserver sh -c 'echo "UseCanonicalName On\nUseCanonicalPhysicalPort On" > /etc/apache2/conf-enabled/usecanonicalphysicalport.conf' # bin/moodle-docker-compose restart webserver [EXPECTED] Try browsing the same home: you'll still get an error from your browser telling about too many redirects, like: ERR_TOO_MANY_REDIRECTS **Allow Port Forwarding by enabling Reverse Proxy setting in Moodle: # sed -i '$i ''$CFG->reverseproxy = true;' $MOODLE_DOCKER_WWWROOT/config.php [EXPECTED] Browse again the same target above: no more redirects, the home will appear and you'll be able to log into Moodle Stop the environment: # bin/moodle-docker-compose down -v

      Description

      I'm running Moodle 3.5 stable in a docker container (nginx + php-fpm). External port number doesn't match internal port number (e.g. 8080:80).

      This setup causes an infinite redirect, because the port numbers don't match here: https://github.com/dimaip/moodle/blob/c092f75791be10f8f2ee382cd73ac1cdcf3a6feb/lib/setuplib.php#L852

      I tried to enable `$CFG->reverseproxy` to circumvent the problem. That gives me `Reverse proxy enabled, server can not be accessed directly, sorry` error becuase that check only evaluates host names, and not port numbers.

      A possible fix would be  to change this line https://github.com/moodle/moodle/blob/master/lib/setuplib.php#L907

      into `if (!empty($CFG->reverseproxy) && $rurl['host'] === $wwwroot['host'] && $rurl['port'] === $wwwroot['port']) {`

      For reference, my container has these fastcgi params: https://github.com/psmb/docker-neos-alpine/blob/master/root/etc/nginx/fastcgi_params

      To reproduce

      Prepare the test environment

      1. You can use the Moodle Docker Toolbox, by selecting any DB Server - the fastest in your setup - and prepare the Moodle DB:

        # export MOODLE_DOCKER_WWWROOT=/path/to/moodle/moodle/
        # export MOODLE_DOCKER_PHP_VERSION=7.3
        # export MOODLE_DOCKER_DB=mysql
        # export MOODLE_DOCKER_WEB_HOST=<Docker Engine IP/Host e.g. 1.2.3.4, even 127.0.0.1>
        # export MOODLE_DOCKER_WEB_PORT=81
        # cp config.docker-template.php $MOODLE_DOCKER_WWWROOT/config.php
        # bin/moodle-docker-compose up -d
        # Check the public port for the private port 80/tcp binding: it should be 81
        # bin/moodle-docker-compose port webserver 80
        127.0.0.1:81
        

        Due to the localhost binding above - it depends on your Docker environment versions - , if your Docker Host is running on a different host you should apply the following change to moodle-docker code:

        # bin/moodle-docker-compose down -v
        $ git diff
        diff --git a/webserver.port.yml b/webserver.port.yml
        index bff93e6..0edfdb7 100644
        --- a/webserver.port.yml
        +++ b/webserver.port.yml
        @@ -2,6 +2,7 @@ version: "2"
         services:
           webserver:
             environment:
        +      MOODLE_DOCKER_WEB_HOST: "${MOODLE_DOCKER_WEB_HOST}"
               MOODLE_DOCKER_WEB_PORT: "${MOODLE_DOCKER_WEB_PORT}"
             ports:
        -      - "${MOODLE_DOCKER_WEB_PORT}:80"
        +      - "${MOODLE_DOCKER_WEB_HOST}:${MOODLE_DOCKER_WEB_PORT}:80"
        

        and re-apply the sequence of command above to get:

        # bin/moodle-docker-compose port webserver 80
        0.0.0.0:81
        

        Finally:

        # bin/moodle-docker-compose exec webserver php admin/cli/install_database.php --agree-license \
              --fullname="Docker Moodle Test MDL-63770" --shortname="docker_moodle_MDL-63770" \
              --adminpass="test" --adminemail="admin@example.com"
        -------------------------------------------------------------------------------
        == Setting up database ==
        -->System
        [...]
        -->logstore_standard
        ++ Success ++
        Installation completed successfully.
        

      Before applying the fix

      1. [EXPECTED] Browse the hostname above, prepending http:// and using the public port above (81): Moodle home appears and you are able to successfully log in as admin/test. Log out and close the browser.
      2. Change the Web Server configuration:

        # bin/moodle-docker-compose exec webserver sh -c 'echo "UseCanonicalName On\nUseCanonicalPhysicalPort On" > /etc/apache2/conf-enabled/usecanonicalphysicalport.conf'
        # bin/moodle-docker-compose restart webserver
        

      3. [EXPECTED] Try browsing the same home: you'll get an error from your browser telling about too many redirects, like: ERR_TOO_MANY_REDIRECTS
      4. Allow Port Forwarding by enabling Reverse Proxy setting in Moodle:

        # sed -i '$i ''$CFG->reverseproxy = true;' $MOODLE_DOCKER_WWWROOT/config.php
        

      5.  [ERROR] Browse again the same target above: no more redirects but Error code: reverseproxyabused
      6. Stop the environment, without closing the shell

        # bin/moodle-docker-compose down -v
        

       

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              matteo Matteo Scaramuccia
              Reporter:
              dimaip dimaip
              Peer reviewer:
              Jordi Pujol-Ahulló Jordi Pujol-Ahulló
              Integrator:
              Jun Pataleta Jun Pataleta
              Tester:
              Huong Nguyen Huong Nguyen
              Participants:
              Component watchers:
              Adrian Greeve, Jake Dallimore, Mathew May, Mihail Geshoski, Peter Dias, Sujith Haridasan
              Votes:
              4 Vote for this issue
              Watchers:
              13 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Fix Release Date:
                29/Jul/21

                  Time Tracking

                  Estimated:
                  Original Estimate - 0 minutes
                  0m
                  Remaining:
                  Remaining Estimate - 0 minutes
                  0m
                  Logged:
                  Time Spent - 5 hours
                  5h