我有一个 GKE 私有 k8s 集群,其中运行着 nginx 和一个使用 wsgi 和 asgi 运行的 django 应用程序。nginx 的日志显示 websocket 请求获得 403,而 daphne pod 上的日志显示“拒绝访问”类型的错误。我还有一个运行相同应用程序的集群,但不在这些 websocket 正常运行的 VPC 内。
我不介意 nginx 流量通过 wsgi 传输到由 django api 驱动的 React 应用。但此服务包含一些“聊天”功能,该功能依赖于运行 Daphne 服务器的 pod 来提供 websocket 和 django-channels 来提供应用程序集成。
集群由 helm 管理,包括 nginx 配置和 daphne pod。以下是 nginx 配置的关键部分;
server {
listen 80;
server_name {{ range .domains }}{{ .host }} {{ end -}};
root /usr/src/app/;
if ($http_x_forwarded_proto != "https") {
return 301 https://$host$request_uri;
}
location / {
try_files $uri /index.html;
add_header X-Frame-Options "SAMEORIGIN";
}
location ^~ /api/ {
proxy_pass http://draft-appserver:8000/;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
}
location ^~ /ws/ {
proxy_pass http://draft-daphne:8301;
proxy_redirect default;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
}
}
daphne服务器运行以下命令;
command: [
"wait-for-it.sh", "{{ .Values.redis_server }}:6379", "-t", "60", "--",
"wait-for-it.sh", "localhost:3306", "-t", "60", "--",
"daphne",
"-b", "0.0.0.0",
"-v", "2",
"-p", "8301",
"myapp.asgi:application"
]
来自 nginx 的服务器日志如下所示;
[24/May/2023:21:40:16 +0000] "GET /ws/1-1 HTTP/1.1" 403 5 "-" "Mozilla/5.0
还有瑞香荚;
2023-05-24 21:40:19,433 daphne.server INFO failing WebSocket opening handshake ('Access denied')
2023-05-24 21:40:19,433 daphne.server WARNING dropping connection to peer tcp4:10.254.0.118:34828 with abort=False: Access denied
10.254.0.118
这是 nginx pod 的 IP。
django 的 ASGI 端设置如下;
asgi.py
django_asgi_app = get_asgi_application()
from core import routing as core_routing
application = ProtocolTypeRouter(
{
"http": django_asgi_app,
"websocket": AllowedHostsOriginValidator(
AuthMiddlewareStack(URLRouter(core_routing.websocket_urlpatterns))
),
}
)
我已经运行了此应用程序,但并未AllowedHostsOriginValidator
确认这不是主机验证的问题。
以及那些 URL 模式;
websocket_urlpatterns = [
re_path(
r"^ws/(?P<league_id>[0-9]+)-(?P<entry_id>[0-9]+)",
consumers.MyConsumer.as_asgi(),
)
]
答案1
这是一个忽略 django 设置的简单案例。
虽然我已经更新了ALLOWED_HOSTS
对于 django,SESSION_COOKIE_DOMAIN
尚未更新以考虑单个设置文件使用两个域的情况。
nginx 日志中看到的 403 是在 django-channels 中抛出的,该通道会对AuthMiddlewareStack
会话进行检查