未按安装指南操作时,网站可通过IP地址访问

出于安全考虑,我认为默认情况下,当在浏览器中直接导航到 IP 地址时,Discourse 论坛不应可见。

原因如下:

  • 允许在不使用 HTTPS 的情况下使用站点,既适用于用户,也适用于管理员的初始配置。
  • 会泄露源服务器地址。如果您使用 Cloudflare 或类似服务来保护源 IP 免受 DDoS 攻击或服务器入侵尝试(尤其是当黑客认为服务器具有高价值时),这非常不利。目前有一些人在运行扫描所有网络托管商 IP 范围的机器人。

此外,现在的 Discourse 安装程序会确认域名/子域名是否配置正确,否则不会继续安装。

只需在 Docker 容器内的 /etc/nginx/conf.d/discourse.conf 文件底部添加以下内容:

server {
    listen 80;
    server_name 1.1.1.1;
    server_tokens off;
    return 404;
}

其中 1.1.1.1 是服务器的公网 IP 地址。可能有一种更优雅的方式来包含 IP 地址,而不是硬编码。我尝试了几种方法,但未能成功。

对我来说效果很好(包括使用 Cloudflare 代理的情况)。我想不出有多少情况下允许直接通过 IP 进行 Web 访问是实用或必要的。禁止这种访问似乎是相当普遍的做法。不过,我很乐意听到任何反对这样做的理由!

1 个赞

既然我们的默认指南能让您的网站在仅使用 HTTPS 的情况下正常运行,为什么要进行任何更改呢?

有特殊需求的用户可以自行调整,但我们的默认设置将保持不变,即默认使用可正常工作的域名和 HTTPS。

9 个赞

非常感谢!

1 个赞

客观来说,这并不准确。它并非仅支持 HTTPS,因为你仍然可以通过非 HTTPS 的 IP 地址直接访问该网站。

区别在于禁止在不使用 HTTPS 的情况下进行不安全连接,并暴露服务器的源 IP 地址。我不知道这样做有什么好处。

如果你对全球前 50 大网站进行 DNS 查询,你会发现其中没有一个可以通过 IP 地址直接以不安全的方式访问。我认为假设全球前 50 大网站采用最佳实践并非不合理。

这是一个相当准确的前列网站列表:

这是一个 DNS 查询工具:

默认情况下,尝试通过 IP 访问会返回一个 301 重定向 到正确的域名:

$ curl 159.203.68.6 -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.16.1
Date: Mon, 29 Jun 2020 20:24:41 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://falcoland.falco.dev/

您提出的方案是将 301 改为 404 吗?

3 个赞

8 次安装中有 8 次通过 DigitalOcean 镜像完成,无论是通过 Communiteq(原 DiscourseHosting)安装(随后迁移)还是按照本指南 discourse/docs/INSTALL-cloud.md at main · discourse/discourse · GitHub 手动安装,默认情况下均可通过 IP 地址以不安全的方式访问。其中两个是上周安装的(使用上述 GitHub 指南)。

是不是我漏掉了某个额外步骤?我认为返回 404 错误比 301 重定向更好,毕竟大多数随意探查 IP 地址的人可能心怀不轨。不过,301 重定向总比允许不安全访问要好。

无法复现……

http://38.242.24.122 已正确将重定向到 https://discourse.codinghorror.com/

4 个赞

嗯,也许是 Cloudflare 模板。这很可能是它们与完全原生安装之间唯一一致的区别。

1 个赞

如果您采取的步骤未在云安装列表中列出,那么从定义上讲,它就不是“原生安装”。

Cloudflare 模板并未做任何明显会干扰重定向的操作:

run:
  - file:
      path: /tmp/add-cloudflare-ips
      chmod: +x
      contents: |
        #!/bin/bash -e
        # 下载 CloudFlare IP 列表
        wget https://www.cloudflare.com/ips-v4/ -O - > /tmp/cloudflare-ips
        wget https://www.cloudflare.com/ips-v6/ -O - >> /tmp/cloudflare-ips
        # 转换为 nginx 命令并转义,以便嵌入到 sed 追加命令中
        CONTENTS=$(</tmp/cloudflare-ips sed 's/^/set_real_ip_from /' | sed 's/$/;/' | tr '\n' '\\' | sed 's/\\/\\n/g')
        
        echo CloudFlare IPs:
        echo $(echo | sed "/^/a $CONTENTS")
        # 插入到 discourse.conf 中
        sed -i "/sendfile on;/a $CONTENTS\nreal_ip_header CF-Connecting-IP;" /etc/nginx/conf.d/discourse.conf
        # 清理
        rm /tmp/cloudflare-ips

  - exec: "/tmp/add-cloudflare-ips"
  - exec: "rm /tmp/add-cloudflare-ips"

它会获取 IP 范围,临时存储为 cloudflare-ips,并添加对 CF-Connecting-IP 的支持。

2 个赞

没错,我并没有声称它们是“原生安装”。

因此,我在其中一台服务器上测试了移除官方 Cloudflare 模板后重新构建,但遗憾的是并未产生任何改变。它仍然可以通过 IP 不安全地访问。

实在想不出这些安装之间还有什么其他异常之处。该实例上唯一的插件是默认自带的 Docker 管理器和官方广告插件。它运行在稳定分支上,但其他同样存在该问题的网站则分别运行在稳定版、测试版和测试通过版上。

