Rethink how proxied headers are handled

- Request Apache to send X-Forwarded-Proto header.

- Use X-Forwarded-Proto header to understand original protocol
  requested.

- Use X-Forwarded-Host header to understand original host requested.

- Allow any incoming host header so that FreedomBox can have any
  hostname and when user requests for Plint with that hostname, it
  works.

- Don't depend on Apache to rewrite the Location: header.  Instead use
  the original host and original scheme to set proper Location: header.
This commit is contained in:
Sunil Mohan Adapa 2014-11-14 22:26:09 +05:30
parent eec249d006
commit 1b6969a8a6
5 changed files with 47 additions and 5 deletions

View File

@ -5,7 +5,8 @@
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
## Use HTTP Strict Transport Security to force client to use secure connections only ## Use HTTP Strict Transport Security to force client to use secure
## connections only
Header always set Strict-Transport-Security "max-age=31536000" Header always set Strict-Transport-Security "max-age=31536000"
## Shared options. ## Shared options.
@ -28,7 +29,7 @@
## Make sure to provide plinth with a default directory: /plinth ## Make sure to provide plinth with a default directory: /plinth
<Location /plinth> <Location /plinth>
ProxyPass http://localhost:8000/plinth ProxyPass http://localhost:8000/plinth
ProxyPassReverse http://localhost:8000/plinth RequestHeader set X-Forwarded-Proto 'https' env=HTTPS
Order Deny,Allow Order Deny,Allow
Deny from All Deny from All

View File

@ -22,3 +22,18 @@ pidfile = %(pid_dir)s/plinth.pid
[Network] [Network]
host = 127.0.0.1 host = 127.0.0.1
port = 8000 port = 8000
# Enable the following only if Plinth is behind a proxy server. The
# proxy server should properly clean and the following HTTP headers:
# X-Forwarded-Host
# X-Forwarded-Proto
# If you enable these unnecessarily, this will lead to serious security
# problems. For more information, see
# https://docs.djangoproject.com/en/1.7/ref/settings/
#
# These are enabled by default in Plinth because the default
# configuration allows only connections from localhost
#
# Leave the values blank to disable
use_x_forwarded_host = True
secure_proxy_ssl_header = HTTP_X_FORWARDED_PROTO

View File

@ -22,3 +22,18 @@ pidfile = %(pid_dir)s/plinth.pid
[Network] [Network]
host = 127.0.0.1 host = 127.0.0.1
port = 8000 port = 8000
# Enable the following only if Plinth is behind a proxy server. The
# proxy server should properly clean and the following HTTP headers:
# X-Forwarded-Host
# X-Forwarded-Proto
# If you enable these unnecessarily, this will lead to serious security
# problems. For more information, see
# https://docs.djangoproject.com/en/1.7/ref/settings/
#
# These are enabled by default in Plinth because the default
# configuration allows only connections from localhost
#
# Leave the values blank to disable
use_x_forwarded_host = True
secure_proxy_ssl_header = HTTP_X_FORWARDED_PROTO

View File

@ -182,8 +182,13 @@ def configure_django():
'plinth'] 'plinth']
applications += module_loader.get_modules_to_load() applications += module_loader.get_modules_to_load()
sessions_directory = os.path.join(cfg.data_dir, 'sessions') sessions_directory = os.path.join(cfg.data_dir, 'sessions')
secure_proxy_ssl_header = None
if cfg.secure_proxy_ssl_header:
secure_proxy_ssl_header = (cfg.secure_proxy_ssl_header, 'https')
django.conf.settings.configure( django.conf.settings.configure(
ALLOWED_HOSTS=['127.0.0.1', 'localhost'], ALLOWED_HOSTS=['*'],
CACHES={'default': CACHES={'default':
{'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}, {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}},
DATABASES={'default': DATABASES={'default':
@ -205,10 +210,12 @@ def configure_django():
'plinth.modules.first_boot.middleware.FirstBootMiddleware', 'plinth.modules.first_boot.middleware.FirstBootMiddleware',
), ),
ROOT_URLCONF='plinth.urls', ROOT_URLCONF='plinth.urls',
SECURE_PROXY_SSL_HEADER=secure_proxy_ssl_header,
SESSION_ENGINE='django.contrib.sessions.backends.file', SESSION_ENGINE='django.contrib.sessions.backends.file',
SESSION_FILE_PATH=sessions_directory, SESSION_FILE_PATH=sessions_directory,
STATIC_URL='/'.join([cfg.server_dir, 'static/']).replace('//', '/'), STATIC_URL='/'.join([cfg.server_dir, 'static/']).replace('//', '/'),
TEMPLATE_CONTEXT_PROCESSORS=context_processors) TEMPLATE_CONTEXT_PROCESSORS=context_processors,
USE_X_FORWARDED_HOST=bool(cfg.use_x_forwarded_host))
django.setup() django.setup()
LOGGER.info('Configured Django with applications - %s', applications) LOGGER.info('Configured Django with applications - %s', applications)

View File

@ -34,6 +34,8 @@ access_log_file = None
pidfile = None pidfile = None
host = None host = None
port = None port = None
use_x_forwarded_host = False
secure_proxy_ssl_header = None
debug = False debug = False
no_daemon = False no_daemon = False
server_dir = '/' server_dir = '/'
@ -75,7 +77,9 @@ def read():
('Path', 'access_log_file'), ('Path', 'access_log_file'),
('Path', 'pidfile'), ('Path', 'pidfile'),
('Network', 'host'), ('Network', 'host'),
('Network', 'port')} ('Network', 'port'),
('Network', 'secure_proxy_ssl_header'),
('Network', 'use_x_forwarded_host')}
for section, name in config_items: for section, name in config_items:
try: try: