Discourse将服务器IP/localhost显示为用户的IP

您好,我在自己的服务器上部署了 Discourse,一切正常,除了检测用户的 IP 地址。我甚至编写了一个 PHP 脚本(在 Docker 容器外部)来获取所有可能包含 IP 的标头:

REMOTE_ADDR: 212.58.xxx.xxx
SERVER_PORT: 80
SERVER_ADDR: 85.25.xxx.xxx
SERVER_SOFTWARE: Apache:
HTTP_CF_CONNECTING_IP: 212.58.xxx.xxx
HTTP_CDN_LOOP: cloudflare
HTTP_X_REAL_IP: 162.158.xxx.xxx

详细信息:
服务器安装了 BrainyCP 面板,带有 Apache 和 Nginx(目前网站使用 Nginx,它反向代理了 Docker 容器)。
HTTP_CF_CONNECTING_IP 在 Docker 容器内部显示为 127.0.0.1,但在外部它们具有正常值。
在不使用自定义命令更改标头的情况下,Discourse 显示的是服务器的 IP。

(很快会添加更多详细信息,因为我的 Discourse 实例正在重新构建)

我不确定你的设置,但注意到你在帖子中提到了 Cloudflare。你是否将 Cloudflare 模板添加到了你的 app.yml 文件中?

  - "templates/cloudflare.template.yml"

编辑:使用了错误的“ ”

不,我已经将其添加到模板列表中,现在正在等待重新构建。

1 个赞