这不针对任何特定配置或 Cloudflare,只是另一个数据点和观点:

我们可以通过 Apache2 和 Nginx 以多种方式设置代理,将“裸 IP 地址(例如端口 80)”重定向到任意其他 FQDN。

实现方法有很多(如重写并重定向、虚拟主机并重定向等)。

例如,我们可以在反向代理上创建一个虚拟主机,让该反向代理监听特定 IP 地址的 80 端口,并将所有请求重定向到我们选择的任意 FQDN(或 IP 地址)。

我们也可以使用 Apache2 的 mod_rewrite 模块或 Nginx 的重写规则,通过反向代理实现相同功能。

在我们所有 Discourse 部署(生产环境)中,Discourse 前面都部署了反向代理(部分使用 Apache2,部分使用 Nginx)。通过配置反向代理来处理此类问题及特殊情况,可以轻松地缓解这些问题(当它们出现时)。

话虽如此,我并未将 Cloudflare 作为反向代理的特殊案例来使用,但看起来任何代理都可以配置为管理此类问题,就像任何反向代理都可以配置为将“几乎任何内容重定向到任何其他内容”一样。

更进一步,如果我是商业代理用户(如 Cloudflare),并且希望将某个特定 IP 地址或域名重定向(或黑洞化),我会配置(或请求)该代理(此处为 Cloudflare)将“端口 80 上的裸 IP 地址”重定向到我选择的 FQDN(或任意位置)。

这正是代理设计用来处理的功能;如前所述,使用 Apache2 或 Nginx 可以轻松实现此类重定向,因此我推测(虽然我不是 Cloudflare 用户),像 Cloudflare 这样的商业服务也能轻松管理此类简单的重定向。

3 个赞

我使用以下配置,将直接通过 IP 访问的机器人重定向到特殊页面:

server {
        listen 80;
        # listen [::]:80;

        server_name ~^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+;

        root /var/www/ip-address;
        default_type text/plain;
        index nothing.doing;
        location / {
                try_files $uri /nothing.doing;
        }
}

但我和其他人一样,也无法在我的私有论坛中通过 IP 直接访问。我总会收到重定向。而且我的论坛没有任何特殊配置,没有使用 Cloudflare,并且实际上运行在一台每月 0 美元的虚拟服务器上,没有任何额外功能。

3 个赞

但如果你仔细想想,可能会意识到它们都运行在负载均衡的架构上,这些基础设施的成本高达(数千万)美元。因此,它们同样不具备代表性。

迁移并不会复制任何 nginx 设置,因此这实际上是一次全新安装。

2 个赞

太好了,感谢分享这段代码片段 @elijah,非常感谢!我会用你的正则表达式替换硬编码的 IP,或者直接使用完整的代码片段。:slight_smile:

2 个赞

是的,这进一步表明这些网站很可能无法通过任何直接 IP 地址在 Web 上访问。无论如何,似乎没有人支持允许通过 Web 进行不安全的直接 IP 访问。

是的,你说得对。

1 个赞

我刚刚测试了在 Digital Ocean 上使用其市场应用快速启动两个 Discourse 实例。

我想在几乎无需自定义配置的情况下进行测试,只需编辑 SMTP、开发邮箱和 discourse_hostname,填入虚假详情(以允许重建)。

由于我设置的域名/子域名未能通过域名验证步骤,安装程序停止了(并建议手动编辑 app.yml 文件后重新构建)。

在编辑 app.yml 并重新构建后(仅修改了 SMTP、开发邮箱和 discourse_hostname),网站可以通过 IP 地址以不安全的方式访问,无需涉及 Cloudflare,也不会重定向到设置的 discourse_hostname。

我的大多数安装并未使用 Digital Ocean 市场应用进行设置,而是通过标准的 Docker 安装指南手动完成的。

需要注意的是,由于无法验证域名而导致安装程序停止的情况,也发生在我最近进行的两次使用 Cloudflare 的安装中,这可能是因为代理设置。其他安装则是在安装程序中尚未加入域名验证步骤之前完成的。

编辑:请注意,在初始安装过程中,8 个 Discourse 实例中仅有 2 个出现了域名验证问题(不包括上述两个测试实例)。Discourse 设置脚本建议在出现域名验证错误时手动编辑 app.yml 并重新构建。如果这没什么用也没关系,这对我自己来说并非解决方案。

编辑:通常使用 Cloudflare 的灵活 SSL,而不是 Let’s Encrypt(后者会更好)。感谢 @neounix

供参考 @markersocial

我们所有的 Discourse 安装都会将 http://the.ip.add.res 重定向到 .yml Discourse 容器文件中通过启用 LETSENCRYPT 配置的 https://FQDN

要使这一切正常工作,并且让 LETSENCRYPT 证书生效,您需要一个完全正常的 SSL 配置(通常使用 LETSENCRYPT),这一点您应该已经知道了。

只是提醒一下……希望这能帮到您。

2 个赞

Vanilla 拥有有效域名并使用 discourse 设置脚本。

如果您两者都不做,结果不同也就不足为奇了。

此主题没有可操作的信息,而且如果按照说明操作,我们无法复现该问题。

7 个赞