Websocket + SSL в AWS Application Balancer - PullRequest
       47

Websocket + SSL в AWS Application Balancer

0 голосов
/ 04 сентября 2018

У меня есть приложение Django, развернутое на ElastickBeanstalk. Недавно я перенес балансировщик нагрузки из Classic -> Application для поддержки Websocket (слой, образованный: Django-channel (~ = 1.1.8, channel-api == 0.4.0), Redis Elasticache AWS и Daphne (~ = 1.4)). HTTP, HTTPS и протокол Web Socket работают нормально.

Но я не могу найти способ развернуть Websocket через Secure SSL. Это убивает меня и блокирует, поскольку HTTPS-соединение с браузером обрезает незащищенные запросы ws: // peer.

Вот моя конфигурация ALB У кого-нибудь есть решение проблемы?

enter image description here

Ответы [ 3 ]

0 голосов
/ 17 октября 2018

Я также много боролся с SSL, EBS и каналами 1.x, с тем же сценарием, который вы описали, но, наконец, я смог развернуть свое приложение. SSL всегда был проблемой, поскольку Django игнорировал мои маршруты в файле routing.py для всех запросов SSL, и до этого все работало просто отлично.

Я решил отправить все запросы websockets на уникальный корневой путь на сервере, скажем, /ws/*. Затем добавили конкретное правило в балансировщик нагрузки, который получает все эти запросы через порт 443 и перенаправляет их на порт 5000 (который слушает работник Daphne) в виде HTTP-запроса (не HTTPS!). Это, исходя из предположения, что за балансировщиком нагрузки VPC достаточно безопасен. Помните, что эта конфигурация может быть связана с проблемами безопасности для других проектов.

Теперь моя конфигурация балансировщика нагрузки выглядит следующим образом enter image description here

... поскольку HTTPS-соединение из браузера отключает небезопасные запросы ws: // peer.

Еще одна вещь. Вы должны начать соединения через сокет через HTTPS с wss://. Вы можете написать что-то подобное в вашем файле .js.

var wsScheme = window.location.protocol.includes('https') ? 'wss' : 'ws';
var wsPath = wsScheme + '://' + window.location.host + '/your/ws/path';
var ws = new ReconnectingWebSocket(wsPath);

Удачи!

0 голосов
/ 18 октября 2018

После еще 2 дней расследования я наконец взломал этот конфиг!

Вот ответ:

  1. Право, и МИНИМАЛЬНЫЕ, aws - ALB Config: enter image description here Действительно, нам нужно

    • Декодирование SSL (это не сквозное шифрование)
    • Вперед Весь трафик в Дафну. Причина, по которой я не пошел на очень распространенное в сети conf: «/ ws / *» маршрутизация к Дафне, заключается в том, что она действительно дала мне рукопожатие, но после этого ничто, nada, websocket не могло быть возвращено к подписчик. Я полагаю, что причина в том, что откат от Дафни не учитывает конечный URL-адрес пользовательской базы, который вы настраиваете в своей конфигурации. Кроме того, я не могу быть уверен в этой интерпретации. Однако я уверен в том, что если я не перенаправлю весь трафик на Дафну, он не будет работать после рукопожатия.

      1. Минимальное развертывание CONF
    • НЕТ НЕОБХОДИМОСТИ полного прокси переопределения .ebextension в развертывании:

enter image description here .ebextensions / 05_channels.config

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/post/start_supervisor.sh":
  mode: "000755"
  owner: root
  group: root
  content: |
    #!/usr/bin/env bash
    sudo virtualenv -p /usr/bin/python2.7 /tmp/senv
    source /tmp/senv/bin/activate && source /opt/python/current/env
    sudo python --version > /tmp/version_check.txt
    sudo pip install supervisor

    sudo /usr/local/bin/supervisord -c /opt/python/current/app/fxf/custom_eb_deployment/supervisord.conf
    sudo /usr/local/bin/supervisorctl -c /opt/python/current/app/fxf/custom_eb_deployment/supervisord.conf reread
    sudo /usr/local/bin/supervisorctl -c /opt/python/current/app/fxf/custom_eb_deployment/supervisord.conf update
    sudo /usr/local/bin/supervisorctl -c /opt/python/current/app/fxf/custom_eb_deployment/supervisord.conf restart all
    sudo /usr/local/bin/supervisorctl -c /opt/python/current/app/fxf/custom_eb_deployment/supervisord.conf status
  • start_daphne.sh (замечание, я выбираю порт 8001, согласно моей конфигурации ALB)

    #!/usr/bin/env bash source /opt/python/run/venv/bin/activate && source /opt/python/current/env /opt/python/run/venv/bin/daphne -b 0.0.0.0 -p 8001 fxf.asgi:channel_layer

  • start_worker.sh

    #!/usr/bin/env bash source /opt/python/run/venv/bin/activate && source /opt/python/current/env python /opt/python/current/app/fxf/manage.py runworker

  • supervisord.conf

`

[unix_http_server]
file=/tmp/supervisor.sock   ; (the path to the socket file)

[supervisord]
logfile=/tmp/supervisord.log ; supervisord log file
loglevel=error ; info, debug, warn, trace
logfile_maxbytes=50MB        ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10           ; (num of main logfile rotation backups;default 10)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false               ; (start in foreground if true;default false)
minfds=1024                  ; (min. avail startup file descriptors;default 1024)
minprocs=200                 ; (min. avail process descriptors;default 200)

; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket

[program:Daphne]
environment=PATH="/opt/python/run/venv/bin"
command=sh /opt/python/current/app/fxf/custom_eb_deployment/start_daphne.sh --log-file /tmp/start_daphne.log
directory=/opt/python/current/app
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/tmp/daphne.out.log
stderr_logfile=/tmp/daphne.err.log

[program:Worker]
environment=PATH="/opt/python/run/venv/bin"
command=sh /opt/python/current/app/fxf/custom_eb_deployment/start_worker.sh --log-file /tmp/start_worker.log
directory=/opt/python/current/app
process_name=%(program_name)s_%(process_num)02d
numprocs=2
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/tmp/workers.out.log
stderr_logfile=/tmp/workers.err.log

; When resorting to send SIGKILL to the program to terminate it
; send SIGKILL to its whole process group instead,
; taking care of its children as well.
killasgroup=true

`

Если кто-то все еще борется с этим конфом, я мог бы опубликовать туто в среду или что-то в этом роде. Не стесняйтесь подталкивать меня к ответам;)

0 голосов
/ 05 сентября 2018

вы должны использовать wss: // вместо ws: //. и поменяй настройки про прокси. Я только что добавил свой wsgi.conf.

<VirtualHost *:80>

WSGIPassAuthorization On

WSGIScriptAlias / /opt/python/current/app/config/wsgi.py

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule .* https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]

LoadModule proxy_wstunnel_module /usr/lib/apache2/modules/mod_proxy_wstunnel.so

ProxyPreserveHost On
ProxyRequests Off

ProxyPass "/ws/chat" "ws://**your site**/ws/chat" Keepalive=On
ProxyPassReverse "/ws/chat" "ws://**your site**/ws/chat" Keepalive=On