重建了,但仍然显示服务器 IP(我已经注释掉了自定义命令

## 任何要在构建后运行的自定义命令
run:
  - exec: echo "Beginning of custom commands"
  ## 如果您想为第一次注册设置“发件人”电子邮件地址,请取消注释并更改:
  ## 获取第一封注册电子邮件后,请重新注释该行。它只需要运行一次。
  - exec: rails r "SiteSetting.notification_email='noreply@zeronet.space'"
  #- replace:
  #   filename: /etc/nginx/conf.d/discourse.conf
  #   from: "types {"
  #   to: |
  #     set_real_ip_from 85.25.134.45;
  #     real_ip_header CF-Connection-IP;
  #     real_ip_recursive on;
  #     types {
  #- replace:
  #   filename: /etc/nginx/conf.d/discourse.conf
  #   from: $proxy_add_x_forwarded_for
  #   to: $send_http_cf_connection_ip;
  #   global: true
  - exec: echo "End of custom commands"

我需要取消注释它们吗?(还想注意到,即使在我将 Cloudflare 模板添加到 app.yml 之前,它们也无法正常工作)

取消注释后,$sent_http_cf_connection_ip 返回 127.0.0.1
image

Nginx 可能正在报告 127.0.0.1,而不是 Discourse 本身,您可能需要在 nginx 中设置 realip

我已经添加了 cloudflare.template.yml,它添加了 realip 指令,但仍然无效。
我甚至删除了更改为自定义标头的自定义命令,现在 Discourse 会报告所有用户的服务器 IP 而不是 localhost。

此外,这是面板本身为域名 zeronet.space 生成的 Nginx 配置

server {
	listen 85.25.xxx.xx:443 ssl http2;
	server_name  zeronet.space www.zeronet.space;
	root  /home/ay0ks/workspace/sites/zeronet.space;
	
	# ssl on;
	ssl_certificate  /etc/certs/ay0ks/zeronet.space_1655753906.crt;
	ssl_certificate_key /etc/certs/ay0ks/zeronet.space_1655753906.key;
	#ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	#ssl_ciphers  "HIGH:!RC4:!aNULL:!MD5:!kEDH";
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
	ssl_ciphers TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-256-GCM-SHA384:ECDHE:!COMPLEMENTOFDEFAULT;
	ssl_prefer_server_ciphers on;
	
	add_header Strict-Transport-Security 'max-age=604800';
	
	access_log /etc/nginx/vhost_logs/zeronet.space_access;
	error_log /etc/nginx/vhost_logs/zeronet.space_error;
	
	location ~ /.well-known {
		allow all;
	}
	
	location ~ /\\.ht {
		deny all;
		access_log off;
		log_not_found off;
	}

	location / {
		root /home/ay0ks/workspace/sites/zeronet.space;
		proxy_pass http://85.25.xxx.xx:31080; # Discourse is deployed on ports 31080/31443
		proxy_redirect     off;
		proxy_force_ranges on;
		proxy_set_header   Host $host;
		proxy_set_header   X-Real-IP $remote_addr;
		proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header   X-Forwarded-Proto $scheme;
		proxy_set_header   HTTPS $scheme;
		
		proxy_cache off;
		proxy_cache_key "$request_method|$http_if_modified_since|$http_if_none_match|$host|$request_uri";
		#access_log /etc/nginx/vhost_logs//home/ay0ks/workspace/sites/zeronet.space;
		
		proxy_cache_valid 3s;
		proxy_cache_min_uses 2;
		# proxy_cache_lock on;
		# proxy_cache_use_stale error timeout;
		# proxy_cache_use_stale updating http_502 http_504;
		limit_conn lone 100;
		# limit_req zone=ltwo burst=10;
		
		client_body_buffer_size    128k;
		client_max_body_size       1024m;
		proxy_connect_timeout      180;
		proxy_send_timeout         180;
		proxy_read_timeout         180;
		send_timeout               180;
		
		proxy_buffer_size          4k;
		proxy_buffers              8 32k;
		proxy_busy_buffers_size    68k;
		proxy_temp_file_write_size 10m;
	}

	# error_page  404              /404.html;
	# error_page   500 502 503 504  /50x.html;
}

另外,我想说明一下请求的“路径”:
用户 -> Cloudflare -> 服务器 (Nginx -> Docker -> Discourse)
并请注意,用户的 IP 在 cloudflare 的 CF-Connecting-IP 标头中对于 Docker 外部是可见的

我不太清楚 Cloudflare 真实 IP 的工作原理,但我的猜测是,您的 Discourse nginx 需要将 set_real_ip_from 设置为它看到的代理 nginx 的 IP 地址。是 127.0.0.1 吗?还是其他内部地址?公网地址?不确定它会看到哪个地址。

一旦您知道了该地址,我认为我会保留 cloudflare 模板,然后添加一个新的 replace 仅用于 set_real_ip_from

除此之外,您的代理 nginx 需要配置为传递 CF-Connecting-IP 标头,如果它尚未配置或默认不传递的话。这部分我帮不了您。

和我一样,我的问题是 nginx 没有配置将 docker IP 配置为 realip 的范围。

set_real_ip_from 172.18.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
set_real_ip_from 172.18.0.0/16;

所以我走的是 用户 > Cloudflare > 服务器 Nginx (SWAG Docker) > Discourse

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Real-IP $remote_addr;
templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
## 如果您想添加 Lets Encrypt (https),请取消注释这两行
#  - "templates/web.ssl.template.yml"
#  - "templates/web.letsencrypt.ssl.template.yml"
#  - "templates/web.socketed.template.yml"
  - "templates/cloudflare.template.yml"
4 个赞

这可能是您遇到问题的原因。尝试在没有安装任何面板或反向代理的服务器上设置 Discourse,并报告是否遇到相同的问题。

作为第一步,请先修改 Discourse 的 location 块,使其与此处提供的信息匹配:Run other websites on the same machine as Discourse

1 个赞

那不是一个问题的解决方案,基本上购买一个新的每月 30 欧元的专用服务器可以解决任何问题,哈哈(这样这个帖子就不存在了)。

我将在此处发布结果

是否还需要在 Discourse Nginx 配置(在 Docker 内部)中添加标头?因为仍然显示服务器地址而不是用户地址。

根据您的路径,我无法理解。\n\n您的 nginx 指向 discourse 到 docker,为什么您的 discourse 还要使用自己的 nginx?

不知道,我已经通过面板(也通过 ssh 检查过)将您的 Nginx 指令添加到了我的指令中,但它仍然显示服务器的 IP 地址。

这是我的 app.yml:

## 这是独立运行的 Discourse Docker 容器模板
##
## 修改此文件后,您必须重建
## /var/discourse/launcher rebuild app
##
## 编辑时请*极其小心*!
## YAML 文件对空格或对齐的错误非常非常敏感!
## 如有需要,请访问 http://www.yamllint.com/ 来验证此文件

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/cloudflare.template.yml"
## 如果您想添加 Lets Encrypt (https),请取消注释这两行
  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

## 此容器应暴露哪些 TCP/IP 端口?
## 如果您希望 Discourse 与 Apache 或 nginx 等其他 Web 服务器共享端口,
## 请参阅 https://meta.discourse.org/t/17247 获取详细信息
expose:
  - "31080:80"   # http
  - "31443:443" # https

params:
  db_default_text_search_config: "pg_catalog.russian"

  ## 将 db_shared_buffers 设置为总内存的最多 25%。
  ## 将由 bootstrap 根据检测到的 RAM 自动设置,或者您可以覆盖它
  db_shared_buffers: "4096MB"

  ## 可以提高排序性能,但会增加每个连接的内存使用量
  #db_work_mem: "40MB"

  ## 此容器应使用哪个 Git 版本? (默认:tests-passed)
  #version: tests-passed

env:
  LC_ALL: ru_RU.UTF-8
  LANG: ru_RU.UTF-8
  LANGUAGE: ru_RU.UTF-8
  DISCOURSE_DEFAULT_LOCALE: ru

  ## 支持多少并发 Web 请求?取决于内存和 CPU 核心。
  ## 将由 bootstrap 根据检测到的 CPU 自动设置,或者您可以覆盖它
  UNICORN_WORKERS: 8

  ## TODO:此 Discourse 实例将响应的域名
  ## 必需。Discourse 不能使用纯 IP 地址运行。
  DISCOURSE_HOSTNAME: 'zeronet.space'

  ## 如果您希望容器以与上面指定的相同主机名 (-h 选项) 启动,请取消注释
  ## (默认值为“$hostname-$config”)
  #DOCKER_USE_HOSTNAME: true

  ## TODO:将成为初始注册管理员和开发人员的逗号分隔的电子邮件列表
  ## 示例:'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'contact@zeronet.space'

  ## TODO:用于验证新帐户和发送通知的 SMTP 邮件服务器
  # 需要 SMTP 地址、用户名和密码
  # 警告:SMTP 密码中的字符 '#' 可能会导致问题!
  DISCOURSE_SMTP_ADDRESS: smtp.zeronet.space
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: noreply@zeronet.space
  DISCOURSE_SMTP_PASSWORD: "xxxxxxx"
  DISCOURSE_SMTP_ENABLE_START_TLS: true
  DISCOURSE_SMTP_AUTHENTICATION: login
  DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none
  DISCOURSE_NOTIFICATION_EMAIL: "noreply@zeronet.space"
  #DISCOURSE_SMTP_DOMAIN: "zeronet.space"

  ## 如果您添加了 Lets Encrypt 模板,请取消注释下方以获取免费 SSL 证书
  #LETSENCRYPT_ACCOUNT_EMAIL: me@example.com

  ## 此 Discourse 实例的 HTTP 或 HTTPS CDN 地址 (配置为拉取)
  ## 请参阅 https://meta.discourse.org/t/14857 获取详细信息
  #DISCOURSE_CDN_URL: https://discourse-cdn.example.com

  ## 用于 IP 地址查找的 maxmind 地理位置 IP 地址密钥
  ## 请参阅 https://meta.discourse.org/t/-/137387/23 获取详细信息
  #DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456

## Docker 容器是无状态的;所有数据都存储在 /shared 中
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

## 插件在此处
## 请参阅 https://meta.discourse.org/t/19157 获取详细信息
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git

## 构建后要运行的任何自定义命令
run:
  - exec: echo "开始执行自定义命令"
  ## 如果您想设置首次注册的“发件人”电子邮件地址,请取消注释并进行更改:
  ## 在收到首次注册电子邮件后,重新注释该行。它只需要运行一次。
  - exec: rails r "SiteSetting.notification_email='noreply@zeronet.space'"
  - exec: echo "自定义命令执行完毕"

答案在上面已链接。你需要类似这样的东西。

4 个赞

这修复了 IP 检测问题(现在一切正常),但现在有些图片无法加载

编辑:这是一个缓存问题,现在一切正常!谢谢大家!

2 个赞

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.