【发布时间】:2016-03-19 00:07:08
【问题描述】:
我将 nginx 设置为反向代理,并在后台使用 gunicorn。这个网络服务器设置为我的 Django 应用程序提供数据,它有一个 postgresql 后端。整个设置托管在两台 Ubuntu 机器上(一个是应用程序机器,另一个是数据库机器)。
我只通过 gunicorn 测试了这个设置,没有 nginx。工作完美。接下来为了生产,我在 gunicorn 前面添加了 nginx 反向代理。我立刻遇到了一个令人沮丧的错误:invalid input syntax for type inet: ""(当用户尝试登录我的 Django 应用程序时出现)
登录我的应用程序的用户的 IP 保存在会话表中; Django 自己做到这一点。现在众所周知,Postgresql 要求所有客户端 IP 为 INET sort(其他一些数据库也允许字符串 IP,但不允许 postgres)。 INET 类型不允许“”(即空)值,而是抛出错误invalid input syntax for type inet: ""。
换句话说,我的 nginx 反向代理没有将 REMOTE_ADDR 的值发送到 Django 应用程序。仅使用 gunicorn 正确设置该值(因此一切正常)。如何让 nginx 在 Django 的 request.META 中将 $remote_addr 值传递给 REMOTE_ADDR?
我尝试在我的 /etc/nginx/sites-avaialble/myproject 文件的 location 块中包含 proto_set_header REMOTE_ADDR $remote_addr;。它不起作用 - 之后我可以在 request.META 中看到 HTTP_REMOTE_ADDR 值,但 REMOTE_ADDR 仍然是“”。
那么如何在 Django 的 request.META 中设置 REMOTE_ADDR(即客户端的 IP 地址)字段?也许我可以通过 gunicorn 明确地传递它?有人提到我应该在数据库端处理它 - 我不确定我该怎么做?我应该编辑 pg_hba.conf 或 postgresql.conf 还是什么?我查看了这些文件,没有选项可以记录“允许 IP 的空值”。此外,我宁愿将 $remote_addr 中的任何值传递给 Django,而不是让所有登录用户的 IP 为空。
别忘了,如果我单独使用 gunicorn,Django 的 request.META 中的 REMOTE_ADDR 会正确设置;所以我的猜测是问题在于我如何通过 nginx 传递它。
请帮忙!如果您觉得需要,请随时询问更多信息。
/etc/nginx/sites-available/myproject:
server {
listen 80;
server_name example.cloudapp.net;
charset utf-8;
underscores_in_headers on;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/mhb11/folder/myproject;
}
location / {
proxy_pass_request_headers on;
include proxy_params;
proxy_pass http://unix:/home/mhb11/folder/myproject/myproject.sock;
}
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/mhb11/folder/myproject/templates/;
}
}
/etc/nginx/proxy_params:
proxy_set_header Host $host;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
【问题讨论】:
-
你能不能把
proxy_set_header REMOTE_ADDR $remote_addr;改成proxy_set_header REMOTE-ADDR $remote_addr;? -
试一试,不幸的是结果完全相同。我之前也尝试过,认为正确的语法可能是使用连字符而不是下划线,就像每个指令一样。没用。
-
也许有办法通过 gunicorn 显式传递这个?如果可以传递secure_scheme_headers:docs.gunicorn.org/en/19.3/settings.html#secure-scheme-headers,或许也可以传递REMOTE_ADDR 的值?
标签: python django postgresql nginx proxy