<Directory /opt/python/current/app/>
  Require all granted
</Directory>

</VirtualHost>

тогда это даст вам 200 статус для подключения. "/ ws / chat /" должен быть заменен вашим URL веб-сокета.

Прежде чем создавать этот файл, вы должны убедиться, что ваш daphne сервер включен. Проблемы, с которыми я столкнулся - это djangoenv и работник для daemon.config.

Во-первых, djangoenv должен быть в одной строке. Это означает отсутствие разрыва строки. во-вторых, если вы используете django канал v2, то он не нуждается в работнике. так что сотри его.

это мой daemon.config (я использую порт 8001):

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/post/run_supervised_daemon.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash

      # Get django environment variables
      djangoenv=`cat /opt/python/current/env | tr '\n' ',' | sed 's/%/%%/g' | sed 's/export //g' | sed 's/$PATH/%(ENV_PATH)s/g' | sed 's/$PYTHONPATH//g' | sed 's/$LD_LIBRARY_PATH//g'`
      djangoenv=${djangoenv%?}

      # Create daemon configuraiton script
      daemonconf="[program:daphne]
      ; Set full path to channels program if using virtualenv
      command=/opt/python/run/venv/bin/daphne -b 0.0.0.0 -p 8001 config.asgi:application
      directory=/opt/python/current/app
      user=ec2-user
      numprocs=1
      stdout_logfile=/var/log/stdout_daphne.log
      stderr_logfile=/var/log/stderr_daphne.log
      autostart=true
      autorestart=true
      startsecs=10

      ; Need to wait for currently executing tasks to finish at shutdown.
      ; Increase this if you have very long running tasks.
      stopwaitsecs = 600

      ; When resorting to send SIGKILL to the program to terminate it
      ; send SIGKILL to its whole process group instead,
      ; taking care of its children as well.
      killasgroup=true

      ; if rabbitmq is supervised, set its priority higher
      ; so it starts first
      priority=998

      environment=$djangoenv"

      # Create the supervisord conf script
      echo "$daemonconf" | sudo tee /opt/python/etc/daemon.conf

      # Add configuration script to supervisord conf (if not there already)
      if ! grep -Fxq "[include]" /opt/python/etc/supervisord.conf
          then
          echo "[include]" | sudo tee -a /opt/python/etc/supervisord.conf
          echo "files: daemon.conf" | sudo tee -a /opt/python/etc/supervisord.conf
      fi

      # Reread the supervisord config
      sudo /usr/local/bin/supervisorctl -c /opt/python/etc/supervisord.conf reread

      # Update supervisord in cache without restarting all services
      sudo /usr/local/bin/supervisorctl -c /opt/python/etc/supervisord.conf update

      # Start/Restart processes through supervisord
      sudo /usr/local/bin/supervisorctl -c /opt/python/etc/supervisord.conf restart daphne

И еще раз проверьте вашу группу безопасности alb до ec2. удачи!

...