Bug 1362443 - Vagrant: Replace varnish with iptables rule

By default webservers like Django's runserver, gunicorn or the
Webpack devserver only bind to the loopback adapter (127.0.0.1) and
so are not accessible from outside the Vagrant / virtualbox VM,
since port forwarding only forwards traffic to the non-loopback
adapters.

Previously varnish (which listened on `0.0.0.0`) was reverse
proxying traffic to runserver/gunicorn, however we need to now do so
for webpack-dev-server on another port too. Doing both with varnish
adds complexity, and we don't actually need any of varnish's other
features, so ideally want to stop using it.

Rather than having to override each webserver to bind to all
adapters (using the IP `0.0.0.0`), it's possible to forward traffic
to the loopback adapter using iptables NAT PREROUTING rules. This
is still secure so long as the Vagrantfile port forwarding uses a
`host_ip` of `127.0.0.1`. To prevent this "Martian packet" traffic
from being blocked, `route_localnet` must also be set to `1`. See:
https://unix.stackexchange.com/questions/111433/iptables-redirect-outside-requests-to-127-0-0-1

By default neither sysctl or iptables settings are persisted across
reboots, and fixing that requires more complexity (eg installing the
iptables-persistent package and handling config changes during
provision). As such, it's just easier to re-run the commands on each
login since they take <30ms.
This commit is contained in:
Ed Morley 2017-05-05 18:13:02 +01:00
Родитель f6e320aa92
Коммит 4735e9d434
6 изменённых файлов: 20 добавлений и 23 удалений

2
Vagrantfile поставляемый
Просмотреть файл

@ -8,7 +8,7 @@ Vagrant.configure("2") do |config|
# required for NFS to work
config.vm.network "private_network", type: "dhcp"
# for web server access from host
config.vm.network "forwarded_port", guest: 80, host: 8000, host_ip: "127.0.0.1"
config.vm.network "forwarded_port", guest: 8000, host: 8000, host_ip: "127.0.0.1"
# for DB access from host
config.vm.network "forwarded_port", guest: 3306, host: 3308, host_ip: "127.0.0.1"

Просмотреть файл

@ -13,7 +13,6 @@ Gunicorn
--------
A wsgi server in charge of serving the restful api and the static UI assets.
All the requests to this server are proxied through Varnish.
Celery task worker
------------------

Просмотреть файл

@ -106,8 +106,12 @@ MIDDLEWARE_CLASSES = [middleware for middleware in [
] if middleware]
if ENABLE_DEBUG_TOOLBAR:
# set INTERNAL_IPS if debug enabled, so the toolbar works
INTERNAL_IPS = ['127.0.0.1']
# django-debug-toolbar requires that not only DEBUG be set, but that the request IP
# be in Django's INTERNAL_IPS setting. When using Vagrant, requests don't come from localhost:
# http://blog.joshcrompton.com/2014/01/how-to-make-django-debug-toolbar-display-when-using-vagrant/
# If the Vagrant IPs vary by platform or if there isn't a consistent IP when we switch to Docker,
# we'll have to do: https://github.com/jazzband/django-debug-toolbar/pull/805#issuecomment-240976813
INTERNAL_IPS = ['127.0.0.1', '10.0.2.2']
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',

Просмотреть файл

@ -1,6 +1,17 @@
# Source .bashrc, since the default .profile we're replacing did so.
. "$HOME/.bashrc"
# Hack to avoid servers having to bind to 0.0.0.0 to be accessible from the VM host (bug 1362443).
# This is still secure so long as the Vagrantfile port forwarding uses a `host_ip` of `127.0.0.1`.
# To prevent this "Martian packet" traffic from being blocked, `route_localnet` has to enabled. See:
# https://unix.stackexchange.com/questions/111433/iptables-redirect-outside-requests-to-127-0-0-1
# By default neither sysctl or iptables settings are persisted across reboots, and fixing that
# requires a bizarre amount of complexity (installing iptables-persistent and then more boilerplate).
# As such, it's just easier to re-run the commands on each login since they take <30ms.
sudo sysctl -q -w net.ipv4.conf.all.route_localnet=1
sudo iptables -t nat --flush
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp -j DNAT --to 127.0.0.1
# Activate the virtualenv.
. "$HOME/venv/bin/activate"

Просмотреть файл

@ -60,7 +60,6 @@ sudo -E apt-get -yqq install --no-install-recommends \
python2.7 \
python2.7-dev \
rabbitmq-server \
varnish \
yarn \
zlib1g-dev
@ -83,13 +82,6 @@ if ! cmp -s vagrant/mysql.cnf /etc/mysql/conf.d/treeherder.cnf; then
sudo service mysql restart
fi
if ! (cmp -s vagrant/varnish.vcl /etc/varnish/default.vcl && grep -q 'DAEMON_OPTS=\"-a :80' /etc/default/varnish); then
echo '-----> Configuring Varnish'
sudo sed -i '/^DAEMON_OPTS=\"-a :6081* / s/6081/80/' /etc/default/varnish
sudo cp vagrant/varnish.vcl /etc/varnish/default.vcl
sudo service varnish restart
fi
if [[ ! -f /usr/local/bin/pip ]]; then
echo '-----> Installing pip'
curl -sSf https://bootstrap.pypa.io/get-pip.py | sudo -H python -
@ -130,5 +122,7 @@ echo '-----> Running Django migrations and loading reference data'
echo '-----> Performing cleanup'
# Celery sometimes gets stuck and requires that celerybeat-schedule be deleted.
rm -f celerybeat-schedule || true
# TODO: Remove in a few weeks.
sudo apt-get remove -y varnish
echo '-----> Setup complete!'

Просмотреть файл

@ -1,11 +0,0 @@
# We use Varnish even for development, since gunicorn/runserver default to 127.0.0.1:8000,
# and to be accessible from outside the VM we'd have to use 0.0.0.0.
backend gunicorn {
.host = "127.0.0.1";
.port = "8000";
}
sub vcl_recv {
set req.backend = gunicorn;
return (pass);
}